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.
@@ -0,0 +1,25 @@
1
+ #ifndef NUMTHEORY_PRIMES_H
2
+ #define NUMTHEORY_PRIMES_H
3
+
4
+ unsigned long init_sieve(unsigned long max_n); // returns prime_pi(max_n)
5
+
6
+ #define ULONG_SZ sizeof(unsigned long)
7
+
8
+ extern unsigned long *numtheory_is_prime;
9
+ extern unsigned long *numtheory_primes;
10
+
11
+ static inline unsigned long
12
+ is_set(unsigned long* ary, unsigned long n)
13
+ {
14
+ long k = n >> 1;
15
+ return ary[k / ULONG_SZ] & (1 << (k & (ULONG_SZ - 1)));
16
+ }
17
+
18
+ static inline void
19
+ unset_bit(unsigned long* ary, unsigned long n)
20
+ {
21
+ long k = n >> 1;
22
+ ary[k / ULONG_SZ] &= ~(1 << (k & (ULONG_SZ - 1)));
23
+ }
24
+
25
+ #endif
@@ -0,0 +1,63 @@
1
+ #ifndef NUMTHEORY_QUEUE_H
2
+ #define NUMTHEORY_QUEUE_H
3
+
4
+ #include <stdlib.h>
5
+
6
+ typedef struct Node Node;
7
+ struct Node {
8
+ void* val;
9
+ Node* next;
10
+ };
11
+
12
+ typedef struct {
13
+ Node* first;
14
+ Node* last;
15
+ } Queue;
16
+
17
+ static inline Queue* queue_new()
18
+ {
19
+ Queue* q;
20
+ q = malloc(sizeof(Queue));
21
+ q -> first = q -> last = NULL;
22
+ return q;
23
+ }
24
+
25
+ static inline void queue_push(Queue* q, void* elem)
26
+ {
27
+ Node* new_node = malloc(sizeof(Node));
28
+ new_node -> val = elem;
29
+ new_node -> next = NULL;
30
+ if (q -> last)
31
+ {
32
+ q -> last -> next = new_node;
33
+ }
34
+ else
35
+ {
36
+ q -> first = new_node;
37
+ }
38
+ q -> last = new_node;
39
+ }
40
+
41
+ static inline void* queue_pop(Queue* q)
42
+ {
43
+ if (q -> first == NULL)
44
+ {
45
+ return NULL;
46
+ }
47
+ Node* fst_node = q -> first;
48
+ void* elem = fst_node -> val;
49
+ q -> first = fst_node -> next;
50
+ if (q -> first == NULL)
51
+ {
52
+ q -> last = NULL;
53
+ }
54
+ free(fst_node);
55
+ return elem;
56
+ }
57
+
58
+ static inline int queue_empty(Queue* q)
59
+ {
60
+ return q -> first == NULL;
61
+ }
62
+
63
+ #endif
@@ -0,0 +1,234 @@
1
+ #include <string.h>
2
+ #include "numtheory.h"
3
+
4
+ #define MULADD(i, j) \
5
+ __asm__ volatile( \
6
+ "movl %6, %%eax \n\t" \
7
+ "mull %7 \n\t" \
8
+ "addl %%eax, %0 \n\t" \
9
+ "adcl %%edx, %1 \n\t" \
10
+ "adcl $0, %2 \n\t" : \
11
+ "=m"(c0), "=m"(c1), "=m"(c2) : \
12
+ "m"(c0), "m"(c1), "m"(c2), "m"(i), "m"(j) : \
13
+ "%eax","%edx", "%cc");
14
+
15
+ #define BITSPERDIG (SIZEOF_BDIGITS * CHAR_BIT)
16
+ #define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
17
+ #define BIGLO(x) ((BDIGIT)((x) & (BIGRAD - 1)))
18
+
19
+ #define RBIGNUM_SET_LEN(b,l) \
20
+ ((RBASIC(b)->flags & RBIGNUM_EMBED_FLAG) ? \
21
+ (void)(RBASIC(b)->flags = \
22
+ (RBASIC(b)->flags & ~RBIGNUM_EMBED_LEN_MASK) | \
23
+ ((l) << RBIGNUM_EMBED_LEN_SHIFT)) : \
24
+ (void)(RBIGNUM(b)->as.heap.len = (l)))
25
+
26
+ inline static VALUE rshift_digits_inplace(VALUE n, int k)
27
+ {
28
+ if (FIXNUM_P(n)) {
29
+ return INT2FIX(0);
30
+ }
31
+
32
+ BDIGIT* ds = RBIGNUM_DIGITS(n);
33
+ int len = RBIGNUM_LEN(n);
34
+ int i;
35
+ if (len > k)
36
+ {
37
+ memmove(ds, ds + k, SIZEOF_BDIGITS * (len - k));
38
+ RBIGNUM_SET_LEN(n, len - k);
39
+ return n;
40
+ }
41
+ else
42
+ {
43
+ RBIGNUM_SET_LEN(n, 0);
44
+ return n;
45
+ }
46
+ }
47
+
48
+ inline static VALUE power_of_two(int p)
49
+ {
50
+ return rb_big_lshift(rb_int2big(1), INT2FIX(p));
51
+ }
52
+
53
+ static VALUE
54
+ bigmul_low_digits(VALUE x, VALUE y, int digits)
55
+ {
56
+ int xn = RBIGNUM_LEN(x);
57
+ if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
58
+ int yn = RBIGNUM_LEN(y);
59
+
60
+ int all = 0;
61
+ if (digits > xn + yn)
62
+ {
63
+ digits = xn + yn;
64
+ all = 1;
65
+ }
66
+ VALUE z = rb_big_new(digits, 1);
67
+
68
+ BDIGIT* xds = RBIGNUM_DIGITS(x);
69
+ BDIGIT* yds = RBIGNUM_DIGITS(y);
70
+ BDIGIT* zds = RBIGNUM_DIGITS(z);
71
+
72
+ BDIGIT c0,c1,c2; // carry
73
+ int i, j, k, beg, end;
74
+ for (k = c0 = c1 = c2 = 0; k < digits; k++)
75
+ {
76
+ beg = k >= yn - 1 ? k - yn + 1 : 0;
77
+ end = k >= xn ? xn - 1 : k;
78
+ for (i = beg, j = k - beg; i <= end; ++i, --j)
79
+ MULADD(xds[i], yds[j]);
80
+ zds[k] = c0;
81
+ c0 = c1;
82
+ c1 = c2;
83
+ c2 = 0;
84
+ }
85
+ return rb_big_norm(z);
86
+ }
87
+ /*
88
+ VALUE bigmul_low_digits_old(VALUE x, VALUE y, int digits)
89
+ {
90
+ int xn = RBIGNUM_LEN(x);
91
+ if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
92
+ int yn = RBIGNUM_LEN(y);
93
+ VALUE z = rb_big_new(digits, 1);
94
+ BDIGIT* xds = RBIGNUM_DIGITS(x);
95
+ BDIGIT* yds = RBIGNUM_DIGITS(y);
96
+ BDIGIT* zds = RBIGNUM_DIGITS(z);
97
+
98
+ int i, j, k;
99
+ for (i = 0; i < digits; zds[i++] = 0);
100
+ BDIGIT_DBL dd, carry;
101
+ for (i = 0; i < xn; ++i)
102
+ {
103
+ dd = xds[i];
104
+ carry = 0;
105
+ k = digits - i;
106
+ if (k > yn) k = yn;
107
+ for (j = 0; j < k; ++j)
108
+ {
109
+ carry += dd * yds[j] + zds[i + j];
110
+ zds[i + j] = BIGLO(carry);
111
+ carry >>= BITSPERDIG;
112
+ }
113
+ if (carry && (i + j) < digits)
114
+ zds[i + j] = carry;
115
+ }
116
+ return rb_big_norm(z);
117
+ } */
118
+
119
+ static VALUE
120
+ bigmul_high_digits(VALUE x, VALUE y, int dontcare, int x_right_shift)
121
+ {
122
+ int xn = RBIGNUM_LEN(x);
123
+ if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
124
+ int yn = RBIGNUM_LEN(y);
125
+
126
+
127
+ BDIGIT* xds = RBIGNUM_DIGITS(x);
128
+ BDIGIT* yds = RBIGNUM_DIGITS(y);
129
+
130
+ /* in order to avoid rb_big_clone call,
131
+ let's virtually "shift" x instead of actual shifting */
132
+ if (x_right_shift >= xn) {
133
+ return rb_int2big(0);
134
+ } else {
135
+ xds += x_right_shift;
136
+ xn -= x_right_shift;
137
+ }
138
+
139
+ int digits = xn + yn;
140
+ int i, j, k;
141
+ VALUE z = rb_big_new(digits, 1);
142
+ BDIGIT* zds = RBIGNUM_DIGITS(z);
143
+ for (i = 0; i < digits; zds[i++] = 0);
144
+
145
+ int beg, end;
146
+
147
+ BDIGIT c0, c1, c2;
148
+ for (k = dontcare, c0 = c1 = c2 = 0; k < digits; k++)
149
+ {
150
+ beg = k >= yn - 1 ? k - yn + 1 : 0;
151
+ end = k >= xn ? xn - 1 : k;
152
+ for (i = beg, j = k - beg; i <= end; ++i, --j)
153
+ MULADD(xds[i], yds[j]);
154
+ zds[k] = c0;
155
+ c0 = c1;
156
+ c1 = c2;
157
+ c2 = 0;
158
+ }
159
+ return z;
160
+ }
161
+
162
+ /*
163
+ VALUE bigmul_high_digits_old(VALUE x, VALUE y, int dontcare)
164
+ {
165
+ int xn = RBIGNUM_LEN(x);
166
+ if (FIXNUM_P(y)) y = rb_int2big(FIX2LONG(y));
167
+ int yn = RBIGNUM_LEN(y);
168
+ VALUE z = rb_big_new(xn + yn, 1);
169
+ BDIGIT* xds = RBIGNUM_DIGITS(x);
170
+ BDIGIT* yds = RBIGNUM_DIGITS(y);
171
+ BDIGIT* zds = RBIGNUM_DIGITS(z);
172
+
173
+ int i, j, k;
174
+ for (i = 0; i < xn + yn; zds[i++] = 0);
175
+ BDIGIT_DBL dd, carry;
176
+ for (i = 0; i < xn; ++i)
177
+ {
178
+ dd = xds[i];
179
+ carry = 0;
180
+ k = dontcare - i;
181
+ if (k < 0) k = 0;
182
+ for (j = k; j < yn; ++j)
183
+ {
184
+ carry += dd * yds[j] + zds[i + j];
185
+ zds[i + j] = BIGLO(carry);
186
+ carry >>= BITSPERDIG;
187
+ }
188
+ if (i+j >= dontcare)
189
+ zds[i+j] = carry;
190
+ }
191
+ return z;
192
+ }*/
193
+
194
+
195
+ VALUE rb_big_barrett_mu(VALUE m)
196
+ {
197
+ long len = RBIGNUM_LEN(m);
198
+ return rb_big_div(power_of_two(2 * len * BITSPERDIG), m);
199
+ }
200
+
201
+ VALUE rb_big_barrett_reduce(VALUE x, VALUE m, VALUE mu, int inplace)
202
+ {
203
+ if (!NEGATIVE_P(x) && MORE(m, x))
204
+ {
205
+ return x;
206
+ }
207
+ unsigned long len = RBIGNUM_LEN(m); /* >= 1 */
208
+ if (FIXNUM_P(x))
209
+ {
210
+ return FIX2LONG(x) >= 0 ? x : rb_big_plus(m, x);
211
+ }
212
+
213
+ VALUE q = bigmul_high_digits(x, mu, len - 1, len - 1);
214
+ /* q is not normed */
215
+ q = rshift_digits_inplace(q, len + 1);
216
+ /* [x/m] - 3 <= q <= [x/m] */
217
+ q = bigmul_low_digits(q, m, len + 1);
218
+ /* q is normed */
219
+
220
+ VALUE a = inplace ? x : rb_big_clone(x);
221
+ if (RBIGNUM_LEN(a) > (long)len + 1)
222
+ {
223
+ RBIGNUM_SET_LEN(a, len + 1);
224
+ }
225
+
226
+ a = rb_big_minus(a, q);
227
+ if (NEGATIVE_P(a))
228
+ a = ADD(a, power_of_two((len + 1) * BITSPERDIG));
229
+ /* a = (x - q * m) mod (base ** (len + 1)) */
230
+
231
+ while (!MORE(m, a)) /* that is, m <= a */
232
+ a = SUB(a, m);
233
+ return rb_big_norm(a);
234
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef NUMTHEORY_REDUCE_H
2
+ #define NUMTHEORY_REDUCE_H
3
+
4
+ VALUE rb_big_barrett_reduce(VALUE,VALUE,VALUE,int);
5
+ VALUE rb_big_barrett_mu(VALUE);
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
+ #endif
@@ -0,0 +1,24 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = "ruby-numtheory"
3
+ gem.homepage = "http://github.com/lomereiter/ruby-numtheory"
4
+ gem.license = "MIT"
5
+ gem.summary = "Ruby number theory library"
6
+ gem.version = "0.0.6"
7
+ gem.platform = Gem::Platform::RUBY
8
+
9
+ gem.description = <<-EOF
10
+ The library is written as C extension and aims to provide
11
+ common number-theoretical functions such as powermod, jacobi symbol,
12
+ various multiplicative ones, etc.
13
+ EOF
14
+
15
+ gem.email = "lomereiter@gmail.com"
16
+ gem.authors = ["Artem Tarasov"]
17
+
18
+ gem.extensions = FileList["ext/numtheory/extconf.rb"]
19
+ gem.require_path = 'ext'
20
+ gem.files = `git ls-files`.split("\n")
21
+
22
+ gem.has_rdoc = true
23
+ gem.extra_rdoc_files = ["ext/numtheory/numtheory.c", "LICENSE.txt"]
24
+ end
metadata CHANGED
@@ -1,24 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-numtheory
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 0
8
- - 5
9
- version: 0.0.5
4
+ prerelease:
5
+ version: 0.0.6
10
6
  platform: ruby
11
7
  authors:
12
- - lomereiter
8
+ - Artem Tarasov
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
12
 
17
- date: 2011-05-27 00:00:00 +04:00
18
- default_executable:
13
+ date: 2012-08-27 00:00:00 Z
19
14
  dependencies: []
20
15
 
21
- 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"
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"
22
17
  email: lomereiter@gmail.com
23
18
  executables: []
24
19
 
@@ -26,40 +21,52 @@ extensions:
26
21
  - ext/numtheory/extconf.rb
27
22
  extra_rdoc_files:
28
23
  - ext/numtheory/numtheory.c
24
+ - LICENSE.txt
29
25
  files:
30
- - ext/numtheory/numtheory.c
26
+ - Gemfile
27
+ - LICENSE.txt
28
+ - README.md
29
+ - Rakefile
30
+ - ext/numtheory/Makefile
31
+ - ext/numtheory/constants.h
31
32
  - ext/numtheory/extconf.rb
32
- has_rdoc: true
33
- homepage: http://code.google.com/p/ruby-numtheory
34
- licenses: []
35
-
33
+ - ext/numtheory/numtheory.c
34
+ - ext/numtheory/numtheory.h
35
+ - ext/numtheory/numtheory_macros.c
36
+ - ext/numtheory/powermod.h
37
+ - ext/numtheory/primes.c
38
+ - ext/numtheory/primes.h
39
+ - ext/numtheory/queue.h
40
+ - ext/numtheory/reduce.c
41
+ - ext/numtheory/reduce.h
42
+ - ruby-numtheory.gemspec
43
+ homepage: http://github.com/lomereiter/ruby-numtheory
44
+ licenses:
45
+ - MIT
36
46
  post_install_message:
37
47
  rdoc_options: []
38
48
 
39
49
  require_paths:
40
- - lib
50
+ - ext
41
51
  required_ruby_version: !ruby/object:Gem::Requirement
42
52
  none: false
43
53
  requirements:
44
54
  - - ">="
45
55
  - !ruby/object:Gem::Version
56
+ hash: -228771462311290448
46
57
  segments:
47
- - 1
48
- - 9
49
58
  - 0
50
- version: 1.9.0
59
+ version: "0"
51
60
  required_rubygems_version: !ruby/object:Gem::Requirement
52
61
  none: false
53
62
  requirements:
54
63
  - - ">="
55
64
  - !ruby/object:Gem::Version
56
- segments:
57
- - 0
58
65
  version: "0"
59
66
  requirements: []
60
67
 
61
68
  rubyforge_project:
62
- rubygems_version: 1.3.7
69
+ rubygems_version: 1.8.24
63
70
  signing_key:
64
71
  specification_version: 3
65
72
  summary: Ruby number theory library