ruby-numtheory 0.0.4-x86-linux → 0.0.5-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 +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
|
|