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.
@@ -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