better_prime 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,15 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |s|
4
+ s.name = "better_prime"
5
+ s.summary = "An Uber-fast primality testing library."
6
+ s.email = "burke@burkelibbey.org"
7
+ s.homepage = "http://github.com/burke/better_prime"
8
+ s.description = "An Uber-fast primality testing library."
9
+ s.authors = ["Burke Libbey", "Ryan Neufeld"]
10
+ s.files = FileList["[A-Z]*", "{src,ext,lib}/**/*"]
11
+ s.extensions = ["ext/extconf.rb"]
12
+ end
13
+ rescue LoadError
14
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
15
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,157 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin10.0
8
+ hdrdir = $(topdir)
9
+ VPATH = $(srcdir):$(topdir):$(hdrdir)
10
+ exec_prefix = $(prefix)
11
+ prefix = $(DESTDIR)/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr
12
+ sharedstatedir = $(prefix)/com
13
+ mandir = $(DESTDIR)/usr/share/man
14
+ psdir = $(docdir)
15
+ oldincludedir = $(DESTDIR)/usr/include
16
+ localedir = $(datarootdir)/locale
17
+ bindir = $(exec_prefix)/bin
18
+ libexecdir = $(exec_prefix)/libexec
19
+ sitedir = $(DESTDIR)/Library/Ruby/Site
20
+ htmldir = $(docdir)
21
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
22
+ includedir = $(prefix)/include
23
+ infodir = $(DESTDIR)/usr/share/info
24
+ vendorlibdir = $(vendordir)/$(ruby_version)
25
+ sysconfdir = $(prefix)/etc
26
+ libdir = $(exec_prefix)/lib
27
+ sbindir = $(exec_prefix)/sbin
28
+ rubylibdir = $(libdir)/ruby/$(ruby_version)
29
+ docdir = $(datarootdir)/doc/$(PACKAGE)
30
+ dvidir = $(docdir)
31
+ vendordir = $(libdir)/ruby/vendor_ruby
32
+ datarootdir = $(prefix)/share
33
+ pdfdir = $(docdir)
34
+ archdir = $(rubylibdir)/$(arch)
35
+ sitearchdir = $(sitelibdir)/$(sitearch)
36
+ datadir = $(datarootdir)
37
+ localstatedir = $(prefix)/var
38
+ sitelibdir = $(sitedir)/$(ruby_version)
39
+
40
+ CC = gcc
41
+ LIBRUBY = $(LIBRUBY_SO)
42
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
43
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
44
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)
45
+
46
+ RUBY_EXTCONF_H =
47
+ CFLAGS = -fno-common -arch i386 -arch x86_64 -g -Os -pipe -fno-common -DENABLE_DTRACE -fno-common -pipe -fno-common $(cflags)
48
+ INCFLAGS = -I. -I$(topdir) -I$(hdrdir) -I$(srcdir)
49
+ DEFS =
50
+ CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
51
+ CXXFLAGS = $(CFLAGS)
52
+ ldflags = -L. -arch i386 -arch x86_64
53
+ dldflags =
54
+ archflag =
55
+ DLDFLAGS = $(ldflags) $(dldflags) $(archflag)
56
+ LDSHARED = cc -arch i386 -arch x86_64 -pipe -bundle -undefined dynamic_lookup
57
+ AR = ar
58
+ EXEEXT =
59
+
60
+ RUBY_INSTALL_NAME = ruby
61
+ RUBY_SO_NAME = ruby
62
+ arch = universal-darwin10.0
63
+ sitearch = universal-darwin10.0
64
+ ruby_version = 1.8
65
+ ruby = /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby
66
+ RUBY = $(ruby)
67
+ RM = rm -f
68
+ MAKEDIRS = mkdir -p
69
+ INSTALL = /usr/bin/install -c
70
+ INSTALL_PROG = $(INSTALL) -m 0755
71
+ INSTALL_DATA = $(INSTALL) -m 644
72
+ COPY = cp
73
+
74
+ #### End of system configuration section. ####
75
+
76
+ preload =
77
+
78
+ libpath = . $(libdir)
79
+ LIBPATH = -L. -L$(libdir)
80
+ DEFFILE =
81
+
82
+ CLEANFILES = mkmf.log
83
+ DISTCLEANFILES =
84
+
85
+ extout =
86
+ extout_prefix =
87
+ target_prefix =
88
+ LOCAL_LIBS =
89
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl
90
+ SRCS = prime.c
91
+ OBJS = prime.o
92
+ TARGET = better_prime
93
+ DLLIB = $(TARGET).bundle
94
+ EXTSTATIC =
95
+ STATIC_LIB =
96
+
97
+ BINDIR = $(bindir)
98
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
99
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
100
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
101
+
102
+ TARGET_SO = $(DLLIB)
103
+ CLEANLIBS = $(TARGET).bundle $(TARGET).il? $(TARGET).tds $(TARGET).map
104
+ CLEANOBJS = *.o *.a *.s[ol] *.pdb *.exp *.bak
105
+
106
+ all: $(DLLIB)
107
+ static: $(STATIC_LIB)
108
+
109
+ clean:
110
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
111
+
112
+ distclean: clean
113
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
114
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
115
+
116
+ realclean: distclean
117
+ install: install-so install-rb
118
+
119
+ install-so: $(RUBYARCHDIR)
120
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
121
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
122
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
123
+ install-rb: pre-install-rb install-rb-default
124
+ install-rb-default: pre-install-rb-default
125
+ pre-install-rb: Makefile
126
+ pre-install-rb-default: Makefile
127
+ $(RUBYARCHDIR):
128
+ $(MAKEDIRS) $@
129
+
130
+ site-install: site-install-so site-install-rb
131
+ site-install-so: install-so
132
+ site-install-rb: install-rb
133
+
134
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
135
+
136
+ .cc.o:
137
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
138
+
139
+ .cxx.o:
140
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
141
+
142
+ .cpp.o:
143
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
144
+
145
+ .C.o:
146
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) -c $<
147
+
148
+ .c.o:
149
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) -c $<
150
+
151
+ $(DLLIB): $(OBJS)
152
+ @-$(RM) $@
153
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
154
+
155
+
156
+
157
+ $(OBJS): ruby.h defines.h
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ extension_name = 'better_prime'
4
+ dir_config(extension_name)
5
+ create_makefile(extension_name, '.')
@@ -0,0 +1,115 @@
1
+ #include <stdbool.h>
2
+
3
+ #include "ruby.h"
4
+
5
+ typedef unsigned long long ullong;
6
+
7
+ ullong
8
+ expmod(ullong base, ullong exponent, ullong modulus)
9
+ {
10
+ ullong result = 1;
11
+ while(exponent > 0) {
12
+ if ((exponent & 1) == 1) {
13
+ result = (result * base) % modulus;
14
+ }
15
+ exponent >>= 1;
16
+ base = (base * base) % modulus;
17
+ }
18
+ return result;
19
+ }
20
+
21
+ VALUE
22
+ mrprime(VALUE obj)
23
+ {
24
+ rb_require("better_prime/mr_prime");
25
+ VALUE mrprime = rb_define_class("MR_Prime", rb_cObject);
26
+ return rb_funcall(mrprime, rb_intern("[]"), 1, obj);
27
+ }
28
+
29
+ /* Miller-Rabin algorithm to determine primality of a number.
30
+ * Uses values for a that guarantee correct results up to 314T.
31
+ * Above that, uses ryan@ryanneufeld.ca's Mr.Prime.
32
+ */
33
+ VALUE
34
+ integer_is_prime(VALUE self)
35
+ {
36
+ if (!FIXNUM_P(self)) {
37
+ return mrprime(self);
38
+ }
39
+
40
+ ullong n = NUM2ULL(self);
41
+
42
+ int *primes;
43
+ int nprimes;
44
+ int k, i, j;
45
+ ullong m, b;
46
+ bool prime;
47
+
48
+ static int primes_1[] = {2, 3};
49
+ static int primes_2[] = {31, 73};
50
+ static int primes_3[] = {2, 7, 61};
51
+ static int primes_4[] = {2, 3, 5, 7, 11};
52
+ static int primes_5[] = {2, 3, 5, 7, 11, 13};
53
+ static int primes_6[] = {2, 3, 5, 7, 11, 13, 17};
54
+
55
+ if (n < 2) {
56
+ return Qfalse;
57
+ } else if (n < 4) {
58
+ return Qtrue;
59
+ } else if (n < 1373653) {
60
+ primes = primes_1;
61
+ nprimes = 2;
62
+ } else if (n < 9080191) {
63
+ primes = primes_2;
64
+ nprimes = 2;
65
+ } else if (n < 4759123141ULL) {
66
+ primes = primes_3;
67
+ nprimes = 3;
68
+ } else if (n < 2152302989747ULL) {
69
+ primes = primes_4;
70
+ nprimes = 5;
71
+ } else if (n < 3474749660383ULL) {
72
+ primes = primes_5;
73
+ nprimes = 6;
74
+ } else if (n < 341550071728321ULL) {
75
+ primes = primes_6;
76
+ nprimes = 7;
77
+ } else {
78
+ // Quick, do something sensible!
79
+ return mrprime(self);
80
+ }
81
+
82
+ k = 0;
83
+ m = n - 1;
84
+ while (m & 1) {
85
+ m >>= 1;
86
+ k += 1;
87
+ }
88
+
89
+ for (i = 0; i < nprimes; i++) {
90
+ b = expmod(primes[i], m, n);
91
+
92
+ if (b != 1) {
93
+ prime = false;
94
+ for (j = 0; j < k; j++) {
95
+ if (b == n - 1) {
96
+ prime = true;
97
+ break;
98
+ }
99
+ b = expmod(b, 2, n);
100
+ }
101
+ if (!prime) {
102
+ return Qfalse;
103
+ }
104
+ }
105
+ }
106
+
107
+ return Qtrue;
108
+ }
109
+
110
+ void
111
+ Init_better_prime()
112
+ {
113
+ VALUE cNumeric = rb_define_class("Numeric", rb_cObject);
114
+ rb_define_method(cNumeric, "prime?", integer_is_prime, 0);
115
+ }
@@ -0,0 +1,119 @@
1
+ # Thanks Bruce Schneier for this gem
2
+ def exponent_mod(base,exponent,modulus)
3
+ result = 1;
4
+ while(exponent > 0)
5
+ if ((exponent & 1) == 1)
6
+ result = (result * base) % modulus;
7
+ end
8
+ exponent >>= 1;
9
+ base = (base * base) % modulus;
10
+ end
11
+
12
+ return result;
13
+ end
14
+
15
+
16
+ # Test r&s can reconstitute n properly
17
+ class MR_Prime
18
+ attr_accessor :number
19
+ attr_reader :r,:s,:trials
20
+
21
+ # Allow for easier access to instance of class via MR_Prime[n]
22
+ def self.[](n,opts={})
23
+ MR_Prime.new(n,opts).prime?
24
+ end
25
+
26
+ def self.trials_for_precision(prec)
27
+ k = 1
28
+ while( 1.0 / (4.0 ** k) > prec)
29
+ k += 1
30
+ end
31
+ return k
32
+ end
33
+
34
+ def initialize(n,opts={})
35
+ self.number = n
36
+ set_trials(opts)
37
+ end
38
+
39
+ def witnessed_by?(a)
40
+ result = exponent_mod(a,@s,@number)
41
+ if result == 1
42
+ return true
43
+ else
44
+ 0.upto(@r-1) do |j|
45
+ result = exponent_mod(a,(2**j)*@s,@number)
46
+ if result == -1 or result == @number - 1
47
+ return true
48
+ end
49
+ end
50
+ end
51
+ return false
52
+ end
53
+
54
+ def number=(n)
55
+ @number = n
56
+ resolve_r_and_s
57
+ end
58
+
59
+ def prime?
60
+ witnesses.all? { |a| witnessed_by? a }
61
+ end
62
+
63
+ #private
64
+
65
+ # Set the number of trials to the max of num required for precision, witnesses opt, or 19 (giving at max 1.0e-10 chance of failure)
66
+ def set_trials(opts)
67
+ trials = [19] # default precision of 0.00000000036% chance of failure
68
+ if opts[:precision]
69
+ if opts[:precision] == 0 # Short circuit of absolute precision is required
70
+ @absolute = true
71
+ @trials = -1
72
+ return
73
+ else
74
+ trials.push(MR_Prime.trials_for_precision(opts[:precision]))
75
+ end
76
+ end
77
+ trials.push(opts[:witnesses]) if opts[:witnesses]
78
+ @trials = trials.max
79
+ end
80
+
81
+ # Find R and S such that 2^r * s + 1 == @number (as per MR def'n)
82
+ def resolve_r_and_s
83
+ @r,@s=0,@number-1
84
+ while(@s.even?)
85
+ @r += 1
86
+ @s /= 2
87
+ end
88
+ end
89
+
90
+ # Witnesses require for absoulte certainty for any number < key
91
+ # OR
92
+ # the number of trials specified by :witnesses or :precision arguments
93
+ # Source Wikipedia and "The Primes Page"
94
+ def witnesses
95
+ witnesses = []
96
+ if @number < 1_373_653
97
+ witnesses = [2,3]
98
+ elsif @number < 9_080_191
99
+ witnesses = [31,73]
100
+ elsif @number < 4_759_123_141
101
+ witnesses = [2,7,61]
102
+ elsif @number < 2_152_302_898_747
103
+ witnesses = [2,3,5,7,11]
104
+ elsif @number < 3_474_749_660_383
105
+ witnesses = [2, 3, 5, 7, 11, 13]
106
+ elsif @number < 341_550_071_728_321
107
+ witnesses = [2, 3, 5, 7, 11, 13, 17]
108
+ elsif @precision
109
+ witnesses = (2...@number)
110
+ else
111
+ witnesses = Array.new(@trials).map { rand(@number-1)+1 }
112
+ end
113
+ return witnesses
114
+ end
115
+ end
116
+
117
+ if __FILE__ == $0 and !ARGV.empty?
118
+ puts MR_Prime[ARGV.shift.to_i]
119
+ end
metadata ADDED
@@ -0,0 +1,61 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_prime
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Burke Libbey
8
+ - Ryan Neufeld
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-12-07 00:00:00 -06:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: An Uber-fast primality testing library.
18
+ email: burke@burkelibbey.org
19
+ executables: []
20
+
21
+ extensions:
22
+ - ext/extconf.rb
23
+ extra_rdoc_files: []
24
+
25
+ files:
26
+ - Rakefile
27
+ - VERSION
28
+ - ext/Makefile
29
+ - ext/extconf.rb
30
+ - ext/prime.c
31
+ - lib/better_prime/mr_prime.rb
32
+ has_rdoc: true
33
+ homepage: http://github.com/burke/better_prime
34
+ licenses: []
35
+
36
+ post_install_message:
37
+ rdoc_options:
38
+ - --charset=UTF-8
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ version:
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ requirements: []
54
+
55
+ rubyforge_project:
56
+ rubygems_version: 1.3.5
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: An Uber-fast primality testing library.
60
+ test_files: []
61
+