ruby-numtheory 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +8 -0
- data/LICENSE.txt +20 -0
- data/README.md +22 -0
- data/Rakefile +34 -0
- data/ext/numtheory/Makefile +187 -0
- data/ext/numtheory/constants.h +24 -0
- data/ext/numtheory/extconf.rb +1 -0
- data/ext/numtheory/numtheory.c +45 -281
- data/ext/numtheory/numtheory.h +183 -0
- data/ext/numtheory/numtheory_macros.c +201 -0
- data/ext/numtheory/powermod.h +9 -0
- data/ext/numtheory/primes.c +57 -0
- data/ext/numtheory/primes.h +25 -0
- data/ext/numtheory/queue.h +63 -0
- data/ext/numtheory/reduce.c +234 -0
- data/ext/numtheory/reduce.h +11 -0
- data/ruby-numtheory.gemspec +24 -0
- metadata +29 -22
data/Gemfile
ADDED
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 };
|
data/ext/numtheory/extconf.rb
CHANGED
data/ext/numtheory/numtheory.c
CHANGED
@@ -1,58 +1,26 @@
|
|
1
|
-
#include
|
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
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
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
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
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
|
-
|
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
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
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)
|