random_variable 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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