ext/games_dice/probabilities.c in games_dice-0.3.3 vs ext/games_dice/probabilities.c in games_dice-0.3.5
- old
+ new
@@ -19,20 +19,20 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// General utils
//
-static inline int max( int *a, int n ) {
+inline int max( int *a, int n ) {
int m = -1000000000;
int i;
for ( i=0; i < n; i++ ) {
m = a[i] > m ? a[i] : m;
}
return m;
}
-static inline int min( int *a, int n ) {
+inline int min( int *a, int n ) {
int m = 1000000000;
int i;
for ( i=0; i < n; i++ ) {
m = a[i] < m ? a[i] : m;
}
@@ -44,11 +44,11 @@
// Quick factorials, that fit into unsigned longs . . . the size of this structure sets the
// maximum possible n in repeat_n_sum_k calculations
//
// There is no point calculating these, a cache of them is just fine.
-static double nfact[171] = {
+double nfact[171] = {
1.0, 1.0, 2.0, 6.0,
24.0, 120.0, 720.0, 5040.0,
40320.0, 362880.0, 3628800.0, 39916800.0,
479001600.0, 6227020800.0, 87178291200.0, 1307674368000.0,
20922789888000.0, 355687428096000.0, 6402373705728000.0, 121645100408832000.0,
@@ -89,11 +89,11 @@
7.471062926282894e+275, 1.1729568794264145e+278, 1.853271869493735e+280, 2.9467022724950384e+282,
4.7147236359920616e+284, 7.590705053947219e+286, 1.2296942187394494e+289, 2.0044015765453026e+291,
3.287218585534296e+293, 5.423910666131589e+295, 9.003691705778438e+297, 1.503616514864999e+300,
2.5260757449731984e+302, 4.269068009004705e+304, 7.257415615307999e+306 };
-static double num_arrangements( int *args, int nargs ) {
+double num_arrangements( int *args, int nargs ) {
int sum = 0;
double div_by = 1.0;
int i;
for ( i = 0; i < nargs; i++ ) {
sum += args[i];
@@ -108,11 +108,11 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Probability List basics - create, delete, copy
//
-static ProbabilityList *create_probability_list() {
+ProbabilityList *create_probability_list() {
ProbabilityList *pl;
pl = malloc (sizeof(ProbabilityList));
if ( pl == NULL ) {
rb_raise(rb_eRuntimeError, "Could not allocate memory for Probabilities");
}
@@ -121,32 +121,34 @@
pl->slots = 0;
pl->offset = 0;
return pl;
}
-static void destroy_probability_list( ProbabilityList *pl ) {
+void destroy_probability_list( ProbabilityList *pl ) {
xfree( pl->cumulative );
xfree( pl->probs );
xfree( pl );
return;
}
-static double *alloc_probs( ProbabilityList *pl, int slots ) {
+double *alloc_probs( ProbabilityList *pl, int slots ) {
+ double *pr;
+
if ( slots < 1 || slots > 1000000 ) {
rb_raise(rb_eArgError, "Bad number of probability slots");
}
pl->slots = slots;
- double *pr = ALLOC_N( double, slots );
+ pr = ALLOC_N( double, slots );
pl->probs = pr;
pl->cumulative = ALLOC_N( double, slots );
return pr;
}
-static double calc_cumulative( ProbabilityList *pl ) {
+double calc_cumulative( ProbabilityList *pl ) {
double *c = pl->cumulative;
double *pr = pl->probs;
int i;
double t = 0.0;
for(i=0; i < pl->slots; i++) {
@@ -154,33 +156,36 @@
c[i] = t;
}
return t;
}
-static double *alloc_probs_iv( ProbabilityList *pl, int slots, double iv ) {
+double *alloc_probs_iv( ProbabilityList *pl, int slots, double iv ) {
+ double *pr;
+ int i;
+
if ( iv < 0.0 || iv > 1.0 ) {
rb_raise(rb_eArgError, "Bad single probability value");
}
- double *pr = alloc_probs( pl, slots );
- int i;
+ pr= alloc_probs( pl, slots );
for(i=0; i<slots; i++) {
pr[i] = iv;
}
calc_cumulative( pl );
return pr;
}
-static ProbabilityList *copy_probability_list( ProbabilityList *orig ) {
+ProbabilityList *copy_probability_list( ProbabilityList *orig ) {
ProbabilityList *pl = create_probability_list();
- double *pr = alloc_probs( pl, orig->slots );
+ double *pr;
+ pr = alloc_probs( pl, orig->slots );
pl->offset = orig->offset;
memcpy( pr, orig->probs, orig->slots * sizeof(double) );
memcpy( pl->cumulative, orig->cumulative, orig->slots * sizeof(double) );
return pl;
}
-static inline ProbabilityList *new_basic_pl( int nslots, double iv, int o ) {
+inline ProbabilityList *new_basic_pl( int nslots, double iv, int o ) {
ProbabilityList *pl = create_probability_list();
alloc_probs_iv( pl, nslots, iv );
pl->offset = o;
return pl;
}
@@ -188,88 +193,90 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Probability List core "native" methods
//
-static inline int pl_min( ProbabilityList *pl ) {
+inline int pl_min( ProbabilityList *pl ) {
return pl->offset;
}
-static inline int pl_max( ProbabilityList *pl ) {
+inline int pl_max( ProbabilityList *pl ) {
return pl->offset + pl->slots - 1;
}
-static ProbabilityList *pl_add_distributions( ProbabilityList *pl_a, ProbabilityList *pl_b ) {
+ProbabilityList *pl_add_distributions( ProbabilityList *pl_a, ProbabilityList *pl_b ) {
+ double *pr;
int s = pl_a->slots + pl_b->slots - 1;
int o = pl_a->offset + pl_b->offset;
int i,j;
ProbabilityList *pl = create_probability_list();
pl->offset = o;
- double *pr = alloc_probs_iv( pl, s, 0.0 );
+ pr = alloc_probs_iv( pl, s, 0.0 );
for ( i=0; i < pl_a->slots; i++ ) { for ( j=0; j < pl_b->slots; j++ ) {
pr[ i + j ] += (pl_a->probs)[i] * (pl_b->probs)[j];
} }
calc_cumulative( pl );
return pl;
}
-static ProbabilityList *pl_add_distributions_mult( int mul_a, ProbabilityList *pl_a, int mul_b, ProbabilityList *pl_b ) {
+ProbabilityList *pl_add_distributions_mult( int mul_a, ProbabilityList *pl_a, int mul_b, ProbabilityList *pl_b ) {
int pts[4] = {
mul_a * pl_min( pl_a ) + mul_b * pl_min( pl_b ),
mul_a * pl_max( pl_a ) + mul_b * pl_min( pl_b ),
mul_a * pl_min( pl_a ) + mul_b * pl_max( pl_b ),
mul_a * pl_max( pl_a ) + mul_b * pl_max( pl_b ) };
+ double *pr;
int combined_min = min( pts, 4 );
int combined_max = max( pts, 4 );
int s = 1 + combined_max - combined_min;
+ int i,j;
ProbabilityList *pl = create_probability_list();
pl->offset = combined_min;
- double *pr = alloc_probs_iv( pl, s, 0.0 );
- int i,j;
+ pr = alloc_probs_iv( pl, s, 0.0 );
for ( i=0; i < pl_a->slots; i++ ) { for ( j=0; j < pl_b->slots; j++ ) {
int k = mul_a * (i + pl_a->offset) + mul_b * (j + pl_b->offset) - combined_min;
pr[ k ] += (pl_a->probs)[i] * (pl_b->probs)[j];
} }
calc_cumulative( pl );
return pl;
}
-static inline double pl_p_eql( ProbabilityList *pl, int target ) {
+inline double pl_p_eql( ProbabilityList *pl, int target ) {
int idx = target - pl->offset;
if ( idx < 0 || idx >= pl->slots ) {
return 0.0;
}
return (pl->probs)[idx];
}
-static inline double pl_p_gt( ProbabilityList *pl, int target ) {
+inline double pl_p_gt( ProbabilityList *pl, int target ) {
return 1.0 - pl_p_le( pl, target );
}
-static inline double pl_p_lt( ProbabilityList *pl, int target ) {
+inline double pl_p_lt( ProbabilityList *pl, int target ) {
return pl_p_le( pl, target - 1 );
}
-static inline double pl_p_le( ProbabilityList *pl, int target ) {
+inline double pl_p_le( ProbabilityList *pl, int target ) {
int idx = target - pl->offset;
if ( idx < 0 ) {
return 0.0;
}
if ( idx >= pl->slots - 1 ) {
return 1.0;
}
return (pl->cumulative)[idx];
}
-static inline double pl_p_ge( ProbabilityList *pl, int target ) {
+inline double pl_p_ge( ProbabilityList *pl, int target ) {
return 1.0 - pl_p_le( pl, target - 1 );
}
-static inline double pl_expected( ProbabilityList *pl ) {
+inline double pl_expected( ProbabilityList *pl ) {
double t = 0.0;
int o = pl->offset;
int s = pl->slots;
double *pr = pl->probs;
int i;
@@ -277,71 +284,86 @@
t += ( i + o ) * pr[i];
}
return t;
}
-static ProbabilityList *pl_given_ge( ProbabilityList *pl, int target ) {
+ProbabilityList *pl_given_ge( ProbabilityList *pl, int target ) {
int m = pl_min( pl );
+ double p, mult;
+ double *pr;
+ double *new_pr;
+ int o,i,s;
+ ProbabilityList *new_pl;
+
if ( m > target ) {
target = m;
}
- double p = pl_p_ge( pl, target );
+ p = pl_p_ge( pl, target );
if ( p <= 0.0 ) {
rb_raise( rb_eRuntimeError, "Cannot calculate given probabilities, divide by zero" );
}
- double mult = 1.0/p;
- int s = pl->slots + pl->offset - target;
- double *pr = pl->probs;
+ mult = 1.0/p;
+ s = pl->slots + pl->offset - target;
+ pr = pl->probs;
- ProbabilityList *new_pl = create_probability_list();
+ new_pl = create_probability_list();
new_pl->offset = target;
- double *new_pr = alloc_probs( new_pl, s );
- int o = target - pl->offset;
- int i;
+ new_pr = alloc_probs( new_pl, s );
+ o = target - pl->offset;
+
for ( i = 0; i < s; i++ ) {
new_pr[i] = pr[o + i] * mult;
}
calc_cumulative( new_pl );
return new_pl;
}
-static ProbabilityList *pl_given_le( ProbabilityList *pl, int target ) {
+ProbabilityList *pl_given_le( ProbabilityList *pl, int target ) {
int m = pl_max( pl );
+ double p, mult;
+ double *pr;
+ double *new_pr;
+ int i,s;
+ ProbabilityList *new_pl;
+
if ( m < target ) {
target = m;
}
- double p = pl_p_le( pl, target );
+ p = pl_p_le( pl, target );
if ( p <= 0.0 ) {
rb_raise( rb_eRuntimeError, "Cannot calculate given probabilities, divide by zero" );
}
- double mult = 1.0/p;
- int s = target - pl->offset + 1;
- double *pr = pl->probs;
+ mult = 1.0/p;
+ s = target - pl->offset + 1;
+ pr = pl->probs;
- ProbabilityList *new_pl = create_probability_list();
+ new_pl = create_probability_list();
new_pl->offset = pl->offset;
- double *new_pr = alloc_probs( new_pl, s );
- int i;
+ new_pr = alloc_probs( new_pl, s );
+
for ( i = 0; i < s; i++ ) {
new_pr[i] = pr[i] * mult;
}
calc_cumulative( new_pl );
return new_pl;
}
-static ProbabilityList *pl_repeat_sum( ProbabilityList *pl, int n ) {
+ProbabilityList *pl_repeat_sum( ProbabilityList *pl, int n ) {
+ ProbabilityList *pd_power = NULL;
+ ProbabilityList *pd_result = NULL;
+ ProbabilityList *pd_next = NULL;
+ int power = 1;
+
if ( n < 1 ) {
rb_raise( rb_eRuntimeError, "Cannot calculate repeat_sum when n < 1" );
}
if ( n * pl->slots - n > 1000000 ) {
rb_raise( rb_eRuntimeError, "Too many probability slots" );
}
- ProbabilityList *pd_power = copy_probability_list( pl );
- ProbabilityList *pd_result = NULL;
- ProbabilityList *pd_next = NULL;
- int power = 1;
+ pd_power = copy_probability_list( pl );
+
while ( 1 ) {
if ( power & n ) {
if ( pd_result ) {
pd_next = pl_add_distributions( pd_result, pd_power );
destroy_probability_list( pd_result );
@@ -360,11 +382,11 @@
return pd_result;
}
// Assigns { p_rejected, p_maybe, p_kept } to buffer
-static void calc_p_table( ProbabilityList *pl, int q, int kbest, double *buffer ) {
+void calc_p_table( ProbabilityList *pl, int q, int kbest, double *buffer ) {
if ( kbest ) {
buffer[2] = pl_p_gt( pl, q );
buffer[1] = pl_p_eql( pl, q );
buffer[0] = pl_p_lt( pl, q );
} else {
@@ -374,16 +396,16 @@
}
return;
}
// Assigns a list of pl variants to a buffer
-static void calc_keep_distributions( ProbabilityList *pl, int k, int q, int kbest, ProbabilityList **pl_array ) {
- // Init array
+void calc_keep_distributions( ProbabilityList *pl, int k, int q, int kbest, ProbabilityList **pl_array ) {
+ ProbabilityList *pl_kd;
+
int n;
for ( n=0; n<k; n++) { pl_array[n] = NULL; }
pl_array[0] = new_basic_pl( 1, 1.0, q * k );
- ProbabilityList *pl_kd;
if ( kbest ) {
if ( pl_p_gt( pl, q ) > 0.0 && k > 1 ) {
pl_kd = pl_given_ge( pl, q + 1 );
for ( n = 1; n < k; n++ ) {
@@ -402,21 +424,34 @@
}
return;
}
-static inline void clear_pl_array( int k, ProbabilityList **pl_array ) {
+inline void clear_pl_array( int k, ProbabilityList **pl_array ) {
int n;
for ( n=0; n<k; n++) {
if ( pl_array[n] != NULL ) {
destroy_probability_list( pl_array[n] );
}
}
return;
}
-static ProbabilityList *pl_repeat_n_sum_k( ProbabilityList *pl, int n, int k, int kbest ) {
+ProbabilityList *pl_repeat_n_sum_k( ProbabilityList *pl, int n, int k, int kbest ) {
+ // Table of probabilities ( reject, maybe, keep ) for each "pivot point"
+ double p_table[3];
+ int keep_combos[3];
+ // Table of distributions for each count of > pivot point (vs == pivot point)
+ ProbabilityList *keep_distributions[171];
+ ProbabilityList *kd;
+ ProbabilityList *pl_result = NULL;
+
+ double *pr;
+ int d = n - k;
+ int i, j, q, dn, kn, mn, kdq;
+ double p_sequence;
+
if ( n < 1 ) {
rb_raise( rb_eRuntimeError, "Cannot calculate repeat_n_sum_k when n < 1" );
}
if ( k < 1 ) {
rb_raise( rb_eRuntimeError, "Cannot calculate repeat_sum_k when k < 1" );
@@ -430,25 +465,14 @@
if ( n > 170 ) {
rb_raise( rb_eRuntimeError, "Too many dice to calculate combinations" );
}
// Init target
- ProbabilityList *pl_result = create_probability_list();
- double *pr = alloc_probs_iv( pl_result, 1 + k * (pl->slots - 1), 0.0 );
+ pl_result = create_probability_list();
+ pr = alloc_probs_iv( pl_result, 1 + k * (pl->slots - 1), 0.0 );
pl_result->offset = pl->offset * k;
- // Table of probabilities ( reject, maybe, keep ) for each "pivot point"
- double p_table[3];
- int keep_combos[3];
- // Table of distributions for each count of > pivot point (vs == pivot point)
- ProbabilityList *keep_distributions[171];
- ProbabilityList *kd;
-
- int d = n - k;
- int i, j, q, dn, kn, mn, kdq;
- double p_sequence;
-
for ( i = 0; i < pl->slots; i++ ) {
if ( ! pl->probs[i] > 0.0 ) continue;
q = i + pl->offset;
calc_keep_distributions( pl, k, q, kbest, keep_distributions );
@@ -489,36 +513,42 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Ruby integration
//
-static inline VALUE pl_as_ruby_class( ProbabilityList *pl, VALUE klass ) {
+inline VALUE pl_as_ruby_class( ProbabilityList *pl, VALUE klass ) {
return Data_Wrap_Struct( klass, 0, destroy_probability_list, pl );
}
-static VALUE pl_alloc(VALUE klass) {
+VALUE pl_alloc(VALUE klass) {
return pl_as_ruby_class( create_probability_list(), klass );
}
-inline static ProbabilityList *get_probability_list( VALUE obj ) {
+inline ProbabilityList *get_probability_list( VALUE obj ) {
ProbabilityList *pl;
Data_Get_Struct( obj, ProbabilityList, pl );
return pl;
}
-static void assert_value_wraps_pl( VALUE obj ) {
+void assert_value_wraps_pl( VALUE obj ) {
if ( TYPE(obj) != T_DATA ||
RDATA(obj)->dfree != (RUBY_DATA_FUNC)destroy_probability_list) {
rb_raise( rb_eTypeError, "Expected a Probabilities object, but got something else" );
}
}
// Validate key/value from hash, and adjust object properties as required
int validate_key_value( VALUE key, VALUE val, VALUE obj ) {
int k = NUM2INT( key );
- double v = NUM2DBL( val );
ProbabilityList *pl = get_probability_list( obj );
+ // Not assigned (to avoid "unused" warning), but this throws execption if val cannot be coerced to double
+ NUM2DBL( val );
+
+ if ( k > 0x7fffffff ) {
+ rb_raise( rb_eArgError, "Result too large" );
+ }
+
if ( k < pl->offset ) {
if ( pl->slots < 1 ) {
pl->slots = 1;
} else {
pl->slots = pl->slots - k + pl->offset;
@@ -542,43 +572,51 @@
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Ruby class and instance methods for Probabilities
//
-static VALUE probabilities_initialize( VALUE self, VALUE arr, VALUE offset ) {
- int o = NUM2INT(offset);
+VALUE probabilities_initialize( VALUE self, VALUE arr, VALUE offset ) {
+ int i, o, s;
+ double error, p_item;
+ ProbabilityList *pl;
+ double *pr;
+
+ o = NUM2INT(offset);
Check_Type( arr, T_ARRAY );
- int s = FIX2INT( rb_funcall( arr, rb_intern("count"), 0 ) );
- ProbabilityList *pl = get_probability_list( self );
+ s = FIX2INT( rb_funcall( arr, rb_intern("count"), 0 ) );
+ pl = get_probability_list( self );
pl->offset = o;
- int i;
- double *pr = alloc_probs( pl, s );
+ pr = alloc_probs( pl, s );
for(i=0; i<s; i++) {
- double p_item = NUM2DBL( rb_ary_entry( arr, i ) );
+ p_item = NUM2DBL( rb_ary_entry( arr, i ) );
if ( p_item < 0.0 ) {
rb_raise( rb_eArgError, "Negative probability not allowed" );
} else if ( p_item > 1.0 ) {
rb_raise( rb_eArgError, "Probability must be in range 0.0..1.0" );
}
pr[i] = p_item;
}
- double error = calc_cumulative( pl ) - 1.0;
+ error = calc_cumulative( pl ) - 1.0;
if ( error < -1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are less than 1.0" );
} else if ( error > 1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are greater than 1.0" );
}
return self;
}
-static VALUE probabilities_initialize_copy( VALUE copy, VALUE orig ) {
+VALUE probabilities_initialize_copy( VALUE copy, VALUE orig ) {
+ ProbabilityList *pl_copy;
+ ProbabilityList *pl_orig;
+ double *pr;
+
if (copy == orig) return copy;
- ProbabilityList *pl_copy = get_probability_list( copy );
- ProbabilityList *pl_orig = get_probability_list( orig );
+ pl_copy = get_probability_list( copy );
+ pl_orig = get_probability_list( orig );
- double *pr = alloc_probs( pl_copy, pl_orig->slots );
+ pr = alloc_probs( pl_copy, pl_orig->slots );
pl_copy->offset = pl_orig->offset;
memcpy( pr, pl_orig->probs, pl_orig->slots * sizeof(double) );
memcpy( pl_copy->cumulative, pl_orig->cumulative, pl_orig->slots * sizeof(double) );;
return copy;
@@ -647,25 +685,29 @@
int n = NUM2INT(nsum);
ProbabilityList *pl = get_probability_list( self );
return pl_as_ruby_class( pl_repeat_sum( pl, n ), Probabilities );
}
-static VALUE probabilities_repeat_n_sum_k( int argc, VALUE* argv, VALUE self ) {
+VALUE probabilities_repeat_n_sum_k( int argc, VALUE* argv, VALUE self ) {
VALUE nsum, nkeepers, kmode;
+ int keep_best, n, k;
+ ProbabilityList *pl;
+
rb_scan_args( argc, argv, "21", &nsum, &nkeepers, &kmode );
- int keep_best = 1;
+
+ keep_best = 1;
if (NIL_P(kmode)) {
keep_best = 1;
} else if ( rb_intern("keep_worst") == SYM2ID(kmode) ) {
keep_best = 0;
} else if ( rb_intern("keep_best") != SYM2ID(kmode) ) {
rb_raise( rb_eArgError, "Keep mode not recognised" );
}
- int n = NUM2INT(nsum);
- int k = NUM2INT(nkeepers);
- ProbabilityList *pl = get_probability_list( self );
+ n = NUM2INT(nsum);
+ k = NUM2INT(nkeepers);
+ pl = get_probability_list( self );
return pl_as_ruby_class( pl_repeat_n_sum_k( pl, n, k, keep_best ), Probabilities );
}
VALUE probabilities_each( VALUE self ) {
ProbabilityList *pl = get_probability_list( self );
@@ -683,63 +725,78 @@
return self;
}
VALUE probabilities_for_fair_die( VALUE self, VALUE sides ) {
int s = NUM2INT( sides );
+ VALUE obj;
+ ProbabilityList *pl;
+
if ( s < 1 ) {
rb_raise( rb_eArgError, "Number of sides should be 1 or more" );
}
if ( s > 100000 ) {
rb_raise( rb_eArgError, "Number of sides should be less than 100001" );
}
- VALUE obj = pl_alloc( Probabilities );
- ProbabilityList *pl = get_probability_list( obj );
+ obj = pl_alloc( Probabilities );
+ pl = get_probability_list( obj );
pl->offset = 1;
alloc_probs_iv( pl, s, 1.0/s );
return obj;
}
VALUE probabilities_from_h( VALUE self, VALUE hash ) {
VALUE obj = pl_alloc( Probabilities );
ProbabilityList *pl = get_probability_list( obj );
+ double error;
+
// Set these up so that they get adjusted during hash iteration
- pl->offset = 2000000000;
+ pl->offset = 0x7fffffff;
pl->slots = 0;
// First iteration establish min/max and validate all key/values
rb_hash_foreach( hash, validate_key_value, obj );
- double *pr = alloc_probs_iv( pl, pl->slots, 0.0 );
+ alloc_probs_iv( pl, pl->slots, 0.0 );
// Second iteration copy key/value pairs into structure
rb_hash_foreach( hash, copy_key_value, obj );
- double error = calc_cumulative( pl ) - 1.0;
+ error = calc_cumulative( pl ) - 1.0;
if ( error < -1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are less than 1.0" );
} else if ( error > 1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are greater than 1.0" );
}
return obj;
}
VALUE probabilities_add_distributions( VALUE self, VALUE gdpa, VALUE gdpb ) {
- assert_value_wraps_pl( gdpa );
- assert_value_wraps_pl( gdpb );
ProbabilityList *pl_a = get_probability_list( gdpa );
ProbabilityList *pl_b = get_probability_list( gdpb );
+ assert_value_wraps_pl( gdpa );
+ assert_value_wraps_pl( gdpb );
+ pl_a = get_probability_list( gdpa );
+ pl_b = get_probability_list( gdpb );
return pl_as_ruby_class( pl_add_distributions( pl_a, pl_b ), Probabilities );
}
VALUE probabilities_add_distributions_mult( VALUE self, VALUE m_a, VALUE gdpa, VALUE m_b, VALUE gdpb ) {
+ int mul_a, mul_b;
+ ProbabilityList *pl_a;
+ ProbabilityList *pl_b;
+
assert_value_wraps_pl( gdpa );
assert_value_wraps_pl( gdpb );
- int mul_a = NUM2INT( m_a );
- ProbabilityList *pl_a = get_probability_list( gdpa );
- int mul_b = NUM2INT( m_b );
- ProbabilityList *pl_b = get_probability_list( gdpb );
+ mul_a = NUM2INT( m_a );
+ pl_a = get_probability_list( gdpa );
+ mul_b = NUM2INT( m_b );
+ pl_b = get_probability_list( gdpb );
return pl_as_ruby_class( pl_add_distributions_mult( mul_a, pl_a, mul_b, pl_b ), Probabilities );
}
+VALUE probabilities_implemented_in( VALUE self ) {
+ return ID2SYM( rb_intern("c") );
+}
+
///////////////////////////////////////////////////////////////////////////////////////////////////
//
// Setup Probabilities class for Ruby interpretter
//
@@ -763,8 +820,9 @@
rb_define_method( Probabilities, "repeat_sum", probabilities_repeat_sum, 1 );
rb_define_method( Probabilities, "repeat_n_sum_k", probabilities_repeat_n_sum_k, -1 );
rb_define_singleton_method( Probabilities, "for_fair_die", probabilities_for_fair_die, 1 );
rb_define_singleton_method( Probabilities, "add_distributions", probabilities_add_distributions, 2 );
rb_define_singleton_method( Probabilities, "add_distributions_mult", probabilities_add_distributions_mult, 4 );
+ rb_define_singleton_method( Probabilities, "implemented_in", probabilities_implemented_in, 0 );
rb_define_singleton_method( Probabilities, "from_h", probabilities_from_h, 1 );
return;
}