ruby-numtheory 0.0.5 → 0.0.6

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/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "rake", ">= 0.9"
5
+ gem "rspec", "~> 2.10.0"
6
+ gem "bundler", ">= 1.0.0"
7
+ gem "rake-compiler"
8
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Artem Tarasov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # ruby-numtheory
2
+
3
+ The library is written as C extension and aims to provide fast implementations of common number-theoretical algorithms.
4
+
5
+ ## Currently implemented
6
+
7
+ * powermod (uses sliding window exponentiation)
8
+ * miller-rabin test for primality
9
+ * standard BPSW primality test
10
+ * eratosthenes sieve
11
+ * factorization (via trial division)
12
+ * factorial (uses PrimeSwing algorithm)
13
+ * sigma (σ)
14
+ * moebius (μ)
15
+ * eulerphi (φ)
16
+ * primepi (π)
17
+ * fibonacci
18
+ * modular inverse
19
+ * extended gcd
20
+ * primitive pythagorean triple generator
21
+ * integer square root
22
+ * square root in Z/pZ (for prime p)
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ spec = Gem::Specification.load('ruby-numtheory.gemspec')
15
+
16
+ require 'rspec/core'
17
+ require 'rspec/core/rake_task'
18
+ RSpec::Core::RakeTask.new(:spec) do |spec|
19
+ spec.pattern = FileList["spec/**/*_spec.rb"]
20
+ end
21
+
22
+ task :test => :spec
23
+ task :default => :test
24
+
25
+ require 'rubygems/package_task'
26
+ Gem::PackageTask.new(spec) do |pkg|
27
+ end
28
+
29
+ task :build => :gem
30
+
31
+ require 'rake/extensiontask'
32
+ Rake::ExtensionTask.new('numtheory', spec) do |ext|
33
+ ext.cross_compile = true
34
+ end
@@ -0,0 +1,187 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /usr/local/include/ruby-1.9.1
8
+ hdrdir = /usr/local/include/ruby-1.9.1
9
+ arch_hdrdir = /usr/local/include/ruby-1.9.1/$(arch)
10
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
11
+ prefix = $(DESTDIR)/usr/local
12
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
13
+ exec_prefix = $(prefix)
14
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
15
+ sitehdrdir = $(rubyhdrdir)/site_ruby
16
+ rubyhdrdir = $(includedir)/$(RUBY_BASE_NAME)-$(ruby_version)
17
+ vendordir = $(rubylibprefix)/vendor_ruby
18
+ sitedir = $(rubylibprefix)/site_ruby
19
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
20
+ mandir = $(datarootdir)/man
21
+ localedir = $(datarootdir)/locale
22
+ libdir = $(exec_prefix)/lib
23
+ psdir = $(docdir)
24
+ pdfdir = $(docdir)
25
+ dvidir = $(docdir)
26
+ htmldir = $(docdir)
27
+ infodir = $(datarootdir)/info
28
+ docdir = $(datarootdir)/doc/$(PACKAGE)
29
+ oldincludedir = $(DESTDIR)/usr/include
30
+ includedir = $(prefix)/include
31
+ localstatedir = $(prefix)/var
32
+ sharedstatedir = $(prefix)/com
33
+ sysconfdir = $(prefix)/etc
34
+ datadir = $(datarootdir)
35
+ datarootdir = $(prefix)/share
36
+ libexecdir = $(exec_prefix)/libexec
37
+ sbindir = $(exec_prefix)/sbin
38
+ bindir = $(exec_prefix)/bin
39
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
40
+ archdir = $(rubylibdir)/$(arch)
41
+ sitelibdir = $(sitedir)/$(ruby_version)
42
+ sitearchdir = $(sitelibdir)/$(sitearch)
43
+ vendorlibdir = $(vendordir)/$(ruby_version)
44
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
45
+
46
+ CC = gcc
47
+ CXX = g++
48
+ LIBRUBY = $(LIBRUBY_A)
49
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
50
+ LIBRUBYARG_SHARED = -Wl,-R -Wl,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)
51
+ LIBRUBYARG_STATIC = -Wl,-R -Wl,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static
52
+ OUTFLAG = -o
53
+ COUTFLAG = -o
54
+
55
+ RUBY_EXTCONF_H =
56
+ cflags = $(optflags) $(debugflags) $(warnflags)
57
+ optflags = -O3
58
+ debugflags = -ggdb
59
+ warnflags = -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long
60
+ CFLAGS = -fPIC $(cflags)
61
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
62
+ DEFS = -D_FILE_OFFSET_BITS=64
63
+ CPPFLAGS = $(DEFS) $(cppflags)
64
+ CXXFLAGS = $(CFLAGS) $(cxxflags)
65
+ ldflags = -L. -rdynamic -Wl,-export-dynamic
66
+ dldflags =
67
+ ARCH_FLAG =
68
+ DLDFLAGS = $(ldflags) $(dldflags)
69
+ LDSHARED = $(CC) -shared
70
+ LDSHAREDXX = $(CXX) -shared
71
+ AR = ar
72
+ EXEEXT =
73
+
74
+ RUBY_BASE_NAME = ruby
75
+ RUBY_INSTALL_NAME = ruby
76
+ RUBY_SO_NAME = ruby
77
+ arch = i686-linux
78
+ sitearch = $(arch)
79
+ ruby_version = 1.9.1
80
+ ruby = /usr/local/bin/ruby
81
+ RUBY = $(ruby)
82
+ RM = rm -f
83
+ RM_RF = $(RUBY) -run -e rm -- -rf
84
+ RMDIRS = $(RUBY) -run -e rmdir -- -p
85
+ MAKEDIRS = /bin/mkdir -p
86
+ INSTALL = /usr/bin/install -c
87
+ INSTALL_PROG = $(INSTALL) -m 0755
88
+ INSTALL_DATA = $(INSTALL) -m 644
89
+ COPY = cp
90
+
91
+ #### End of system configuration section. ####
92
+
93
+ preload =
94
+
95
+ libpath = . $(libdir)
96
+ LIBPATH = -L. -L$(libdir) -Wl,-R$(libdir)
97
+ DEFFILE =
98
+
99
+ CLEANFILES = mkmf.log
100
+ DISTCLEANFILES =
101
+ DISTCLEANDIRS =
102
+
103
+ extout =
104
+ extout_prefix =
105
+ target_prefix =
106
+ LOCAL_LIBS =
107
+ LIBS = -lpthread -lrt -ldl -lcrypt -lm -lc
108
+ SRCS = numtheory_macros.c primes.c queue.c reduce.c numtheory.c
109
+ OBJS = numtheory_macros.o primes.o queue.o reduce.o numtheory.o
110
+ TARGET = numtheory
111
+ DLLIB = $(TARGET).so
112
+ EXTSTATIC =
113
+ STATIC_LIB =
114
+
115
+ BINDIR = $(bindir)
116
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
117
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
118
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
119
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
120
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
121
+
122
+ TARGET_SO = $(DLLIB)
123
+ CLEANLIBS = $(TARGET).so
124
+ CLEANOBJS = *.o *.bak
125
+
126
+ all: $(DLLIB)
127
+ static: $(STATIC_LIB)
128
+ .PHONY: all install static install-so install-rb
129
+ .PHONY: clean clean-so clean-rb
130
+
131
+ clean-rb-default::
132
+ clean-rb::
133
+ clean-so::
134
+ clean: clean-so clean-rb-default clean-rb
135
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
136
+
137
+ distclean-rb-default::
138
+ distclean-rb::
139
+ distclean-so::
140
+ distclean: clean distclean-so distclean-rb-default distclean-rb
141
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
142
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
143
+ @-$(RMDIRS) $(DISTCLEANDIRS)
144
+
145
+ realclean: distclean
146
+ install: install-so install-rb
147
+
148
+ install-so: $(RUBYARCHDIR)
149
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
150
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
151
+ @-$(MAKEDIRS) $(@D)
152
+ $(INSTALL_PROG) $(DLLIB) $(@D)
153
+ install-rb: pre-install-rb install-rb-default
154
+ install-rb-default: pre-install-rb-default
155
+ pre-install-rb: Makefile
156
+ pre-install-rb-default: Makefile
157
+ $(RUBYARCHDIR):
158
+ $(MAKEDIRS) $@
159
+
160
+ site-install: site-install-so site-install-rb
161
+ site-install-so: install-so
162
+ site-install-rb: install-rb
163
+
164
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
165
+
166
+ .cc.o:
167
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
168
+
169
+ .cxx.o:
170
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
171
+
172
+ .cpp.o:
173
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
174
+
175
+ .C.o:
176
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
177
+
178
+ .c.o:
179
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
180
+
181
+ $(DLLIB): $(OBJS) Makefile
182
+ @-$(RM) $(@)
183
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
184
+
185
+
186
+
187
+ $(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
@@ -0,0 +1,24 @@
1
+ unsigned long long numtheory_small_factorials[] =
2
+ { 1ULL, 1ULL, 2ULL, 6ULL, 24ULL, 120ULL, 720ULL, 5040ULL, 40320ULL,
3
+ 362880ULL, 3628800ULL, 39916800ULL, 479001600ULL, 6227020800ULL,
4
+ 87178291200ULL, 1307674368000ULL, 20922789888000ULL, 355687428096000ULL,
5
+ 6402373705728000ULL, 121645100408832000ULL, 2432902008176640000ULL };
6
+
7
+ unsigned long long numtheory_small_odd_swings[] =
8
+ { 1ULL, 1ULL, 1ULL, 3ULL, 3ULL, 15ULL, 5ULL, 35ULL, 35ULL, 315ULL, 63ULL,
9
+ 693ULL, 231ULL, 3003ULL, 429ULL, 6435ULL, 6435ULL, 109395ULL, 12155ULL,
10
+ 230945ULL, 46189ULL, 969969ULL, 88179ULL, 2028117ULL, 676039ULL, 16900975ULL,
11
+ 1300075ULL, 35102025ULL, 5014575ULL, 145422675ULL, 9694845ULL, 300540195ULL,
12
+ 300540195ULL, 9917826435ULL, 583401555ULL, 20419054425ULL, 2268783825ULL,
13
+ 83945001525ULL, 4418157975ULL, 172308161025ULL, 34461632205ULL,
14
+ 1412926920405ULL, 67282234305ULL, 2893136075115ULL, 263012370465ULL,
15
+ 11835556670925ULL, 514589420475ULL, 24185702762325ULL, 8061900920775ULL,
16
+ 395033145117975ULL, 15801325804719ULL, 805867616040669ULL, 61989816618513ULL,
17
+ 3285460280781189ULL, 121683714103007ULL, 6692604275665385ULL,
18
+ 956086325095055ULL, 54496920530418135ULL, 1879204156221315ULL,
19
+ 110873045217057585ULL, 7391536347803839ULL, 450883717216034179ULL,
20
+ 14544636039226909ULL, 916312070471295267ULL, 916312070471295267ULL };
21
+
22
+ char issquare_mod256[] = { 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 };
23
+
24
+ char issquare_mod255[] = { 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
@@ -1,2 +1,3 @@
1
1
  require 'mkmf'
2
+ $CFLAGS = "-g -O3 -funroll-all-loops -fPIC -pedantic -std=c99"
2
3
  create_makefile 'numtheory'
@@ -1,58 +1,26 @@
1
- #include <ruby.h>
2
- #include <stdio.h>
3
- #include <math.h>
1
+ #include "numtheory.h"
4
2
 
5
3
  #include "primes.h"
6
4
  #include "queue.h"
5
+ #include "reduce.h"
7
6
  #include "numtheory_macros.c"
8
7
  #include "constants.h"
9
8
 
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
9
  static VALUE mNumTheory;
39
10
  static ID primality_tests_ID;
40
11
 
41
- static ID id_rand, id_mod, id_divmod,
42
- id_gcd, id_lcm, id_pow, id_mul;
43
-
44
12
  static unsigned long PRIMES_UPPER_LIMIT = 3141592;
45
13
  static unsigned long NUM_OF_PRIMES;
46
14
 
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);
15
+ const VALUE zero = INT2FIX(0);
16
+ const VALUE one = INT2FIX(1);
17
+ const VALUE two = INT2FIX(2);
18
+ const VALUE three = INT2FIX(3);
19
+ const VALUE four = INT2FIX(4);
20
+ const VALUE five = INT2FIX(5);
21
+ const VALUE six = INT2FIX(6);
22
+ const VALUE seven = INT2FIX(7);
23
+ const VALUE eight = INT2FIX(8);
56
24
 
57
25
  /*
58
26
  * The <code>NumTheory</code> module contains basic number-theoretical
@@ -71,6 +39,7 @@ Init_numtheory()
71
39
 
72
40
  id_rand = rb_intern("rand");
73
41
  id_mod = rb_intern("modulo");
42
+ id_div = rb_intern("div");
74
43
  id_divmod = rb_intern("divmod");
75
44
  id_gcd = rb_intern("gcd");
76
45
  id_lcm = rb_intern("lcm");
@@ -180,150 +149,6 @@ numtheory_precompute_primes_upto(VALUE obj, VALUE n)
180
149
  return Qnil;
181
150
  }
182
151
 
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
- #define NEGATE(x) do { if (FIXNUM_P(x)) x = -x; \
221
- else RBIGNUM_SET_SIGN(x, !RBIGNUM_SIGN(x)); } \
222
- while(0);
223
-
224
- inline static VALUE MUL(VALUE x, VALUE y) {
225
- return rb_funcall(x, id_mul, 1, y);
226
- }
227
-
228
- inline static VALUE POW(VALUE b, VALUE p) {
229
- return rb_funcall(b, id_pow, 1, p);
230
- }
231
-
232
- inline static VALUE DIV(VALUE x, VALUE y) {
233
- if (ZERO_P(y))
234
- {
235
- rb_raise(rb_eZeroDivError, "divided by 0");
236
- }
237
- return FIXNUM_P(x) ? FIXNUM_P(y) ?
238
- INT2FIX( FIX2LONG(x) / FIX2LONG(y)) :
239
- zero :
240
- rb_big_div(x, y);
241
- }
242
-
243
- inline static VALUE DIVMOD(VALUE x, VALUE y) {
244
- return rb_funcall(x, id_divmod, 1, y);
245
- }
246
-
247
- inline static VALUE MOD(VALUE x, VALUE y) {
248
- return rb_funcall(x, id_mod, 1, y);
249
- }
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
-
263
- inline static int EQL(VALUE x, VALUE y) {
264
- return (FIXNUM_P(x) && FIXNUM_P(y)) ?
265
- x == y :
266
- rb_big_eq(TO_BIGNUM(x), y) == Qtrue;
267
- }
268
-
269
- inline static int MORE(VALUE x, VALUE y) {
270
- return (FIXNUM_P(x) && FIXNUM_P(y)) ?
271
- FIX2LONG(x) > FIX2LONG(y) :
272
- rb_big_cmp(TO_BIGNUM(x), y) == one;
273
- }
274
-
275
- inline static int LESS(VALUE x, VALUE y) {
276
- return (FIXNUM_P(x) && FIXNUM_P(y)) ?
277
- FIX2LONG(x) < FIX2LONG(y) :
278
- rb_big_cmp(TO_BIGNUM(x), y) == INT2FIX(-1);
279
- }
280
-
281
- inline static int MORE_EQL(VALUE x, VALUE y) {
282
- return (FIXNUM_P(x) && FIXNUM_P(y)) ?
283
- FIX2LONG(x) >= FIX2LONG(y) :
284
- rb_big_cmp(TO_BIGNUM(x), y) != INT2FIX(-1);
285
- }
286
-
287
- inline static VALUE ABS(VALUE x) {
288
- if (FIXNUM_P(x))
289
- return INT2FIX(abs(FIX2LONG(x)));
290
- VALUE v = rb_big_clone(x);
291
- RBIGNUM_SET_SIGN(v, 1);
292
- return v;
293
- }
294
-
295
- inline static int NEGATIVE_P(VALUE x) {
296
- return FIXNUM_P(x) ? FIX2LONG(x) < 0 : RBIGNUM_NEGATIVE_P(x);
297
- }
298
-
299
- inline static VALUE CLONE(VALUE x) {
300
- return FIXNUM_P(x) ? x : rb_big_clone(x);
301
- }
302
-
303
- inline static int INTEGER_P(VALUE x) {
304
- return (TYPE(x) == T_FIXNUM) || (TYPE(x) == T_BIGNUM);
305
- }
306
-
307
- inline static VALUE DOUBLED(VALUE x) {
308
- return FIXNUM_P(x) ? LONG2NUM(FIX2LONG(x) << 1) :
309
- rb_big_lshift(x, one);
310
- }
311
-
312
- inline static VALUE HALF(VALUE x) {
313
- return FIXNUM_P(x) ? INT2FIX(FIX2LONG(x) >> 1) :
314
- rb_big_rshift(x, one);
315
- }
316
-
317
- inline static VALUE RIGHT_SHIFT(VALUE x, int s) {
318
- return FIXNUM_P(x) ? INT2FIX(FIX2LONG(x) >> s) :
319
- rb_big_rshift(x, INT2FIX(s));
320
- }
321
-
322
- #ifdef min
323
- #undef min
324
- #endif
325
- inline static int min(int a, int b) { return a < b ? a : b; }
326
-
327
152
  /*
328
153
  * call-seq:
329
154
  * NumTheory.powermod(base, power, [modulo, one]) -> obj
@@ -362,6 +187,7 @@ numtheory_powermod(int argc, VALUE *argv)
362
187
  }
363
188
 
364
189
  static VALUE int_powermod_sliding_window(VALUE,VALUE,VALUE);
190
+ static VALUE int_powermod_sliding_window_br(VALUE,VALUE,VALUE);
365
191
 
366
192
  /*
367
193
  * call-seq:
@@ -395,19 +221,30 @@ numtheory_int_powermod(VALUE b, VALUE p, VALUE m){
395
221
  {
396
222
  b = MOD(b, m);
397
223
  }
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
- {
224
+ const int SLIDING_WINDOW_THRESHOLD = 4;
225
+ const int BARRETT_REDUCE_THRESHOLD = 4;
226
+
227
+ int use_barrett = 0,
228
+ use_sliding_window = 0;
229
+
230
+ if (!FIXNUM_P(p) && RBIGNUM_LEN(p) >= SLIDING_WINDOW_THRESHOLD)
231
+ use_sliding_window = 1;
232
+
233
+ if (!FIXNUM_P(m) && RBIGNUM_LEN(m) >= BARRETT_REDUCE_THRESHOLD)
234
+ use_barrett = 1;
235
+
236
+ if (use_barrett)
237
+ return int_powermod_sliding_window_br(b, p, m);
238
+
239
+ if (use_sliding_window)
409
240
  return int_powermod_sliding_window(b, p, m);
410
- }
241
+
242
+ VALUE result = one;
243
+ FOR_BITS(p, result = MUL(result, result),
244
+ {},
245
+ result = MUL(result, b),
246
+ result = MOD(result, m));
247
+ return result;
411
248
  }
412
249
 
413
250
  static int tail_zeros(VALUE n)
@@ -1240,7 +1077,7 @@ numtheory_multiplicative_order(VALUE a, VALUE m)
1240
1077
  return result;
1241
1078
  }
1242
1079
 
1243
- inline VALUE* triple_new(VALUE v1, VALUE v2, VALUE v3)
1080
+ static inline VALUE* triple_new(VALUE v1, VALUE v2, VALUE v3)
1244
1081
  {
1245
1082
  VALUE* v = malloc(sizeof(VALUE)*3);
1246
1083
  v[0] = v1; v[1] = v2; v[2] = v3;
@@ -1327,7 +1164,7 @@ numtheory_popcount(VALUE n)
1327
1164
  return ULONG2NUM(k);
1328
1165
  }
1329
1166
 
1330
- static int
1167
+ int
1331
1168
  int_bitlength(unsigned int v)
1332
1169
  {
1333
1170
  // taken from http://graphics.stanford.edu/~seander/bithacks.html
@@ -1762,83 +1599,10 @@ numtheory_bpsw_pseudoprime_p(VALUE n)
1762
1599
  return lucas_pseudoprime_p(num, one, RIGHT_SHIFT(SUB(one, INT2FIX(d)), 2));
1763
1600
  }
1764
1601
 
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
- }
1602
+ DEFINE_POWERMOD_SLIDING_WINDOW(int_powermod_sliding_window,
1603
+ {},
1604
+ MOD)
1605
+
1606
+ DEFINE_POWERMOD_SLIDING_WINDOW(int_powermod_sliding_window_br,
1607
+ VALUE mu = rb_big_barrett_mu(m),
1608
+ BARRETT_MOD)