ruby-numtheory 0.0.3-x86-linux → 0.0.4-x86-linux
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/ext/numtheory/numtheory.c +1726 -0
- data/lib/numtheory.so +0 -0
- metadata +6 -5
@@ -0,0 +1,1726 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <stdio.h>
|
3
|
+
#include <math.h>
|
4
|
+
|
5
|
+
#include "primes.h"
|
6
|
+
#include "queue.h"
|
7
|
+
#include "numtheory_macros.c"
|
8
|
+
#include "constants.h"
|
9
|
+
|
10
|
+
static VALUE numtheory_powermod(int argc, VALUE *argv);
|
11
|
+
static VALUE numtheory_int_powermod(VALUE b, VALUE p, VALUE m);
|
12
|
+
static VALUE numtheory_miller_rabin_pseudoprime_p(VALUE n);
|
13
|
+
static VALUE numtheory_nextprime(VALUE n);
|
14
|
+
static VALUE numtheory_precompute_primes_upto(VALUE obj, VALUE n);
|
15
|
+
static VALUE numtheory_prime(VALUE obj, VALUE i);
|
16
|
+
static VALUE numtheory_prime_p(VALUE n);
|
17
|
+
static VALUE numtheory_primepi(VALUE obj, VALUE n);
|
18
|
+
static VALUE numtheory_fibonacci(int argc, VALUE *argv);
|
19
|
+
static VALUE numtheory_sigma(int argc, VALUE *argv);
|
20
|
+
static VALUE numtheory_eulerphi(VALUE obj, VALUE n);
|
21
|
+
static VALUE numtheory_moebius(VALUE obj, VALUE n);
|
22
|
+
static VALUE numtheory_prime_division(VALUE n);
|
23
|
+
static VALUE numtheory_product(VALUE obj, VALUE arr);
|
24
|
+
static VALUE numtheory_primes_upto(VALUE min, VALUE max);
|
25
|
+
static VALUE numtheory_factorial_primeswing(VALUE n);
|
26
|
+
static VALUE numtheory_extended_gcd(VALUE x, VALUE y);
|
27
|
+
static VALUE numtheory_modular_inverse(VALUE x, VALUE y);
|
28
|
+
static VALUE numtheory_multiplicative_order(VALUE a, VALUE m);
|
29
|
+
static VALUE numtheory_pythagorean_triples(VALUE obj, VALUE max_l);
|
30
|
+
static VALUE numtheory_popcount(VALUE n);
|
31
|
+
static VALUE numtheory_bitlength(VALUE n);
|
32
|
+
static VALUE numtheory_jacobi(VALUE a, VALUE n);
|
33
|
+
static VALUE numtheory_sqrtmod(VALUE a, VALUE p);
|
34
|
+
static VALUE numtheory_isqrt(VALUE n);
|
35
|
+
static VALUE numtheory_perfect_square_p(VALUE n);
|
36
|
+
static VALUE numtheory_bpsw_pseudoprime_p(VALUE n);
|
37
|
+
|
38
|
+
static VALUE mNumTheory;
|
39
|
+
static ID primality_tests_ID;
|
40
|
+
|
41
|
+
static ID id_rand, id_mod, id_divmod,
|
42
|
+
id_gcd, id_lcm, id_pow, id_mul;
|
43
|
+
|
44
|
+
static unsigned long PRIMES_UPPER_LIMIT = 3141592;
|
45
|
+
static unsigned long NUM_OF_PRIMES;
|
46
|
+
|
47
|
+
static const VALUE zero = INT2FIX(0);
|
48
|
+
static const VALUE one = INT2FIX(1);
|
49
|
+
static const VALUE two = INT2FIX(2);
|
50
|
+
static const VALUE three = INT2FIX(3);
|
51
|
+
static const VALUE four = INT2FIX(4);
|
52
|
+
static const VALUE five = INT2FIX(5);
|
53
|
+
static const VALUE six = INT2FIX(6);
|
54
|
+
static const VALUE seven = INT2FIX(7);
|
55
|
+
static const VALUE eight = INT2FIX(8);
|
56
|
+
|
57
|
+
/*
|
58
|
+
* The <code>NumTheory</code> module contains basic number-theoretical
|
59
|
+
* functions.
|
60
|
+
*/
|
61
|
+
|
62
|
+
void
|
63
|
+
Init_numtheory()
|
64
|
+
{
|
65
|
+
#if 0
|
66
|
+
VALUE rb_cInteger = rb_define_class("Integer", rb_cObject);
|
67
|
+
VALUE rb_cFixnum = rb_define_class("Fixnum", rb_cObject);
|
68
|
+
#endif
|
69
|
+
VALUE rb_mNumTheory = rb_define_module("NumTheory");
|
70
|
+
mNumTheory = rb_mNumTheory;
|
71
|
+
|
72
|
+
id_rand = rb_intern("rand");
|
73
|
+
id_mod = rb_intern("modulo");
|
74
|
+
id_divmod = rb_intern("divmod");
|
75
|
+
id_gcd = rb_intern("gcd");
|
76
|
+
id_lcm = rb_intern("lcm");
|
77
|
+
id_pow = rb_intern("**");
|
78
|
+
id_mul = rb_intern("*");
|
79
|
+
|
80
|
+
primality_tests_ID = rb_intern("PrimalityTests");
|
81
|
+
/* PrimalityTests: the number of rounds in Miller-Rabin test for primality. */
|
82
|
+
rb_define_const(rb_mNumTheory, "PrimalityTests", INT2FIX(20));
|
83
|
+
|
84
|
+
rb_define_module_function(rb_mNumTheory, "powermod",
|
85
|
+
numtheory_powermod, -1);
|
86
|
+
rb_define_module_function(rb_mNumTheory, "fibonacci",
|
87
|
+
numtheory_fibonacci, -1);
|
88
|
+
rb_define_module_function(rb_mNumTheory, "precompute_primes_upto",
|
89
|
+
numtheory_precompute_primes_upto, 1);
|
90
|
+
rb_define_module_function(rb_mNumTheory, "prime",
|
91
|
+
numtheory_prime, 1);
|
92
|
+
rb_define_module_function(rb_mNumTheory, "primepi",
|
93
|
+
numtheory_primepi, 1);
|
94
|
+
rb_define_module_function(rb_mNumTheory, "sigma",
|
95
|
+
numtheory_sigma, -1);
|
96
|
+
rb_define_module_function(rb_mNumTheory, "eulerphi",
|
97
|
+
numtheory_eulerphi, 1);
|
98
|
+
rb_define_module_function(rb_mNumTheory, "moebius",
|
99
|
+
numtheory_moebius, 1);
|
100
|
+
rb_define_module_function(rb_mNumTheory, "product",
|
101
|
+
numtheory_product, 1);
|
102
|
+
|
103
|
+
rb_define_module_function(rb_mNumTheory, "triples",
|
104
|
+
numtheory_pythagorean_triples, 1);
|
105
|
+
|
106
|
+
rb_define_method(rb_cInteger, "powermod",
|
107
|
+
numtheory_int_powermod, 2);
|
108
|
+
rb_define_method(rb_cInteger, "prime?",
|
109
|
+
numtheory_prime_p, 0);
|
110
|
+
rb_define_method(rb_cInteger, "MR_pseudoprime?",
|
111
|
+
numtheory_miller_rabin_pseudoprime_p, 0);
|
112
|
+
rb_define_method(rb_cInteger, "BPSW_pseudoprime?",
|
113
|
+
numtheory_bpsw_pseudoprime_p, 0);
|
114
|
+
rb_define_method(rb_cInteger, "nextprime",
|
115
|
+
numtheory_nextprime, 0);
|
116
|
+
rb_define_method(rb_cInteger, "prime_division",
|
117
|
+
numtheory_prime_division, 0);
|
118
|
+
rb_define_method(rb_cFixnum, "factorial",
|
119
|
+
numtheory_factorial_primeswing, 0);
|
120
|
+
rb_define_method(rb_cInteger, "primes_upto",
|
121
|
+
numtheory_primes_upto, 1);
|
122
|
+
rb_define_method(rb_cInteger, "extended_gcd",
|
123
|
+
numtheory_extended_gcd, 1);
|
124
|
+
rb_define_method(rb_cInteger, "inverse",
|
125
|
+
numtheory_modular_inverse, 1);
|
126
|
+
rb_define_method(rb_cInteger, "znorder",
|
127
|
+
numtheory_multiplicative_order, 1);
|
128
|
+
rb_define_method(rb_cInteger, "popcount",
|
129
|
+
numtheory_popcount, 0);
|
130
|
+
rb_define_method(rb_cInteger, "bitlength",
|
131
|
+
numtheory_bitlength, 0);
|
132
|
+
rb_define_method(rb_cInteger, "jacobi",
|
133
|
+
numtheory_jacobi, 1);
|
134
|
+
rb_define_method(rb_cInteger, "sqrt_mod",
|
135
|
+
numtheory_sqrtmod, 1);
|
136
|
+
rb_define_method(rb_cInteger, "isqrt",
|
137
|
+
numtheory_isqrt, 0);
|
138
|
+
rb_define_method(rb_cInteger, "square?",
|
139
|
+
numtheory_perfect_square_p, 0);
|
140
|
+
|
141
|
+
NUM_OF_PRIMES = init_sieve(PRIMES_UPPER_LIMIT);
|
142
|
+
/* PRECOMPUTED_PRIMES: the number of precomputed primes. */
|
143
|
+
rb_define_const(rb_mNumTheory, "PRECOMPUTED_PRIMES",
|
144
|
+
INT2NUM(NUM_OF_PRIMES));
|
145
|
+
|
146
|
+
}
|
147
|
+
|
148
|
+
/*
|
149
|
+
* call-seq:
|
150
|
+
* NumTheory.precompute_primes_upto(n)
|
151
|
+
*
|
152
|
+
* Precomputes primes up to the <i>n</i> via Eratosthenes' sieve method.
|
153
|
+
*
|
154
|
+
* NumTheory.precompute_primes_upto(20000000)
|
155
|
+
*/
|
156
|
+
static VALUE
|
157
|
+
numtheory_precompute_primes_upto(VALUE obj, VALUE n)
|
158
|
+
{
|
159
|
+
if (FIXNUM_P(n))
|
160
|
+
{
|
161
|
+
unsigned long t = FIX2LONG(n);
|
162
|
+
if (t < PRIMES_UPPER_LIMIT || FIX2LONG(n) < 0)
|
163
|
+
{
|
164
|
+
rb_warn("new size should be more than old one; prime table is unchanged");
|
165
|
+
return Qnil;
|
166
|
+
}
|
167
|
+
PRIMES_UPPER_LIMIT = FIX2LONG(n);
|
168
|
+
|
169
|
+
free(numtheory_is_prime);
|
170
|
+
free(numtheory_primes);
|
171
|
+
|
172
|
+
NUM_OF_PRIMES = init_sieve(PRIMES_UPPER_LIMIT);
|
173
|
+
rb_const_set(mNumTheory, rb_intern("PRECOMPUTED_PRIMES"),
|
174
|
+
INT2NUM(NUM_OF_PRIMES));
|
175
|
+
}
|
176
|
+
else
|
177
|
+
{
|
178
|
+
rb_raise(rb_eArgError, "The number is too big!");
|
179
|
+
}
|
180
|
+
return Qnil;
|
181
|
+
}
|
182
|
+
|
183
|
+
|
184
|
+
inline static VALUE TO_BIGNUM(VALUE x) {
|
185
|
+
return FIXNUM_P(x) ? rb_int2big(FIX2LONG(x)) : x;
|
186
|
+
}
|
187
|
+
|
188
|
+
inline static unsigned long TO_ULONG(VALUE x) {
|
189
|
+
if (!FIXNUM_P(x))
|
190
|
+
{
|
191
|
+
if (rb_big_cmp(x, ULONG2NUM(ULONG_MAX)) != one)
|
192
|
+
return rb_big2ulong(x);
|
193
|
+
else
|
194
|
+
rb_raise(rb_eNotImpError, "Not implemented for numbers >= 2**32");
|
195
|
+
}
|
196
|
+
return FIX2ULONG(x);
|
197
|
+
}
|
198
|
+
|
199
|
+
inline static int EVEN_P(VALUE x) {
|
200
|
+
return FIXNUM_P(x) ? !(FIX2ULONG(x)&1) : !(RBIGNUM_DIGITS(x)[0]&1);
|
201
|
+
}
|
202
|
+
|
203
|
+
inline static int ZERO_P(VALUE x) {
|
204
|
+
return FIXNUM_P(x) ? FIX2LONG(x) == 0 : rb_bigzero_p(x);
|
205
|
+
}
|
206
|
+
|
207
|
+
inline static VALUE ADD(VALUE x, VALUE y) {
|
208
|
+
return FIXNUM_P(x) ? FIXNUM_P(y) ?
|
209
|
+
LONG2NUM(FIX2LONG(x) + FIX2LONG(y)) :
|
210
|
+
rb_big_plus(y, x) :
|
211
|
+
rb_big_plus(x, y);
|
212
|
+
}
|
213
|
+
|
214
|
+
inline static VALUE SUB(VALUE x, VALUE y) {
|
215
|
+
return (FIXNUM_P(x) && FIXNUM_P(y)) ?
|
216
|
+
LONG2NUM(FIX2LONG(x) - FIX2LONG(y)) :
|
217
|
+
rb_big_minus(TO_BIGNUM(x), y);
|
218
|
+
}
|
219
|
+
|
220
|
+
inline static VALUE MUL(VALUE x, VALUE y) {
|
221
|
+
return rb_funcall(x, id_mul, 1, y);
|
222
|
+
}
|
223
|
+
|
224
|
+
inline static VALUE POW(VALUE b, VALUE p) {
|
225
|
+
return rb_funcall(b, id_pow, 1, p);
|
226
|
+
}
|
227
|
+
|
228
|
+
inline static VALUE DIV(VALUE x, VALUE y) {
|
229
|
+
if (ZERO_P(y))
|
230
|
+
{
|
231
|
+
rb_raise(rb_eZeroDivError, "divided by 0");
|
232
|
+
}
|
233
|
+
return FIXNUM_P(x) ? FIXNUM_P(y) ?
|
234
|
+
INT2FIX( FIX2LONG(x) / FIX2LONG(y)) :
|
235
|
+
zero :
|
236
|
+
rb_big_div(x, y);
|
237
|
+
}
|
238
|
+
|
239
|
+
inline static VALUE DIVMOD(VALUE x, VALUE y) {
|
240
|
+
return rb_funcall(x, id_divmod, 1, y);
|
241
|
+
}
|
242
|
+
|
243
|
+
inline static VALUE MOD(VALUE x, VALUE y) {
|
244
|
+
return rb_funcall(x, id_mod, 1, y);
|
245
|
+
}
|
246
|
+
|
247
|
+
inline static int EQL(VALUE x, VALUE y) {
|
248
|
+
return (FIXNUM_P(x) && FIXNUM_P(y)) ?
|
249
|
+
x == y :
|
250
|
+
rb_big_eq(TO_BIGNUM(x), y) == Qtrue;
|
251
|
+
}
|
252
|
+
|
253
|
+
inline static int MORE(VALUE x, VALUE y) {
|
254
|
+
return (FIXNUM_P(x) && FIXNUM_P(y)) ?
|
255
|
+
FIX2LONG(x) > FIX2LONG(y) :
|
256
|
+
rb_big_cmp(TO_BIGNUM(x), y) == one;
|
257
|
+
}
|
258
|
+
|
259
|
+
inline static int LESS(VALUE x, VALUE y) {
|
260
|
+
return (FIXNUM_P(x) && FIXNUM_P(y)) ?
|
261
|
+
FIX2LONG(x) < FIX2LONG(y) :
|
262
|
+
rb_big_cmp(TO_BIGNUM(x), y) == INT2FIX(-1);
|
263
|
+
}
|
264
|
+
|
265
|
+
inline static int MORE_EQL(VALUE x, VALUE y) {
|
266
|
+
return (FIXNUM_P(x) && FIXNUM_P(y)) ?
|
267
|
+
FIX2LONG(x) >= FIX2LONG(y) :
|
268
|
+
rb_big_cmp(TO_BIGNUM(x), y) != INT2FIX(-1);
|
269
|
+
}
|
270
|
+
|
271
|
+
inline static VALUE ABS(VALUE x) {
|
272
|
+
if (FIXNUM_P(x))
|
273
|
+
return INT2FIX(abs(FIX2LONG(x)));
|
274
|
+
VALUE v = rb_big_clone(x);
|
275
|
+
RBIGNUM_SET_SIGN(v, 1);
|
276
|
+
return v;
|
277
|
+
}
|
278
|
+
|
279
|
+
inline static int NEGATIVE_P(VALUE x) {
|
280
|
+
return FIXNUM_P(x) ? FIX2LONG(x) < 0 : RBIGNUM_NEGATIVE_P(x);
|
281
|
+
}
|
282
|
+
|
283
|
+
inline static VALUE CLONE(VALUE x) {
|
284
|
+
return FIXNUM_P(x) ? x : rb_big_clone(x);
|
285
|
+
}
|
286
|
+
|
287
|
+
inline static int INTEGER_P(VALUE x) {
|
288
|
+
return (TYPE(x) == T_FIXNUM) || (TYPE(x) == T_BIGNUM);
|
289
|
+
}
|
290
|
+
|
291
|
+
inline static VALUE DOUBLED(VALUE x) {
|
292
|
+
return FIXNUM_P(x) ? LONG2NUM(FIX2LONG(x) << 1) :
|
293
|
+
rb_big_lshift(x, one);
|
294
|
+
}
|
295
|
+
|
296
|
+
inline static VALUE HALF(VALUE x) {
|
297
|
+
return FIXNUM_P(x) ? INT2FIX(FIX2LONG(x) >> 1) :
|
298
|
+
rb_big_rshift(x, one);
|
299
|
+
}
|
300
|
+
|
301
|
+
inline static VALUE RIGHT_SHIFT(VALUE x, int s) {
|
302
|
+
return FIXNUM_P(x) ? INT2FIX(FIX2LONG(x) >> s) :
|
303
|
+
rb_big_rshift(x, INT2FIX(s));
|
304
|
+
}
|
305
|
+
|
306
|
+
#ifdef min
|
307
|
+
#undef min
|
308
|
+
#endif
|
309
|
+
inline static int min(int a, int b) { return a < b ? a : b; }
|
310
|
+
|
311
|
+
/*
|
312
|
+
* call-seq:
|
313
|
+
* NumTheory.powermod(base, power, [modulo, one]) -> obj
|
314
|
+
*
|
315
|
+
* Returns (<code>base ** power) % modulo</code> if modulo is not nil.
|
316
|
+
* Otherwise returns <code>base ** power</code>. Parameter <i>one</i>
|
317
|
+
* can be used to provide the identity of the multiplicative group containing
|
318
|
+
* <i>base</i>.
|
319
|
+
*
|
320
|
+
* NumTheory.powermod(2, 20) #=> 1048576
|
321
|
+
* NumTheory.powermod(2, 20, 1000) #=> 576
|
322
|
+
*
|
323
|
+
* require 'matrix'
|
324
|
+
* NumTheory.powermod(Matrix[[1,1],[1,0]], 20, nil,
|
325
|
+
* Matrix.identity(2))
|
326
|
+
* #=> Matrix[[10946, 6765], [6765, 4181]]
|
327
|
+
*/
|
328
|
+
static VALUE
|
329
|
+
numtheory_powermod(int argc, VALUE *argv)
|
330
|
+
{
|
331
|
+
VALUE base, pow, modulo, one;
|
332
|
+
rb_scan_args(argc, argv, "22", &base, &pow, &modulo, &one);
|
333
|
+
|
334
|
+
ID id_mul = rb_intern("*");
|
335
|
+
ID id_mod = rb_intern("%");
|
336
|
+
|
337
|
+
VALUE result = NIL_P(one) ? rb_uint2big(1) : one;
|
338
|
+
FOR_BITS(pow, result = rb_funcall(result, id_mul, 1, result),
|
339
|
+
{},
|
340
|
+
result = rb_funcall(result, id_mul, 1, base),
|
341
|
+
if (!NIL_P(modulo))
|
342
|
+
{
|
343
|
+
result = rb_funcall(result, id_mod, 1, modulo);
|
344
|
+
});
|
345
|
+
return result;
|
346
|
+
}
|
347
|
+
|
348
|
+
/*
|
349
|
+
* call-seq:
|
350
|
+
* integer.powermod(power, modulo) -> integer
|
351
|
+
*
|
352
|
+
* Returns (+self+ ** <i>power</i>) % <i>modulo</i>.
|
353
|
+
* Both <i>power</i> and <i>modulo</i> must be integer.
|
354
|
+
*
|
355
|
+
* 172.powermod(238, 239) #=> 1
|
356
|
+
*/
|
357
|
+
static VALUE
|
358
|
+
numtheory_int_powermod(VALUE b, VALUE p, VALUE m){
|
359
|
+
VALUE result = one;
|
360
|
+
if (!INTEGER_P(p))
|
361
|
+
{
|
362
|
+
rb_raise(rb_eArgError, "power must be integer");
|
363
|
+
}
|
364
|
+
if (!INTEGER_P(m))
|
365
|
+
{
|
366
|
+
rb_raise(rb_eTypeError, "modulo must be integer");
|
367
|
+
}
|
368
|
+
if (NEGATIVE_P(p))
|
369
|
+
{
|
370
|
+
b = numtheory_modular_inverse(b, m);
|
371
|
+
p = ABS(p);
|
372
|
+
}
|
373
|
+
FOR_BITS(p, result = MUL(result, result),
|
374
|
+
{},
|
375
|
+
result = MUL(result, b),
|
376
|
+
result = MOD(result, m));
|
377
|
+
return result;
|
378
|
+
}
|
379
|
+
|
380
|
+
static int tail_zeros(VALUE n)
|
381
|
+
{
|
382
|
+
if (FIXNUM_P(n))
|
383
|
+
{
|
384
|
+
int t = FIX2LONG(n);
|
385
|
+
int s = 0;
|
386
|
+
while (!(t & 1))
|
387
|
+
t >>= 1, ++s;
|
388
|
+
return s;
|
389
|
+
}
|
390
|
+
else
|
391
|
+
{
|
392
|
+
BDIGIT* digit = RBIGNUM_DIGITS(n);
|
393
|
+
unsigned int L = RBIGNUM_LEN(n);
|
394
|
+
unsigned int i, j, s, z;
|
395
|
+
const unsigned long MAX = 1 << (SIZEOF_BDIGITS * 8 - 1);
|
396
|
+
for (i = s = 0, z = 1; i < L; ++i, ++digit)
|
397
|
+
{
|
398
|
+
for (j = 1; j <= MAX; j <<= 1)
|
399
|
+
if ((*digit & j) || j == MAX)
|
400
|
+
{
|
401
|
+
z = 0;
|
402
|
+
break;
|
403
|
+
}
|
404
|
+
else
|
405
|
+
{
|
406
|
+
++s;
|
407
|
+
}
|
408
|
+
if (z == 0) break;
|
409
|
+
}
|
410
|
+
return s;
|
411
|
+
}
|
412
|
+
}
|
413
|
+
|
414
|
+
/*
|
415
|
+
* call-seq:
|
416
|
+
* integer.MR_pseudoprime? -> true or false
|
417
|
+
*
|
418
|
+
* Returns <code>true</code> if +self+ is pseudoprime
|
419
|
+
* accordingly to Miller-Rabin test with <i>NumTheory::PrimalityTests</i>
|
420
|
+
* rounds. Otherwise returns <code>false</code>.
|
421
|
+
*/
|
422
|
+
static VALUE
|
423
|
+
numtheory_miller_rabin_pseudoprime_p(VALUE n)
|
424
|
+
{
|
425
|
+
long PRIMALITY_TESTS = FIX2LONG(rb_const_get(mNumTheory, primality_tests_ID));
|
426
|
+
|
427
|
+
if (FIXNUM_P(n))
|
428
|
+
{
|
429
|
+
long t = FIX2LONG(n);
|
430
|
+
if (t < 0) t = -t;
|
431
|
+
if (t == 2) return Qtrue;
|
432
|
+
if (!(t & 1)) return Qfalse;
|
433
|
+
if (t < 2) return Qfalse;
|
434
|
+
}
|
435
|
+
|
436
|
+
VALUE num;
|
437
|
+
if (NEGATIVE_P(n))
|
438
|
+
{
|
439
|
+
num = ABS(n);
|
440
|
+
}
|
441
|
+
else
|
442
|
+
{
|
443
|
+
num = n; // keeps just a reference instead of clone
|
444
|
+
}
|
445
|
+
|
446
|
+
if (EVEN_P(num))
|
447
|
+
{
|
448
|
+
return Qfalse;
|
449
|
+
}
|
450
|
+
|
451
|
+
VALUE num_minus_one = SUB(num, one);
|
452
|
+
VALUE d = CLONE(num_minus_one);
|
453
|
+
VALUE num_minus_four = SUB(num, four);
|
454
|
+
|
455
|
+
int s = tail_zeros(d);
|
456
|
+
d = RIGHT_SHIFT(d, s);
|
457
|
+
|
458
|
+
int i,j;
|
459
|
+
for (i = 0; i < PRIMALITY_TESTS; ++i)
|
460
|
+
{
|
461
|
+
|
462
|
+
VALUE a = rb_funcall(rb_cRandom,
|
463
|
+
id_rand,
|
464
|
+
1,
|
465
|
+
num_minus_four);
|
466
|
+
a = ADD(a, two);
|
467
|
+
|
468
|
+
VALUE x = numtheory_int_powermod(a, d, num);
|
469
|
+
if (EQL(x, one) ||
|
470
|
+
EQL(x, num_minus_one))
|
471
|
+
{
|
472
|
+
continue;
|
473
|
+
}
|
474
|
+
for(j = 0; j < s; ++j)
|
475
|
+
{
|
476
|
+
x = MOD(MUL(x, x), num);
|
477
|
+
if (EQL(x, one))
|
478
|
+
{
|
479
|
+
return Qfalse;
|
480
|
+
}
|
481
|
+
if (EQL(x, num_minus_one))
|
482
|
+
{
|
483
|
+
break;
|
484
|
+
}
|
485
|
+
}
|
486
|
+
if (!EQL(x, num_minus_one))
|
487
|
+
{
|
488
|
+
return Qfalse;
|
489
|
+
}
|
490
|
+
}
|
491
|
+
return Qtrue;
|
492
|
+
}
|
493
|
+
|
494
|
+
inline static int
|
495
|
+
prime_p(unsigned long t)
|
496
|
+
{
|
497
|
+
return (t & 1) ? t == 3 ? 1 :
|
498
|
+
((t % 6 == 1) || (t % 6 == 5)) ?
|
499
|
+
t < PRIMES_UPPER_LIMIT ?
|
500
|
+
is_set(numtheory_is_prime, t) ? 1 : 0 :
|
501
|
+
numtheory_bpsw_pseudoprime_p(ULL2NUM(t)) :
|
502
|
+
0
|
503
|
+
: t == 2 ? 1 : 0;
|
504
|
+
}
|
505
|
+
|
506
|
+
/*
|
507
|
+
* call-seq:
|
508
|
+
* integer.prime? -> true or false
|
509
|
+
*
|
510
|
+
* Returns exact result for values which are precomputed, and result
|
511
|
+
* of standard Baillie-Pomerance-Selfridge-Wagstaff test for larger values.
|
512
|
+
*
|
513
|
+
* 29.prime? #=> true
|
514
|
+
*/
|
515
|
+
static VALUE
|
516
|
+
numtheory_prime_p(VALUE n)
|
517
|
+
{
|
518
|
+
unsigned long t;
|
519
|
+
if (FIXNUM_P(n) && (t = abs(FIX2LONG(n)), t < PRIMES_UPPER_LIMIT))
|
520
|
+
{
|
521
|
+
return prime_p(t) ? Qtrue : Qfalse;
|
522
|
+
}
|
523
|
+
else
|
524
|
+
{
|
525
|
+
return numtheory_bpsw_pseudoprime_p(n);
|
526
|
+
}
|
527
|
+
}
|
528
|
+
|
529
|
+
/*
|
530
|
+
* call-seq:
|
531
|
+
* integer.nextprime -> integer
|
532
|
+
*
|
533
|
+
* Returns the least (pseudo)prime > +self+.
|
534
|
+
*
|
535
|
+
* (10**28).nextprime #=> 10000000000000000000000000331
|
536
|
+
*/
|
537
|
+
static VALUE
|
538
|
+
numtheory_nextprime(VALUE n)
|
539
|
+
{
|
540
|
+
VALUE p = n;
|
541
|
+
for(;;)
|
542
|
+
{
|
543
|
+
p = ADD(p, one);
|
544
|
+
if (numtheory_prime_p(p))
|
545
|
+
return p;
|
546
|
+
}
|
547
|
+
}
|
548
|
+
|
549
|
+
inline static void raise_not_enough_exception()
|
550
|
+
{
|
551
|
+
rb_raise(rb_eArgError, "Not enough precomputed primes");
|
552
|
+
}
|
553
|
+
|
554
|
+
inline static unsigned long
|
555
|
+
nth_prime(long n)
|
556
|
+
{
|
557
|
+
return numtheory_primes[n-1];
|
558
|
+
}
|
559
|
+
|
560
|
+
/*
|
561
|
+
* call-seq:
|
562
|
+
* NumTheory.prime(integer) -> integer
|
563
|
+
*
|
564
|
+
* Returns prime with corresponding index.
|
565
|
+
* The prime 2 is assumed to have index 1.
|
566
|
+
*
|
567
|
+
* NumTheory.prime 1 #=> 2
|
568
|
+
* NumTheory.prime 1000 #=> 7919
|
569
|
+
*/
|
570
|
+
static VALUE
|
571
|
+
numtheory_prime(VALUE obj, VALUE i)
|
572
|
+
{
|
573
|
+
long t;
|
574
|
+
if (FIXNUM_P(i))
|
575
|
+
{
|
576
|
+
t = FIX2LONG(i);
|
577
|
+
if (t < 1)
|
578
|
+
{
|
579
|
+
rb_raise(rb_eArgError, "the argument must be positive");
|
580
|
+
}
|
581
|
+
if ((unsigned long)t > NUM_OF_PRIMES)
|
582
|
+
{
|
583
|
+
raise_not_enough_exception();
|
584
|
+
}
|
585
|
+
return ULONG2NUM(nth_prime((unsigned long)t));
|
586
|
+
}
|
587
|
+
raise_not_enough_exception();
|
588
|
+
return Qnil;
|
589
|
+
}
|
590
|
+
|
591
|
+
long
|
592
|
+
primepi(unsigned long t)
|
593
|
+
{
|
594
|
+
if (t < 2) return 0;
|
595
|
+
|
596
|
+
unsigned long l, m, r;
|
597
|
+
l = 0;
|
598
|
+
r = NUM_OF_PRIMES - 1;
|
599
|
+
|
600
|
+
if (numtheory_primes[r] <= t)
|
601
|
+
{
|
602
|
+
return r + 1;
|
603
|
+
}
|
604
|
+
|
605
|
+
while (l < r-1)
|
606
|
+
{
|
607
|
+
m = (l + r) >> 1;
|
608
|
+
if (numtheory_primes[m] > t)
|
609
|
+
r = m;
|
610
|
+
else if (numtheory_primes[m] < t)
|
611
|
+
l = m;
|
612
|
+
else return m + 1;
|
613
|
+
}
|
614
|
+
return r;
|
615
|
+
}
|
616
|
+
|
617
|
+
/*
|
618
|
+
* call-seq:
|
619
|
+
* NumTheory.primepi(integer) -> integer
|
620
|
+
*
|
621
|
+
* Returns the number of primes less or equal than a given value.
|
622
|
+
*
|
623
|
+
* NumTheory.primepi 10 #=> 4
|
624
|
+
* NumTheory.primepi -10 #=> 0
|
625
|
+
*/
|
626
|
+
static VALUE
|
627
|
+
numtheory_primepi(VALUE obj, VALUE n)
|
628
|
+
{
|
629
|
+
if (NEGATIVE_P(n))
|
630
|
+
{
|
631
|
+
return zero;
|
632
|
+
}
|
633
|
+
unsigned long t = TO_ULONG(n);
|
634
|
+
if (t <= PRIMES_UPPER_LIMIT)
|
635
|
+
{
|
636
|
+
return ULONG2NUM(primepi(t));
|
637
|
+
}
|
638
|
+
raise_not_enough_exception();
|
639
|
+
return Qnil;
|
640
|
+
}
|
641
|
+
|
642
|
+
/*
|
643
|
+
* call-seq:
|
644
|
+
* NumTheory.fibonacci(n, [modulo]) -> integer
|
645
|
+
*
|
646
|
+
* Returns <i>n</i>-th fibonacci number (<code>% modulo</code>
|
647
|
+
* if the <i>modulo</i> is given).
|
648
|
+
* 0-th fibonacci number is assumed to be zero.
|
649
|
+
*
|
650
|
+
* NumTheory.fibonacci 10 #=> 55
|
651
|
+
* NumTheory.fibonacci 10**30, 1234567890 #=> 862134135
|
652
|
+
*/
|
653
|
+
static VALUE
|
654
|
+
numtheory_fibonacci(int argc, VALUE* argv)
|
655
|
+
{
|
656
|
+
VALUE n, modulo;
|
657
|
+
rb_scan_args(argc, argv, "11", &n, &modulo);
|
658
|
+
|
659
|
+
if (FIXNUM_P(n) && FIX2LONG(n) < 2)
|
660
|
+
{
|
661
|
+
return n;
|
662
|
+
}
|
663
|
+
|
664
|
+
if (!INTEGER_P(n) || NEGATIVE_P(n))
|
665
|
+
{
|
666
|
+
rb_raise(rb_eArgError, "n must be nonnegative integer");
|
667
|
+
}
|
668
|
+
if (!NIL_P(modulo) && !INTEGER_P(modulo))
|
669
|
+
{
|
670
|
+
rb_raise(rb_eTypeError, "modulo must be integer");
|
671
|
+
}
|
672
|
+
|
673
|
+
VALUE a, b, c, old_a, old_b, old_c, old_b_sq;
|
674
|
+
a = c = one;
|
675
|
+
b = zero;
|
676
|
+
|
677
|
+
n = SUB(n, one);
|
678
|
+
|
679
|
+
FOR_BITS(n, { old_a = a; old_b = b; old_c = c;
|
680
|
+
old_b_sq = MUL(b, b);
|
681
|
+
|
682
|
+
a = ADD(MUL(a, a), old_b_sq);
|
683
|
+
c = ADD(MUL(c, c), old_b_sq);
|
684
|
+
b = MUL(b, ADD(old_a, old_c));
|
685
|
+
},
|
686
|
+
{
|
687
|
+
},
|
688
|
+
{ c = b;
|
689
|
+
b = a;
|
690
|
+
a = ADD(b, c);
|
691
|
+
},
|
692
|
+
if (!NIL_P(modulo))
|
693
|
+
{
|
694
|
+
a = MOD(a, modulo);
|
695
|
+
b = MOD(b, modulo);
|
696
|
+
c = MOD(c, modulo);
|
697
|
+
});
|
698
|
+
return a;
|
699
|
+
}
|
700
|
+
|
701
|
+
/*
|
702
|
+
* call-seq:
|
703
|
+
* NumTheory.sigma(n, [pow=1]) -> integer
|
704
|
+
*
|
705
|
+
* Returns sum of <i>pow</i>-th powers of
|
706
|
+
* divisors of <code>|n|</code>. <i>pow</i> must be
|
707
|
+
* nonnegative integer.
|
708
|
+
*
|
709
|
+
* NumTheory.sigma 1234567890, 0 #=> 48
|
710
|
+
* NumTheory.sigma 1234567890, 1 #=> 3211610688
|
711
|
+
*/
|
712
|
+
static VALUE
|
713
|
+
numtheory_sigma(int argc, VALUE* argv)
|
714
|
+
{
|
715
|
+
VALUE n, pow;
|
716
|
+
rb_scan_args(argc, argv, "11", &n, &pow);
|
717
|
+
|
718
|
+
if (!INTEGER_P(n))
|
719
|
+
{
|
720
|
+
rb_raise(rb_eTypeError, "n must be integer");
|
721
|
+
}
|
722
|
+
n = ABS(n);
|
723
|
+
|
724
|
+
if (NIL_P(pow))
|
725
|
+
{
|
726
|
+
pow = one;
|
727
|
+
}
|
728
|
+
else if (!INTEGER_P(pow))
|
729
|
+
{
|
730
|
+
rb_raise(rb_eTypeError, "power must be integer");
|
731
|
+
}
|
732
|
+
if (NEGATIVE_P(pow))
|
733
|
+
{
|
734
|
+
rb_raise(rb_eArgError, "power must be >= 0");
|
735
|
+
}
|
736
|
+
if (ZERO_P(n))
|
737
|
+
{
|
738
|
+
rb_raise(rb_eArgError, "n can't be zero");
|
739
|
+
}
|
740
|
+
VALUE result = one;
|
741
|
+
VALUE tmp1, tmp2;
|
742
|
+
int i;
|
743
|
+
FOR_PRIME_FACTORS(n, p, d,
|
744
|
+
{ tmp1 = one;
|
745
|
+
tmp2 = rb_big_pow(TO_BIGNUM(p), pow);
|
746
|
+
for (i = FIX2LONG(d); i; --i)
|
747
|
+
{
|
748
|
+
tmp1 = MUL(tmp1, tmp2);
|
749
|
+
tmp1 = ADD(tmp1, one);
|
750
|
+
}
|
751
|
+
result = MUL(result, tmp1);
|
752
|
+
});
|
753
|
+
return result;
|
754
|
+
}
|
755
|
+
|
756
|
+
/*
|
757
|
+
* call-seq:
|
758
|
+
* NumTheory.eulerphi(n) -> integer
|
759
|
+
*
|
760
|
+
* Returns the number of positive integers less than <code>|n|</code>
|
761
|
+
* and coprime with <code>n</code>.
|
762
|
+
*
|
763
|
+
* NumTheory.eulerphi(1234567890) #=> 329040288
|
764
|
+
*/
|
765
|
+
static VALUE
|
766
|
+
numtheory_eulerphi(VALUE obj, VALUE n)
|
767
|
+
{
|
768
|
+
if (!INTEGER_P(n))
|
769
|
+
{
|
770
|
+
rb_raise(rb_eTypeError, "n must be integer");
|
771
|
+
}
|
772
|
+
VALUE num = ABS(n);
|
773
|
+
if (ZERO_P(num))
|
774
|
+
{
|
775
|
+
rb_raise(rb_eArgError, "the number must be nonzero");
|
776
|
+
}
|
777
|
+
VALUE result = CLONE(num);
|
778
|
+
FOR_PRIME_FACTORS(num, p, d,
|
779
|
+
{
|
780
|
+
result = MUL(result, SUB(p, one));
|
781
|
+
result = DIV(result, p);
|
782
|
+
});
|
783
|
+
return result;
|
784
|
+
}
|
785
|
+
|
786
|
+
/*
|
787
|
+
* call-seq:
|
788
|
+
* integer.prime_division -> ary
|
789
|
+
*
|
790
|
+
* Returns factorization of the number in the form of
|
791
|
+
* array of pairs <code>[prime, power]</code>.
|
792
|
+
*
|
793
|
+
* 1234567890.prime_division
|
794
|
+
* #=> [[2, 1], [3, 2], [5, 1], [3607, 1], [3803, 1]]
|
795
|
+
* (-987654321).prime_division
|
796
|
+
* #=> [[-1, 1], [3, 2], [17, 2], [379721, 1]]
|
797
|
+
*/
|
798
|
+
static VALUE
|
799
|
+
numtheory_prime_division(VALUE n)
|
800
|
+
{
|
801
|
+
VALUE pd[2];
|
802
|
+
VALUE pds = rb_ary_new();
|
803
|
+
if (NEGATIVE_P(n))
|
804
|
+
{
|
805
|
+
pd[0] = INT2FIX(-1); pd[1] = one;
|
806
|
+
rb_ary_push(pds, rb_ary_new4(2,pd));
|
807
|
+
}
|
808
|
+
VALUE num = ABS(n);
|
809
|
+
if (ZERO_P(n))
|
810
|
+
{
|
811
|
+
pd[0] = zero; pd[1] = one;
|
812
|
+
rb_ary_push(pds, rb_ary_new4(2,pd));
|
813
|
+
}
|
814
|
+
else
|
815
|
+
{
|
816
|
+
FOR_PRIME_FACTORS(num, p, d,
|
817
|
+
{
|
818
|
+
pd[0] = p; pd[1] = d;
|
819
|
+
rb_ary_push(pds, rb_ary_new4(2,pd));
|
820
|
+
});
|
821
|
+
}
|
822
|
+
return pds;
|
823
|
+
}
|
824
|
+
|
825
|
+
/*
|
826
|
+
* call-seq:
|
827
|
+
* NumTheory.moebius(integer) -> -1, 0 or 1
|
828
|
+
*
|
829
|
+
* Returns moebius function of argument.
|
830
|
+
*
|
831
|
+
* NumTheory.moebius(4) #=> 0
|
832
|
+
* NumTheory.moebius(35) #=> 1
|
833
|
+
*/
|
834
|
+
static VALUE
|
835
|
+
numtheory_moebius(VALUE obj, VALUE n)
|
836
|
+
{
|
837
|
+
if (!INTEGER_P(n))
|
838
|
+
{
|
839
|
+
rb_raise(rb_eTypeError, "n must be integer");
|
840
|
+
}
|
841
|
+
VALUE num = ABS(n);
|
842
|
+
if (ZERO_P(num))
|
843
|
+
{
|
844
|
+
rb_raise(rb_eArgError, "the number must be nonzero");
|
845
|
+
}
|
846
|
+
char result = 1;
|
847
|
+
FOR_PRIME_FACTORS(num, p, d,
|
848
|
+
{
|
849
|
+
if (FIX2LONG(d) > 1)
|
850
|
+
{
|
851
|
+
return zero;
|
852
|
+
}
|
853
|
+
else
|
854
|
+
{
|
855
|
+
result *= -1;
|
856
|
+
}
|
857
|
+
});
|
858
|
+
return INT2FIX(result);
|
859
|
+
}
|
860
|
+
|
861
|
+
static VALUE
|
862
|
+
product(VALUE* beg, VALUE* end)
|
863
|
+
{
|
864
|
+
long len = end - beg;
|
865
|
+
if (!len)
|
866
|
+
{
|
867
|
+
return one;
|
868
|
+
}
|
869
|
+
if (len < 4)
|
870
|
+
{
|
871
|
+
VALUE t = *(--end);
|
872
|
+
while (beg != end)
|
873
|
+
t = MUL(t, *(--end));
|
874
|
+
return t;
|
875
|
+
}
|
876
|
+
long half_len = len >> 1;
|
877
|
+
VALUE* mid= beg + half_len;
|
878
|
+
return MUL(product(beg, mid),
|
879
|
+
product(mid, end));
|
880
|
+
}
|
881
|
+
|
882
|
+
static VALUE
|
883
|
+
product_of_ulongs(unsigned long* beg, unsigned long* end)
|
884
|
+
{
|
885
|
+
long len = end - beg;
|
886
|
+
unsigned long tmp;
|
887
|
+
if (len < 4)
|
888
|
+
{
|
889
|
+
tmp = *(--end);
|
890
|
+
VALUE t = ULONG2NUM(tmp);
|
891
|
+
while (beg != end)
|
892
|
+
tmp = *(--end),
|
893
|
+
t = MUL(t, ULONG2NUM(tmp));
|
894
|
+
return t;
|
895
|
+
}
|
896
|
+
long half_len = len >> 1;
|
897
|
+
unsigned long* mid = beg + half_len;
|
898
|
+
return MUL(product_of_ulongs(beg, mid),
|
899
|
+
product_of_ulongs(mid, end));
|
900
|
+
}
|
901
|
+
|
902
|
+
static VALUE
|
903
|
+
primorial(unsigned long min, unsigned long max)
|
904
|
+
{
|
905
|
+
unsigned long *l;
|
906
|
+
long m_pi = primepi(min);
|
907
|
+
if (m_pi == 0)
|
908
|
+
{
|
909
|
+
m_pi = 1;
|
910
|
+
}
|
911
|
+
l = numtheory_primes + m_pi - 1;
|
912
|
+
if (nth_prime(m_pi) < min)
|
913
|
+
{
|
914
|
+
++m_pi;
|
915
|
+
++l;
|
916
|
+
}
|
917
|
+
return product_of_ulongs(l, numtheory_primes + primepi(max));
|
918
|
+
}
|
919
|
+
|
920
|
+
/*
|
921
|
+
* call-seq:
|
922
|
+
* NumTheory.product(ary) -> integer
|
923
|
+
*
|
924
|
+
* Returns product of integer values stored in <i>ary</i>.
|
925
|
+
* Returns 1 if <i>ary</i> is empty.
|
926
|
+
*
|
927
|
+
* NumTheory.product([1,2,3,4,5,6]) #=> 720
|
928
|
+
*/
|
929
|
+
static VALUE
|
930
|
+
numtheory_product(VALUE obj, VALUE arr)
|
931
|
+
{
|
932
|
+
if (!RB_TYPE_P(arr, T_ARRAY))
|
933
|
+
{
|
934
|
+
rb_raise(rb_eTypeError, "the argument must be an array");
|
935
|
+
}
|
936
|
+
return product(RARRAY_PTR(arr), RARRAY_PTR(arr) + RARRAY_LEN(arr));
|
937
|
+
}
|
938
|
+
|
939
|
+
/*
|
940
|
+
* call-seq:
|
941
|
+
* integer.primes_upto(limit) {|i| block } -> self
|
942
|
+
* integer.primes_upto(limit) -> enumerator
|
943
|
+
*
|
944
|
+
* Yields primes in interval from +self+ to <i>limit</i> inclusively.
|
945
|
+
*
|
946
|
+
* 2.primes_upto(17).to_a #=> [2, 3, 5, 7, 11, 13, 17]
|
947
|
+
*/
|
948
|
+
static VALUE
|
949
|
+
numtheory_primes_upto(VALUE min, VALUE _max)
|
950
|
+
{
|
951
|
+
VALUE max = _max;
|
952
|
+
if (!INTEGER_P(max))
|
953
|
+
{
|
954
|
+
if (TYPE(max) == T_FLOAT)
|
955
|
+
{
|
956
|
+
max = rb_to_int(max);
|
957
|
+
}
|
958
|
+
else
|
959
|
+
{
|
960
|
+
rb_raise(rb_eTypeError, "upper bound must be a number");
|
961
|
+
}
|
962
|
+
}
|
963
|
+
if (NEGATIVE_P(SUB(max,min)))
|
964
|
+
{
|
965
|
+
rb_raise(rb_eArgError, "upper bound must be more than lower");
|
966
|
+
}
|
967
|
+
if (NEGATIVE_P(SUB(max, two)))
|
968
|
+
{
|
969
|
+
return rb_ary_new2(0);
|
970
|
+
}
|
971
|
+
if (NEGATIVE_P(SUB(min, two)))
|
972
|
+
{
|
973
|
+
min = two;
|
974
|
+
}
|
975
|
+
unsigned long m = TO_ULONG(min);
|
976
|
+
unsigned long M = TO_ULONG(max);
|
977
|
+
if (M > PRIMES_UPPER_LIMIT)
|
978
|
+
{
|
979
|
+
raise_not_enough_exception();
|
980
|
+
// TODO: allow for bignums
|
981
|
+
}
|
982
|
+
|
983
|
+
RETURN_ENUMERATOR(min, 1, &max);
|
984
|
+
|
985
|
+
long m_pi = primepi(m);
|
986
|
+
long M_pi = primepi(M);
|
987
|
+
|
988
|
+
unsigned long* p_c = numtheory_primes + m_pi - 1;
|
989
|
+
if (*p_c < m)
|
990
|
+
++m_pi, ++p_c;
|
991
|
+
|
992
|
+
for ( ; m_pi <= M_pi; ++m_pi)
|
993
|
+
{
|
994
|
+
rb_yield(ULONG2NUM(*p_c));
|
995
|
+
++p_c;
|
996
|
+
}
|
997
|
+
return min;
|
998
|
+
}
|
999
|
+
|
1000
|
+
static VALUE
|
1001
|
+
odd_swing(long n)
|
1002
|
+
{
|
1003
|
+
if (n < 65)
|
1004
|
+
{
|
1005
|
+
return ULL2NUM(numtheory_small_odd_swings[n]);
|
1006
|
+
}
|
1007
|
+
unsigned long root_n = (int)(floor(sqrt((double)n))+0.5);
|
1008
|
+
unsigned long n3 = n / 3;
|
1009
|
+
long pi_n3 = primepi(n3);
|
1010
|
+
long count = 0;
|
1011
|
+
long q;
|
1012
|
+
VALUE* prime_list = malloc(sizeof(VALUE) * pi_n3);
|
1013
|
+
unsigned long* ptr = numtheory_primes + 1; // initially points to 3
|
1014
|
+
unsigned long prime;
|
1015
|
+
unsigned long prod;
|
1016
|
+
for ( ; *ptr <= root_n; ++ptr)
|
1017
|
+
{
|
1018
|
+
prod = 1;
|
1019
|
+
q = n;
|
1020
|
+
prime = *ptr;
|
1021
|
+
while (q /= prime)
|
1022
|
+
if (q & 1)
|
1023
|
+
prod *= prime;
|
1024
|
+
|
1025
|
+
if (prod > 1)
|
1026
|
+
prime_list[count++] = INT2FIX(prod);
|
1027
|
+
}
|
1028
|
+
for ( ; *ptr <= n3; ++ptr)
|
1029
|
+
{
|
1030
|
+
prime = *ptr;
|
1031
|
+
if ((n / prime) & 1)
|
1032
|
+
prime_list[count++] = INT2FIX(prime);
|
1033
|
+
}
|
1034
|
+
VALUE r = product(prime_list, prime_list + count);
|
1035
|
+
free(prime_list);
|
1036
|
+
return MUL(r, primorial(n/2 + 1, n));
|
1037
|
+
}
|
1038
|
+
|
1039
|
+
|
1040
|
+
static VALUE
|
1041
|
+
rec_factorial(long n)
|
1042
|
+
{
|
1043
|
+
if (n < 2) return one;
|
1044
|
+
VALUE n2fac = rec_factorial(n >> 1);
|
1045
|
+
n2fac = MUL(n2fac, n2fac);
|
1046
|
+
return MUL(n2fac, odd_swing(n));
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
/*
|
1050
|
+
* call-seq:
|
1051
|
+
* integer.factorial -> integer
|
1052
|
+
*
|
1053
|
+
* Returns factorial of the number.
|
1054
|
+
*
|
1055
|
+
* 50.factorial.to_s(31) #=> "283sp352ltrc9csg1398f0dt7dg067g15ikr4b6spf70"
|
1056
|
+
*/
|
1057
|
+
static VALUE
|
1058
|
+
numtheory_factorial_primeswing(VALUE n)
|
1059
|
+
{
|
1060
|
+
long t;
|
1061
|
+
if ((t = FIX2LONG(n)) >= 10000000)
|
1062
|
+
{
|
1063
|
+
rb_raise(rb_eArgError, "the argument is too big!");
|
1064
|
+
}
|
1065
|
+
if (t < 0)
|
1066
|
+
{
|
1067
|
+
rb_raise(rb_eArgError, "factorial of negative number is undefined");
|
1068
|
+
}
|
1069
|
+
if (t <= 20)
|
1070
|
+
{
|
1071
|
+
return ULL2NUM(numtheory_small_factorials[t]);
|
1072
|
+
}
|
1073
|
+
if ((unsigned long)t > PRIMES_UPPER_LIMIT)
|
1074
|
+
{
|
1075
|
+
raise_not_enough_exception();
|
1076
|
+
}
|
1077
|
+
long shift = 0;
|
1078
|
+
long q = t;
|
1079
|
+
while (q > 0)
|
1080
|
+
{
|
1081
|
+
q >>= 1;
|
1082
|
+
shift += q;
|
1083
|
+
}
|
1084
|
+
return rb_big_lshift(rec_factorial(t), LONG2NUM(shift));
|
1085
|
+
}
|
1086
|
+
|
1087
|
+
struct Egcd {
|
1088
|
+
VALUE d, a, b;
|
1089
|
+
};
|
1090
|
+
|
1091
|
+
static struct Egcd
|
1092
|
+
extended_gcd(VALUE x, VALUE y)
|
1093
|
+
{
|
1094
|
+
struct Egcd egcd_old, egcd_new;
|
1095
|
+
if (ZERO_P(y))
|
1096
|
+
{
|
1097
|
+
egcd_new.d = x;
|
1098
|
+
egcd_new.a = one;
|
1099
|
+
egcd_new.b = zero;
|
1100
|
+
return egcd_new;
|
1101
|
+
}
|
1102
|
+
VALUE divmod = DIVMOD(x, y);
|
1103
|
+
egcd_old = extended_gcd(y, rb_ary_entry(divmod, 1));
|
1104
|
+
egcd_new.d = egcd_old.d;
|
1105
|
+
egcd_new.a = egcd_old.b;
|
1106
|
+
egcd_new.b = SUB(egcd_old.a, MUL(rb_ary_entry(divmod, 0),
|
1107
|
+
egcd_old.b));
|
1108
|
+
return egcd_new;
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
/*
|
1112
|
+
* call-seq:
|
1113
|
+
* Integer.extended_gcd(y) -> Integer
|
1114
|
+
*
|
1115
|
+
* Returns array <code>[d, [a, b]]</code> where
|
1116
|
+
* <i>d</i> is +self+.gcd(<i>y</i>) and <code>a*self + b*y = d</code>
|
1117
|
+
*
|
1118
|
+
* 0.extended_gcd(0) #=> [0, [0, 0]]
|
1119
|
+
* 239.extended_gcd(932) #=> [1, [39, -10]]
|
1120
|
+
*/
|
1121
|
+
static VALUE
|
1122
|
+
numtheory_extended_gcd(VALUE x, VALUE y)
|
1123
|
+
{
|
1124
|
+
if (!INTEGER_P(y))
|
1125
|
+
{
|
1126
|
+
rb_raise(rb_eTypeError, "not an integer");
|
1127
|
+
}
|
1128
|
+
struct Egcd egcd;
|
1129
|
+
if (ZERO_P(x) && ZERO_P(y))
|
1130
|
+
{
|
1131
|
+
egcd.d = egcd.a = egcd.b = zero;
|
1132
|
+
}
|
1133
|
+
else
|
1134
|
+
{
|
1135
|
+
egcd = extended_gcd(x, y);
|
1136
|
+
}
|
1137
|
+
VALUE ary = rb_ary_new2(2);
|
1138
|
+
rb_ary_store(ary, 0, egcd.d);
|
1139
|
+
VALUE coeffs = rb_ary_new2(2);
|
1140
|
+
rb_ary_store(coeffs, 0, egcd.a);
|
1141
|
+
rb_ary_store(coeffs, 1, egcd.b);
|
1142
|
+
rb_ary_store(ary, 1, coeffs);
|
1143
|
+
return ary;
|
1144
|
+
}
|
1145
|
+
|
1146
|
+
/*
|
1147
|
+
* call-seq:
|
1148
|
+
* integer.inverse(m) -> integer
|
1149
|
+
*
|
1150
|
+
* Returns modular inverse modulo <i>m</i> of +self+.
|
1151
|
+
*
|
1152
|
+
* 1234.inverse(12345) #=> 9874
|
1153
|
+
*/
|
1154
|
+
static VALUE
|
1155
|
+
numtheory_modular_inverse(VALUE x, VALUE y)
|
1156
|
+
{
|
1157
|
+
struct Egcd egcd = extended_gcd(x, y);
|
1158
|
+
if (egcd.d != one)
|
1159
|
+
{
|
1160
|
+
rb_raise(rb_eArgError, "modular inverse doesn't exist");
|
1161
|
+
}
|
1162
|
+
VALUE result = egcd.a;
|
1163
|
+
if (NEGATIVE_P(result))
|
1164
|
+
{
|
1165
|
+
result = ADD(result, y);
|
1166
|
+
}
|
1167
|
+
return result;
|
1168
|
+
}
|
1169
|
+
|
1170
|
+
/*
|
1171
|
+
* call-seq:
|
1172
|
+
* integer.znorder(modulo) -> integer
|
1173
|
+
*
|
1174
|
+
* Returns minimal positive integer <i>n</i> such that
|
1175
|
+
* <code>+self+.powermod(n, modulo) == 1</code>
|
1176
|
+
*
|
1177
|
+
* 20.znorder(11) => 5
|
1178
|
+
*/
|
1179
|
+
static VALUE
|
1180
|
+
numtheory_multiplicative_order(VALUE a, VALUE m)
|
1181
|
+
{
|
1182
|
+
if (rb_funcall(a, id_gcd, 1, m) != one)
|
1183
|
+
{
|
1184
|
+
rb_raise(rb_eArgError, "not in (Z/nZ)*");
|
1185
|
+
}
|
1186
|
+
VALUE result = one;
|
1187
|
+
VALUE pd, phi, o, x;
|
1188
|
+
FOR_PRIME_FACTORS(ABS(m), p, d,
|
1189
|
+
{
|
1190
|
+
o = one;
|
1191
|
+
pd = POW(p, SUB(d, o));
|
1192
|
+
phi = MUL(SUB(p, o), pd);
|
1193
|
+
pd = MUL(pd, p);
|
1194
|
+
FOR_PRIME_FACTORS(phi, q, e,
|
1195
|
+
{
|
1196
|
+
x = numtheory_int_powermod(a,
|
1197
|
+
DIV(phi, POW(q, e)),
|
1198
|
+
pd);
|
1199
|
+
while (x != one)
|
1200
|
+
{
|
1201
|
+
o = MUL(o, q);
|
1202
|
+
x = numtheory_int_powermod(x, q, pd);
|
1203
|
+
}
|
1204
|
+
});
|
1205
|
+
result = rb_funcall(result, id_lcm, 1, o);
|
1206
|
+
});
|
1207
|
+
return result;
|
1208
|
+
}
|
1209
|
+
|
1210
|
+
inline VALUE* triple_new(VALUE v1, VALUE v2, VALUE v3)
|
1211
|
+
{
|
1212
|
+
VALUE* v = malloc(sizeof(VALUE)*3);
|
1213
|
+
v[0] = v1; v[1] = v2; v[2] = v3;
|
1214
|
+
return v;
|
1215
|
+
}
|
1216
|
+
|
1217
|
+
#define TRIPLE_SUM(triple) \
|
1218
|
+
(ADD(triple[0], ADD(triple[1], triple[2])))
|
1219
|
+
|
1220
|
+
|
1221
|
+
/*
|
1222
|
+
* call-seq:
|
1223
|
+
* NumTheory.triples(max_perimeter) -> enumerator
|
1224
|
+
*
|
1225
|
+
* Yields primitive pythagorean triples with perimeter less
|
1226
|
+
* or equal to <i>max_perimeter</i>.
|
1227
|
+
*/
|
1228
|
+
static VALUE
|
1229
|
+
numtheory_pythagorean_triples(VALUE obj, VALUE max_l)
|
1230
|
+
{
|
1231
|
+
RETURN_ENUMERATOR(obj, 1, &max_l);
|
1232
|
+
|
1233
|
+
Queue* q = queue_new();
|
1234
|
+
|
1235
|
+
VALUE* triple;
|
1236
|
+
|
1237
|
+
queue_push(q, triple_new(three, four, five));
|
1238
|
+
|
1239
|
+
VALUE a, b, c, a2, b2, c2, c3;
|
1240
|
+
VALUE t1,t2,t3;
|
1241
|
+
|
1242
|
+
while (q -> first)
|
1243
|
+
{
|
1244
|
+
triple = queue_pop(q);
|
1245
|
+
if (MORE(TRIPLE_SUM(triple), max_l))
|
1246
|
+
{
|
1247
|
+
free(triple);
|
1248
|
+
continue;
|
1249
|
+
}
|
1250
|
+
|
1251
|
+
a = triple[0]; b = triple[1]; c = triple[2];
|
1252
|
+
rb_yield_values2(3, triple);
|
1253
|
+
|
1254
|
+
// uses ternary pythagorean tree
|
1255
|
+
a2 = DOUBLED(a);
|
1256
|
+
b2 = DOUBLED(b);
|
1257
|
+
c2 = DOUBLED(c);
|
1258
|
+
c3 = ADD(c, c2);
|
1259
|
+
|
1260
|
+
t1 = ADD(a,c2); t2 = ADD(a2,c2); t3 = ADD(a2,c3);
|
1261
|
+
|
1262
|
+
queue_push(q, triple_new(SUB(t1, b2),
|
1263
|
+
SUB(t2, b),
|
1264
|
+
SUB(t3, b2)));
|
1265
|
+
|
1266
|
+
queue_push(q, triple_new(SUB(ADD(b2, c2), a),
|
1267
|
+
SUB(ADD(b, c2), a2),
|
1268
|
+
SUB(ADD(b2, c3), a2)));
|
1269
|
+
|
1270
|
+
queue_push(q, triple_new(ADD(t1, b2),
|
1271
|
+
ADD(t2, b),
|
1272
|
+
ADD(t3, b2)));
|
1273
|
+
free(triple);
|
1274
|
+
}
|
1275
|
+
free(q);
|
1276
|
+
return Qnil;
|
1277
|
+
}
|
1278
|
+
|
1279
|
+
/*
|
1280
|
+
* call-seq:
|
1281
|
+
* integer.popcount -> integer
|
1282
|
+
*
|
1283
|
+
* Returns the number of set bits.
|
1284
|
+
*/
|
1285
|
+
static VALUE
|
1286
|
+
numtheory_popcount(VALUE n)
|
1287
|
+
{
|
1288
|
+
if (NEGATIVE_P(n))
|
1289
|
+
{
|
1290
|
+
rb_raise(rb_eArgError, "popcount is undefined for negative numbers");
|
1291
|
+
}
|
1292
|
+
unsigned long k = 0;
|
1293
|
+
FOR_BITS(n, {}, {}, { ++k; }, {});
|
1294
|
+
return ULONG2NUM(k);
|
1295
|
+
}
|
1296
|
+
|
1297
|
+
static int
|
1298
|
+
int_bitlength(unsigned int v)
|
1299
|
+
{
|
1300
|
+
// taken from http://graphics.stanford.edu/~seander/bithacks.html
|
1301
|
+
const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
|
1302
|
+
const unsigned int S[] = {1, 2, 4, 8, 16};
|
1303
|
+
int i;
|
1304
|
+
|
1305
|
+
register unsigned int r = 0;
|
1306
|
+
for (i = 4; i >= 0; --i)
|
1307
|
+
{
|
1308
|
+
if (v & b[i])
|
1309
|
+
{
|
1310
|
+
v >>= S[i];
|
1311
|
+
r |= S[i];
|
1312
|
+
}
|
1313
|
+
}
|
1314
|
+
return ++r;
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
/*
|
1318
|
+
* call-seq:
|
1319
|
+
* integer.bitlength -> integer
|
1320
|
+
*
|
1321
|
+
* Returns the length in bits. Defined for positive integers only.
|
1322
|
+
* 0 is assumed to have length 1.
|
1323
|
+
*/
|
1324
|
+
static VALUE
|
1325
|
+
numtheory_bitlength(VALUE n)
|
1326
|
+
{
|
1327
|
+
if (NEGATIVE_P(n))
|
1328
|
+
{
|
1329
|
+
rb_raise(rb_eArgError, "n must be positive");
|
1330
|
+
}
|
1331
|
+
long bit_len, half_k;
|
1332
|
+
if (FIXNUM_P(n))
|
1333
|
+
{
|
1334
|
+
return INT2FIX(int_bitlength(FIX2LONG(n)));
|
1335
|
+
}
|
1336
|
+
else
|
1337
|
+
{
|
1338
|
+
long len = RBIGNUM_LEN(n);
|
1339
|
+
bit_len = (len - 1) * SIZEOF_BDIGITS * 8;
|
1340
|
+
return INT2FIX(bit_len + int_bitlength(RBIGNUM_DIGITS(n)[len - 1]));
|
1341
|
+
}
|
1342
|
+
}
|
1343
|
+
|
1344
|
+
static int
|
1345
|
+
ull_jacobi(long long a, unsigned long long n)
|
1346
|
+
{
|
1347
|
+
/* it's assumed that n is odd and > 0 */
|
1348
|
+
int t = 1;
|
1349
|
+
long long tmp;
|
1350
|
+
while (a) {
|
1351
|
+
if (a < 0) {
|
1352
|
+
a = -a; if ((n & 3) == 3) t = -t;
|
1353
|
+
}
|
1354
|
+
switch (n & 7) {
|
1355
|
+
case 1: case 7:
|
1356
|
+
while (!(a&1)) a >>= 1; break;
|
1357
|
+
case 3: case 5:
|
1358
|
+
while (!(a&1)) a >>= 1, t = -t; break;
|
1359
|
+
}
|
1360
|
+
tmp = a; a = n; n = tmp;
|
1361
|
+
if ((a & 3) == 3 && (n & 3) == 3) t = -t;
|
1362
|
+
a %= n;
|
1363
|
+
if (a > (long long)(n >> 1)) a -= n;
|
1364
|
+
}
|
1365
|
+
return n == 1 ? t : 0;
|
1366
|
+
}
|
1367
|
+
|
1368
|
+
/*
|
1369
|
+
* call-seq:
|
1370
|
+
* integer.jacobi(n) -> -1, 0 or 1
|
1371
|
+
*
|
1372
|
+
* Returns jacobi symbol (a|n) where n must be odd positive
|
1373
|
+
*/
|
1374
|
+
static VALUE
|
1375
|
+
numtheory_jacobi(VALUE a, VALUE n)
|
1376
|
+
{
|
1377
|
+
if (EVEN_P(n) || NEGATIVE_P(n))
|
1378
|
+
{
|
1379
|
+
rb_raise(rb_eArgError, "n must be odd positive");
|
1380
|
+
}
|
1381
|
+
int t = 1;
|
1382
|
+
VALUE tmp;
|
1383
|
+
while (!ZERO_P(a))
|
1384
|
+
{
|
1385
|
+
a = MOD(a, n);
|
1386
|
+
if (MORE(a, HALF(n)))
|
1387
|
+
{
|
1388
|
+
a = SUB(a, n);
|
1389
|
+
}
|
1390
|
+
if (FIXNUM_P(n))
|
1391
|
+
{
|
1392
|
+
return INT2FIX(ull_jacobi(FIX2LONG(a), FIX2LONG(n)));
|
1393
|
+
}
|
1394
|
+
if (RBIGNUM_LEN(n) <= 2) // unsigned long long is used
|
1395
|
+
{
|
1396
|
+
return INT2FIX(ull_jacobi(FIXNUM_P(a) ? FIX2LONG(a) : rb_big2ll(a),
|
1397
|
+
rb_big2ull(n)));
|
1398
|
+
}
|
1399
|
+
if (NEGATIVE_P(a))
|
1400
|
+
{
|
1401
|
+
a = SUB(zero, a);
|
1402
|
+
if (MOD(n, four) == three)
|
1403
|
+
t = -t;
|
1404
|
+
}
|
1405
|
+
switch (FIX2LONG(MOD(n, eight)))
|
1406
|
+
{
|
1407
|
+
case 1:
|
1408
|
+
case 7:
|
1409
|
+
while (EVEN_P(a))
|
1410
|
+
a = HALF(a);
|
1411
|
+
break;
|
1412
|
+
case 3:
|
1413
|
+
case 5:
|
1414
|
+
while (EVEN_P(a))
|
1415
|
+
a = HALF(a), t = -t;
|
1416
|
+
break;
|
1417
|
+
}
|
1418
|
+
tmp = a;
|
1419
|
+
a = n;
|
1420
|
+
n = tmp;
|
1421
|
+
if (MOD(a, four) == three && MOD(n, four) == three)
|
1422
|
+
t = -t;
|
1423
|
+
}
|
1424
|
+
if (n == one)
|
1425
|
+
{
|
1426
|
+
return INT2FIX(t);
|
1427
|
+
}
|
1428
|
+
else
|
1429
|
+
{
|
1430
|
+
return zero;
|
1431
|
+
}
|
1432
|
+
}
|
1433
|
+
|
1434
|
+
/*
|
1435
|
+
* call-seq:
|
1436
|
+
* a.sqrt_mod(p) -> integer or nil
|
1437
|
+
*
|
1438
|
+
* If (a|p) = 1 returns the square root of a in Z/pZ
|
1439
|
+
* from the interval [0, p/2]. Otherwise returns +nil+.
|
1440
|
+
*/
|
1441
|
+
static VALUE
|
1442
|
+
numtheory_sqrtmod(VALUE a, VALUE p)
|
1443
|
+
{
|
1444
|
+
if (!INTEGER_P(p))
|
1445
|
+
{
|
1446
|
+
rb_raise(rb_eArgError, "the parameters must be integer");
|
1447
|
+
}
|
1448
|
+
else if (!numtheory_prime_p(p))
|
1449
|
+
{
|
1450
|
+
rb_raise(rb_eArgError, "p must be prime");
|
1451
|
+
}
|
1452
|
+
p = ABS(p);
|
1453
|
+
if (p == two)
|
1454
|
+
{
|
1455
|
+
return EVEN_P(a) ? zero : one;
|
1456
|
+
}
|
1457
|
+
if (numtheory_jacobi(a, p) != one)
|
1458
|
+
{
|
1459
|
+
return Qnil;
|
1460
|
+
}
|
1461
|
+
|
1462
|
+
VALUE t = SUB(p, one);
|
1463
|
+
VALUE p_minus_one = CLONE(t);
|
1464
|
+
|
1465
|
+
int e = tail_zeros(t);
|
1466
|
+
VALUE r;
|
1467
|
+
|
1468
|
+
t = RIGHT_SHIFT(t, e);
|
1469
|
+
|
1470
|
+
if (e == 1)
|
1471
|
+
{
|
1472
|
+
r = numtheory_int_powermod(a, ADD(HALF(t), one), p);
|
1473
|
+
}
|
1474
|
+
else if (e == 2)
|
1475
|
+
{
|
1476
|
+
if (numtheory_int_powermod(a, t, p) == one)
|
1477
|
+
{
|
1478
|
+
r = numtheory_int_powermod(a, ADD(HALF(t), one), p);
|
1479
|
+
}
|
1480
|
+
else
|
1481
|
+
{
|
1482
|
+
a = DOUBLED(a);
|
1483
|
+
r = MOD(MUL(a, numtheory_int_powermod(DOUBLED(a), HALF(t), p)), p);
|
1484
|
+
}
|
1485
|
+
}
|
1486
|
+
else
|
1487
|
+
{
|
1488
|
+
// Tonelli-Shanks algorithm
|
1489
|
+
// implemented as described in "Handbook of Applied Cryptography"
|
1490
|
+
int b = 14;
|
1491
|
+
while(1)
|
1492
|
+
{
|
1493
|
+
if (numtheory_jacobi(INT2FIX(b), p) == INT2FIX(-1))
|
1494
|
+
break;
|
1495
|
+
++b;
|
1496
|
+
}
|
1497
|
+
|
1498
|
+
VALUE a_inv = numtheory_modular_inverse(a, p);
|
1499
|
+
VALUE D = numtheory_int_powermod(INT2FIX(b), t, p);
|
1500
|
+
r = numtheory_int_powermod(a, ADD(HALF(t), one), p);
|
1501
|
+
|
1502
|
+
int i;
|
1503
|
+
VALUE d;
|
1504
|
+
VALUE power_of_two = rb_big_lshift(TO_BIGNUM(one), INT2FIX(e - 2));
|
1505
|
+
for (i = 1; i < e; ++i)
|
1506
|
+
{
|
1507
|
+
d = numtheory_int_powermod(MUL(MUL(r, r), a_inv),
|
1508
|
+
power_of_two, p);
|
1509
|
+
power_of_two = HALF(power_of_two);
|
1510
|
+
if (EQL(d, p_minus_one))
|
1511
|
+
{
|
1512
|
+
r = MOD(MUL(r, D), p);
|
1513
|
+
}
|
1514
|
+
D = MOD(MUL(D, D), p);
|
1515
|
+
}
|
1516
|
+
}
|
1517
|
+
if (MORE(r, HALF(p)))
|
1518
|
+
{
|
1519
|
+
r = SUB(p, r);
|
1520
|
+
}
|
1521
|
+
return r;
|
1522
|
+
}
|
1523
|
+
|
1524
|
+
/*
|
1525
|
+
* call-seq:
|
1526
|
+
* integer.isqrt -> integer
|
1527
|
+
*
|
1528
|
+
* Returns the square root integer part.
|
1529
|
+
*/
|
1530
|
+
static VALUE
|
1531
|
+
numtheory_isqrt(VALUE n)
|
1532
|
+
{
|
1533
|
+
if (NEGATIVE_P(n))
|
1534
|
+
{
|
1535
|
+
rb_raise(rb_eArgError, "can't take square root from negative number");
|
1536
|
+
}
|
1537
|
+
if (ZERO_P(n))
|
1538
|
+
{
|
1539
|
+
return zero;
|
1540
|
+
}
|
1541
|
+
VALUE x, y;
|
1542
|
+
if (FIXNUM_P(n))
|
1543
|
+
{
|
1544
|
+
x = n;
|
1545
|
+
}
|
1546
|
+
else
|
1547
|
+
{
|
1548
|
+
x = rb_big_lshift(TO_BIGNUM(one), ADD(HALF(numtheory_bitlength(n)), one));
|
1549
|
+
}
|
1550
|
+
for ( ; ; )
|
1551
|
+
{
|
1552
|
+
y = HALF(ADD(x, DIV(n, x)));
|
1553
|
+
if (LESS(y, x))
|
1554
|
+
x = y;
|
1555
|
+
else
|
1556
|
+
break;
|
1557
|
+
}
|
1558
|
+
return x;
|
1559
|
+
}
|
1560
|
+
|
1561
|
+
static int MOD_255(VALUE n)
|
1562
|
+
{
|
1563
|
+
if (FIXNUM_P(n))
|
1564
|
+
{
|
1565
|
+
return FIX2LONG(n) % 255;
|
1566
|
+
}
|
1567
|
+
unsigned long long m = 0;
|
1568
|
+
BDIGIT* digit = RBIGNUM_DIGITS(n);
|
1569
|
+
int i;
|
1570
|
+
for (i = 0; i < RBIGNUM_LEN(n); ++i, ++digit)
|
1571
|
+
{
|
1572
|
+
m += *digit & 0xFF;
|
1573
|
+
m += (*digit & 0xFF00) >> 8;
|
1574
|
+
m += (*digit & 0xFF0000) >> 16;
|
1575
|
+
m += (*digit & 0xFF000000UL) >> 24;
|
1576
|
+
}
|
1577
|
+
return m % 255;
|
1578
|
+
}
|
1579
|
+
|
1580
|
+
/*
|
1581
|
+
* call-seq:
|
1582
|
+
* integer.square? -> true or false
|
1583
|
+
*
|
1584
|
+
* Checks whether the integer is a perfect square or not.
|
1585
|
+
*/
|
1586
|
+
static VALUE
|
1587
|
+
numtheory_perfect_square_p(VALUE n)
|
1588
|
+
{
|
1589
|
+
if (NEGATIVE_P(n))
|
1590
|
+
{
|
1591
|
+
return Qfalse;
|
1592
|
+
}
|
1593
|
+
|
1594
|
+
if ( !issquare_mod256[ (FIXNUM_P(n) ? FIX2ULONG(n) : RBIGNUM_DIGITS(n)[0]) & 0xFF ]
|
1595
|
+
||
|
1596
|
+
!issquare_mod255[ MOD_255(n) ])
|
1597
|
+
{
|
1598
|
+
// only 44 residues mod 256 are squares, and only 54 residues mod 255.
|
1599
|
+
// 44/256 * 54/255 = 0.0364 so in 96.4% of cases there's no need to
|
1600
|
+
// check anything else
|
1601
|
+
return Qfalse;
|
1602
|
+
}
|
1603
|
+
|
1604
|
+
VALUE r = numtheory_isqrt(n);
|
1605
|
+
return EQL(MUL(r, r), n) ? Qtrue : Qfalse;
|
1606
|
+
}
|
1607
|
+
|
1608
|
+
static VALUE
|
1609
|
+
lucas_pseudoprime_p(VALUE n, VALUE a, VALUE b)
|
1610
|
+
{
|
1611
|
+
// for internal use only
|
1612
|
+
|
1613
|
+
// the details about the algorithm can be found in the book
|
1614
|
+
// "Prime numbers. A computational perspective."
|
1615
|
+
|
1616
|
+
VALUE d = SUB(MUL(a, a), MUL(b, four));
|
1617
|
+
// it's assumed here that d is not a full square and gcd(2abd, n) = 1
|
1618
|
+
|
1619
|
+
VALUE A = MOD(SUB(MUL(MUL(a, a),
|
1620
|
+
numtheory_modular_inverse(b, n)),
|
1621
|
+
two),
|
1622
|
+
n);
|
1623
|
+
|
1624
|
+
VALUE m = HALF(SUB(n, numtheory_jacobi(d, n)));
|
1625
|
+
|
1626
|
+
VALUE u = two;
|
1627
|
+
VALUE v = CLONE(A);
|
1628
|
+
FOR_BITS(m, {},
|
1629
|
+
{
|
1630
|
+
v = MOD(SUB(MUL(u, v), A), n);
|
1631
|
+
u = MOD(SUB(MUL(u, u), two), n);
|
1632
|
+
},
|
1633
|
+
{
|
1634
|
+
u = MOD(SUB(MUL(u, v), A), n);
|
1635
|
+
v = MOD(SUB(MUL(v, v), two), n);
|
1636
|
+
},
|
1637
|
+
{});
|
1638
|
+
if (EQL( MOD(MUL(A, u), n),
|
1639
|
+
MOD(MUL(two, v), n)))
|
1640
|
+
{
|
1641
|
+
return Qtrue;
|
1642
|
+
}
|
1643
|
+
return Qfalse;
|
1644
|
+
}
|
1645
|
+
|
1646
|
+
static VALUE power_of_2_mod(VALUE p, VALUE m){
|
1647
|
+
// Used internally in base-2 Miller-Rabin test.
|
1648
|
+
// Uses left shift instead of multiplication.
|
1649
|
+
VALUE result = one;
|
1650
|
+
FOR_BITS(p, result = MUL(result, result),
|
1651
|
+
{},
|
1652
|
+
result = DOUBLED(result),
|
1653
|
+
result = MOD(result, m));
|
1654
|
+
return result;
|
1655
|
+
}
|
1656
|
+
|
1657
|
+
static VALUE miller_rabin_base2_pseudoprime_p(VALUE n)
|
1658
|
+
{
|
1659
|
+
// for internal use only
|
1660
|
+
VALUE num = rb_big_clone(TO_BIGNUM(n));
|
1661
|
+
VALUE num_minus_one = SUB(num, one);
|
1662
|
+
VALUE d = rb_big_clone(TO_BIGNUM(num_minus_one));
|
1663
|
+
|
1664
|
+
int s = tail_zeros(d);
|
1665
|
+
d = RIGHT_SHIFT(d, s);
|
1666
|
+
|
1667
|
+
VALUE x = power_of_2_mod(d, num);
|
1668
|
+
if (EQL(x, one) || EQL(x, num_minus_one)) return Qtrue;
|
1669
|
+
|
1670
|
+
while (s--) {
|
1671
|
+
x = MOD(MUL(x, x), num);
|
1672
|
+
if (EQL(x, one)) return Qfalse;
|
1673
|
+
if (EQL(x, num_minus_one)) break;
|
1674
|
+
}
|
1675
|
+
if (!EQL(x, num_minus_one)) {
|
1676
|
+
return Qfalse;
|
1677
|
+
}
|
1678
|
+
return Qtrue;
|
1679
|
+
}
|
1680
|
+
|
1681
|
+
/*
|
1682
|
+
* call-seq:
|
1683
|
+
* integer.BPSW_pseudoprime? -> true or false
|
1684
|
+
*
|
1685
|
+
* Standard BPSW primality test.
|
1686
|
+
*/
|
1687
|
+
static VALUE
|
1688
|
+
numtheory_bpsw_pseudoprime_p(VALUE n)
|
1689
|
+
{
|
1690
|
+
VALUE num = ABS(n);
|
1691
|
+
|
1692
|
+
if (EQL(num, two))
|
1693
|
+
{
|
1694
|
+
return Qtrue;
|
1695
|
+
}
|
1696
|
+
if (LESS(num, two) || EVEN_P(num) ||
|
1697
|
+
(numtheory_perfect_square_p(num) == Qtrue))
|
1698
|
+
{
|
1699
|
+
return Qfalse;
|
1700
|
+
}
|
1701
|
+
|
1702
|
+
// Miller-Rabin test with base 2
|
1703
|
+
if (miller_rabin_base2_pseudoprime_p(num) == Qfalse)
|
1704
|
+
{
|
1705
|
+
return Qfalse;
|
1706
|
+
}
|
1707
|
+
|
1708
|
+
// standard Lucas-Selfridge test. Based on the description from
|
1709
|
+
// http://www.e-maxx.ru/algo/bpsw
|
1710
|
+
int d_abs, d_sign, d;
|
1711
|
+
for (d_abs = 5, d_sign = 1; ; d_abs += 2, d_sign = -d_sign)
|
1712
|
+
{
|
1713
|
+
d = d_abs * d_sign;
|
1714
|
+
VALUE G = rb_funcall(num, id_gcd, 1, INT2FIX(d));
|
1715
|
+
if (MORE(G, one) && LESS(G, num))
|
1716
|
+
{
|
1717
|
+
return Qfalse;
|
1718
|
+
}
|
1719
|
+
if (numtheory_jacobi(INT2FIX(d), num) == INT2FIX(-1))
|
1720
|
+
{
|
1721
|
+
break;
|
1722
|
+
}
|
1723
|
+
}
|
1724
|
+
|
1725
|
+
return lucas_pseudoprime_p(num, one, RIGHT_SHIFT(SUB(one, INT2FIX(d)), 2));
|
1726
|
+
}
|