gmp 0.2.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require '../ext/gmp'
4
+
5
+ multiplicands = ARGV
6
+ random_state = GMP::RandState.new
7
+
8
+ if multiplicands.size > 1
9
+ m, n = multiplicands[0].to_i, multiplicands[1].to_i
10
+ x = random_state.urandomb(m)
11
+ y = random_state.urandomb(n)
12
+ else
13
+ m = multiplicands[0].to_i
14
+ x = random_state.urandomb(m)
15
+ y = x
16
+ end
17
+
18
+ t = GMP::time { z = x * y }
19
+ iterations = (1 + (1e4 / t)).to_i
20
+
21
+ if multiplicands.size > 1
22
+ print "Multiplying %i-bit number with %i-bit number %i times..." % [m, n, iterations]
23
+ else
24
+ print "Squaring a %i-bit number %i times..." % [m, iterations]
25
+ end
26
+ STDOUT.flush
27
+
28
+ t0 = GMP::cputime
29
+ iterations.times do
30
+ z = x * y
31
+ end
32
+ ti = GMP::cputime - t0
33
+
34
+ puts "done!"
35
+ ops_per_sec = 1000.0 * iterations / ti
36
+ f = 100.0
37
+ decimals = 0
38
+ while true
39
+ decimals += 1
40
+ break if ops_per_sec > f
41
+ f = f * 0.1
42
+ end
43
+
44
+ puts "RESULT: %#{decimals}f operations per second\n" % ops_per_sec
data/benchmark/rsa ADDED
@@ -0,0 +1,93 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require '../ext/gmp'
4
+
5
+ RSA_EXP = 0x10001
6
+
7
+ def rsa_sign(msg, p, q, pq, p_i_q, dp, dq)
8
+ pr = msg.powmod(dp, p)
9
+ qr = msg.powmod(dq, q)
10
+
11
+ qr_m_pr = qr - pr
12
+
13
+ t = qr_m_pr * p_i_q
14
+ o = t % q
15
+
16
+ t = o * p
17
+ smsg = pr + t
18
+ smsg % pq
19
+ end
20
+
21
+ n = ARGV[0].to_i
22
+ random_state = GMP::RandState.new
23
+
24
+ print "Generating p, q, d..."
25
+ STDOUT.flush
26
+
27
+ pq = GMP::Z()
28
+ while pq != 1
29
+ p = random_state.urandomb(n/2)
30
+ p[n/2 - 1] = true
31
+ p[n/2 - 2] = true
32
+ p[0] = true
33
+
34
+ q = random_state.urandomb(n/2)
35
+ q[n/2 - 1] = true
36
+ q[n/2 - 2] = true
37
+ q[0] = true
38
+
39
+ pq = p.gcd(q)
40
+ end
41
+
42
+ pq = p * q
43
+
44
+ e = GMP::Z(RSA_EXP)
45
+
46
+ pm1 = p - 1
47
+ qm1 = q - 1
48
+ phi = pm1 * qm1
49
+ d = e.invert(phi)
50
+
51
+ puts "done; pq is %i bits" % pq.sizeinbase(2)
52
+ puts "Precomputing CRT constants"
53
+
54
+ p_i_q = p.invert(q)
55
+
56
+ dp = d % pm1
57
+ dq = d % qm1
58
+
59
+ puts "Generating random messages"
60
+
61
+ msg = []
62
+ (0...1024).each do |i|
63
+ msg << random_state.urandomb(n)
64
+ end
65
+
66
+ print "Calibrating CPU speed..."
67
+ STDOUT.flush
68
+ t = GMP::time { smsg = rsa_sign(msg[0], p, q, pq, p_i_q, dp, dq) }
69
+ puts "done"
70
+
71
+ iterations = (1e4 / t).to_i
72
+ iterations = 1 if iterations == 0
73
+
74
+ print "Signing random messages %i times..." % iterations
75
+ STDOUT.flush
76
+
77
+ t0 = GMP::cputime
78
+ (1..iterations).to_a.reverse.each do |i|
79
+ smsg = rsa_sign(msg[i % 1024], p, q, pq, p_i_q, dp, dq)
80
+ end
81
+ ti = GMP::cputime - t0
82
+
83
+ puts "done!"
84
+ ops_per_sec = 1000.0 * iterations / ti
85
+ f = 100.0
86
+ decimals = 0
87
+ while true
88
+ decimals += 1
89
+ break if ops_per_sec > f
90
+ f = f * 0.1
91
+ end
92
+
93
+ puts "RESULT: %#{decimals}f operations per second\n" % ops_per_sec
@@ -0,0 +1,147 @@
1
+ #! /bin/sh
2
+
3
+ # Copyright 2003 Free Software Foundation, Inc.
4
+
5
+ # This file is part of the GNU GMPbench.
6
+
7
+ # This program is free software; you can redistribute it and/or modify it under
8
+ # the terms of the GNU General Public License as published by the Free Software
9
+ # Foundation; either version 2 of the License, or (at your option) any later
10
+ # version.
11
+
12
+ # This program is distributed in the hope that it will be useful, but WITHOUT
13
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14
+ # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15
+ # details.
16
+
17
+ # You should have received a copy of the GNU General Public License along with
18
+ # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19
+ # Place - Suite 330, Boston, MA 02111-1307, USA.
20
+
21
+
22
+ echo "***** GMPbench version `cat version` *****"
23
+
24
+
25
+ default=false
26
+
27
+ if [ "$1" = -n ]
28
+ then
29
+ echo "Suppressing compilation"
30
+ else
31
+ if [ -z "$CFLAGS" ]
32
+ then
33
+ CFLAGS="-O3 -fomit-frame-pointer"
34
+ echo "Using default CFLAGS = \"$CFLAGS\""
35
+ default=true
36
+ else
37
+ echo "Using CFLAGS = \"$CFLAGS\" from your environment"
38
+ fi
39
+ if [ -z "$CC" ]
40
+ then
41
+ CC="gcc"
42
+ echo "Using default CC = \"$CC\""
43
+ default=true
44
+ else
45
+ echo "Using CC = \"$CC\" from your environment"
46
+ fi
47
+ if [ -z "$LIBS" ]
48
+ then
49
+ LIBS="-static -lgmp"
50
+ echo "Using default LIBS = \"$LIBS\""
51
+ default=true
52
+ else
53
+ echo "Using LIBS = \"$LIBS\" from your environment"
54
+ fi
55
+
56
+ echo "Using compilation command: $CC $CFLAGS foo.c -o foo $LIBS"
57
+
58
+ if $default
59
+ then
60
+ echo "You may want to override CC, CFLAGS, and LIBS"
61
+ fi
62
+
63
+ $CC $CFLAGS gmpver.c $LIBS
64
+ `mv a.exe a.out`
65
+ echo "Using `./a.out`"
66
+
67
+ echo "Compiling benchmarks"
68
+ $CC $CFLAGS gcd.c -o gcd $LIBS
69
+ $CC $CFLAGS gcdext.c -o gcdext $LIBS
70
+ $CC $CFLAGS multiply.c -o multiply $LIBS
71
+ $CC $CFLAGS divide.c -o divide $LIBS
72
+ $CC $CFLAGS rsa.c -o rsa $LIBS
73
+ $CC $CFLAGS pi.c -o pi $LIBS -lm
74
+ fi
75
+
76
+ multiply_args="128 512 8192 131072 2097152 128,128 512,512 8192,8192 131072,131072 2097152,2097152 15000,10000 20000,10000 30000,10000 16777216,512 16777216,262144"
77
+ multiply_weight=1
78
+
79
+ divide_args="8192,32 8192,64 8192,128 8192,4096 131072,65536 8388608,4194304 8192,8064 16777216,262144"
80
+ divide_weight=1
81
+
82
+ gcd_args="128,128 512,512 8192,8192 131072,131072 1048576,1048576"
83
+ gcd_weight=0.5
84
+
85
+ gcdext_args="128,128 512,512 8192,8192 131072,131072 1048576,1048576"
86
+ gcdext_weight=0.5
87
+
88
+ rsa_args="512 1024 2048"
89
+ rsa_weight=1
90
+
91
+ pi_args="10000 100000 1000000"
92
+ pi_weight=1
93
+
94
+ # base_tests="multiply divide gcd gcdext"
95
+ base_tests="multiply divide gcd"
96
+ # app_tests="rsa pi"
97
+ app_tests="rsa"
98
+
99
+ tests="base app"
100
+
101
+ echo "Running benchmarks (propagated score accuracy exceeds printed intermediates)"
102
+
103
+ acc2=1
104
+ n2=0
105
+ for cat in $tests
106
+ do
107
+ echo " Category $cat"
108
+ eval tests=\$${cat}_tests
109
+
110
+ acc1=1
111
+ n1=0
112
+ for t in $tests
113
+ do
114
+ eval weight=\$${t}_weight
115
+ echo " Program $t (weight=$weight)"
116
+ eval args=\$${t}_args
117
+
118
+ acc=1
119
+ n=0
120
+ for a in $args
121
+ do
122
+ ta=`echo $a | sed 's;,; ;g'`
123
+ printf ' %-48s' "GMPbench.$cat.$t($a)"
124
+ ./$t $ta >RES-$t-$a
125
+ res=`grep "^RESULT" RES-$t-$a | sed 's;^RESULT: \([0-9.]*\).*$;\1;'`
126
+ printf '%12s\n' `gexpr -prec 4 "$res"`
127
+ acc=`gexpr -prec 10 "$acc * $res"`
128
+ n=`gexpr $n+1`
129
+ done
130
+
131
+ out=`gexpr -prec 10 "$acc^(1/$n)"`
132
+ printf ' %-40s%12s\n' "GMPbench.$cat.$t" `gexpr -prec 5 "$out"`
133
+ acc1=`gexpr -prec 10 "$acc1 * $out^$weight"`
134
+ n1=`gexpr $n1+$weight`
135
+ done
136
+
137
+ out=`gexpr -prec 10 "$acc1^(1/$n1)"`
138
+ printf ' %-32s%12s\n' "GMPbench.$cat" `gexpr -prec 5 "$out"`
139
+ acc2=`gexpr -prec 10 "$acc2 * $out"`
140
+ n2=`gexpr $n2+1`
141
+ done
142
+
143
+
144
+ out=`gexpr "$acc2^(1/$n2)"`
145
+ echo "GMPbench: $out"
146
+
147
+ exit 0
data/benchmark/version ADDED
@@ -0,0 +1 @@
1
+ 0.2
data/ext/gmp.c CHANGED
@@ -6,11 +6,12 @@
6
6
 
7
7
  #include <ruby_gmp.h>
8
8
 
9
- VALUE mGMP, cGMP_Z, cGMP_Q, cGMP_F;
9
+ VALUE mGMP, cGMP_Z, cGMP_Q, cGMP_F, cGMP_RandState;
10
10
 
11
- void r_gmpz_free(void *ptr) { mpz_clear (ptr); free (ptr); }
12
- void r_gmpq_free(void *ptr) { mpq_clear (ptr); free (ptr); }
13
- void r_gmpf_free(void *ptr) { mpf_clear (ptr); free (ptr); }
11
+ void r_gmpz_free(void *ptr) { mpz_clear (ptr); free (ptr); }
12
+ void r_gmpq_free(void *ptr) { mpq_clear (ptr); free (ptr); }
13
+ void r_gmpf_free(void *ptr) { mpf_clear (ptr); free (ptr); }
14
+ void r_gmprandstate_free(void *ptr) { gmp_randclear (ptr); free (ptr); }
14
15
 
15
16
  static void mpq_str_set(MP_RAT *ROP, char *str)
16
17
  {
@@ -138,10 +139,6 @@ void Init_gmp() {
138
139
  cGMP_Z = rb_define_class_under(mGMP, "Z", rb_cInteger);
139
140
  init_gmpz();
140
141
  rb_define_method(cGMP_Z, "coerce", r_gmpz_coerce, 1);
141
- /*
142
- rb_define_method(cGMP_Z, "gcd", r_gmpz_gcd, 1);
143
- rb_define_method(cGMP_Z, "lcm", r_gmpz_lcm, 1);
144
- */
145
142
 
146
143
  cGMP_Q = rb_define_class_under (mGMP, "Q", rb_cNumeric);
147
144
  init_gmpq();
@@ -157,6 +154,11 @@ void Init_gmp() {
157
154
  rb_define_method(cGMP_F, "coerce", r_gmpf_coerce, 1); // new method - testing
158
155
 
159
156
  /* rb_define_method(cGMP_F, "cmpabs", r_gmpf_cmpabs, 1);*/
157
+
158
+ cGMP_RandState = rb_define_class_under (mGMP, "RandState", rb_cObject);
159
+ init_gmprandstate();
160
+
161
+ init_gmpbench_timing();
160
162
 
161
163
  #ifdef MPFR
162
164
  rb_define_method(cGMP_F, "exp", r_gmpfr_exp, 0);
@@ -0,0 +1,80 @@
1
+ #include <ruby_gmp.h>
2
+
3
+ /*
4
+ * Taken directly from GMPbench.
5
+ */
6
+
7
+ #define TIME(t,func) \
8
+ do { \
9
+ long int __t0, __times, __t, __tmp; \
10
+ __times = 1; \
11
+ {func;} \
12
+ do { \
13
+ __times <<= 1; \
14
+ __t0 = FIX2INT(r_gmpmod_cputime ()); \
15
+ for (__t = 0; __t < __times; __t++) \
16
+ {func;} \
17
+ __tmp = FIX2INT(r_gmpmod_cputime ()) - __t0; \
18
+ } while (__tmp < 250); \
19
+ (t) = (double) __tmp / __times; \
20
+ } while (0)
21
+
22
+ /* Return user CPU time measured in milliseconds. */
23
+ #if !defined (__sun) \
24
+ && (defined (USG) || defined (__SVR4) || defined (_UNICOS) \
25
+ || defined (__hpux) || defined (_WIN32))
26
+ #include <time.h>
27
+
28
+ int
29
+ cputime ()
30
+ {
31
+ return (int) ((double) clock () * 1000 / CLOCKS_PER_SEC);
32
+ }
33
+ #else
34
+ #include <sys/types.h>
35
+ #include <sys/time.h>
36
+ #include <sys/resource.h>
37
+
38
+ int
39
+ cputime ()
40
+ {
41
+ struct rusage rus;
42
+
43
+ getrusage (0, &rus);
44
+ return rus.ru_utime.tv_sec * 1000 + rus.ru_utime.tv_usec / 1000;
45
+ }
46
+ #endif
47
+
48
+ VALUE
49
+ r_gmpmod_cputime (VALUE self)
50
+ {
51
+ (void)self;
52
+ return INT2FIX (cputime ());
53
+ }
54
+
55
+ VALUE
56
+ r_gmpmod_time (VALUE self)
57
+ {
58
+ (void)self;
59
+ long int __t0, __times, __t, __tmp;
60
+ __times = 1;
61
+
62
+ rb_need_block();
63
+
64
+ rb_yield (Qnil);
65
+ do {
66
+ __times <<= 1;
67
+ __t0 = cputime ();
68
+ for (__t = 0; __t < __times; __t++)
69
+ {rb_yield (Qnil);}
70
+ __tmp = cputime () - __t0;
71
+ } while (__tmp < 250);
72
+ return rb_float_new ((double) __tmp / __times);
73
+ }
74
+
75
+ void init_gmpbench_timing()
76
+ {
77
+ mGMP = rb_define_module("GMP");
78
+ rb_define_module_function(mGMP, "cputime", r_gmpmod_cputime, 0);
79
+ rb_define_module_function(mGMP, "time", r_gmpmod_time, 0);
80
+ }
@@ -0,0 +1,224 @@
1
+ #include <gmpz.h>
2
+ #include <gmpq.h>
3
+ #include <gmpf.h>
4
+
5
+ /*
6
+ * Document-class: GMP::Z
7
+ *
8
+ * GMP Multiple Precision Integer.
9
+ *
10
+ * Instances of this class can store variables of the type gmp_randstate_t.
11
+ * This class also contains many methods that act as the functions for
12
+ * gmp_randstate_t variables, as well as a few methods that attempt to make
13
+ * this library more Ruby-ish.
14
+ *
15
+ * The following list is just a simple checklist for me, really. A better
16
+ * reference should be found in the rdocs.
17
+ *
18
+ * Ruby method C Extension function GMP function
19
+ * new r_gmprandstatesg_new gmp_randinit_default
20
+ * seed r_gmprandstate_seed gmp_randseed
21
+ * \--- \------------------ gmp_randseed_ui
22
+ * urandomb r_gmprandstate_urandomb mpz_urandomb
23
+ */
24
+
25
+ /**********************************************************************
26
+ * Random State Initialization *
27
+ **********************************************************************/
28
+
29
+ /*
30
+ * call-seq:
31
+ * GMP::RandState.new()
32
+ * GMP::RandState.new(:mt) #=> uses gmp_randinit_mt
33
+ * GMP::RandState.new(:lc_2exp, a, c, m2exp) #=> uses gmp_randinit_lc_2exp
34
+ * GMP::RandState.new(:lc_2exp_size, size) #=> uses gmp_randinit_lc_2exp_size
35
+ *
36
+ * Initializes a new Random State object. Multiple GMP::RandState objects can
37
+ * be instantiated. They may use different generators and the states
38
+ * are kept separate.
39
+ */
40
+ VALUE r_gmprandstatesg_new(int argc, VALUE *argv, VALUE klass)
41
+ {
42
+ MP_RANDSTATE *rs_val;
43
+ VALUE rs;
44
+ VALUE algorithm, arg2, arg3, arg4;
45
+ ID algorithm_id = rb_intern("default");
46
+ MP_INT *a_val;
47
+ unsigned long c_val, m2exp_val;
48
+ unsigned long size_val;
49
+ int free_a_val = 0;
50
+
51
+ ID default_algorithm = rb_intern("default");
52
+ ID mt_algorithm = rb_intern("mt");
53
+ ID lc_2exp_algorithm = rb_intern("lc_2exp");
54
+ ID lc_2exp_size_algorithm = rb_intern("lc_2exp_size");
55
+
56
+ (void)klass;
57
+
58
+ mprandstate_make_struct(rs, rs_val);
59
+ rb_scan_args(argc, argv, "04", &algorithm, &arg2, &arg3, &arg4);
60
+ if (NIL_P(algorithm)) { algorithm_id = rb_intern("default"); } /* default value */
61
+ if (SYMBOL_P(algorithm)) { algorithm_id = rb_to_id(algorithm); }
62
+ if (algorithm_id == default_algorithm ||
63
+ algorithm_id == mt_algorithm) {
64
+ if (argc > 1)
65
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 0 or 1)", argc);
66
+ gmp_randinit_default(rs_val);
67
+ } else if (algorithm_id == lc_2exp_algorithm) {
68
+ if (argc != 4)
69
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 4)", argc);
70
+ if (GMPZ_P(arg2)) {
71
+ mpz_get_struct(arg2, a_val);
72
+ } else if (FIXNUM_P(arg2)) {
73
+ mpz_temp_alloc(a_val);
74
+ mpz_init_set_ui(a_val, FIX2INT(arg2));
75
+ free_a_val = 1;
76
+ } else if (BIGNUM_P(arg2)) {
77
+ mpz_temp_from_bignum(a_val, arg2);
78
+ free_a_val = 1;
79
+ } else {
80
+ typeerror_as(ZXB, "b");
81
+ }
82
+ c_val = NUM2LONG(arg3);
83
+ m2exp_val = NUM2LONG(arg4);
84
+ gmp_randinit_lc_2exp(rs_val, a_val, c_val, m2exp_val);
85
+ } else if (algorithm_id == lc_2exp_size_algorithm) {
86
+ if (argc != 2)
87
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 2)", argc);
88
+ size_val = NUM2LONG(arg2);
89
+ if (size_val > 128)
90
+ rb_raise(rb_eArgError, "size must be within [0..128]");
91
+ int rv = gmp_randinit_lc_2exp_size(rs_val, size_val);
92
+ if (rv == 0)
93
+ rb_raise(rb_eArgError, "could not gmp_randinit_lc_2exp_size with %d", size_val);
94
+ }
95
+
96
+ if (free_a_val) { mpz_temp_free(a_val); }
97
+ rb_obj_call_init(rs, argc, argv);
98
+
99
+ return rs;
100
+ }
101
+
102
+ VALUE r_gmprandstate_initialize(int argc, VALUE *argv, VALUE self)
103
+ {
104
+ MP_RANDSTATE *self_val;
105
+ (void)argv;
106
+
107
+ if (argc != 0) {
108
+ mprandstate_get_struct(self,self_val);
109
+ }
110
+ return Qnil;
111
+ }
112
+
113
+ /*
114
+ * call-seq:
115
+ * GMP::RandState(arg)
116
+ *
117
+ * A convenience method for +GMP::RandState.new(arg)+.
118
+ */
119
+ VALUE r_gmpmod_randstate(int argc, VALUE *argv, VALUE module)
120
+ {
121
+ (void)module;
122
+ return r_gmprandstatesg_new(argc, argv, cGMP_RandState);
123
+ }
124
+
125
+
126
+ /**********************************************************************
127
+ * Random State Initialization *
128
+ **********************************************************************/
129
+
130
+ /*
131
+ * call-seq:
132
+ * rand_state.seed(integer)
133
+ *
134
+ * From the GMP Manual:
135
+ *
136
+ * Set an initial seed value into state.
137
+ *
138
+ * The size of a seed determines how many different sequences of random numbers
139
+ * that it's possible to generate. The �quality� of the seed is the randomness
140
+ * of a given seed compared to the previous seed used, and this affects the
141
+ * randomness of separate number sequences. The method for choosing a seed is
142
+ * critical if the generated numbers are to be used for important applications,
143
+ * such as generating cryptographic keys.
144
+ *
145
+ * Traditionally the system time has been used to seed, but care needs to be
146
+ * taken with this. If an application seeds often and the resolution of the
147
+ * system clock is low, then the same sequence of numbers might be repeated.
148
+ * Also, the system time is quite easy to guess, so if unpredictability is
149
+ * required then it should definitely not be the only source for the seed
150
+ * value. On some systems there's a special device /dev/random which provides
151
+ * random data better suited for use as a seed.
152
+ */
153
+ VALUE r_gmprandstate_seed(VALUE self, VALUE arg)
154
+ {
155
+ MP_RANDSTATE *self_val;
156
+ MP_INT *arg_val;
157
+
158
+ mprandstate_get_struct(self,self_val);
159
+
160
+ if (GMPZ_P(arg)) {
161
+ mpz_get_struct(arg,arg_val);
162
+ gmp_randseed(self_val, arg_val);
163
+ } else if (FIXNUM_P(arg)) {
164
+ gmp_randseed_ui(self_val, FIX2INT(arg));
165
+ } else if (BIGNUM_P(arg)) {
166
+ mpz_temp_from_bignum(arg_val, arg);
167
+ gmp_randseed(self_val, arg_val);
168
+ } else {
169
+ typeerror(ZXB);
170
+ }
171
+ return arg;
172
+ }
173
+
174
+
175
+ /**********************************************************************
176
+ * Integer Random Numbers *
177
+ **********************************************************************/
178
+
179
+ /*
180
+ * call-seq:
181
+ * rand_state.urandomb(fixnum)
182
+ *
183
+ * From the GMP Manual:
184
+ *
185
+ * Generate a uniformly distributed random integer in the range 0 to
186
+ * 2^fixnum-1, inclusive.
187
+ */
188
+ VALUE r_gmprandstate_urandomb(VALUE self, VALUE arg)
189
+ {
190
+ MP_RANDSTATE *self_val;
191
+ MP_INT *res_val;
192
+ VALUE res;
193
+
194
+ mprandstate_get_struct(self,self_val);
195
+
196
+ if (FIXNUM_P(arg)) {
197
+ mpz_make_struct_init(res, res_val);
198
+ mpz_urandomb(res_val, self_val, FIX2INT(arg));
199
+ } else {
200
+ typeerror(X);
201
+ }
202
+
203
+ return res;
204
+ }
205
+
206
+
207
+ void init_gmprandstate()
208
+ {
209
+ mGMP = rb_define_module("GMP");
210
+ rb_define_module_function(mGMP, "RandState", r_gmpmod_randstate, -1);
211
+
212
+ cGMP_RandState = rb_define_class_under(mGMP, "RandState", rb_cObject);
213
+
214
+ // Random State Initialization
215
+ rb_define_singleton_method(cGMP_RandState, "new", r_gmprandstatesg_new, -1);
216
+ rb_define_method(cGMP_RandState, "initialize", r_gmprandstate_initialize, -1);
217
+
218
+ // Random State Seeding
219
+ rb_define_method(cGMP_RandState, "seed", r_gmprandstate_seed, 1);
220
+
221
+ // Integer Random Numbers
222
+ rb_define_method(cGMP_RandState, "urandomb", r_gmprandstate_urandomb, 1);
223
+
224
+ }