ruby-numtheory 0.0.4-x86-linux → 0.0.5-x86-linux
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/numtheory/numtheory.c +150 -32
- data/lib/numtheory.so +0 -0
- metadata +4 -4
data/ext/numtheory/numtheory.c
CHANGED
@@ -217,6 +217,10 @@ inline static VALUE SUB(VALUE x, VALUE y) {
|
|
217
217
|
rb_big_minus(TO_BIGNUM(x), y);
|
218
218
|
}
|
219
219
|
|
220
|
+
#define NEGATE(x) do { if (FIXNUM_P(x)) x = -x; \
|
221
|
+
else RBIGNUM_SET_SIGN(x, !RBIGNUM_SIGN(x)); } \
|
222
|
+
while(0);
|
223
|
+
|
220
224
|
inline static VALUE MUL(VALUE x, VALUE y) {
|
221
225
|
return rb_funcall(x, id_mul, 1, y);
|
222
226
|
}
|
@@ -243,7 +247,19 @@ inline static VALUE DIVMOD(VALUE x, VALUE y) {
|
|
243
247
|
inline static VALUE MOD(VALUE x, VALUE y) {
|
244
248
|
return rb_funcall(x, id_mod, 1, y);
|
245
249
|
}
|
246
|
-
|
250
|
+
|
251
|
+
inline static int MOD_4(VALUE x) {
|
252
|
+
return FIXNUM_P(x) ? FIX2LONG(x) & 3 :
|
253
|
+
RBIGNUM_SIGN(x) ? RBIGNUM_DIGITS(x)[0] & 3 :
|
254
|
+
4 - RBIGNUM_DIGITS(x)[0] & 3;
|
255
|
+
}
|
256
|
+
|
257
|
+
inline static int MOD_8(VALUE x) {
|
258
|
+
return FIXNUM_P(x) ? FIX2LONG(x) & 7 :
|
259
|
+
RBIGNUM_SIGN(x) ? RBIGNUM_DIGITS(x)[0] & 7 :
|
260
|
+
8 - RBIGNUM_DIGITS(x)[0] & 7;
|
261
|
+
}
|
262
|
+
|
247
263
|
inline static int EQL(VALUE x, VALUE y) {
|
248
264
|
return (FIXNUM_P(x) && FIXNUM_P(y)) ?
|
249
265
|
x == y :
|
@@ -345,6 +361,8 @@ numtheory_powermod(int argc, VALUE *argv)
|
|
345
361
|
return result;
|
346
362
|
}
|
347
363
|
|
364
|
+
static VALUE int_powermod_sliding_window(VALUE,VALUE,VALUE);
|
365
|
+
|
348
366
|
/*
|
349
367
|
* call-seq:
|
350
368
|
* integer.powermod(power, modulo) -> integer
|
@@ -356,7 +374,6 @@ numtheory_powermod(int argc, VALUE *argv)
|
|
356
374
|
*/
|
357
375
|
static VALUE
|
358
376
|
numtheory_int_powermod(VALUE b, VALUE p, VALUE m){
|
359
|
-
VALUE result = one;
|
360
377
|
if (!INTEGER_P(p))
|
361
378
|
{
|
362
379
|
rb_raise(rb_eArgError, "power must be integer");
|
@@ -365,16 +382,32 @@ numtheory_int_powermod(VALUE b, VALUE p, VALUE m){
|
|
365
382
|
{
|
366
383
|
rb_raise(rb_eTypeError, "modulo must be integer");
|
367
384
|
}
|
385
|
+
if (ZERO_P(p))
|
386
|
+
{
|
387
|
+
return one;
|
388
|
+
}
|
368
389
|
if (NEGATIVE_P(p))
|
369
390
|
{
|
370
391
|
b = numtheory_modular_inverse(b, m);
|
371
392
|
p = ABS(p);
|
393
|
+
}
|
394
|
+
else
|
395
|
+
{
|
396
|
+
b = MOD(b, m);
|
397
|
+
}
|
398
|
+
if (FIXNUM_P(p) || RBIGNUM_LEN(p) < 4)
|
399
|
+
{
|
400
|
+
VALUE result = one;
|
401
|
+
FOR_BITS(p, result = MUL(result, result),
|
402
|
+
{},
|
403
|
+
result = MUL(result, b),
|
404
|
+
result = MOD(result, m));
|
405
|
+
return result;
|
406
|
+
}
|
407
|
+
else
|
408
|
+
{
|
409
|
+
return int_powermod_sliding_window(b, p, m);
|
372
410
|
}
|
373
|
-
FOR_BITS(p, result = MUL(result, result),
|
374
|
-
{},
|
375
|
-
result = MUL(result, b),
|
376
|
-
result = MOD(result, m));
|
377
|
-
return result;
|
378
411
|
}
|
379
412
|
|
380
413
|
static int tail_zeros(VALUE n)
|
@@ -1378,48 +1411,52 @@ numtheory_jacobi(VALUE a, VALUE n)
|
|
1378
1411
|
{
|
1379
1412
|
rb_raise(rb_eArgError, "n must be odd positive");
|
1380
1413
|
}
|
1381
|
-
int t = 1;
|
1414
|
+
int t = 1, z;
|
1382
1415
|
VALUE tmp;
|
1416
|
+
|
1417
|
+
a = MOD(a, n);
|
1418
|
+
if (MORE(a, HALF(n))) {
|
1419
|
+
a = SUB(a, n);
|
1420
|
+
}
|
1421
|
+
|
1383
1422
|
while (!ZERO_P(a))
|
1384
1423
|
{
|
1385
|
-
|
1386
|
-
if (MORE(a, HALF(n)))
|
1424
|
+
if (FIXNUM_P(n) && FIXNUM_P(a))
|
1387
1425
|
{
|
1388
|
-
|
1389
|
-
}
|
1390
|
-
if (FIXNUM_P(n))
|
1391
|
-
{
|
1392
|
-
return INT2FIX(ull_jacobi(FIX2LONG(a), FIX2LONG(n)));
|
1426
|
+
return INT2FIX(t * ull_jacobi(FIX2LONG(a), FIX2LONG(n)));
|
1393
1427
|
}
|
1394
1428
|
if (RBIGNUM_LEN(n) <= 2) // unsigned long long is used
|
1395
1429
|
{
|
1396
|
-
return INT2FIX(ull_jacobi(FIXNUM_P(a) ? FIX2LONG(a) : rb_big2ll(a),
|
1397
|
-
|
1430
|
+
return INT2FIX(t * ull_jacobi(FIXNUM_P(a) ? FIX2LONG(a) : rb_big2ll(a),
|
1431
|
+
rb_big2ull(n)));
|
1398
1432
|
}
|
1399
1433
|
if (NEGATIVE_P(a))
|
1400
1434
|
{
|
1401
|
-
|
1402
|
-
if (
|
1435
|
+
NEGATE(a);
|
1436
|
+
if (MOD_4(n) == 3)
|
1403
1437
|
t = -t;
|
1404
1438
|
}
|
1405
|
-
|
1439
|
+
z = tail_zeros(a);
|
1440
|
+
a = RIGHT_SHIFT(a, z);
|
1441
|
+
if (z & 1)
|
1406
1442
|
{
|
1407
|
-
|
1408
|
-
|
1409
|
-
|
1410
|
-
|
1411
|
-
|
1412
|
-
|
1413
|
-
|
1414
|
-
while (EVEN_P(a))
|
1415
|
-
a = HALF(a), t = -t;
|
1416
|
-
break;
|
1443
|
+
switch (MOD_8(n))
|
1444
|
+
{
|
1445
|
+
case 3:
|
1446
|
+
case 5:
|
1447
|
+
t = -t;
|
1448
|
+
break;
|
1449
|
+
}
|
1417
1450
|
}
|
1418
1451
|
tmp = a;
|
1419
1452
|
a = n;
|
1420
|
-
n = tmp;
|
1421
|
-
if (
|
1453
|
+
n = tmp; /* n > 0 */
|
1454
|
+
if (MOD_4(a) == 3 && MOD_4(n) == 3)
|
1422
1455
|
t = -t;
|
1456
|
+
a = MOD(a, n);
|
1457
|
+
if (MORE(a, HALF(n))) {
|
1458
|
+
a = SUB(a, n);
|
1459
|
+
}
|
1423
1460
|
}
|
1424
1461
|
if (n == one)
|
1425
1462
|
{
|
@@ -1724,3 +1761,84 @@ numtheory_bpsw_pseudoprime_p(VALUE n)
|
|
1724
1761
|
|
1725
1762
|
return lucas_pseudoprime_p(num, one, RIGHT_SHIFT(SUB(one, INT2FIX(d)), 2));
|
1726
1763
|
}
|
1764
|
+
|
1765
|
+
static VALUE
|
1766
|
+
int_powermod_sliding_window(VALUE b, VALUE p, VALUE m){
|
1767
|
+
VALUE result = one;
|
1768
|
+
/* used when p is bignum only */
|
1769
|
+
enum { squaring, collecting } state;
|
1770
|
+
|
1771
|
+
state = collecting;
|
1772
|
+
int len, k;
|
1773
|
+
int zeros = 0;
|
1774
|
+
int pow = 0;
|
1775
|
+
|
1776
|
+
/* adjusting window size */
|
1777
|
+
len = RBIGNUM_LEN(p);
|
1778
|
+
if (len < 8) k = 4;
|
1779
|
+
else if (len < 20) k = 5;
|
1780
|
+
else if (len < 48) k = 6;
|
1781
|
+
else k = 7;
|
1782
|
+
|
1783
|
+
len = 0;
|
1784
|
+
|
1785
|
+
VALUE b_squared = MOD(MUL(b, b), m);
|
1786
|
+
VALUE *powers = ALLOCA_N(VALUE, 1<<(k-1));
|
1787
|
+
powers[0] = b;
|
1788
|
+
int i;
|
1789
|
+
/* precomputation of odd powers;
|
1790
|
+
powers[n] = (b ** (2n + 1)) % m */
|
1791
|
+
for (i = 1; i < (1<<(k-1)); ++i)
|
1792
|
+
powers[i] = MOD(MUL(powers[i-1], b_squared), m);
|
1793
|
+
|
1794
|
+
FOR_BITS(p, {},
|
1795
|
+
{ /* if the bit is zero */
|
1796
|
+
if (state == collecting) {
|
1797
|
+
++ len;
|
1798
|
+
++ zeros;
|
1799
|
+
pow <<= 1;
|
1800
|
+
if (len == k) {
|
1801
|
+
pow >>= zeros;
|
1802
|
+
|
1803
|
+
for (i = len; i > zeros; i--)
|
1804
|
+
result = MOD(MUL(result, result), m);
|
1805
|
+
result = MOD(MUL(result, powers[pow>>1]), m);
|
1806
|
+
while (zeros--)
|
1807
|
+
result = MOD(MUL(result, result), m);
|
1808
|
+
|
1809
|
+
state = squaring; pow = len = zeros = 0;
|
1810
|
+
}
|
1811
|
+
} else {
|
1812
|
+
result = MOD(MUL(result, result), m);
|
1813
|
+
}
|
1814
|
+
},
|
1815
|
+
{ /* the bit is one */
|
1816
|
+
if (state == collecting) {
|
1817
|
+
++ len;
|
1818
|
+
zeros = 0;
|
1819
|
+
pow = (pow << 1) + 1;
|
1820
|
+
if (len == k) {
|
1821
|
+
while (len--)
|
1822
|
+
result = MOD(MUL(result, result), m);
|
1823
|
+
result = MOD(MUL(result, powers[pow>>1]), m);
|
1824
|
+
state = squaring;
|
1825
|
+
pow = len = 0;
|
1826
|
+
}
|
1827
|
+
} else {
|
1828
|
+
state = collecting;
|
1829
|
+
pow = 1;
|
1830
|
+
len = 1;
|
1831
|
+
zeros = 0;
|
1832
|
+
}
|
1833
|
+
}, {});
|
1834
|
+
if (len > 0) {
|
1835
|
+
pow >>= zeros;
|
1836
|
+
|
1837
|
+
for (i = len; i > zeros; i--)
|
1838
|
+
result = MOD(MUL(result, result), m);
|
1839
|
+
result = MOD(MUL(result, powers[pow>>1]), m);
|
1840
|
+
while (zeros--)
|
1841
|
+
result = MOD(MUL(result, result), m);
|
1842
|
+
}
|
1843
|
+
return result;
|
1844
|
+
}
|
data/lib/numtheory.so
CHANGED
Binary file
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 5
|
9
|
+
version: 0.0.5
|
10
10
|
platform: x86-linux
|
11
11
|
authors:
|
12
12
|
- lomereiter
|
@@ -14,11 +14,11 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-05-
|
17
|
+
date: 2011-05-27 00:00:00 +04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
21
|
-
description:
|
21
|
+
description: " The library is written as C extension and aims to provide\n common number-theoretical functions such as powermod, jacobi symbol,\n various multiplicative ones, etc.\n"
|
22
22
|
email: lomereiter@gmail.com
|
23
23
|
executables: []
|
24
24
|
|