random_variable 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/ext/extconf.rb CHANGED
@@ -2,6 +2,7 @@ require 'mkmf'
2
2
 
3
3
  extension_name = 'random_variable'
4
4
  have_header 'ruby.h'
5
+ have_header 'stdarg.h'
5
6
  have_header 'math.h'
6
7
  have_header 'limits.h'
7
8
  create_makefile 'random_variable'
@@ -41,6 +41,12 @@
41
41
  #error "No ruby.h header found"
42
42
  #endif /* HAVE_RUBY_H */
43
43
 
44
+ #ifdef HAVE_STDARG_H
45
+ #include <stdarg.h>
46
+ #else
47
+ #error "No stdarg.h header found"
48
+ #endif /* HAVE_STDARG_H */
49
+
44
50
  #ifdef HAVE_MATH_H
45
51
  #include <math.h>
46
52
  #else
@@ -57,1009 +63,563 @@
57
63
  #include "xrandlib.h"
58
64
 
59
65
  /******************************************************************************/
60
- /* class objects */
61
- /******************************************************************************/
62
- static VALUE rb_mRandomVariable;
63
- static VALUE rb_cGenericRV;
64
- static VALUE rb_cBernoulliRV;
65
- static VALUE rb_cBinomialRV;
66
- static VALUE rb_cPoissonRV;
67
- static VALUE rb_cNormalRV;
68
- static VALUE rb_cExponentialRV;
69
- static VALUE rb_cRayleighRV;
70
- static VALUE rb_cContinuousUniformRV;
71
- static VALUE rb_cDiscreteUniformRV;
72
- static VALUE rb_cBetaRV;
73
- static VALUE rb_cFRV;
66
+ /* random variable types */
74
67
  /******************************************************************************/
75
- /* Common Functions */
68
+ typedef enum {
69
+ rv_type_generic = 0,
70
+
71
+ rv_type_bernoulli,
72
+ rv_type_beta,
73
+ rv_type_binomial,
74
+ rv_type_continuous_uniform,
75
+ rv_type_discrete_uniform,
76
+ rv_type_exponential,
77
+ rv_type_f,
78
+ rv_type_normal,
79
+ rv_type_poisson,
80
+ rv_type_rayleigh,
81
+
82
+ /* end of random variable types */
83
+
84
+ RV_NR_TYPES /* has to be the last element in the enum */
85
+ } type_t;
86
+ #define NR_RANDOM_VARIABLES RV_NR_TYPES
76
87
  /******************************************************************************/
77
- #define CAST(f) ((VALUE (*)(void *))(f))
78
-
79
- static inline void check_not_nan(double x, const char *str)
80
- {
81
- if (isnan(x))
82
- rb_raise(rb_eArgError, "%s", str);
83
- }
84
-
85
- #define CHECK_NOT_NAN(x) check_not_nan((x), \
86
- "not a number (NaN) " #x " parameter")
87
-
88
- static inline void check_not_infinite(double x, const char *str)
89
- {
90
- if (isfinite(x))
91
- return;
92
- rb_raise(rb_eArgError, "%s", str);
93
- }
94
-
95
- #define CHECK_NOT_INFINITE(x) check_not_infinite((x),"infinite " #x " paramter")
96
-
97
-
98
- static inline void dbl_check_positive(double x, const char *str)
99
- {
100
- if (x > 0.0)
101
- return;
102
- rb_raise(rb_eArgError, "%s", str);
103
- }
104
-
105
- #define DBL_CHECK_POSITIVE(x) dbl_check_positive((x), \
106
- "non-positive " #x " parameter")
107
-
108
-
109
- static inline void long_check_positive(long x, const char *str)
110
- {
111
- if (x > 0)
112
- return;
113
- rb_raise(rb_eArgError, "%s", str);
114
- }
115
-
116
- #define LONG_CHECK_POSITIVE(x) long_check_positive((x), \
117
- "non-positive " #x " parameter")
118
-
119
- static inline void dbl_check_non_neg(double x, const char *str)
120
- {
121
- if (x >= 0.0)
122
- return;
123
- rb_raise(rb_eArgError, "%s", str);
124
- }
125
-
126
- #define DBL_CHECK_NON_NEG(x) long_check_positive((x), \
127
- "negative " #x " parameter")
128
-
129
- static inline void long_check_non_neg(long x, const char *str)
130
- {
131
- if (x >= 0)
132
- return;
133
- rb_raise(rb_eArgError, "%s", str);
134
- }
135
-
136
- #define LONG_CHECK_NON_NEG(x) long_check_non_neg((x), \
137
- "negative " #x " parameter")
138
-
139
- static inline int
140
- dbl_check_cinterval(double x, double min, double max,
141
- const char *lower, const char *greater)
142
- {
143
- if (x < min)
144
- rb_raise(rb_eArgError, "%s", lower);
145
- else if (x > max)
146
- rb_raise(rb_eArgError, "%s", greater);
147
- return;
148
- }
149
-
150
- #define DBL_CHECK_CINTERVAL(x,min,max) \
151
- (dbl_check_cinterval((x), (min), (max), \
152
- #x " parameter out of bounds (" #x " < " #min ")", \
153
- #x " parameter out of bounds (" #x " > " #max ")"))
154
-
155
- #define CHECK_PROBABILITY(x) DBL_CHECK_CINTERVAL(x,0.0,1.0)
156
-
157
- static inline int
158
- dbl_check_ointerval(double x, double min, double max,
159
- const char *lower, const char *greater)
160
- {
161
- if (x <= min)
162
- rb_raise(rb_eArgError, "%s", lower);
163
- else if (x >= max)
164
- rb_raise(rb_eArgError, "%s", greater);
165
- return;
166
- }
167
-
168
- #define DBL_CHECK_OINTERVAL(x,min,max) \
169
- (dbl_check_ointerval((x), (min), (max), \
170
- #x " parameter out of bounds (" #x " <= " #min ")", \
171
- #x " parameter out of bounds (" #x " >= " #max ")"))
172
-
173
- static inline long get_times(VALUE times)
174
- {
175
- long nr_times;
176
- Check_Type(times, T_FIXNUM);
177
- if ( (nr_times = NUM2LONG(times)) < 0)
178
- rb_raise(rb_eArgError, "negative number of outcomes");
179
- return nr_times;
180
- }
181
88
 
182
- static inline VALUE
183
- _RV_outcomes(void *rv, VALUE (*_RV_outcome)(void *rv), VALUE times)
184
- {
185
- long repeat;
186
- VALUE outcomes_ary;
187
-
188
- repeat = get_times(times);
189
-
190
- outcomes_ary = rb_ary_new();
191
- for (; repeat > 0; --repeat)
192
- rb_ary_push(outcomes_ary, _RV_outcome(rv));
193
- return outcomes_ary;
194
- }
195
-
196
- /******************************************************************************/
197
- /* Bernoulli Random Variable */
198
- /******************************************************************************/
89
+ #define RANDVAR_DATA data
199
90
  typedef struct {
200
- double p;
201
- } bernoulli_rv_t;
202
-
203
- bernoulli_rv_t *bernoulli_rv_create(double p)
204
- {
205
- bernoulli_rv_t *rv;
206
-
207
- CHECK_NOT_NAN(p);
208
- CHECK_NOT_INFINITE(p);
209
-
210
- /* Check p parameter */
211
- if (p <= 0.0 || p >= 1.0) {
212
- rb_raise(rb_eArgError, "wrong parameter value (0 < p < 1)");
213
- return NULL;
91
+ type_t type;
92
+ #define RANDVAR_TYPE(rv) ((rv)->type)
93
+
94
+ union {
95
+ struct { double p; } bernoulli;
96
+ struct { double alpha, beta; } beta;
97
+ struct { long n; double p; } binomial;
98
+ struct { double a,b; } continuous_uniform;
99
+ struct { long a,b; } discrete_uniform;
100
+ struct { double lambda; } exponential;
101
+ struct { double d1, d2; } f;
102
+ struct { double mu, sigma; } normal;
103
+ struct { double lambda; } poisson;
104
+ struct { double sigma; } rayleigh;
105
+ } RANDVAR_DATA; /* union */
106
+ } randvar_t;
107
+ #define RANDVAR_ALLOC() ALLOC(randvar_t)
108
+
109
+ #define RV_NR_PARAMS(name, nr_params) \
110
+ static const int rv_ ##name ##_nr_params = nr_params;
111
+
112
+ #define CREATE_RANDVAR_ACCESSOR(name, param, type) \
113
+ static inline type \
114
+ randvar_##name ##_ ##param(randvar_t *rv) \
115
+ { \
116
+ return rv->RANDVAR_DATA . name . param; \
117
+ } \
118
+ static inline void \
119
+ randvar_##name ##_set_ ##param(randvar_t *rv, type param) \
120
+ { \
121
+ rv->RANDVAR_DATA . name . param = param; \
214
122
  }
215
123
 
216
- /* p parameter correct */
217
- rv = ALLOC(bernoulli_rv_t);
218
- rv->p = p;
219
- return rv;
220
- }
221
-
222
- VALUE BernoulliRV_new(VALUE self, VALUE p)
223
- {
224
- bernoulli_rv_t *rv;
225
- VALUE rb_obj;
226
-
227
- rv = bernoulli_rv_create(NUM2DBL(p));
228
- rb_obj = Data_Wrap_Struct(rb_cBernoulliRV, NULL, xfree, rv);
229
- return rb_obj;
230
- }
231
-
232
- static inline bernoulli_rv_t *_BernoulliRV(VALUE BernoulliRV_obj)
233
- {
234
- bernoulli_rv_t *rv;
235
- Data_Get_Struct(BernoulliRV_obj, bernoulli_rv_t, rv);
236
- return rv;
237
- }
238
-
239
- VALUE BernoulliRV_p(VALUE self)
240
- {
241
- return rb_float_new(_BernoulliRV(self)->p);
242
- }
243
-
244
- static inline VALUE _BernoulliRV_outcome(bernoulli_rv_t *rv)
245
- {
246
- return INT2FIX(genbern(rv->p));
247
- }
248
-
249
- VALUE BernoulliRV_outcome(VALUE self)
250
- {
251
- return _BernoulliRV_outcome(_BernoulliRV(self));
252
- }
253
-
254
- VALUE BernoulliRV_outcomes(VALUE self, VALUE times)
255
- {
256
- bernoulli_rv_t *rv;
257
-
258
- rv = _BernoulliRV(self);
259
- return _RV_outcomes(rv, CAST(_BernoulliRV_outcome), times);
260
- }
261
-
262
- /******************************************************************************/
263
- /* Binomial Random Variable */
264
- /******************************************************************************/
265
- typedef struct {
266
- long n;
267
- double p;
268
- } binomial_rv_t;
269
-
270
- binomial_rv_t *binomial_rv_create(long n, double p)
271
- {
272
- binomial_rv_t *rv;
273
-
274
- LONG_CHECK_NON_NEG(n);
275
-
276
-
277
- CHECK_NOT_NAN(p);
278
- CHECK_NOT_INFINITE(p);
279
- CHECK_PROBABILITY(p);
280
-
281
- /* n & p parameters correct */
282
- rv = ALLOC(binomial_rv_t);
283
- rv->n = n;
284
- rv->p = p;
285
- return rv;
286
- }
287
-
288
- VALUE BinomialRV_new(VALUE self, VALUE n, VALUE p)
289
- {
290
- binomial_rv_t *rv;
291
- VALUE rb_obj;
292
-
293
- Check_Type(n, T_FIXNUM);
294
- rv = binomial_rv_create(NUM2LONG(n), NUM2DBL(p));
295
- rb_obj = Data_Wrap_Struct(rb_cBinomialRV, NULL, xfree, rv);
296
- return rb_obj;
297
- }
298
-
299
- static inline binomial_rv_t *_BinomialRV(VALUE BinomialRV_obj)
300
- {
301
- binomial_rv_t *rv;
302
- Data_Get_Struct(BinomialRV_obj, binomial_rv_t, rv);
303
- return rv;
304
- }
305
-
306
- VALUE BinomialRV_n(VALUE self)
307
- {
308
- return LONG2NUM(_BinomialRV(self)->n);
309
- }
310
-
311
- VALUE BinomialRV_p(VALUE self)
312
- {
313
- return rb_float_new(_BinomialRV(self)->p);
314
- }
315
-
316
- static inline VALUE _BinomialRV_outcome(binomial_rv_t *rv)
317
- {
318
- return INT2FIX(ignbin(rv->n, rv->p));
319
- }
320
-
321
- VALUE BinomialRV_outcome(VALUE self)
322
- {
323
- return _BinomialRV_outcome(_BinomialRV(self));
324
- }
325
-
326
- VALUE BinomialRV_outcomes(VALUE self, VALUE times)
327
- {
328
- binomial_rv_t *rv;
329
-
330
- rv = _BinomialRV(self);
331
- return _RV_outcomes(rv, CAST(_BinomialRV_outcome), times);
332
- }
333
-
334
- /******************************************************************************/
335
- /* Poisson Random Variable */
336
- /******************************************************************************/
337
- typedef struct {
338
- double lambda;
339
- } poisson_rv_t;
340
-
341
- /* avoid overflow */
342
- #define POISSON_LAMBDA_MAX (LONG_MAX - (long)(0.00001*LONG_MAX))
343
-
344
- static inline poisson_rv_t *poisson_rv_create(double lambda)
345
- {
346
- poisson_rv_t *rv;
347
-
348
- check_not_nan(lambda, "not a number (NaN) lambda parameter");
349
- check_not_infinite(lambda, "infinite lambda parameter");
350
-
351
- /* Lambda has to be positive */
352
- if (lambda <= 0.0) {
353
- rb_raise(rb_eArgError, "non-positive lambda parameter");
354
- return NULL;
124
+ #define CREATE_RANDVAR_OUTCOME_FUNC1(name, func, type, param) \
125
+ static inline type \
126
+ randvar_##name ##_ ##outcome(randvar_t *rv) \
127
+ { \
128
+ return func(randvar_##name ##_ ##param(rv)); \
355
129
  }
356
130
 
357
- /* Check lambda parameter limits */
358
- if (lambda > POISSON_LAMBDA_MAX) {
359
- rb_raise(rb_eArgError, "too high lambda parameter");
360
- return NULL;
131
+ #define CREATE_RANDVAR_OUTCOME_FUNC2(name, func, type, param1, param2) \
132
+ static inline type \
133
+ randvar_##name ##_ ##outcome(randvar_t *rv) \
134
+ { \
135
+ return func( randvar_##name ##_ ##param1(rv), \
136
+ randvar_##name ##_ ##param2(rv) ); \
361
137
  }
362
138
 
363
- /* Lambda parameter correct */
364
- rv = ALLOC(poisson_rv_t);
365
- rv->lambda = lambda;
366
- return rv;
367
- }
368
-
369
- VALUE PoissonRV_new(VALUE self, VALUE lambda)
370
- {
371
- poisson_rv_t *rv;
372
- VALUE obj;
373
-
374
- rv = poisson_rv_create(NUM2DBL(lambda));
375
- obj = Data_Wrap_Struct(rb_cPoissonRV, NULL, xfree, rv);
376
- return obj;
377
- }
378
-
379
- static inline poisson_rv_t *_PoissonRV(VALUE PoissonRV_obj)
380
- {
381
- poisson_rv_t *rv;
382
- Data_Get_Struct(PoissonRV_obj, poisson_rv_t, rv);
383
- return rv;
384
- }
385
-
386
- VALUE PoissonRV_max_lambda(VALUE self)
387
- {
388
- return DBL2NUM(POISSON_LAMBDA_MAX);
389
- }
390
-
391
- VALUE PoissonRV_lambda(VALUE self)
392
- {
393
- return rb_float_new(_PoissonRV(self)->lambda);
394
- }
395
-
396
- static inline VALUE _PoissonRV_outcome(poisson_rv_t *rv)
397
- {
398
- return LONG2NUM(ignpoi(rv->lambda));
399
- }
400
-
401
- VALUE PoissonRV_outcome(VALUE self)
402
- {
403
- return _PoissonRV_outcome(_PoissonRV(self));
404
- }
405
-
406
- VALUE PoissonRV_outcomes(VALUE self, VALUE times)
407
- {
408
- poisson_rv_t *rv;
409
-
410
- rv = _PoissonRV(self);
411
- return _RV_outcomes(rv, CAST(_PoissonRV_outcome), times);
412
- }
413
-
139
+ #define CREATE_RANDVAR_RB_OUTCOME(name, conv) \
140
+ static VALUE \
141
+ randvar_##name ##_rb_ ##outcome(randvar_t *rv) \
142
+ { \
143
+ return conv((randvar_##name ##_outcome(rv))); \
144
+ } \
145
+
146
+
147
+ /* generic */
148
+ RV_NR_PARAMS(generic, 1)
149
+ /* bernoulli */
150
+ RV_NR_PARAMS(bernoulli, 1)
151
+ CREATE_RANDVAR_ACCESSOR(bernoulli, p, double)
152
+ CREATE_RANDVAR_OUTCOME_FUNC1(bernoulli, gen_bernoulli, int, p)
153
+ CREATE_RANDVAR_RB_OUTCOME(bernoulli, INT2NUM)
154
+ /* beta */
155
+ RV_NR_PARAMS(beta, 2)
156
+ CREATE_RANDVAR_ACCESSOR(beta, alpha, double)
157
+ CREATE_RANDVAR_ACCESSOR(beta, beta, double)
158
+ CREATE_RANDVAR_OUTCOME_FUNC2(beta, genbet, double, alpha, beta)
159
+ CREATE_RANDVAR_RB_OUTCOME(beta, DBL2NUM)
160
+ /* binomial */
161
+ RV_NR_PARAMS(binomial, 2)
162
+ CREATE_RANDVAR_ACCESSOR(binomial, n, long)
163
+ CREATE_RANDVAR_ACCESSOR(binomial, p, double)
164
+ CREATE_RANDVAR_OUTCOME_FUNC2(binomial, ignbin, long, n, p)
165
+ CREATE_RANDVAR_RB_OUTCOME(binomial, LONG2NUM)
166
+ /* continuous uniform */
167
+ RV_NR_PARAMS(continuous_uniform, 2)
168
+ CREATE_RANDVAR_ACCESSOR(continuous_uniform, a, double)
169
+ CREATE_RANDVAR_ACCESSOR(continuous_uniform, b, double)
170
+ CREATE_RANDVAR_OUTCOME_FUNC2(continuous_uniform, genunf, double, a, b)
171
+ CREATE_RANDVAR_RB_OUTCOME(continuous_uniform, DBL2NUM)
172
+ /* discrete uniform */
173
+ RV_NR_PARAMS(discrete_uniform, 2)
174
+ CREATE_RANDVAR_ACCESSOR(discrete_uniform, a, long)
175
+ CREATE_RANDVAR_ACCESSOR(discrete_uniform, b, long)
176
+ CREATE_RANDVAR_OUTCOME_FUNC2(discrete_uniform, ignuin, long, a, b)
177
+ CREATE_RANDVAR_RB_OUTCOME(discrete_uniform, LONG2NUM)
178
+ /* exponential */
179
+ RV_NR_PARAMS(exponential, 1)
180
+ CREATE_RANDVAR_ACCESSOR(exponential, lambda, double)
181
+ CREATE_RANDVAR_OUTCOME_FUNC1(exponential, gen_exponential , double, lambda)
182
+ CREATE_RANDVAR_RB_OUTCOME(exponential, DBL2NUM)
183
+ /* f */
184
+ RV_NR_PARAMS(f, 2)
185
+ CREATE_RANDVAR_ACCESSOR(f, d1, double)
186
+ CREATE_RANDVAR_ACCESSOR(f, d2, double)
187
+ CREATE_RANDVAR_OUTCOME_FUNC2(f, genf, double, d1, d2)
188
+ CREATE_RANDVAR_RB_OUTCOME(f, DBL2NUM)
189
+ /* normal */
190
+ RV_NR_PARAMS(normal, 2)
191
+ CREATE_RANDVAR_ACCESSOR(normal, mu, double)
192
+ CREATE_RANDVAR_ACCESSOR(normal, sigma, double)
193
+ CREATE_RANDVAR_OUTCOME_FUNC2(normal, gennor, double, mu, sigma)
194
+ CREATE_RANDVAR_RB_OUTCOME(normal, DBL2NUM)
195
+ /* poisson */
196
+ RV_NR_PARAMS(poisson, 1)
197
+ CREATE_RANDVAR_ACCESSOR(poisson,lambda, double)
198
+ CREATE_RANDVAR_OUTCOME_FUNC1(poisson, ignpoi, long, lambda)
199
+ CREATE_RANDVAR_RB_OUTCOME(poisson, LONG2NUM)
200
+ /* rayleigh */
201
+ RV_NR_PARAMS(rayleigh, 1)
202
+ CREATE_RANDVAR_ACCESSOR(rayleigh, sigma, double)
203
+ CREATE_RANDVAR_OUTCOME_FUNC1(rayleigh, gen_rayleigh, double, sigma)
204
+ CREATE_RANDVAR_RB_OUTCOME(rayleigh, DBL2NUM)
414
205
 
415
206
  /******************************************************************************/
416
- /* Normal Random Variable */
207
+ /* class and module objects */
208
+ static VALUE rb_mRandomVariable;
209
+ static VALUE rb_cRandomVariables[NR_RANDOM_VARIABLES];
417
210
  /******************************************************************************/
418
- typedef struct {
419
- double mu;
420
- double sigma;
421
- } normal_rv_t;
422
-
423
- static inline normal_rv_t *normal_rv_create(double mu, double sigma)
424
- {
425
- normal_rv_t *rv;
426
-
427
- check_not_nan(mu, "not a number (NaN) mu parameter");
428
- check_not_infinite(mu, "infinite mu parameter");
429
-
430
- check_not_nan(sigma, "not a number (NaN) sigma parameter");
431
- check_not_infinite(sigma, "infinite sigma parameter");
432
-
433
- if (sigma <= 0.0) {
434
- rb_raise(rb_eArgError, "non-positive sigma parameter");
435
- return NULL;
436
- }
437
-
438
-
439
- rv = ALLOC(normal_rv_t);
440
- rv->mu = mu;
441
- rv->sigma = sigma;
442
- return rv;
443
- }
444
-
445
- VALUE NormalRV_new(VALUE self, VALUE mu, VALUE sigma)
446
- {
447
- normal_rv_t *rv;
448
- VALUE rb_obj;
449
-
450
- rv = normal_rv_create(NUM2DBL(mu), NUM2DBL(sigma));
451
- rb_obj = Data_Wrap_Struct(rb_cNormalRV, NULL, xfree, rv);
452
- return rb_obj;
453
- }
454
-
455
- static inline normal_rv_t *_NormalRV(VALUE NormalRV_obj)
456
- {
457
- normal_rv_t *rv;
458
- Data_Get_Struct(NormalRV_obj, normal_rv_t, rv);
459
- return rv;
460
- }
461
-
462
- VALUE NormalRV_mu(VALUE self)
463
- {
464
- normal_rv_t *rv;
465
- return _NormalRV(self)->mu;
466
- }
467
-
468
- VALUE NormalRV_sigma(VALUE self)
469
- {
470
- normal_rv_t *rv;
471
- return _NormalRV(self)->sigma;
472
- }
473
-
474
- static VALUE _NormalRV_outcome(normal_rv_t *rv)
475
- {
476
- return rb_float_new(
477
- gennor(rv->mu, rv->sigma)
478
- );
479
- }
480
-
481
- VALUE NormalRV_outcome(VALUE self)
482
- {
483
- return _NormalRV_outcome(_NormalRV(self));
484
- }
485
-
486
- VALUE NormalRV_outcomes(VALUE self, VALUE times)
487
- {
488
- normal_rv_t *rv;
489
- rv = _NormalRV(self);
490
- return _RV_outcomes(rv, CAST(_NormalRV_outcome), times);
491
- }
492
-
493
211
 
494
212
  /******************************************************************************/
495
- /* Exponential Random Variable */
213
+ /* function callbacks for the random number generating function */
214
+ static VALUE (*outcome_func[NR_RANDOM_VARIABLES])(randvar_t *);
496
215
  /******************************************************************************/
497
- typedef struct {
498
- double mean;
499
- } exponential_rv_t;
500
-
501
- static inline exponential_rv_t *exponential_rv_create(double lambda)
502
- {
503
- exponential_rv_t *rv;
504
-
505
- check_not_nan(lambda, "not a number (NaN) lambda parameter");
506
- check_not_infinite(lambda, "infinite lambda parameter");
507
-
508
- if (lambda <= 0) {
509
- rb_raise(rb_eArgError, "non-positive parameter value");
510
- return NULL;
511
- }
512
-
513
- rv = ALLOC(exponential_rv_t);
514
-
515
- rv->mean = 1.0 / lambda;
516
- return rv;
517
- }
518
-
519
- VALUE ExponentialRV_new(VALUE self, VALUE lambda)
520
- {
521
- exponential_rv_t *rv;
522
- VALUE ExponentialRV_obj;
523
-
524
- rv = exponential_rv_create(NUM2DBL(lambda));
525
- ExponentialRV_obj =
526
- Data_Wrap_Struct(rb_cExponentialRV, NULL, xfree, rv);
527
- return ExponentialRV_obj;
528
- }
529
-
530
- static inline exponential_rv_t *_ExponentialRV(VALUE ExponentialRV_obj)
531
- {
532
- exponential_rv_t *rv;
533
- Data_Get_Struct(ExponentialRV_obj, exponential_rv_t, rv);
534
- return rv;
535
- }
536
-
537
- VALUE ExponentialRV_lambda(VALUE self)
538
- {
539
- return DBL2NUM(1.0 / _ExponentialRV(self)->mean);
540
- }
541
216
 
542
- static inline VALUE _ExponentialRV_outcome(exponential_rv_t *rv)
217
+ static type_t type(VALUE rb_obj)
543
218
  {
544
- return rb_float_new(genexp(rv->mean));
545
- }
219
+ int i;
220
+ for (i = 0; i < NR_RANDOM_VARIABLES; i++)
221
+ if (rb_obj == rb_cRandomVariables[i])
222
+ return i;
546
223
 
547
- VALUE ExponentialRV_outcome(VALUE self)
548
- {
549
- return _ExponentialRV_outcome(_ExponentialRV(self));
224
+ /* it should never reach this point */
225
+ rb_raise(rb_eException, "unkown random variable type");
550
226
  }
551
227
 
552
- VALUE ExponentialRV_outcomes(VALUE self, VALUE times)
553
- {
554
- exponential_rv_t *rv;
555
-
556
- rv = _ExponentialRV(self);
557
- return _RV_outcomes(rv, CAST(_ExponentialRV_outcome), times);
558
- }
559
228
 
560
229
  /******************************************************************************/
561
- /* Rayleigh Random Variable */
230
+ /* functions and macros for parameter validity checks */
562
231
  /******************************************************************************/
563
- typedef struct {
564
- double sigma;
565
- } rayleigh_rv_t;
566
-
567
- static inline rayleigh_rv_t *rayleigh_rv_create(double sigma)
568
- {
569
- rayleigh_rv_t *rv;
570
-
571
- check_not_nan(sigma, "not a number (NaN) sigma parameter");
572
- check_not_infinite(sigma, "infinite sigma parameter");
573
-
574
- if (sigma <= 0) {
575
- rb_raise(rb_eArgError, "non-positive parameter value");
576
- return NULL;
577
- }
578
-
579
- rv = ALLOC(rayleigh_rv_t);
580
-
581
- rv->sigma = sigma;
582
- return rv;
583
- }
584
-
585
- VALUE RayleighRV_new(VALUE self, VALUE sigma)
586
- {
587
- rayleigh_rv_t *rv;
588
- VALUE RayleighRV_obj;
589
-
590
- rv = rayleigh_rv_create(NUM2DBL(sigma));
591
- RayleighRV_obj =
592
- Data_Wrap_Struct(rb_cRayleighRV, NULL, xfree, rv);
593
- return RayleighRV_obj;
594
- }
595
-
596
- static inline rayleigh_rv_t *_RayleighRV(VALUE RayleighRV_obj)
597
- {
598
- rayleigh_rv_t *rv;
599
- Data_Get_Struct(RayleighRV_obj, rayleigh_rv_t, rv);
600
- return rv;
601
- }
602
-
603
- VALUE RayleighRV_sigma(VALUE self)
604
- {
605
- return DBL2NUM(_RayleighRV(self)->sigma);
606
- }
607
-
608
- static inline VALUE _RayleighRV_outcome(rayleigh_rv_t *rv)
609
- {
610
- return rb_float_new(genray(rv->sigma));
611
- }
612
-
613
- VALUE RayleighRV_outcome(VALUE self)
614
- {
615
- return _RayleighRV_outcome(_RayleighRV(self));
616
- }
617
-
618
- VALUE RayleighRV_outcomes(VALUE self, VALUE times)
619
- {
620
- rayleigh_rv_t *rv;
621
-
622
- rv = _RayleighRV(self);
623
- return _RV_outcomes(rv, CAST(_RayleighRV_outcome), times);
624
- }
625
-
232
+ #define CHECK_POSITIVE(x) \
233
+ do { \
234
+ if ((x) <= 0.0) \
235
+ rb_raise(rb_eArgError, \
236
+ "non-positive " #x \
237
+ " parameter"); \
238
+ } while (0)
239
+
240
+ #define CHECK_NON_NEGATIVE(x) \
241
+ do { \
242
+ if ((x) < 0.0) \
243
+ rb_raise(rb_eArgError, \
244
+ "negative " #x \
245
+ " parameter"); \
246
+ } while (0)
247
+
248
+ #define CHECK_LESS_THAN(a,b) \
249
+ do { \
250
+ if ((a) >= (b)) \
251
+ rb_raise(rb_eArgError, \
252
+ #a " parameter not " \
253
+ "lower than " #b \
254
+ " parameter"); \
255
+ } while (0)
256
+
257
+ #define CHECK_RB_INTEGER(x, str) \
258
+ do { \
259
+ if (!rb_obj_is_kind_of(x, rb_cInteger)) \
260
+ rb_raise(rb_eArgError, \
261
+ str " parameter not " \
262
+ "integer"); \
263
+ } while (0)
264
+
265
+ #define CHECK_PROBABILITY(x) \
266
+ do { \
267
+ if (x > 1.0 || x < 0.0) \
268
+ rb_raise(rb_eArgError, \
269
+ #x " parameter " \
270
+ "is not a " \
271
+ "probability"); \
272
+ } while (0)
273
+
274
+ #define VAR_DECLARATIONS va_list ap; \
275
+ randvar_t *rv = NULL; \
276
+ VALUE rb_rv = Qnil; \
277
+ VALUE klass = 0;
278
+ #define SET_KLASS(name) \
279
+ (klass = rb_cRandomVariables[rv_type_ ##name])
280
+ #define GET_NEXT_ARG(ap) va_arg((ap), VALUE)
281
+ #define CREATE_WRAPPING(rv) Data_Wrap_Struct(klass, NULL, xfree, (rv))
282
+
283
+ #define SET_PARAM(name, param) \
284
+ randvar_ ##name ##_set_ ##param(rv, param)
285
+
286
+ /* memory allocation !! */
287
+ #define RANDVAR_INIT(name) \
288
+ do { \
289
+ rv = RANDVAR_ALLOC(); \
290
+ RANDVAR_TYPE(rv) = rv_type_ ##name; \
291
+ rb_rv = CREATE_WRAPPING(rv); \
292
+ } while (0)
293
+
294
+ #define CASE(name) \
295
+ case rv_type_ ##name: \
296
+ {
297
+
298
+ #define CASE_END \
299
+ break; \
300
+ }
626
301
  /******************************************************************************/
627
- /* Continuous Uniform Random Variable */
302
+ /* instantiate Ruby random variable objects */
628
303
  /******************************************************************************/
629
- typedef struct {
630
- double a;
631
- double b;
632
- } continuous_uniform_rv_t;
633
-
634
- static inline
635
- continuous_uniform_rv_t *continuous_uniform_rv_create(double a, double b)
304
+ VALUE rb_create_instance(VALUE rb_obj, ...)
636
305
  {
637
- continuous_uniform_rv_t *rv;
306
+ VAR_DECLARATIONS
638
307
 
639
- check_not_nan(a, "not a number (NaN) a parameter");
640
- check_not_infinite(a, "infinite a parameter");
308
+ /* initialize ap for use with the va_arg and va_end macros */
309
+ va_start(ap, rb_obj);
641
310
 
642
- check_not_nan(b, "not a number (NaN) b parameter");
643
- check_not_infinite(b, "infinite b parameter");
311
+ switch (type(rb_obj)) {
312
+ CASE(bernoulli)
313
+ VALUE rb_p;
314
+ double p;
644
315
 
645
- if (a >= b) {
646
- rb_raise(rb_eArgError, "a < b");
647
- return NULL;
648
- }
316
+ SET_KLASS(bernoulli);
649
317
 
650
- rv = ALLOC(continuous_uniform_rv_t);
318
+ rb_p = GET_NEXT_ARG(ap);
319
+ p = NUM2DBL(rb_p);
651
320
 
652
- rv->a = a;
653
- rv->b = b;
654
- return rv;
655
- }
321
+ /* 0 <= p <= 1 */
322
+ CHECK_PROBABILITY(p);
656
323
 
657
- VALUE ContinuousUniformRV_new(VALUE self, VALUE a, VALUE b)
658
- {
659
- continuous_uniform_rv_t *rv;
660
- VALUE ContinuousUniformRV_obj;
324
+ /* p parameter correct */
325
+ RANDVAR_INIT(bernoulli);
326
+ SET_PARAM(bernoulli, p);
327
+ CASE_END
661
328
 
662
- rv = continuous_uniform_rv_create(NUM2DBL(a), NUM2DBL(b));
663
- ContinuousUniformRV_obj =
664
- Data_Wrap_Struct(rb_cContinuousUniformRV, NULL, xfree, rv);
665
- return ContinuousUniformRV_obj;
666
- }
329
+ CASE(beta)
330
+ VALUE rb_alpha, rb_beta;
331
+ double alpha, beta;
667
332
 
668
- static inline
669
- continuous_uniform_rv_t *_ContinuousUniformRV(VALUE ContinuousUniformRV_obj)
670
- {
671
- continuous_uniform_rv_t *rv;
672
- Data_Get_Struct(ContinuousUniformRV_obj, continuous_uniform_rv_t, rv);
673
- return rv;
674
- }
333
+ SET_KLASS(beta);
675
334
 
676
- VALUE ContinuousUniformRV_a(VALUE self)
677
- {
678
- return DBL2NUM(_ContinuousUniformRV(self)->a);
679
- }
335
+ rb_alpha = GET_NEXT_ARG(ap);
336
+ rb_beta = GET_NEXT_ARG(ap);
337
+
338
+ alpha = NUM2DBL(rb_alpha);
339
+ beta = NUM2DBL(rb_beta);
680
340
 
681
- VALUE ContinuousUniformRV_b(VALUE self)
682
- {
683
- return DBL2NUM(_ContinuousUniformRV(self)->b);
684
- }
341
+ /* alpha > 0 */
342
+ CHECK_POSITIVE(alpha);
685
343
 
686
- static inline VALUE _ContinuousUniformRV_outcome(continuous_uniform_rv_t *rv)
687
- {
688
- return rb_float_new(genunf(rv->a, rv->b));
689
- }
344
+ /* beta > 0 */
345
+ CHECK_POSITIVE(beta);
690
346
 
691
- VALUE ContinuousUniformRV_outcome(VALUE self)
692
- {
693
- return _ContinuousUniformRV_outcome(_ContinuousUniformRV(self));
694
- }
347
+ /* alpha and beta parameters correct */
348
+ RANDVAR_INIT(beta);
349
+ SET_PARAM(beta, alpha);
350
+ SET_PARAM(beta, beta);
351
+ CASE_END
695
352
 
696
- VALUE ContinuousUniformRV_outcomes(VALUE self, VALUE times)
697
- {
698
- continuous_uniform_rv_t *rv;
699
-
700
- rv = _ContinuousUniformRV(self);
701
- return _RV_outcomes(rv, CAST(_ContinuousUniformRV_outcome), times);
702
- }
353
+ CASE(binomial)
354
+ VALUE rb_n, rb_p;
355
+ long n;
356
+ double p;
703
357
 
704
- /******************************************************************************/
705
- /* Discrete Uniform Random Variable */
706
- /******************************************************************************/
707
- typedef struct {
708
- long a;
709
- long b;
710
- } discrete_uniform_rv_t;
358
+ SET_KLASS(binomial);
359
+
360
+ rb_n = GET_NEXT_ARG(ap);
361
+ rb_p = GET_NEXT_ARG(ap);
711
362
 
712
- static inline
713
- discrete_uniform_rv_t *discrete_uniform_rv_create(long a, long b)
714
- {
715
- discrete_uniform_rv_t *rv;
363
+ CHECK_RB_INTEGER(rb_n, "n");
716
364
 
717
- if (a >= b) {
718
- rb_raise(rb_eArgError, "not a < b");
719
- return NULL;
720
- }
365
+ n = NUM2LONG(rb_n);
366
+ p = NUM2DBL(rb_p);
367
+
368
+ /* n >= 0 */
369
+ CHECK_NON_NEGATIVE(n);
721
370
 
722
- rv = ALLOC(discrete_uniform_rv_t);
371
+ /* 0 <= p <= 1 */
372
+ CHECK_PROBABILITY(p);
373
+
374
+ /* n and p parameters correct */
375
+ RANDVAR_INIT(binomial);
376
+ SET_PARAM(binomial, n);
377
+ SET_PARAM(binomial, p);
378
+ CASE_END
379
+
380
+ CASE(continuous_uniform)
381
+ VALUE rb_a, rb_b;
382
+ double a,b;
383
+
384
+ SET_KLASS(continuous_uniform);
385
+
386
+ rb_a = GET_NEXT_ARG(ap);
387
+ rb_b = GET_NEXT_ARG(ap);
388
+
389
+ a = NUM2DBL(rb_a);
390
+ b = NUM2DBL(rb_b);
391
+
392
+ /* a < b */
393
+ CHECK_LESS_THAN(a,b);
394
+
395
+ /* a and b parameters correct */
396
+ RANDVAR_INIT(continuous_uniform);
397
+ SET_PARAM(continuous_uniform, a);
398
+ SET_PARAM(continuous_uniform, b);
399
+ CASE_END
400
+
401
+ CASE(discrete_uniform)
402
+ VALUE rb_a, rb_b;
403
+ double a,b;
404
+
405
+ SET_KLASS(discrete_uniform);
406
+
407
+ rb_a = GET_NEXT_ARG(ap);
408
+ rb_b = GET_NEXT_ARG(ap);
409
+
410
+ CHECK_RB_INTEGER(rb_a, "a");
411
+ CHECK_RB_INTEGER(rb_b, "b");
412
+
413
+ a = NUM2LONG(rb_a);
414
+ b = NUM2LONG(rb_b);
415
+
416
+ /* a < b */
417
+ CHECK_LESS_THAN(a,b);
418
+
419
+ /* a and b parameters correct */
420
+ RANDVAR_INIT(discrete_uniform);
421
+ SET_PARAM(discrete_uniform, a);
422
+ SET_PARAM(discrete_uniform, b);
423
+ CASE_END
424
+
425
+ CASE(exponential)
426
+ VALUE rb_lambda;
427
+ double lambda;
428
+
429
+ SET_KLASS(exponential);
430
+
431
+ rb_lambda = GET_NEXT_ARG(ap);
432
+ lambda = NUM2DBL(rb_lambda);
433
+
434
+ /* lambda > 0 */
435
+ CHECK_POSITIVE(lambda);
436
+
437
+ /* lambda parameter correct */
438
+ RANDVAR_INIT(exponential);
439
+ SET_PARAM(exponential, lambda);
440
+ CASE_END
441
+
442
+ CASE(f)
443
+ VALUE rb_d1, rb_d2;
444
+ double d1, d2;
445
+
446
+ SET_KLASS(f);
447
+
448
+ rb_d1 = GET_NEXT_ARG(ap);
449
+ rb_d2 = GET_NEXT_ARG(ap);
450
+
451
+ d1 = NUM2DBL(rb_d1);
452
+ d2 = NUM2DBL(rb_d2);
453
+
454
+ /* d1 > 0 */
455
+ /* d2 > 0 */
456
+ CHECK_POSITIVE(d1);
457
+ CHECK_POSITIVE(d2);
458
+
459
+ /* d1, d2 parameters correct */
460
+ RANDVAR_INIT(f);
461
+ SET_PARAM(f, d1);
462
+ SET_PARAM(f, d2);
463
+ CASE_END
464
+
465
+ CASE(normal)
466
+ VALUE rb_mu, rb_sigma;
467
+ double mu, sigma;
468
+
469
+ SET_KLASS(normal);
470
+
471
+ rb_mu = GET_NEXT_ARG(ap);
472
+ rb_sigma = GET_NEXT_ARG(ap);
473
+ mu = NUM2DBL(rb_mu);
474
+ sigma = NUM2DBL(rb_sigma);
475
+
476
+ /* sigma > 0 */
477
+ CHECK_POSITIVE(sigma);
478
+
479
+ /* sigma parameter correct */
480
+ RANDVAR_INIT(normal);
481
+ SET_PARAM(normal, mu);
482
+ SET_PARAM(normal, sigma);
483
+ CASE_END
484
+
485
+ CASE(poisson)
486
+ VALUE rb_lambda;
487
+ double lambda;
488
+
489
+ SET_KLASS(poisson);
490
+
491
+ rb_lambda = GET_NEXT_ARG(ap);
492
+ lambda = NUM2DBL(rb_lambda);
493
+ /* lambda > 0 */
494
+ CHECK_POSITIVE(lambda);
495
+
496
+ /* lambda parameter correct */
497
+ RANDVAR_INIT(poisson);
498
+ SET_PARAM(poisson, lambda);
499
+ CASE_END
723
500
 
724
- rv->a = a;
725
- rv->b = b;
726
- return rv;
727
- }
501
+ CASE(rayleigh)
502
+ VALUE rb_sigma;
503
+ double sigma;
728
504
 
729
- VALUE DiscreteUniformRV_new(VALUE self, VALUE a, VALUE b)
730
- {
731
- discrete_uniform_rv_t *rv;
732
- VALUE DiscreteUniformRV_obj;
505
+ SET_KLASS(rayleigh);
733
506
 
734
- /* Check both parameters are integers only */
735
- VALUE a_is_integer, b_is_integer;
736
- a_is_integer = rb_obj_is_kind_of(a, rb_cInteger);
737
- b_is_integer = rb_obj_is_kind_of(b, rb_cInteger);
738
-
739
- if (!a_is_integer && b_is_integer)
740
- rb_raise(rb_eArgError, "not integer a parameter");
741
- else if (a_is_integer && !b_is_integer)
742
- rb_raise(rb_eArgError, "not integer b parameter");
743
- else if (!a_is_integer && !b_is_integer)
744
- rb_raise(rb_eArgError, "not integer a and b parameters");
507
+ rb_sigma = GET_NEXT_ARG(ap);
508
+ sigma = NUM2DBL(rb_sigma);
745
509
 
746
-
747
- rv = discrete_uniform_rv_create(NUM2LONG(a), NUM2LONG(b));
748
- DiscreteUniformRV_obj =
749
- Data_Wrap_Struct(rb_cDiscreteUniformRV, NULL, xfree, rv);
750
- return DiscreteUniformRV_obj;
751
- }
752
-
753
- static inline
754
- discrete_uniform_rv_t *_DiscreteUniformRV(VALUE DiscreteUniformRV_obj)
755
- {
756
- discrete_uniform_rv_t *rv;
757
- Data_Get_Struct(DiscreteUniformRV_obj, discrete_uniform_rv_t, rv);
758
- return rv;
759
- }
760
-
761
- VALUE DiscreteUniformRV_a(VALUE self)
762
- {
763
- return LONG2NUM(_DiscreteUniformRV(self)->a);
764
- }
765
-
766
- VALUE DiscreteUniformRV_b(VALUE self)
767
- {
768
- return LONG2NUM(_DiscreteUniformRV(self)->b);
769
- }
770
-
771
- static inline VALUE _DiscreteUniformRV_outcome(discrete_uniform_rv_t *rv)
772
- {
773
- return rb_float_new(genunf(rv->a, rv->b));
774
- }
775
-
776
- VALUE DiscreteUniformRV_outcome(VALUE self)
777
- {
778
- return _DiscreteUniformRV_outcome(_DiscreteUniformRV(self));
779
- }
780
-
781
- VALUE DiscreteUniformRV_outcomes(VALUE self, VALUE times)
782
- {
783
- discrete_uniform_rv_t *rv;
784
-
785
- rv = _DiscreteUniformRV(self);
786
- return _RV_outcomes(rv, CAST(_DiscreteUniformRV_outcome), times);
787
- }
788
-
510
+ /* sigma > 0 */
511
+ CHECK_POSITIVE(sigma);
512
+
513
+ RANDVAR_INIT(rayleigh);
514
+ SET_PARAM(rayleigh, sigma);
515
+ CASE_END
516
+
517
+ default:
518
+ rb_rv = Qnil;
519
+
520
+ } /* switch */
521
+ va_end(ap);
522
+ return rb_rv;
523
+ }
524
+ #undef CHECK_POSITIVE
525
+ #undef CHECK_NON_NEGATIVE
526
+ #undef CHECK_LESS_THAN
527
+ #undef CHECK_RB_INTEGER
528
+ #undef CHECK_PROBABILITY
529
+ #undef VAR_DECLARATIONS
530
+ #undef SET_KLASS
531
+ #undef GET_NEXT_ARG
532
+ #undef CREATE_WRAPPING
533
+ #undef SET_PARAM
534
+ #undef RANDVAR_INIT
535
+ #undef CASE
536
+ #undef CASE_END
537
+
538
+
539
+ #define GET_DATA(rb_obj, rv) Data_Get_Struct((rb_obj), randvar_t, (rv))
789
540
  /******************************************************************************/
790
- /* Beta Random Variable */
541
+ /* obtain a single outcome from the Ruby random variable object */
791
542
  /******************************************************************************/
792
- typedef struct {
793
- double alpha;
794
- double beta;
795
- } beta_rv_t;
796
-
797
- static inline
798
- beta_rv_t *beta_rv_create(double alpha, double beta)
543
+ VALUE rb_outcome(VALUE rb_obj)
799
544
  {
800
- beta_rv_t *rv;
801
-
802
- CHECK_NOT_NAN(alpha);
803
- CHECK_NOT_INFINITE(alpha);
804
-
805
- CHECK_NOT_NAN(beta);
806
- CHECK_NOT_INFINITE(beta);
807
-
808
- DBL_CHECK_POSITIVE(alpha);
809
- DBL_CHECK_POSITIVE(beta);
810
-
811
- rv = ALLOC(beta_rv_t);
545
+ randvar_t *rv = NULL;
812
546
 
813
- rv->alpha = alpha;
814
- rv->beta = beta;
815
- return rv;
816
- }
817
-
818
- VALUE BetaRV_new(VALUE self, VALUE alpha, VALUE beta)
819
- {
820
- beta_rv_t *rv;
821
- VALUE BetaRV_obj;
822
-
823
- rv = beta_rv_create(NUM2DBL(alpha), NUM2DBL(beta));
824
- BetaRV_obj =
825
- Data_Wrap_Struct(rb_cBetaRV, NULL, xfree, rv);
826
- return BetaRV_obj;
827
- }
828
-
829
- static inline
830
- beta_rv_t *_BetaRV(VALUE BetaRV_obj)
831
- {
832
- beta_rv_t *rv;
833
- Data_Get_Struct(BetaRV_obj, beta_rv_t, rv);
834
- return rv;
835
- }
836
-
837
- VALUE BetaRV_alpha(VALUE self)
838
- {
839
- return DBL2NUM(_BetaRV(self)->alpha);
840
- }
841
-
842
- VALUE BetaRV_beta(VALUE self)
843
- {
844
- return DBL2NUM(_BetaRV(self)->beta);
845
- }
547
+ GET_DATA(rb_obj, rv);
846
548
 
847
- static inline VALUE _BetaRV_outcome(beta_rv_t *rv)
848
- {
849
- return rb_float_new(genbet(rv->alpha, rv->beta));
850
- }
851
-
852
- VALUE BetaRV_outcome(VALUE self)
853
- {
854
- return _BetaRV_outcome(_BetaRV(self));
549
+ return (*(outcome_func[RANDVAR_TYPE(rv)]))(rv);
855
550
  }
856
551
 
857
- VALUE BetaRV_outcomes(VALUE self, VALUE times)
552
+ static inline long get_nr_times(VALUE rb_nr_times)
858
553
  {
859
- beta_rv_t *rv;
860
-
861
- rv = _BetaRV(self);
862
- return _RV_outcomes(rv, CAST(_BetaRV_outcome), times);
554
+ long nr_times;
555
+ Check_Type(rb_nr_times, T_FIXNUM);
556
+ if (0 > (nr_times = NUM2LONG(rb_nr_times)))
557
+ rb_raise(rb_eArgError,
558
+ "the number of outcomes cannot be negative");
559
+ return nr_times;
863
560
  }
864
561
 
865
562
  /******************************************************************************/
866
- /* F Random Variable */
563
+ /* obtain several outcomes from the Ruby random variable object */
867
564
  /******************************************************************************/
868
- typedef struct {
869
- double d1;
870
- double d2;
871
- } f_rv_t;
872
-
873
- static inline
874
- f_rv_t *f_rv_create(double d1, double d2)
875
- {
876
- f_rv_t *rv;
877
-
878
- CHECK_NOT_NAN(d1);
879
- CHECK_NOT_INFINITE(d1);
880
-
881
- CHECK_NOT_NAN(d2);
882
- CHECK_NOT_INFINITE(d2);
883
-
884
- DBL_CHECK_POSITIVE(d1);
885
- DBL_CHECK_POSITIVE(d2);
886
-
887
- rv = ALLOC(f_rv_t);
888
-
889
- rv->d1 = d1;
890
- rv->d2 = d2;
891
- return rv;
892
- }
893
-
894
- VALUE FRV_new(VALUE self, VALUE d1, VALUE d2)
565
+ VALUE rb_outcomes(VALUE rb_obj, VALUE rb_nr_times)
895
566
  {
896
- f_rv_t *rv;
897
- VALUE FRV_obj;
898
-
899
- rv = f_rv_create(NUM2DBL(d1), NUM2DBL(d2));
900
- FRV_obj =
901
- Data_Wrap_Struct(rb_cFRV, NULL, xfree, rv);
902
- return FRV_obj;
903
- }
904
-
905
- static inline
906
- f_rv_t *_FRV(VALUE FRV_obj)
907
- {
908
- f_rv_t *rv;
909
- Data_Get_Struct(FRV_obj, f_rv_t, rv);
910
- return rv;
911
- }
912
-
913
- VALUE FRV_d1(VALUE self)
914
- {
915
- return DBL2NUM(_FRV(self)->d1);
916
- }
917
-
918
- VALUE FRV_d2(VALUE self)
919
- {
920
- return DBL2NUM(_FRV(self)->d2);
921
- }
567
+ randvar_t *rv = NULL;
568
+ VALUE outcomes_ary;
569
+ long nr_times;
570
+ VALUE (*func)(randvar_t *);
922
571
 
923
- static inline VALUE _FRV_outcome(f_rv_t *rv)
924
- {
925
- return rb_float_new(genf(rv->d1, rv->d2));
926
- }
572
+ nr_times = get_nr_times(rb_nr_times);
573
+ GET_DATA(rb_obj, rv);
927
574
 
928
- VALUE FRV_outcome(VALUE self)
929
- {
930
- return _FRV_outcome(_FRV(self));
575
+ func = outcome_func[RANDVAR_TYPE(rv)];
576
+ for (outcomes_ary = rb_ary_new(); nr_times > 0; --nr_times)
577
+ rb_ary_push(outcomes_ary, (*func)(rv));
578
+ return outcomes_ary;
931
579
  }
580
+ #undef GET_DATA
932
581
 
933
- VALUE FRV_outcomes(VALUE self, VALUE times)
934
- {
935
- f_rv_t *rv;
936
-
937
- rv = _FRV(self);
938
- return _RV_outcomes(rv, CAST(_FRV_outcome), times);
939
- }
582
+ /******************************************************************************/
583
+ /* macros for the extension entry point */
584
+ /******************************************************************************/
585
+ #define CREATE_RANDOM_VARIABLE_CLASS(rb_name, name) \
586
+ do { \
587
+ VALUE *rb_objp = &rb_cRandomVariables[rv_type_ ##name]; \
588
+ \
589
+ *rb_objp = rb_define_class_under(rb_mRandomVariable, \
590
+ rb_name, rb_cRandomVariables[rv_type_generic]); \
591
+ \
592
+ rb_define_singleton_method(*rb_objp, "new", \
593
+ (VALUE (*) (ANYARGS)) rb_create_instance, \
594
+ rv_ ##name ##_nr_params); \
595
+ \
596
+ rb_define_method(*rb_objp, "outcome" , rb_outcome, 0); \
597
+ rb_define_method(*rb_objp, "outcomes", rb_outcomes, 1); \
598
+ outcome_func[rv_type_ ##name] = \
599
+ randvar_ ##name ##_rb_outcome; \
600
+ } while (0)
940
601
 
941
602
  /******************************************************************************/
942
- /* Extension Initialization */
603
+ /* extension entry point */
943
604
  /******************************************************************************/
944
605
  void Init_random_variable(void)
945
606
  {
946
- /* RandomVariable */
607
+ /* the RandomVariable module */
947
608
  rb_mRandomVariable = rb_define_module("RandomVariable");
948
-
949
609
  /* Generic */
950
- rb_cGenericRV = rb_define_class_under(rb_mRandomVariable, "Generic",
951
- rb_cObject);
952
-
953
- /* Bernoulli */
954
- rb_cBernoulliRV = rb_define_class_under(rb_mRandomVariable,"Bernoulli", rb_cGenericRV);
955
- rb_define_singleton_method(rb_cBernoulliRV, "new", BernoulliRV_new, 1);
956
- rb_define_method(rb_cBernoulliRV, "p", BernoulliRV_p, 0);
957
- rb_define_method(rb_cBernoulliRV, "outcome", BernoulliRV_outcome, 0);
958
- rb_define_method(rb_cBernoulliRV, "outcomes", BernoulliRV_outcomes, 1);
959
-
960
- /* Binomial */
961
- rb_cBinomialRV = rb_define_class_under(rb_mRandomVariable,"Binomial", rb_cGenericRV);
962
- rb_define_singleton_method(rb_cBinomialRV, "new", BinomialRV_new, 2);
963
- rb_define_method(rb_cBinomialRV, "n", BinomialRV_n, 0);
964
- rb_define_method(rb_cBinomialRV, "p", BinomialRV_p, 0);
965
- rb_define_method(rb_cBinomialRV, "outcome", BinomialRV_outcome, 0);
966
- rb_define_method(rb_cBinomialRV, "outcomes", BinomialRV_outcomes, 1);
967
-
968
- /* Poisson */
969
- rb_cPoissonRV = rb_define_class_under(rb_mRandomVariable,"Poisson", rb_cGenericRV);
970
- rb_define_singleton_method(rb_cPoissonRV, "new", PoissonRV_new, 1);
971
- rb_define_singleton_method(rb_cPoissonRV,
972
- "lambda_max", PoissonRV_max_lambda, 0);
973
- rb_define_method(rb_cPoissonRV, "lambda", PoissonRV_lambda, 0);
974
- rb_define_method(rb_cPoissonRV, "mean", PoissonRV_lambda, 0);
975
- rb_define_method(rb_cPoissonRV, "var", PoissonRV_lambda, 0);
976
- rb_define_method(rb_cPoissonRV, "outcome", PoissonRV_outcome, 0);
977
- rb_define_method(rb_cPoissonRV, "outcomes", PoissonRV_outcomes, 1);
978
-
979
- /* Normal */
980
- rb_cNormalRV = rb_define_class_under(rb_mRandomVariable,"Normal", rb_cGenericRV);
981
- rb_define_singleton_method(rb_cNormalRV, "new", NormalRV_new, 2);
982
- rb_define_method(rb_cNormalRV, "outcome", NormalRV_outcome, 0);
983
- rb_define_method(rb_cNormalRV, "outcomes", NormalRV_outcomes, 1);
984
-
985
- /* Exponential */
986
- rb_cExponentialRV = rb_define_class_under(rb_mRandomVariable,"Exponential", rb_cGenericRV);
987
- rb_define_singleton_method(rb_cExponentialRV, "new",
988
- ExponentialRV_new, 1);
989
- rb_define_method(rb_cExponentialRV, "lambda", ExponentialRV_lambda, 0);
990
- rb_define_method(rb_cExponentialRV, "rate", ExponentialRV_lambda, 0);
991
- rb_define_method(rb_cExponentialRV, "outcome",
992
- ExponentialRV_outcome, 0);
993
- rb_define_method(rb_cExponentialRV, "outcomes",
994
- ExponentialRV_outcomes, 1);
995
-
996
- /* Rayleigh */
997
- rb_cRayleighRV = rb_define_class_under(rb_mRandomVariable,"Rayleigh", rb_cGenericRV);
998
- rb_define_singleton_method(rb_cRayleighRV, "new",
999
- RayleighRV_new, 1);
1000
- rb_define_method(rb_cRayleighRV, "sigma", RayleighRV_sigma, 0);
1001
- rb_define_method(rb_cRayleighRV, "outcome",
1002
- RayleighRV_outcome, 0);
1003
- rb_define_method(rb_cRayleighRV, "outcomes",
1004
- RayleighRV_outcomes, 1);
1005
-
1006
- /* Continuous Uniform */
1007
- rb_cContinuousUniformRV =
1008
- rb_define_class_under(rb_mRandomVariable,"ContinuousUniform", rb_cGenericRV);
1009
- rb_define_singleton_method(rb_cContinuousUniformRV, "new",
1010
- ContinuousUniformRV_new, 2);
1011
- rb_define_method(rb_cContinuousUniformRV,
1012
- "a", ContinuousUniformRV_a, 0);
1013
- rb_define_method(rb_cContinuousUniformRV,
1014
- "b", ContinuousUniformRV_b, 0);
1015
- rb_define_method(rb_cContinuousUniformRV, "outcome",
1016
- ContinuousUniformRV_outcome, 0);
1017
- rb_define_method(rb_cContinuousUniformRV, "outcomes",
1018
- ContinuousUniformRV_outcomes, 1);
1019
-
1020
- /* Discrete Uniform */
1021
- rb_cDiscreteUniformRV =
1022
- rb_define_class_under(rb_mRandomVariable,"DiscreteUniform", rb_cGenericRV);
1023
- rb_define_singleton_method(rb_cDiscreteUniformRV, "new",
1024
- DiscreteUniformRV_new, 2);
1025
- rb_define_method(rb_cDiscreteUniformRV,
1026
- "a", DiscreteUniformRV_a, 0);
1027
- rb_define_method(rb_cDiscreteUniformRV,
1028
- "b", DiscreteUniformRV_b, 0);
1029
- rb_define_method(rb_cDiscreteUniformRV, "outcome",
1030
- DiscreteUniformRV_outcome, 0);
1031
- rb_define_method(rb_cDiscreteUniformRV, "outcomes",
1032
- DiscreteUniformRV_outcomes, 1);
1033
-
1034
- /* Beta */
1035
- rb_cBetaRV =
1036
- rb_define_class_under(rb_mRandomVariable,"Beta", rb_cGenericRV);
1037
- rb_define_singleton_method(rb_cBetaRV, "new",
1038
- BetaRV_new, 2);
1039
- rb_define_method(rb_cBetaRV,
1040
- "alpha", BetaRV_alpha, 0);
1041
- rb_define_method(rb_cBetaRV,
1042
- "beta", BetaRV_beta, 0);
1043
- rb_define_method(rb_cBetaRV, "outcome",
1044
- BetaRV_outcome, 0);
1045
- rb_define_method(rb_cBetaRV, "outcomes",
1046
- BetaRV_outcomes, 1);
1047
-
1048
- /* F */
1049
- rb_cFRV =
1050
- rb_define_class_under(rb_mRandomVariable,"F", rb_cGenericRV);
1051
- rb_define_singleton_method(rb_cFRV, "new",
1052
- FRV_new, 2);
1053
- rb_define_method(rb_cFRV,
1054
- "d1", FRV_d1, 0);
1055
- rb_define_method(rb_cFRV,
1056
- "d2", FRV_d2, 0);
1057
- rb_define_method(rb_cFRV, "outcome",
1058
- FRV_outcome, 0);
1059
- rb_define_method(rb_cFRV, "outcomes",
1060
- FRV_outcomes, 1);
1061
-
1062
- return;
1063
- }
1064
-
610
+ rb_cRandomVariables[rv_type_generic] =
611
+ rb_define_class_under(rb_mRandomVariable,
612
+ "Generic", rb_cObject);
613
+ CREATE_RANDOM_VARIABLE_CLASS("Bernoulli", bernoulli);
614
+ CREATE_RANDOM_VARIABLE_CLASS("Beta", beta);
615
+ CREATE_RANDOM_VARIABLE_CLASS("Binomial", binomial);
616
+ CREATE_RANDOM_VARIABLE_CLASS("ContinuousUniform", continuous_uniform);
617
+ CREATE_RANDOM_VARIABLE_CLASS("DiscreteUniform", discrete_uniform);
618
+ CREATE_RANDOM_VARIABLE_CLASS("Exponential", exponential);
619
+ CREATE_RANDOM_VARIABLE_CLASS("F", f);
620
+ CREATE_RANDOM_VARIABLE_CLASS("Normal", normal);
621
+ CREATE_RANDOM_VARIABLE_CLASS("Poisson", poisson);
622
+ CREATE_RANDOM_VARIABLE_CLASS("Rayleigh", rayleigh);
623
+ }
624
+ #undef CREATE_RANDOM_VARIABLE_CLASS
1065
625