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 +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)
|