gmp 0.2.2 → 0.4.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.
@@ -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
+ }