ruby-numtheory 0.0.6 → 0.0.7

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/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  The library is written as C extension and aims to provide fast implementations of common number-theoretical algorithms.
4
4
 
5
+ [![Build Status](https://secure.travis-ci.org/lomereiter/ruby-numtheory.png)](http://travis-ci.org/lomereiter/ruby-numtheory)
6
+
5
7
  ## Currently implemented
6
8
 
7
9
  * powermod (uses sliding window exponentiation)
data/Rakefile CHANGED
@@ -11,24 +11,24 @@ rescue Bundler::BundlerError => e
11
11
  end
12
12
  require 'rake'
13
13
 
14
- spec = Gem::Specification.load('ruby-numtheory.gemspec')
15
-
16
14
  require 'rspec/core'
17
15
  require 'rspec/core/rake_task'
18
16
  RSpec::Core::RakeTask.new(:spec) do |spec|
19
17
  spec.pattern = FileList["spec/**/*_spec.rb"]
20
18
  end
21
19
 
22
- task :test => :spec
23
- task :default => :test
24
-
20
+ spec = Gem::Specification.load('ruby-numtheory.gemspec')
21
+
25
22
  require 'rubygems/package_task'
26
23
  Gem::PackageTask.new(spec) do |pkg|
27
24
  end
28
25
 
29
- task :build => :gem
30
-
31
26
  require 'rake/extensiontask'
32
27
  Rake::ExtensionTask.new('numtheory', spec) do |ext|
33
28
  ext.cross_compile = true
34
29
  end
30
+
31
+ task :spec => :compile
32
+ task :test => :spec
33
+ task :default => :test
34
+ task :build => :gem
@@ -1,3 +1,3 @@
1
1
  require 'mkmf'
2
- $CFLAGS = "-g -O3 -funroll-all-loops -fPIC -pedantic -std=c99"
2
+ $CFLAGS = "-g -O3 -funroll-all-loops -fPIC -pedantic -std=c99 -Wall -Wno-unused-but-set-variable"
3
3
  create_makefile 'numtheory'
@@ -2,10 +2,16 @@
2
2
 
3
3
  #include "primes.h"
4
4
  #include "queue.h"
5
+ #if RUBY_VERSION_MINOR != 8
5
6
  #include "reduce.h"
6
- #include "numtheory_macros.c"
7
+ #endif
8
+ #include "numtheory_macros.h"
7
9
  #include "constants.h"
8
10
 
11
+ #ifdef DEBUG
12
+ #include <stdio.h>
13
+ #endif
14
+
9
15
  static VALUE mNumTheory;
10
16
  static ID primality_tests_ID;
11
17
 
@@ -45,6 +51,10 @@ Init_numtheory()
45
51
  id_lcm = rb_intern("lcm");
46
52
  id_pow = rb_intern("**");
47
53
  id_mul = rb_intern("*");
54
+ #if RUBY_VERSION_MINOR == 8
55
+ id_cmp = rb_intern("<=>");
56
+ id_equal = rb_intern("==");
57
+ #endif
48
58
 
49
59
  primality_tests_ID = rb_intern("PrimalityTests");
50
60
  /* PrimalityTests: the number of rounds in Miller-Rabin test for primality. */
@@ -122,7 +132,7 @@ Init_numtheory()
122
132
  *
123
133
  * NumTheory.precompute_primes_upto(20000000)
124
134
  */
125
- static VALUE
135
+ VALUE
126
136
  numtheory_precompute_primes_upto(VALUE obj, VALUE n)
127
137
  {
128
138
  if (FIXNUM_P(n))
@@ -166,7 +176,7 @@ numtheory_precompute_primes_upto(VALUE obj, VALUE n)
166
176
  * Matrix.identity(2))
167
177
  * #=> Matrix[[10946, 6765], [6765, 4181]]
168
178
  */
169
- static VALUE
179
+ VALUE
170
180
  numtheory_powermod(int argc, VALUE *argv)
171
181
  {
172
182
  VALUE base, pow, modulo, one;
@@ -175,7 +185,7 @@ numtheory_powermod(int argc, VALUE *argv)
175
185
  ID id_mul = rb_intern("*");
176
186
  ID id_mod = rb_intern("%");
177
187
 
178
- VALUE result = NIL_P(one) ? rb_uint2big(1) : one;
188
+ VALUE result = NIL_P(one) ? INT2BIG(1) : one;
179
189
  FOR_BITS(pow, result = rb_funcall(result, id_mul, 1, result),
180
190
  {},
181
191
  result = rb_funcall(result, id_mul, 1, base),
@@ -187,7 +197,9 @@ numtheory_powermod(int argc, VALUE *argv)
187
197
  }
188
198
 
189
199
  static VALUE int_powermod_sliding_window(VALUE,VALUE,VALUE);
200
+ #if RUBY_VERSION_MINOR != 8
190
201
  static VALUE int_powermod_sliding_window_br(VALUE,VALUE,VALUE);
202
+ #endif
191
203
 
192
204
  /*
193
205
  * call-seq:
@@ -198,7 +210,7 @@ static VALUE int_powermod_sliding_window_br(VALUE,VALUE,VALUE);
198
210
  *
199
211
  * 172.powermod(238, 239) #=> 1
200
212
  */
201
- static VALUE
213
+ VALUE
202
214
  numtheory_int_powermod(VALUE b, VALUE p, VALUE m){
203
215
  if (!INTEGER_P(p))
204
216
  {
@@ -233,8 +245,10 @@ numtheory_int_powermod(VALUE b, VALUE p, VALUE m){
233
245
  if (!FIXNUM_P(m) && RBIGNUM_LEN(m) >= BARRETT_REDUCE_THRESHOLD)
234
246
  use_barrett = 1;
235
247
 
248
+ #if RUBY_VERSION_MINOR != 8
236
249
  if (use_barrett)
237
250
  return int_powermod_sliding_window_br(b, p, m);
251
+ #endif
238
252
 
239
253
  if (use_sliding_window)
240
254
  return int_powermod_sliding_window(b, p, m);
@@ -251,8 +265,8 @@ static int tail_zeros(VALUE n)
251
265
  {
252
266
  if (FIXNUM_P(n))
253
267
  {
254
- int t = FIX2LONG(n);
255
- int s = 0;
268
+ long t = FIX2LONG(n);
269
+ long s = 0;
256
270
  while (!(t & 1))
257
271
  t >>= 1, ++s;
258
272
  return s;
@@ -261,8 +275,9 @@ static int tail_zeros(VALUE n)
261
275
  {
262
276
  BDIGIT* digit = RBIGNUM_DIGITS(n);
263
277
  unsigned int L = RBIGNUM_LEN(n);
264
- unsigned int i, j, s, z;
265
- const unsigned long MAX = 1 << (SIZEOF_BDIGITS * 8 - 1);
278
+ unsigned int i, s, z;
279
+ unsigned LONG_LONG j;
280
+ const unsigned LONG_LONG MAX = 1ULL << (SIZEOF_BDIGITS * 8 - 1);
266
281
  for (i = s = 0, z = 1; i < L; ++i, ++digit)
267
282
  {
268
283
  for (j = 1; j <= MAX; j <<= 1)
@@ -289,7 +304,7 @@ static int tail_zeros(VALUE n)
289
304
  * accordingly to Miller-Rabin test with <i>NumTheory::PrimalityTests</i>
290
305
  * rounds. Otherwise returns <code>false</code>.
291
306
  */
292
- static VALUE
307
+ VALUE
293
308
  numtheory_miller_rabin_pseudoprime_p(VALUE n)
294
309
  {
295
310
  long PRIMALITY_TESTS = FIX2LONG(rb_const_get(mNumTheory, primality_tests_ID));
@@ -329,7 +344,12 @@ numtheory_miller_rabin_pseudoprime_p(VALUE n)
329
344
  for (i = 0; i < PRIMALITY_TESTS; ++i)
330
345
  {
331
346
 
332
- VALUE a = rb_funcall(rb_cRandom,
347
+ VALUE a = rb_funcall(
348
+ #if RUBY_VERSION_MINOR == 8
349
+ rb_mKernel,
350
+ #else
351
+ rb_cRandom,
352
+ #endif
333
353
  id_rand,
334
354
  1,
335
355
  num_minus_four);
@@ -362,12 +382,12 @@ numtheory_miller_rabin_pseudoprime_p(VALUE n)
362
382
  }
363
383
 
364
384
  inline static int
365
- prime_p(unsigned long t)
385
+ prime_p(unsigned LONG_LONG t)
366
386
  {
367
387
  return (t & 1) ? t == 3 ? 1 :
368
388
  ((t % 6 == 1) || (t % 6 == 5)) ?
369
389
  t < PRIMES_UPPER_LIMIT ?
370
- is_set(numtheory_is_prime, t) ? 1 : 0 :
390
+ is_set(numtheory_is_prime, (unsigned long)t) ? 1 : 0 :
371
391
  numtheory_bpsw_pseudoprime_p(ULL2NUM(t)) :
372
392
  0
373
393
  : t == 2 ? 1 : 0;
@@ -382,16 +402,22 @@ prime_p(unsigned long t)
382
402
  *
383
403
  * 29.prime? #=> true
384
404
  */
385
- static VALUE
405
+ VALUE
386
406
  numtheory_prime_p(VALUE n)
387
407
  {
388
408
  unsigned long t;
389
409
  if (FIXNUM_P(n) && (t = abs(FIX2LONG(n)), t < PRIMES_UPPER_LIMIT))
390
410
  {
411
+ #ifdef DEBUG
412
+ fprintf(stderr, "[prime_p] looking up in the precomputed table...\n");
413
+ #endif
391
414
  return prime_p(t) ? Qtrue : Qfalse;
392
415
  }
393
416
  else
394
417
  {
418
+ #ifdef DEBUG
419
+ fprintf(stderr, "[prime_p] calling BPSW primality test...\n");
420
+ #endif
395
421
  return numtheory_bpsw_pseudoprime_p(n);
396
422
  }
397
423
  }
@@ -404,7 +430,7 @@ numtheory_prime_p(VALUE n)
404
430
  *
405
431
  * (10**28).nextprime #=> 10000000000000000000000000331
406
432
  */
407
- static VALUE
433
+ VALUE
408
434
  numtheory_nextprime(VALUE n)
409
435
  {
410
436
  VALUE p = n;
@@ -437,7 +463,7 @@ nth_prime(long n)
437
463
  * NumTheory.prime 1 #=> 2
438
464
  * NumTheory.prime 1000 #=> 7919
439
465
  */
440
- static VALUE
466
+ VALUE
441
467
  numtheory_prime(VALUE obj, VALUE i)
442
468
  {
443
469
  long t;
@@ -493,7 +519,7 @@ primepi(unsigned long t)
493
519
  * NumTheory.primepi 10 #=> 4
494
520
  * NumTheory.primepi -10 #=> 0
495
521
  */
496
- static VALUE
522
+ VALUE
497
523
  numtheory_primepi(VALUE obj, VALUE n)
498
524
  {
499
525
  if (NEGATIVE_P(n))
@@ -520,7 +546,7 @@ numtheory_primepi(VALUE obj, VALUE n)
520
546
  * NumTheory.fibonacci 10 #=> 55
521
547
  * NumTheory.fibonacci 10**30, 1234567890 #=> 862134135
522
548
  */
523
- static VALUE
549
+ VALUE
524
550
  numtheory_fibonacci(int argc, VALUE* argv)
525
551
  {
526
552
  VALUE n, modulo;
@@ -540,13 +566,13 @@ numtheory_fibonacci(int argc, VALUE* argv)
540
566
  rb_raise(rb_eTypeError, "modulo must be integer");
541
567
  }
542
568
 
543
- VALUE a, b, c, old_a, old_b, old_c, old_b_sq;
569
+ VALUE a, b, c, old_a, old_b_sq, old_c;
544
570
  a = c = one;
545
571
  b = zero;
546
572
 
547
573
  n = SUB(n, one);
548
574
 
549
- FOR_BITS(n, { old_a = a; old_b = b; old_c = c;
575
+ FOR_BITS(n, { old_a = a; old_c = c;
550
576
  old_b_sq = MUL(b, b);
551
577
 
552
578
  a = ADD(MUL(a, a), old_b_sq);
@@ -579,7 +605,7 @@ numtheory_fibonacci(int argc, VALUE* argv)
579
605
  * NumTheory.sigma 1234567890, 0 #=> 48
580
606
  * NumTheory.sigma 1234567890, 1 #=> 3211610688
581
607
  */
582
- static VALUE
608
+ VALUE
583
609
  numtheory_sigma(int argc, VALUE* argv)
584
610
  {
585
611
  VALUE n, pow;
@@ -632,7 +658,7 @@ numtheory_sigma(int argc, VALUE* argv)
632
658
  *
633
659
  * NumTheory.eulerphi(1234567890) #=> 329040288
634
660
  */
635
- static VALUE
661
+ VALUE
636
662
  numtheory_eulerphi(VALUE obj, VALUE n)
637
663
  {
638
664
  if (!INTEGER_P(n))
@@ -665,7 +691,7 @@ numtheory_eulerphi(VALUE obj, VALUE n)
665
691
  * (-987654321).prime_division
666
692
  * #=> [[-1, 1], [3, 2], [17, 2], [379721, 1]]
667
693
  */
668
- static VALUE
694
+ VALUE
669
695
  numtheory_prime_division(VALUE n)
670
696
  {
671
697
  VALUE pd[2];
@@ -701,7 +727,7 @@ numtheory_prime_division(VALUE n)
701
727
  * NumTheory.moebius(4) #=> 0
702
728
  * NumTheory.moebius(35) #=> 1
703
729
  */
704
- static VALUE
730
+ VALUE
705
731
  numtheory_moebius(VALUE obj, VALUE n)
706
732
  {
707
733
  if (!INTEGER_P(n))
@@ -796,10 +822,10 @@ primorial(unsigned long min, unsigned long max)
796
822
  *
797
823
  * NumTheory.product([1,2,3,4,5,6]) #=> 720
798
824
  */
799
- static VALUE
825
+ VALUE
800
826
  numtheory_product(VALUE obj, VALUE arr)
801
827
  {
802
- if (!RB_TYPE_P(arr, T_ARRAY))
828
+ if (TYPE(arr) != T_ARRAY)
803
829
  {
804
830
  rb_raise(rb_eTypeError, "the argument must be an array");
805
831
  }
@@ -815,7 +841,7 @@ numtheory_product(VALUE obj, VALUE arr)
815
841
  *
816
842
  * 2.primes_upto(17).to_a #=> [2, 3, 5, 7, 11, 13, 17]
817
843
  */
818
- static VALUE
844
+ VALUE
819
845
  numtheory_primes_upto(VALUE min, VALUE _max)
820
846
  {
821
847
  VALUE max = _max;
@@ -924,7 +950,7 @@ rec_factorial(long n)
924
950
  *
925
951
  * 50.factorial.to_s(31) #=> "283sp352ltrc9csg1398f0dt7dg067g15ikr4b6spf70"
926
952
  */
927
- static VALUE
953
+ VALUE
928
954
  numtheory_factorial_primeswing(VALUE n)
929
955
  {
930
956
  long t;
@@ -951,7 +977,7 @@ numtheory_factorial_primeswing(VALUE n)
951
977
  q >>= 1;
952
978
  shift += q;
953
979
  }
954
- return rb_big_lshift(rec_factorial(t), LONG2NUM(shift));
980
+ return rb_big_lshift(TO_BIGNUM(rec_factorial(t)), LONG2NUM(shift));
955
981
  }
956
982
 
957
983
  struct Egcd {
@@ -988,7 +1014,7 @@ extended_gcd(VALUE x, VALUE y)
988
1014
  * 0.extended_gcd(0) #=> [0, [0, 0]]
989
1015
  * 239.extended_gcd(932) #=> [1, [39, -10]]
990
1016
  */
991
- static VALUE
1017
+ VALUE
992
1018
  numtheory_extended_gcd(VALUE x, VALUE y)
993
1019
  {
994
1020
  if (!INTEGER_P(y))
@@ -1021,7 +1047,7 @@ numtheory_extended_gcd(VALUE x, VALUE y)
1021
1047
  *
1022
1048
  * 1234.inverse(12345) #=> 9874
1023
1049
  */
1024
- static VALUE
1050
+ VALUE
1025
1051
  numtheory_modular_inverse(VALUE x, VALUE y)
1026
1052
  {
1027
1053
  struct Egcd egcd = extended_gcd(x, y);
@@ -1046,7 +1072,7 @@ numtheory_modular_inverse(VALUE x, VALUE y)
1046
1072
  *
1047
1073
  * 20.znorder(11) => 5
1048
1074
  */
1049
- static VALUE
1075
+ VALUE
1050
1076
  numtheory_multiplicative_order(VALUE a, VALUE m)
1051
1077
  {
1052
1078
  if (rb_funcall(a, id_gcd, 1, m) != one)
@@ -1095,7 +1121,7 @@ static inline VALUE* triple_new(VALUE v1, VALUE v2, VALUE v3)
1095
1121
  * Yields primitive pythagorean triples with perimeter less
1096
1122
  * or equal to <i>max_perimeter</i>.
1097
1123
  */
1098
- static VALUE
1124
+ VALUE
1099
1125
  numtheory_pythagorean_triples(VALUE obj, VALUE max_l)
1100
1126
  {
1101
1127
  RETURN_ENUMERATOR(obj, 1, &max_l);
@@ -1119,7 +1145,11 @@ numtheory_pythagorean_triples(VALUE obj, VALUE max_l)
1119
1145
  }
1120
1146
 
1121
1147
  a = triple[0]; b = triple[1]; c = triple[2];
1148
+ #if RUBY_VERSION_MINOR == 8
1149
+ rb_yield_values(3, triple[0], triple[1], triple[2]);
1150
+ #else
1122
1151
  rb_yield_values2(3, triple);
1152
+ #endif
1123
1153
 
1124
1154
  // uses ternary pythagorean tree
1125
1155
  a2 = DOUBLED(a);
@@ -1152,7 +1182,7 @@ numtheory_pythagorean_triples(VALUE obj, VALUE max_l)
1152
1182
  *
1153
1183
  * Returns the number of set bits.
1154
1184
  */
1155
- static VALUE
1185
+ VALUE
1156
1186
  numtheory_popcount(VALUE n)
1157
1187
  {
1158
1188
  if (NEGATIVE_P(n))
@@ -1165,15 +1195,23 @@ numtheory_popcount(VALUE n)
1165
1195
  }
1166
1196
 
1167
1197
  int
1168
- int_bitlength(unsigned int v)
1198
+ long_bitlength(unsigned long v)
1169
1199
  {
1170
- // taken from http://graphics.stanford.edu/~seander/bithacks.html
1171
- const unsigned int b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
1172
- const unsigned int S[] = {1, 2, 4, 8, 16};
1173
- int i;
1200
+ /* taken from http://graphics.stanford.edu/~seander/bithacks.html */
1174
1201
 
1175
- register unsigned int r = 0;
1202
+ #if SIZEOF_LONG == 8
1203
+ const unsigned long b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000ULL};
1204
+ const unsigned long S[] = {1, 2, 4, 8, 16, 32};
1205
+ int i;
1206
+ register unsigned long r = 0;
1207
+ for (i = 5; i >= 0; --i)
1208
+ #else
1209
+ const unsigned long b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000 };
1210
+ const unsigned long S[] = {1, 2, 4, 8, 16};
1211
+ int i;
1212
+ register unsigned long r = 0;
1176
1213
  for (i = 4; i >= 0; --i)
1214
+ #endif
1177
1215
  {
1178
1216
  if (v & b[i])
1179
1217
  {
@@ -1191,32 +1229,32 @@ int_bitlength(unsigned int v)
1191
1229
  * Returns the length in bits. Defined for positive integers only.
1192
1230
  * 0 is assumed to have length 1.
1193
1231
  */
1194
- static VALUE
1232
+ VALUE
1195
1233
  numtheory_bitlength(VALUE n)
1196
1234
  {
1197
1235
  if (NEGATIVE_P(n))
1198
1236
  {
1199
1237
  rb_raise(rb_eArgError, "n must be positive");
1200
1238
  }
1201
- long bit_len, half_k;
1239
+ long bit_len;
1202
1240
  if (FIXNUM_P(n))
1203
1241
  {
1204
- return INT2FIX(int_bitlength(FIX2LONG(n)));
1242
+ return INT2FIX(long_bitlength(FIX2LONG(n)));
1205
1243
  }
1206
1244
  else
1207
1245
  {
1208
1246
  long len = RBIGNUM_LEN(n);
1209
1247
  bit_len = (len - 1) * SIZEOF_BDIGITS * 8;
1210
- return INT2FIX(bit_len + int_bitlength(RBIGNUM_DIGITS(n)[len - 1]));
1248
+ return INT2FIX(bit_len + long_bitlength(RBIGNUM_DIGITS(n)[len - 1]));
1211
1249
  }
1212
1250
  }
1213
1251
 
1214
1252
  static int
1215
- ull_jacobi(long long a, unsigned long long n)
1253
+ ull_jacobi(LONG_LONG a, unsigned LONG_LONG n)
1216
1254
  {
1217
1255
  /* it's assumed that n is odd and > 0 */
1218
1256
  int t = 1;
1219
- long long tmp;
1257
+ LONG_LONG tmp;
1220
1258
  while (a) {
1221
1259
  if (a < 0) {
1222
1260
  a = -a; if ((n & 3) == 3) t = -t;
@@ -1230,7 +1268,7 @@ ull_jacobi(long long a, unsigned long long n)
1230
1268
  tmp = a; a = n; n = tmp;
1231
1269
  if ((a & 3) == 3 && (n & 3) == 3) t = -t;
1232
1270
  a %= n;
1233
- if (a > (long long)(n >> 1)) a -= n;
1271
+ if (a > (LONG_LONG)(n >> 1)) a -= n;
1234
1272
  }
1235
1273
  return n == 1 ? t : 0;
1236
1274
  }
@@ -1241,7 +1279,7 @@ ull_jacobi(long long a, unsigned long long n)
1241
1279
  *
1242
1280
  * Returns jacobi symbol (a|n) where n must be odd positive
1243
1281
  */
1244
- static VALUE
1282
+ VALUE
1245
1283
  numtheory_jacobi(VALUE a, VALUE n)
1246
1284
  {
1247
1285
  if (EVEN_P(n) || NEGATIVE_P(n))
@@ -1262,7 +1300,7 @@ numtheory_jacobi(VALUE a, VALUE n)
1262
1300
  {
1263
1301
  return INT2FIX(t * ull_jacobi(FIX2LONG(a), FIX2LONG(n)));
1264
1302
  }
1265
- if (RBIGNUM_LEN(n) <= 2) // unsigned long long is used
1303
+ if (RBIGNUM_LEN(n) <= 2) // unsigned LONG_LONG is used
1266
1304
  {
1267
1305
  return INT2FIX(t * ull_jacobi(FIXNUM_P(a) ? FIX2LONG(a) : rb_big2ll(a),
1268
1306
  rb_big2ull(n)));
@@ -1312,7 +1350,7 @@ numtheory_jacobi(VALUE a, VALUE n)
1312
1350
  * If (a|p) = 1 returns the square root of a in Z/pZ
1313
1351
  * from the interval [0, p/2]. Otherwise returns +nil+.
1314
1352
  */
1315
- static VALUE
1353
+ VALUE
1316
1354
  numtheory_sqrtmod(VALUE a, VALUE p)
1317
1355
  {
1318
1356
  if (!INTEGER_P(p))
@@ -1401,7 +1439,7 @@ numtheory_sqrtmod(VALUE a, VALUE p)
1401
1439
  *
1402
1440
  * Returns the square root integer part.
1403
1441
  */
1404
- static VALUE
1442
+ VALUE
1405
1443
  numtheory_isqrt(VALUE n)
1406
1444
  {
1407
1445
  if (NEGATIVE_P(n))
@@ -1438,7 +1476,7 @@ static int MOD_255(VALUE n)
1438
1476
  {
1439
1477
  return FIX2LONG(n) % 255;
1440
1478
  }
1441
- unsigned long long m = 0;
1479
+ unsigned LONG_LONG m = 0;
1442
1480
  BDIGIT* digit = RBIGNUM_DIGITS(n);
1443
1481
  int i;
1444
1482
  for (i = 0; i < RBIGNUM_LEN(n); ++i, ++digit)
@@ -1457,7 +1495,7 @@ static int MOD_255(VALUE n)
1457
1495
  *
1458
1496
  * Checks whether the integer is a perfect square or not.
1459
1497
  */
1460
- static VALUE
1498
+ VALUE
1461
1499
  numtheory_perfect_square_p(VALUE n)
1462
1500
  {
1463
1501
  if (NEGATIVE_P(n))
@@ -1530,19 +1568,32 @@ static VALUE power_of_2_mod(VALUE p, VALUE m){
1530
1568
 
1531
1569
  static VALUE miller_rabin_base2_pseudoprime_p(VALUE n)
1532
1570
  {
1533
- // for internal use only
1571
+ /* for internal use only */
1572
+ #ifdef DEBUG
1573
+ fprintf(stderr, "[miller-rabin base 2] start test for %s...\n", TO_CSTRING(n));
1574
+ #endif
1534
1575
  VALUE num = rb_big_clone(TO_BIGNUM(n));
1535
1576
  VALUE num_minus_one = SUB(num, one);
1536
1577
  VALUE d = rb_big_clone(TO_BIGNUM(num_minus_one));
1537
1578
 
1538
1579
  int s = tail_zeros(d);
1580
+ #ifdef DEBUG
1581
+ fprintf(stderr, "[miller-rabin base 2] p-1 = %s...\n", TO_CSTRING(d));
1582
+ fprintf(stderr, "[miller-rabin base 2] tail zeros: %d\n", s);
1583
+ #endif
1539
1584
  d = RIGHT_SHIFT(d, s);
1540
1585
 
1541
1586
  VALUE x = power_of_2_mod(d, num);
1587
+ #ifdef DEBUG
1588
+ fprintf(stderr, "[miller-rabin base 2] 2**d = %s modulo %s\n", TO_CSTRING(x), TO_CSTRING(num));
1589
+ #endif
1542
1590
  if (EQL(x, one) || EQL(x, num_minus_one)) return Qtrue;
1543
1591
 
1544
1592
  while (s--) {
1545
1593
  x = MOD(MUL(x, x), num);
1594
+ #ifdef DEBUG
1595
+ fprintf(stderr, "[miller-rabin base 2] x = %s modulo %s\n", TO_CSTRING(x), TO_CSTRING(num));
1596
+ #endif
1546
1597
  if (EQL(x, one)) return Qfalse;
1547
1598
  if (EQL(x, num_minus_one)) break;
1548
1599
  }
@@ -1558,7 +1609,7 @@ static VALUE miller_rabin_base2_pseudoprime_p(VALUE n)
1558
1609
  *
1559
1610
  * Standard BPSW primality test.
1560
1611
  */
1561
- static VALUE
1612
+ VALUE
1562
1613
  numtheory_bpsw_pseudoprime_p(VALUE n)
1563
1614
  {
1564
1615
  VALUE num = ABS(n);
@@ -1570,12 +1621,18 @@ numtheory_bpsw_pseudoprime_p(VALUE n)
1570
1621
  if (LESS(num, two) || EVEN_P(num) ||
1571
1622
  (numtheory_perfect_square_p(num) == Qtrue))
1572
1623
  {
1624
+ #ifdef DEBUG
1625
+ fprintf(stderr, "[bpsw_pseudoprime_p] the number is less than 2, even or a perfect square\n");
1626
+ #endif
1573
1627
  return Qfalse;
1574
1628
  }
1575
1629
 
1576
1630
  // Miller-Rabin test with base 2
1577
1631
  if (miller_rabin_base2_pseudoprime_p(num) == Qfalse)
1578
1632
  {
1633
+ #ifdef DEBUG
1634
+ fprintf(stderr, "[bpsw_pseudoprime_p] Miller-Rabin test with base 2 returned false\n");
1635
+ #endif
1579
1636
  return Qfalse;
1580
1637
  }
1581
1638
 
@@ -1595,7 +1652,10 @@ numtheory_bpsw_pseudoprime_p(VALUE n)
1595
1652
  break;
1596
1653
  }
1597
1654
  }
1598
-
1655
+
1656
+ #ifdef DEBUG
1657
+ fprintf(stderr, "[bpsw_pseudoprime_p] calling Lucas primality test...\n");
1658
+ #endif
1599
1659
  return lucas_pseudoprime_p(num, one, RIGHT_SHIFT(SUB(one, INT2FIX(d)), 2));
1600
1660
  }
1601
1661
 
@@ -1603,6 +1663,8 @@ DEFINE_POWERMOD_SLIDING_WINDOW(int_powermod_sliding_window,
1603
1663
  {},
1604
1664
  MOD)
1605
1665
 
1666
+ #if RUBY_VERSION_MINOR != 8
1606
1667
  DEFINE_POWERMOD_SLIDING_WINDOW(int_powermod_sliding_window_br,
1607
1668
  VALUE mu = rb_big_barrett_mu(m),
1608
1669
  BARRETT_MOD)
1670
+ #endif
@@ -2,52 +2,105 @@
2
2
  #define NUMTHEORY_H
3
3
 
4
4
  #include <ruby.h>
5
- #include <stdio.h>
6
5
  #include <math.h>
7
6
 
7
+ #ifndef HAVE_RUBY_VERSION_H
8
+ #include <version.h>
9
+ #else
10
+ #include <ruby/version.h>
11
+ #endif
12
+
13
+ #if RUBY_VERSION_MINOR == 8
14
+ #include <intern.h>
15
+ #include <defines.h>
16
+ #endif
17
+
18
+ #ifdef DEBUG
19
+ #include <stdio.h>
20
+ inline static char* TO_CSTRING(VALUE x) {
21
+ VALUE v = rb_String(x);
22
+ return StringValueCStr(v);
23
+ }
24
+ #endif
25
+
8
26
  ID id_rand, id_mod, id_divmod, id_div,
9
27
  id_gcd, id_lcm, id_pow, id_mul;
10
28
 
11
29
  extern const VALUE zero,one,two,three,four,five,six,seven,eight;
12
30
 
13
- static VALUE numtheory_powermod(int argc, VALUE *argv);
14
- static VALUE numtheory_miller_rabin_pseudoprime_p(VALUE n);
15
- static VALUE numtheory_nextprime(VALUE n);
16
- static VALUE numtheory_precompute_primes_upto(VALUE obj, VALUE n);
17
- static VALUE numtheory_prime(VALUE obj, VALUE i);
18
- static VALUE numtheory_primepi(VALUE obj, VALUE n);
19
- static VALUE numtheory_fibonacci(int argc, VALUE *argv);
20
- static VALUE numtheory_sigma(int argc, VALUE *argv);
21
- static VALUE numtheory_eulerphi(VALUE obj, VALUE n);
22
- static VALUE numtheory_moebius(VALUE obj, VALUE n);
23
- static VALUE numtheory_prime_division(VALUE n);
24
- static VALUE numtheory_product(VALUE obj, VALUE arr);
25
- static VALUE numtheory_primes_upto(VALUE min, VALUE max);
26
- static VALUE numtheory_factorial_primeswing(VALUE n);
27
- static VALUE numtheory_extended_gcd(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_sqrtmod(VALUE a, VALUE p);
33
- static VALUE numtheory_isqrt(VALUE n);
34
- static VALUE numtheory_perfect_square_p(VALUE n);
35
- static VALUE numtheory_bpsw_pseudoprime_p(VALUE n);
36
-
37
- static VALUE numtheory_int_powermod(VALUE b, VALUE p, VALUE m);
38
-
39
- static VALUE numtheory_prime_p(VALUE n);
40
- static VALUE numtheory_modular_inverse(VALUE x, VALUE y);
41
- static VALUE numtheory_jacobi(VALUE a, VALUE n);
31
+ VALUE numtheory_powermod(int argc, VALUE *argv);
32
+ VALUE numtheory_miller_rabin_pseudoprime_p(VALUE n);
33
+ VALUE numtheory_nextprime(VALUE n);
34
+ VALUE numtheory_precompute_primes_upto(VALUE obj, VALUE n);
35
+ VALUE numtheory_prime(VALUE obj, VALUE i);
36
+ VALUE numtheory_primepi(VALUE obj, VALUE n);
37
+ VALUE numtheory_fibonacci(int argc, VALUE *argv);
38
+ VALUE numtheory_sigma(int argc, VALUE *argv);
39
+ VALUE numtheory_eulerphi(VALUE obj, VALUE n);
40
+ VALUE numtheory_moebius(VALUE obj, VALUE n);
41
+ VALUE numtheory_prime_division(VALUE n);
42
+ VALUE numtheory_product(VALUE obj, VALUE arr);
43
+ VALUE numtheory_primes_upto(VALUE min, VALUE max);
44
+ VALUE numtheory_factorial_primeswing(VALUE n);
45
+ VALUE numtheory_extended_gcd(VALUE x, VALUE y);
46
+ VALUE numtheory_multiplicative_order(VALUE a, VALUE m);
47
+ VALUE numtheory_pythagorean_triples(VALUE obj, VALUE max_l);
48
+ VALUE numtheory_popcount(VALUE n);
49
+ VALUE numtheory_bitlength(VALUE n);
50
+ VALUE numtheory_sqrtmod(VALUE a, VALUE p);
51
+ VALUE numtheory_isqrt(VALUE n);
52
+ VALUE numtheory_perfect_square_p(VALUE n);
53
+ VALUE numtheory_bpsw_pseudoprime_p(VALUE n);
54
+ VALUE numtheory_int_powermod(VALUE b, VALUE p, VALUE m);
55
+
56
+ VALUE numtheory_prime_p(VALUE n);
57
+ VALUE numtheory_modular_inverse(VALUE x, VALUE y);
58
+ VALUE numtheory_jacobi(VALUE a, VALUE n);
42
59
 
43
60
  #define BITSPERDIG (SIZEOF_BDIGITS * CHAR_BIT)
44
61
  #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
45
62
  #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD - 1)))
46
63
 
64
+ inline static VALUE INT2BIG(long x) {
65
+ return rb_int2big(x);
66
+ }
67
+
68
+ inline static VALUE INTVALUE2BIG(VALUE x) {
69
+ #ifdef DEBUG
70
+ fprintf(stderr, "[intvalue2big] initial value = %s\n", TO_CSTRING(x));
71
+ fprintf(stderr, "[intvalue2big] after conversion to long: %ld\n", FIX2LONG(x));
72
+ fprintf(stderr, "[intvalue2big] after conversion to BIGNUM: %s\n", TO_CSTRING(rb_int2big(FIX2LONG(x))));
73
+ #endif
74
+ return rb_int2big(FIX2LONG(x));
75
+ }
76
+
47
77
  inline static VALUE TO_BIGNUM(VALUE x) {
48
- return FIXNUM_P(x) ? rb_int2big(FIX2LONG(x)) : x;
78
+ return FIXNUM_P(x) ? INTVALUE2BIG(x) : x;
49
79
  }
50
80
 
81
+ #if RUBY_VERSION_MINOR == 8
82
+ static ID id_cmp, id_equal;
83
+
84
+ inline static VALUE rb_big_cmp(VALUE x, VALUE y) {
85
+ return rb_funcall(x, id_cmp, 1, y);
86
+ }
87
+
88
+ inline static int rb_bigzero_p(VALUE x) {
89
+ return rb_funcall(x, id_equal, 1, zero) == Qtrue;
90
+ }
91
+
92
+ inline static VALUE rb_big_eq(VALUE x, VALUE y) {
93
+ return rb_funcall(x, id_equal, 1, y);
94
+ }
95
+
96
+ inline static VALUE rb_big_div(VALUE x, VALUE y) {
97
+ return rb_funcall(x, id_div, 1, y);
98
+ }
99
+ #undef RBIGNUM_DIGITS
100
+ #define RBIGNUM_DIGITS(obj) ((BDIGIT*)(RBIGNUM(obj)->digits))
101
+
102
+ #endif
103
+
51
104
  inline static unsigned long TO_ULONG(VALUE x) {
52
105
  if (!FIXNUM_P(x))
53
106
  {
@@ -80,7 +133,7 @@ inline static VALUE SUB(VALUE x, VALUE y) {
80
133
  rb_big_minus(TO_BIGNUM(x), y);
81
134
  }
82
135
 
83
- #define NEGATE(x) do { if (FIXNUM_P(x)) x = -x; \
136
+ #define NEGATE(x) do { if (FIXNUM_P(x)) x = INT2FIX(-FIX2LONG(x)); \
84
137
  else RBIGNUM_SET_SIGN(x, !RBIGNUM_SIGN(x)); } \
85
138
  while(0);
86
139
 
@@ -107,13 +160,13 @@ inline static VALUE MOD(VALUE x, VALUE y) {
107
160
  inline static int MOD_4(VALUE x) {
108
161
  return FIXNUM_P(x) ? FIX2LONG(x) & 3 :
109
162
  RBIGNUM_SIGN(x) ? RBIGNUM_DIGITS(x)[0] & 3 :
110
- 4 - RBIGNUM_DIGITS(x)[0] & 3;
163
+ 4 - (RBIGNUM_DIGITS(x)[0] & 3);
111
164
  }
112
165
 
113
166
  inline static int MOD_8(VALUE x) {
114
167
  return FIXNUM_P(x) ? FIX2LONG(x) & 7 :
115
168
  RBIGNUM_SIGN(x) ? RBIGNUM_DIGITS(x)[0] & 7 :
116
- 8 - RBIGNUM_DIGITS(x)[0] & 7;
169
+ 8 - (RBIGNUM_DIGITS(x)[0] & 7);
117
170
  }
118
171
 
119
172
  inline static int EQL(VALUE x, VALUE y) {
@@ -141,8 +194,14 @@ inline static int MORE_EQL(VALUE x, VALUE y) {
141
194
  }
142
195
 
143
196
  inline static VALUE ABS(VALUE x) {
144
- if (FIXNUM_P(x))
145
- return INT2FIX(abs(FIX2LONG(x)));
197
+ if (FIXNUM_P(x)) {
198
+ #ifdef DEBUG
199
+ fprintf(stderr, "[abs] x = %s\n", TO_CSTRING(x));
200
+ fprintf(stderr, "[abs] FIX2LONG(x) = %ld\n", FIX2LONG(x));
201
+ fprintf(stderr, "[abs] result = %s\n", TO_CSTRING(LONG2FIX(labs(FIX2LONG(x)))));
202
+ #endif
203
+ return LONG2FIX(labs(FIX2LONG(x)));
204
+ }
146
205
  VALUE v = rb_big_clone(x);
147
206
  RBIGNUM_SET_SIGN(v, 1);
148
207
  return v;
@@ -161,8 +220,8 @@ inline static int INTEGER_P(VALUE x) {
161
220
  }
162
221
 
163
222
  inline static VALUE DOUBLED(VALUE x) {
164
- return FIXNUM_P(x) ? LONG2NUM(FIX2LONG(x) << 1) :
165
- rb_big_lshift(x, one);
223
+ return FIXNUM_P(x) ? INT2FIX(FIX2LONG(x) << 1) :
224
+ rb_big_lshift(x, one);
166
225
  }
167
226
 
168
227
  inline static VALUE HALF(VALUE x) {
@@ -180,4 +239,5 @@ inline static VALUE RIGHT_SHIFT(VALUE x, int s) {
180
239
  #endif
181
240
  inline static int min(int a, int b) { return a < b ? a : b; }
182
241
 
242
+
183
243
  #endif
@@ -1,7 +1,10 @@
1
+ #ifndef NUMTHEORY_MACROS_H
2
+ #define NUMTHEORY_MACROS_H 1
3
+
1
4
  #define FOR_PRIME_FACTORS(n, p, d, action) do { \
2
5
  int __d; \
3
- unsigned long __i; \
4
- unsigned long long __t; \
6
+ BDIGIT __i; \
7
+ unsigned LONG_LONG __t; \
5
8
  VALUE __num = (FIXNUM_P(n) ? n : rb_big_clone(n)); \
6
9
  if (!FIXNUM_P(__num)) \
7
10
  { \
@@ -11,7 +14,7 @@
11
14
  } \
12
15
  else \
13
16
  { \
14
- rb_raise(rb_eNotImpError, "Not implemented for numbers >= 2**64"); \
17
+ rb_raise(rb_eNotImpError, "Factorization is not implemented for numbers >= 2**64"); \
15
18
  } \
16
19
  } \
17
20
  else \
@@ -19,7 +22,7 @@
19
22
  __t = FIX2LONG(__num); \
20
23
  } \
21
24
  \
22
- unsigned long long __p; \
25
+ unsigned LONG_LONG __p; \
23
26
  VALUE p, d; \
24
27
  if (prime_p(__t)) \
25
28
  { \
@@ -93,7 +96,7 @@
93
96
  else { \
94
97
  BDIGIT* _digits = RBIGNUM_DIGITS(n); \
95
98
  long _digits_length = RBIGNUM_LEN(n); \
96
- BDIGIT _j; \
99
+ unsigned LONG_LONG _j; \
97
100
  BDIGIT* _digit = _digits + _digits_length - 1; \
98
101
  BDIGIT _half_fst_digit = (*_digit) >> 1; \
99
102
  for (_j = 1; _j <= _half_fst_digit; _j <<= 1); \
@@ -104,7 +107,7 @@
104
107
  else if_zero_action; \
105
108
  final_action; \
106
109
  } \
107
- _j = 1 << (SIZEOF_BDIGITS * 8 - 1); \
110
+ _j = 1ULL << (SIZEOF_BDIGITS * 8 - 1); \
108
111
  } \
109
112
  } \
110
113
  } while(0)
@@ -121,7 +124,7 @@ FUNC_NAME(VALUE b, VALUE p, VALUE m) {\
121
124
  int pow = 0; \
122
125
  \
123
126
  /* adjusting window size */ \
124
- if (FIXNUM_P(p)) p = rb_int2big(FIX2LONG(p)); \
127
+ if (FIXNUM_P(p)) p = INTVALUE2BIG(p); \
125
128
  len = RBIGNUM_LEN(p); \
126
129
  if (len < 8) k = 4; \
127
130
  else if (len < 20) k = 5; \
@@ -199,3 +202,5 @@ FUNC_NAME(VALUE b, VALUE p, VALUE m) {\
199
202
  }
200
203
 
201
204
  #define BARRETT_MOD(x, m) rb_big_barrett_reduce(x, m, mu, 1)
205
+
206
+ #endif
@@ -15,13 +15,12 @@ init_sieve(unsigned long max_n)
15
15
  unset_bit(numtheory_is_prime, 1);
16
16
  numtheory_primes = calloc((long)((double)max_n/(log((double)max_n)-4.0)+1), ULONG_SZ);
17
17
 
18
- unsigned long long i;
19
18
  unsigned long j;
20
19
  unsigned long p = 0;
21
20
  numtheory_primes[p++] = 2;
22
21
  numtheory_primes[p++] = 3;
23
22
 
24
- unsigned long long i1, i2, s;
23
+ unsigned LONG_LONG i1, i2, s;
25
24
  unsigned long max_n_sqrt = (unsigned long)(sqrt((double)max_n));
26
25
 
27
26
  for (i1 = 5, i2 = 7; ; i1 += 6, i2 += 6)
@@ -1,6 +1,8 @@
1
1
  #ifndef NUMTHEORY_PRIMES_H
2
2
  #define NUMTHEORY_PRIMES_H
3
3
 
4
+ #include <ruby.h>
5
+
4
6
  unsigned long init_sieve(unsigned long max_n); // returns prime_pi(max_n)
5
7
 
6
8
  #define ULONG_SZ sizeof(unsigned long)
@@ -1,6 +1,8 @@
1
1
  #include <string.h>
2
2
  #include "numtheory.h"
3
3
 
4
+ #if RUBY_VERSION_MINOR != 8
5
+
4
6
  #define MULADD(i, j) \
5
7
  __asm__ volatile( \
6
8
  "movl %6, %%eax \n\t" \
@@ -31,7 +33,6 @@ inline static VALUE rshift_digits_inplace(VALUE n, int k)
31
33
 
32
34
  BDIGIT* ds = RBIGNUM_DIGITS(n);
33
35
  int len = RBIGNUM_LEN(n);
34
- int i;
35
36
  if (len > k)
36
37
  {
37
38
  memmove(ds, ds + k, SIZEOF_BDIGITS * (len - k));
@@ -47,21 +48,19 @@ inline static VALUE rshift_digits_inplace(VALUE n, int k)
47
48
 
48
49
  inline static VALUE power_of_two(int p)
49
50
  {
50
- return rb_big_lshift(rb_int2big(1), INT2FIX(p));
51
+ return rb_big_lshift(INT2BIG(1), INT2FIX(p));
51
52
  }
52
53
 
53
54
  static VALUE
54
55
  bigmul_low_digits(VALUE x, VALUE y, int digits)
55
56
  {
56
57
  int xn = RBIGNUM_LEN(x);
57
- if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
58
+ if (FIXNUM_P(y)) y = INTVALUE2BIG(y);
58
59
  int yn = RBIGNUM_LEN(y);
59
60
 
60
- int all = 0;
61
61
  if (digits > xn + yn)
62
62
  {
63
63
  digits = xn + yn;
64
- all = 1;
65
64
  }
66
65
  VALUE z = rb_big_new(digits, 1);
67
66
 
@@ -88,7 +87,7 @@ bigmul_low_digits(VALUE x, VALUE y, int digits)
88
87
  VALUE bigmul_low_digits_old(VALUE x, VALUE y, int digits)
89
88
  {
90
89
  int xn = RBIGNUM_LEN(x);
91
- if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
90
+ if (FIXNUM_P(y)) y = INTVALUE2BIG(y);
92
91
  int yn = RBIGNUM_LEN(y);
93
92
  VALUE z = rb_big_new(digits, 1);
94
93
  BDIGIT* xds = RBIGNUM_DIGITS(x);
@@ -120,7 +119,7 @@ static VALUE
120
119
  bigmul_high_digits(VALUE x, VALUE y, int dontcare, int x_right_shift)
121
120
  {
122
121
  int xn = RBIGNUM_LEN(x);
123
- if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
122
+ if (FIXNUM_P(y)) y = INTVALUE2BIG(y);
124
123
  int yn = RBIGNUM_LEN(y);
125
124
 
126
125
 
@@ -130,7 +129,7 @@ bigmul_high_digits(VALUE x, VALUE y, int dontcare, int x_right_shift)
130
129
  /* in order to avoid rb_big_clone call,
131
130
  let's virtually "shift" x instead of actual shifting */
132
131
  if (x_right_shift >= xn) {
133
- return rb_int2big(0);
132
+ return INT2BIG(0);
134
133
  } else {
135
134
  xds += x_right_shift;
136
135
  xn -= x_right_shift;
@@ -163,7 +162,7 @@ bigmul_high_digits(VALUE x, VALUE y, int dontcare, int x_right_shift)
163
162
  VALUE bigmul_high_digits_old(VALUE x, VALUE y, int dontcare)
164
163
  {
165
164
  int xn = RBIGNUM_LEN(x);
166
- if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
165
+ if (FIXNUM_P(y)) y = INTVALUE2BIG(y);
167
166
  int yn = RBIGNUM_LEN(y);
168
167
  VALUE z = rb_big_new(xn + yn, 1);
169
168
  BDIGIT* xds = RBIGNUM_DIGITS(x);
@@ -232,3 +231,5 @@ VALUE rb_big_barrett_reduce(VALUE x, VALUE m, VALUE mu, int inplace)
232
231
  a = SUB(a, m);
233
232
  return rb_big_norm(a);
234
233
  }
234
+
235
+ #endif
@@ -4,8 +4,4 @@
4
4
  VALUE rb_big_barrett_reduce(VALUE,VALUE,VALUE,int);
5
5
  VALUE rb_big_barrett_mu(VALUE);
6
6
 
7
- BDIGIT montgomery_setup(BDIGIT);
8
- VALUE rb_big_montgomery_reduce(VALUE,VALUE,VALUE,int);
9
- BDIGIT small_montgomery_reduce(BDIGIT_DBL, BDIGIT, BDIGIT);
10
-
11
7
  #endif
@@ -3,7 +3,7 @@ Gem::Specification.new do |gem|
3
3
  gem.homepage = "http://github.com/lomereiter/ruby-numtheory"
4
4
  gem.license = "MIT"
5
5
  gem.summary = "Ruby number theory library"
6
- gem.version = "0.0.6"
6
+ gem.version = "0.0.7"
7
7
  gem.platform = Gem::Platform::RUBY
8
8
 
9
9
  gem.description = <<-EOF
@@ -0,0 +1,31 @@
1
+ require 'numtheory'
2
+
3
+ describe "arithmetic function" do
4
+ include NumTheory
5
+
6
+ describe "primepi" do
7
+ it "should raise ArgumentError if there're not enough precomputed primes" do
8
+ expect { primepi(100_000_000_000) }.should raise_error
9
+ end
10
+
11
+ it "should return the number of primes less or equal than a given number" do
12
+ primepi(1).should == 0
13
+ primepi(2).should == 1
14
+ primepi(123512).should == 11607
15
+ primepi(498765).should == 41438
16
+ primepi(312361).should == 26983
17
+ primepi(-123513).should == 0
18
+ end
19
+ end
20
+
21
+ describe "eulerphi" do
22
+ it "should raise ArgumentError if the number is zero" do
23
+ expect { eulerphi(0) }.should raise_error
24
+ end
25
+
26
+ it "should return the number of positive integers less than 'n' and coprime with 'n'" do
27
+ eulerphi(12312361361).should == 11664342324
28
+ eulerphi(12361212371236123).should == 11713214239144000
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ require 'numtheory'
2
+
3
+ describe "bit functions" do
4
+ describe "popcount" do
5
+ it "should return the number of bits set in a non-negative number" do
6
+ 12351231231235091328209183029825132908123295012351.popcount.should == 84
7
+ 82362346211236.popcount.should == 23
8
+ end
9
+
10
+ it "should raise ArgumentError for negative numbers" do
11
+ expect { (-5).popcount }.should raise_error
12
+ expect { (-112351235123512351235).popcount }.should raise_error
13
+ end
14
+ end
15
+
16
+ describe "bitlength" do
17
+ it "should return the length of a positive number in bits" do
18
+ 123512351235125312.bitlength.should == 57
19
+ 12355312.bitlength.should == 24
20
+ 9123616312361235523462346311236136123123136212361.bitlength.should == 163
21
+ end
22
+
23
+ it "should return 1 when argument is 0" do
24
+ 0.bitlength.should == 1
25
+ end
26
+
27
+ it "should raise ArgumentError for negative numbers" do
28
+ expect { (-12351).bitlength }.should raise_error
29
+ expect { (-2039462306492384059132).bitlength }.should raise_error
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,64 @@
1
+ require 'numtheory'
2
+
3
+ describe "Z/pZ" do
4
+
5
+ describe "modular inverse" do
6
+ it "should raise ArgumentError if the inverse doesn't exist" do
7
+ expect { 3.inverse(1236123) }.should raise_error
8
+ expect { 636356661312236113261221231.inverse(71324141236123712312361347131) }.should raise_error
9
+ end
10
+
11
+ it "should return the inverse modulo 'p' if it exists" do
12
+ 170149610396103139612301.inverse(91023960139513512035130519351035).should == 47319168690720853552108144675271
13
+ 10239613261.inverse(1713461351236).should == 1314959799745
14
+ 61235.inverse(13271).should == 10552
15
+ end
16
+ end
17
+
18
+ describe "jacobi symbol (a|n)" do
19
+ it "should raise ArgumentError for negative 'n'" do
20
+ expect { 23.jacobi(-15) }.should raise_error
21
+ end
22
+
23
+ it "should raise ArgumentError for even 'n'" do
24
+ expect { 17.jacobi(24) }.should raise_error
25
+ end
26
+
27
+ it "should return 0 when 'a' and 'n' have common divisors" do
28
+ 25.jacobi(35).should be_zero
29
+ -24.jacobi(9).should be_zero
30
+ 33.jacobi(3).should be_zero
31
+ 128367169183989283691832619381.jacobi(1829631238193612396183612312361231123).should be_zero
32
+ end
33
+
34
+ it "should return 1 when 'a' is a square residue modulo 'n'" do
35
+ 26.jacobi(25).should == 1
36
+ 261235125312351.jacobi(251235123123512351).should == 1
37
+ 123412354123123512351235123512455123.jacobi(12351231236123112351235123523513411).should == 1
38
+ end
39
+
40
+ it "should return -1 in all the other cases" do
41
+ 123412354123123512351235123512455123.jacobi(1235123123612311235123512352351341).should == -1
42
+ 1386136123613661.jacobi(19381923138198391).should == -1
43
+ 2.jacobi(5).should == -1
44
+ 17.jacobi(23).should == -1
45
+ end
46
+ end
47
+
48
+ describe "square root" do
49
+
50
+ it "should raise ArgumentError if 'p' is not a prime number" do
51
+ expect { 7.sqrt_mod(9)}.should raise_error
52
+ end
53
+
54
+ it "should return nil if there is no square root" do
55
+ 33.sqrt_mod(3).should be_nil
56
+ 1231356123521351251.sqrt_mod(123061236013903516123121612316123612379).should be_nil
57
+ end
58
+
59
+ it "should otherwise return the square root from range [0 .. p/2]" do
60
+ 1235112351311.sqrt_mod(123061936032513553).should == 20377270042474840
61
+ 910836013912301293612035135.sqrt_mod(45734753461235122313131523613612412341612361691).should == 17194653522779996910096883279884862754880186510
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,44 @@
1
+ require 'numtheory'
2
+
3
+ describe "primality tests" do
4
+
5
+ describe "prime? method" do
6
+ it "should return exact result for precomputed values" do
7
+ 0.should_not be_prime
8
+ 1.should_not be_prime
9
+ 2.should be_prime
10
+ 3.should be_prime
11
+ 9.should_not be_prime
12
+ -1.should_not be_prime
13
+ -2.should be_prime
14
+ -13.should be_prime
15
+ -16.should_not be_prime
16
+ end
17
+
18
+ it "should apply BPSW test for larger values" do
19
+ 12351236123627.should_not be_prime
20
+ 12351236123659.should be_prime
21
+ 12351236123627123612361235012532906135124234123512356123512342219.should_not be_prime
22
+ 12351236123627123612361235012532906135124234123512356123512342221.should be_prime
23
+ end
24
+
25
+ it "should return true for BPSW pseudoprimes" do
26
+ # no one is found yet :-)
27
+ end
28
+ end
29
+
30
+ describe "miller-rabin test" do
31
+ it "should perform NumTheory::PrimalityTests rounds of Miller-Rabin test" do
32
+ NumTheory.module_eval { remove_const :PrimalityTests }
33
+ NumTheory::PrimalityTests = 1
34
+ srand(100) # MR test uses random base to start
35
+ 671.should be_MR_pseudoprime
36
+ 671.should_not be_BPSW_pseudoprime
37
+
38
+ NumTheory.module_eval { remove_const :PrimalityTests }
39
+ NumTheory::PrimalityTests = 10
40
+ srand(42)
41
+ 671.should_not be_MR_pseudoprime
42
+ end
43
+ end
44
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ruby-numtheory
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.6
5
+ version: 0.0.7
6
6
  platform: ruby
7
7
  authors:
8
8
  - Artem Tarasov
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-08-27 00:00:00 Z
13
+ date: 2012-08-28 00:00:00 Z
14
14
  dependencies: []
15
15
 
16
16
  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"
@@ -23,6 +23,7 @@ extra_rdoc_files:
23
23
  - ext/numtheory/numtheory.c
24
24
  - LICENSE.txt
25
25
  files:
26
+ - .travis.yml
26
27
  - Gemfile
27
28
  - LICENSE.txt
28
29
  - README.md
@@ -32,7 +33,7 @@ files:
32
33
  - ext/numtheory/extconf.rb
33
34
  - ext/numtheory/numtheory.c
34
35
  - ext/numtheory/numtheory.h
35
- - ext/numtheory/numtheory_macros.c
36
+ - ext/numtheory/numtheory_macros.h
36
37
  - ext/numtheory/powermod.h
37
38
  - ext/numtheory/primes.c
38
39
  - ext/numtheory/primes.h
@@ -40,6 +41,10 @@ files:
40
41
  - ext/numtheory/reduce.c
41
42
  - ext/numtheory/reduce.h
42
43
  - ruby-numtheory.gemspec
44
+ - spec/numtheory/arithmetic_functions_spec.rb
45
+ - spec/numtheory/bit_function_spec.rb
46
+ - spec/numtheory/modular_arithmetic_spec.rb
47
+ - spec/numtheory/primality_tests_spec.rb
43
48
  homepage: http://github.com/lomereiter/ruby-numtheory
44
49
  licenses:
45
50
  - MIT
@@ -53,7 +58,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
53
58
  requirements:
54
59
  - - ">="
55
60
  - !ruby/object:Gem::Version
56
- hash: -228771462311290448
61
+ hash: -4196605072839558477
57
62
  segments:
58
63
  - 0
59
64
  version: "0"