abst 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,38 @@
1
+ require_relative 'include/compatibility'
2
+
3
+ module Abst
4
+ ABST_ROOT = File.dirname(__FILE__) + '/'
5
+
6
+ # Integer block byte size
7
+ BASE_BYTE = 1.size
8
+ INFINITY = Float::INFINITY
9
+
10
+ I = Complex::I
11
+ end
12
+
13
+ require_relative 'config'
14
+
15
+ require_relative 'include/bisect'
16
+ require_relative 'include/cache'
17
+
18
+ require_relative 'include/group'
19
+ require_relative 'include/ring'
20
+
21
+ require_relative 'include/array'
22
+ require_relative 'include/complex'
23
+ require_relative 'include/float'
24
+ require_relative 'include/fundamental'
25
+ require_relative 'include/graph'
26
+ require_relative 'include/integer'
27
+ require_relative 'include/prime'
28
+ require_relative 'include/prime_mpqs'
29
+ require_relative 'include/rational'
30
+ require_relative 'include/residue'
31
+ require_relative 'include/sequence'
32
+ require_relative 'include/set'
33
+
34
+ require_relative 'include/vector'
35
+ require_relative 'include/polynomial'
36
+ require_relative 'include/matrix'
37
+
38
+ include Abst if Abst::AUTO_INCLUDE
@@ -0,0 +1,21 @@
1
+ module Abst
2
+ # Precompute primes under the value
3
+ PRIME_CACHE_LIMIT = 1_000_000
4
+
5
+ # System cache files will be created in this directory
6
+ DATA_DIR = ABST_ROOT + 'data/'
7
+
8
+ # User cache files will be created in this directory
9
+ CACHE_DIR = ABST_ROOT + 'cache/'
10
+
11
+ # Cache primes
12
+ PRIMES_LIST = DATA_DIR + 'primes_list'
13
+
14
+ # Bit size of Fixnum
15
+ # integer e s.t. (2 ** e) is not Fixnum and (2 ** e - 1) is Fixnum
16
+ FIXNUM_BIT_SIZE = 30
17
+
18
+ THREAD_NUM = defined?(JRUBY_VERSION) ? 6 : 1
19
+
20
+ AUTO_INCLUDE = false
21
+ end
@@ -0,0 +1,45 @@
1
+ class Array
2
+ def each_coefficient(init = nil)
3
+ return Enumerator.new(self, :each_coefficient, init) unless block_given?
4
+
5
+ init = Array.new(self.size, 0) unless init
6
+ current = init.dup
7
+
8
+ loop do
9
+ yield current.dup
10
+
11
+ # next coef
12
+ self.size.times do |i|
13
+ if self[i] == current[i]
14
+ return if i == self.size - 1
15
+ current[i] = 0
16
+ else
17
+ current[i] += 1
18
+ break
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ def to_set(sortable = true, &compare)
25
+ return SortableSet.new(self, &compare) if sortable
26
+ return Set.new(self)
27
+ end
28
+
29
+ # to_vector
30
+ def to_v(coef_class = nil)
31
+ vector = Abst::Vector(coef_class || self[0].class, self.size)
32
+ return vector.new(self)
33
+ end
34
+
35
+ # to_matrix
36
+ def to_m(coef_class = nil)
37
+ matrix = Abst::Matrix(coef_class || self[0][0].class, self.size, self[0].size)
38
+ return matrix.new(self)
39
+ end
40
+
41
+ # Create integer from factorization of it
42
+ def to_i
43
+ return self.map{|p, e| p ** e}.inject(&:*)
44
+ end
45
+ end
@@ -0,0 +1,95 @@
1
+ module Bisect
2
+ module_function
3
+
4
+ def bisect_left(list, item, lo = 0, hi = list.size)
5
+ if block_given?
6
+ while lo < hi
7
+ i = (lo + hi - 1) >> 1
8
+
9
+ if 0 <= yield(list[i], item)
10
+ hi = i
11
+ else
12
+ lo = i + 1
13
+ end
14
+ end
15
+ else
16
+ while lo < hi
17
+ i = (lo + hi - 1) >> 1
18
+
19
+ if 0 <= (list[i] <=> item)
20
+ hi = i
21
+ else
22
+ lo = i + 1
23
+ end
24
+ end
25
+ end
26
+
27
+ return hi
28
+ end
29
+
30
+ def bisect_right(list, item, lo = 0, hi = list.size)
31
+ if block_given?
32
+ while lo < hi
33
+ i = (lo + hi - 1) >> 1
34
+
35
+ if 0 < yield(list[i], item)
36
+ hi = i
37
+ else
38
+ lo = i + 1
39
+ end
40
+ end
41
+ else
42
+ while lo < hi
43
+ i = (lo + hi - 1) >> 1
44
+
45
+ if 0 < (list[i] <=> item)
46
+ hi = i
47
+ else
48
+ lo = i + 1
49
+ end
50
+ end
51
+ end
52
+
53
+ return lo
54
+ end
55
+
56
+ def insert_left(list, item, lo = 0, hi = list.size, &block)
57
+ i = bisect_left(list, item, lo, hi, &block)
58
+ list.insert(i, item)
59
+ end
60
+
61
+ def insert_right(list, item, lo = 0, hi = list.size, &block)
62
+ i = bisect_right(list, item, lo, hi, &block)
63
+ list.insert(i, item)
64
+ end
65
+
66
+ # Locate the leftmost value exactly equal to item
67
+ def index(list, item, &block)
68
+ i = bisect_left(list, item, &block)
69
+ return list[i] == item ? i : nil
70
+ end
71
+
72
+ # Find rightmost value less than item
73
+ def find_lt(list, item, &block)
74
+ i = bisect_left(list, item, &block)
75
+ return list[i - 1] unless 0 == i
76
+ end
77
+
78
+ # Find rightmost value less than or equal to item
79
+ def find_le(list, item, &block)
80
+ i = bisect_right(list, item, &block)
81
+ return list[i - 1] unless 0 == i
82
+ end
83
+
84
+ # Find leftmost value greater than item
85
+ def find_gt(list, item, &block)
86
+ i = bisect_right(list, item, &block)
87
+ return list[i] unless list.size == i
88
+ end
89
+
90
+ # Find leftmost item greater than or equal to item
91
+ def find_ge(list, item, &block)
92
+ i = bisect_left(list, item, &block)
93
+ return list[i] unless list.size == i
94
+ end
95
+ end
@@ -0,0 +1,60 @@
1
+ module Abst
2
+ class Cache
3
+ PREFIX = 'abst_cache_'
4
+ CACHE_DIR = CACHE_DIR
5
+
6
+ def self.mkdir(dir)
7
+ pdir = File.dirname(dir)
8
+ mkdir(pdir) unless FileTest.exist?(pdir)
9
+ Dir::mkdir(dir)
10
+ end
11
+
12
+ def self.[]=(cache_id, data)
13
+ if nil == data
14
+ delete(cache_id)
15
+ return
16
+ end
17
+
18
+ path = get_path(cache_id)
19
+ dir = File.dirname(path)
20
+
21
+ mkdir(dir) unless FileTest.exist?(dir)
22
+ open(path, "w") {|io| Marshal.dump(data, io)}
23
+ end
24
+
25
+ def self.[](cache_id)
26
+ path = get_path(cache_id)
27
+
28
+ return nil unless FileTest.exist?(path)
29
+ open(path) {|io| return Marshal.load(io)}
30
+ end
31
+
32
+ def self.delete(cache_id)
33
+ path = get_path(cache_id)
34
+
35
+ File.delete(path) if FileTest.exist?(path)
36
+ end
37
+
38
+ def self.clear
39
+ raise NotImplementedError
40
+ end
41
+
42
+ def self.exist?(cache_id)
43
+ return FileTest.exist?(get_path(cache_id))
44
+ end
45
+
46
+ def self.get_path(cache_id)
47
+ cache_id = cache_id.to_s
48
+ unless /^[a-z0-9_]+$/ =~ cache_id
49
+ raise ArgumentError, "Invalid cache_id. (Only a-z 0-9 and _ are available)"
50
+ end
51
+
52
+ return self::CACHE_DIR + self::PREFIX + cache_id
53
+ end
54
+ end
55
+
56
+ class SystemCache < Cache
57
+ PREFIX = ''
58
+ CACHE_DIR = DATA_DIR
59
+ end
60
+ end
@@ -0,0 +1,3 @@
1
+ class Float
2
+ INFINITY = 1 / 0.0 unless defined?(INFINITY)
3
+ end
@@ -0,0 +1,10 @@
1
+ class Complex
2
+ def self.one
3
+ return Complex(1, 0)
4
+ end
5
+
6
+ def self.zero
7
+ return Complex(0, 0)
8
+ end
9
+ end
10
+
@@ -0,0 +1,19 @@
1
+ class Float
2
+ def self.one
3
+ return 1.0
4
+ end
5
+
6
+ def self.zero
7
+ return 0.0
8
+ end
9
+
10
+ def inverse
11
+ return 1.0 / self
12
+ end
13
+
14
+ # Return:: formatted string
15
+ def to_fs
16
+ return self.to_s.gsub(/(?<=\d)(?=(\d\d\d)+\.)/, ' ')
17
+ end
18
+ end
19
+
@@ -0,0 +1,903 @@
1
+ module Abst
2
+ module_function
3
+
4
+ # Right-Left Binary Power
5
+ # Param:: group element g
6
+ # integer n
7
+ # Euclidean domain element mod
8
+ # Return:: g ** n % mod
9
+ def right_left_power(g, n, mod = nil)
10
+ rslt = g.class.one
11
+ return rslt if 0 == n
12
+
13
+ if n < 0
14
+ n = -n
15
+ g **= (-1)
16
+ end
17
+
18
+ g %= mod if mod
19
+
20
+ loop do
21
+ rslt *= g if n.odd?
22
+ rslt %= mod if mod
23
+
24
+ n >>= 1
25
+ break if 0 == n
26
+
27
+ g = g ** 2
28
+ g %= mod if mod
29
+ end
30
+
31
+ return rslt
32
+ end
33
+
34
+ # Left-Right Binary Power
35
+ # Param:: group element g
36
+ # integer n
37
+ # Euclidean domain element mod
38
+ # Return:: g ** n % mod
39
+ def left_right_power(g, n, mod = nil)
40
+ return g.class.one if 0 == n
41
+
42
+ if n < 0
43
+ n = -n
44
+ g **= (-1)
45
+ end
46
+
47
+ g %= mod if mod
48
+ e = ilog2(n)
49
+
50
+ rslt = g
51
+ while 0 != e
52
+ e -= 1
53
+
54
+ rslt *= rslt
55
+ rslt %= mod if mod
56
+
57
+ if 1 == n[e]
58
+ rslt *= g
59
+ rslt %= mod if mod
60
+ end
61
+ end
62
+
63
+ return rslt
64
+ end
65
+ alias power left_right_power
66
+ module_function :power
67
+
68
+ # Left-Right Base 2**k Power
69
+ # Param:: group element g
70
+ # integer n
71
+ # Euclidean domain element mod
72
+ # base bit size k
73
+ # Return:: g ** n % mod
74
+ def left_right_base2k_power(g, n, mod = nil, k = nil)
75
+ rslt = g.class.one
76
+ return rslt if 0 == n
77
+
78
+ # Initialize
79
+ if n < 0
80
+ n = -n
81
+ g **= (-1)
82
+ end
83
+
84
+ g %= mod if mod
85
+
86
+ unless k
87
+ e = ilog2(n)
88
+ optim = [0, 8, 24, 69, 196, 538, 1433, 3714]
89
+
90
+ if e <= optim.last
91
+ k = Bisect.bisect_left(optim, e)
92
+ else
93
+ k = optim.size
94
+ k += 1 until e <= k * (k + 1) * (1 << (k << 1)) / ((1 << (k + 1)) - k - 2)
95
+ end
96
+ end
97
+
98
+ # convert n into base 2**k
99
+ digits = []
100
+ mask = (1 << k) - 1
101
+ until 0 == n
102
+ digits.unshift(n & mask)
103
+ n >>= k
104
+ end
105
+
106
+ # Precomputations
107
+ z_powers = [nil, g]
108
+ g_square = g * g
109
+ g_square %= mod if mod
110
+ 3.step((1 << k) - 1, 2) do |i|
111
+ z_powers[i] = z_powers[i - 2] * g_square
112
+ z_powers[i] %= mod if mod
113
+ end
114
+
115
+ digits.each do |a|
116
+ # Multiply
117
+ if 0 == a
118
+ k.times do
119
+ rslt = rslt ** 2
120
+ rslt %= mod if mod
121
+ end
122
+ else
123
+ t = 0
124
+ t += 1 while 0 == a[t]
125
+ a >>= t if 0 < t
126
+
127
+ (k - t).times do
128
+ rslt = rslt ** 2
129
+ rslt %= mod if mod
130
+ end
131
+ rslt *= z_powers[a]
132
+ rslt %= mod if mod
133
+ t.times do
134
+ rslt = rslt ** 2
135
+ rslt %= mod if mod
136
+ end
137
+ end
138
+ end
139
+
140
+ return rslt
141
+ end
142
+
143
+ # GCD
144
+ # Param:: a and b are member of a Euclidean domain
145
+ # Return:: gcd of a and b
146
+ def gcd(a, b)
147
+ until b.zero?
148
+ a, b = b, a % b
149
+ end
150
+
151
+ return a
152
+ end
153
+
154
+ def lcm(a, b)
155
+ return a * b / gcd(a, b)
156
+ end
157
+
158
+ # Param:: integer a, b
159
+ # Return:: gcd of a and b
160
+ def lehmer_gcd(a, b)
161
+ a = -a if a < 0
162
+ b = -b if b < 0
163
+ a, b = b, a if a < b
164
+
165
+ until 0 == b
166
+ return gcd(a, b) if b.instance_of?(Fixnum)
167
+
168
+ # Get most significant digits of a and b
169
+ shift_size = (a < b ? b : a).bit_size - FIXNUM_BIT_SIZE
170
+ a_ = a >> shift_size
171
+ b_ = b >> shift_size
172
+
173
+ _A = 1
174
+ _B = 0 # a_ == msd(a) * _A + msd(b) * _B
175
+ _C = 0
176
+ _D = 1 # b_ == msd(a) * _C + msd(b) * _D
177
+
178
+ # Always
179
+ # a_ + _B <= msd(a * _A + b * _B) < a_ + _A AND
180
+ # b_ + _C <= msd(a * _C + b * _D) < a_ + _D
181
+ # OR
182
+ # a_ + _B > msd(a * _A + b * _B) >= a_ + _A AND
183
+ # b_ + _C > msd(a * _C + b * _D) >= a_ + _D
184
+
185
+ # Test quotient
186
+ until 0 == b_ + _C or 0 == b_ + _D
187
+ q1 = (a_ + _A) / (b_ + _C)
188
+ q2 = (a_ + _B) / (b_ + _D)
189
+ break if q1 != q2
190
+
191
+ # Euclidean step
192
+ _A, _C = _C, _A - q1 * _C
193
+ _B, _D = _D, _B - q1 * _D
194
+ a_, b_ = b_, a_ - q1 * b_
195
+ end
196
+
197
+ # Multi-precision step
198
+ if 0 == _B
199
+ a, b = b, a % b
200
+ else
201
+ a, b = a * _A + b * _B, a * _C + b * _D
202
+ end
203
+ end
204
+
205
+ return a
206
+ end
207
+
208
+ # Binary GCD
209
+ # Param:: integer a, b
210
+ # Return:: gcd of a and b
211
+ def binary_gcd(a, b)
212
+ a = -a if a < 0
213
+ b = -b if b < 0
214
+ a, b = b, a if a < b
215
+ return a if 0 == b
216
+
217
+ # Reduce size once
218
+ a, b = b, a % b
219
+ return a if 0 == b
220
+
221
+ # Compute powers of 2
222
+ k = 0
223
+ k += 1 while 0 == a[k] and 0 == b[k]
224
+ if 0 < k
225
+ a >>= k
226
+ b >>= k
227
+ end
228
+
229
+ # Remove initial power of 2
230
+ a >>= 1 while a.even?
231
+ b >>= 1 while b.even?
232
+
233
+ loop do
234
+ # Subtract (Here a and b are both odd.)
235
+ t = a - b
236
+ return a << k if 0 == t
237
+
238
+ count = 0
239
+ count += 1 while 0 == t[count]
240
+ t >>= count
241
+
242
+ (0 < t) ? a = t : b = -t
243
+ end
244
+ end
245
+
246
+ # Param:: a and b are member of a Euclidean domain
247
+ # Return:: (u, v, d) s.t. a*u + b*v = gcd(a, b) = d
248
+ def extended_gcd(a, b)
249
+ u0 = a.class.one
250
+ u1 = a.class.zero
251
+
252
+ return u0, u1, a if b.zero?
253
+
254
+ d0 = a # d0 = a * u0 + b * v0
255
+ d1 = b # d1 = a * u1 + b * v1
256
+
257
+ loop do
258
+ q, r = d0.divmod(d1)
259
+
260
+ return u1, (d1 - a * u1) / b, d1 if r.zero?
261
+
262
+ d0, d1 = d1, r
263
+ u0, u1 = u1, u0 - q * u1
264
+ end
265
+ end
266
+
267
+ # Param:: non-negative integer a, b
268
+ # Return:: (u, v, d) s.t. a*u + b*v = gcd(a, b) = d
269
+ def extended_lehmer_gcd(a, b)
270
+ d0 = a
271
+ u0 = 1 # d0 = a * u0 + b * v0
272
+ d1 = b
273
+ u1 = 0 # d1 = a * u1 + b * v1
274
+
275
+ loop do
276
+ if d1.instance_of?(Fixnum)
277
+ _u, _v, d = extended_gcd(d0, d1)
278
+
279
+ # here
280
+ # d == _u * d0 + _v * d1
281
+ # d0 == u0 * a + v0 * b
282
+ # d1 == u1 * a + v1 * b
283
+
284
+ u = _u * u0 + _v * u1
285
+ v = (d - u * a) / b
286
+
287
+ return u, v, d
288
+ end
289
+
290
+ # Get most significant digits of d0 and d1
291
+ shift_size = (d0 < d1 ? d1 : d0).bit_size - FIXNUM_BIT_SIZE
292
+ a_ = d0 >> shift_size
293
+ b_ = d1 >> shift_size
294
+
295
+ # Initialize (Here a_ and b_ are next value of d0, d1)
296
+ _A = 1
297
+ _B = 0 # a_ == msd(d0) * _A + msd(d1) * _B
298
+ _C = 0
299
+ _D = 1 # b_ == msd(d0) * _C + msd(d1) * _D
300
+
301
+ # Test Quotient
302
+ until 0 == b_ + _C or 0 == b_ + _D
303
+ q1 = (a_ + _B) / (b_ + _D)
304
+ q2 = (a_ + _A) / (b_ + _C)
305
+ break if q1 != q2
306
+
307
+ # Euclidean step
308
+ _A, _C = _C, _A - q1 * _C
309
+ _B, _D = _D, _B - q1 * _D
310
+ a_, b_ = b_, a_ - q1 * b_
311
+ end
312
+
313
+ # Multi-precision step
314
+ if 0 == _B
315
+ q, r = d0.divmod(d1)
316
+ d0, d1 = d1, r
317
+ u0, u1 = u1, u0 - q * u1
318
+ else
319
+ d0, d1 = d0 * _A + d1 * _B, d0 * _C + d1 * _D
320
+ u0, u1 =u0 * _A + u1 * _B, u0 * _C + u1 * _D
321
+ end
322
+ end
323
+ end
324
+
325
+ # Param:: non-negative integer a, b
326
+ # Return:: (u, v, d) s.t. a*u + b*v = gcd(a, b) = d
327
+ def extended_binary_gcd(a, b)
328
+ if a < b
329
+ a, b = b, a
330
+ exchange_flag_1 = true
331
+ end
332
+
333
+ if 0 == b
334
+ return 0, 1, a if exchange_flag_1
335
+ return 1, 0, a
336
+ end
337
+
338
+ # Reduce size once
339
+ _Q, r = a.divmod(b)
340
+ if 0 == r
341
+ return 1, 0, b if exchange_flag_1
342
+ return 0, 1, b
343
+ end
344
+ a, b = b, r
345
+
346
+ # Compute power of 2
347
+ _K = 0
348
+ _K += 1 while 0 == a[_K] and 0 == b[_K]
349
+ if 0 < _K
350
+ a >>= _K
351
+ b >>= _K
352
+ end
353
+
354
+ if b.even?
355
+ a, b = b, a
356
+ exchange_flag_2 = true
357
+ end
358
+
359
+ # Initialize
360
+ u = 1
361
+ d = a # d == a * u + b * v, (v = 0)
362
+ u_ = 0
363
+ d_ = b # d_ == a * u_ + b * v_, (v_ = 1)
364
+
365
+ # Remove intial power of 2
366
+ while d.even?
367
+ d >>= 1
368
+ u += b if u.odd?
369
+ u >>= 1
370
+ end
371
+
372
+ loop do
373
+ # Substract
374
+ next_u = u - u_
375
+ next_d = d - d_ # next_d == a * next_u + b * next_v
376
+ next_u += b if next_u < 0
377
+
378
+ break if 0 == next_d
379
+
380
+ # Remove powers of 2
381
+ while next_d.even?
382
+ next_d >>= 1
383
+ next_u += b if next_u.odd?
384
+ next_u >>= 1
385
+ end
386
+
387
+ if 0 < next_d
388
+ u = next_u
389
+ d = next_d
390
+ else
391
+ u_ = b - next_u
392
+ d_ = -next_d
393
+ end
394
+ end
395
+
396
+ v = (d - a * u) / b
397
+
398
+ u, v = v, u if exchange_flag_2
399
+ d <<= _K
400
+ u, v = v, u - v * _Q
401
+ u, v = v, u if exchange_flag_1
402
+
403
+ return u, v, d
404
+ end
405
+
406
+ # Param:: integer n
407
+ # positive integer mod which is reratively prime with n
408
+ # Return:: inverse of n modulo mod. (1 <= inverse < mod)
409
+ def inverse(n, mod)
410
+ u, _, d = extended_gcd(n, mod)
411
+
412
+ raise ArgumentError, 'n and mod must be reratively prime.' unless 1 == d
413
+
414
+ return u % mod
415
+ end
416
+
417
+ # Chinese Remainder Theorem using Algorithm 1.3.12 of [CCANT]
418
+ # Param:: array of pair integer s.t. [[x_1, m_1], [x_2, m_2], ... , [x_k, m_k]]
419
+ # m_i are pairwise coprime
420
+ # Return:: integer x s.t. x = x_i (mod m_i) for all i
421
+ # and 0 <= x < m_1 * m_2 * ... * m_k
422
+ # Example: chinese_remainder_theorem([(1,2),(2,3),(3,5)]) return 23
423
+ def chinese_remainder_theorem(list)
424
+ x, m = list.shift
425
+
426
+ list.each do |xi, mi|
427
+ u, v, = extended_gcd(m, mi)
428
+ x = u * m * xi + v * mi * x
429
+ m *= mi
430
+ x %= m
431
+ end
432
+
433
+ return x
434
+ end
435
+
436
+ # Param:: integer a, b, a_, b_ s.t. (real number x s.t. a/b <= x <= a_/b_)
437
+ # Return:: continueed fraction expansion of x
438
+ # and lower and upper bounds for this next partial quotient.
439
+ # Format: [[continueed fraction expansion...], [lower, upper]]
440
+ def continued_fraction(a, b, a_, b_)
441
+ # Initialize
442
+ q = q_ = nil
443
+ rslt = []
444
+
445
+ until 0 == b or 0 == b_
446
+ # Euclidean step
447
+ q, r = a.divmod(b)
448
+
449
+ r_ = a_ - b_ * q
450
+ if r_ < 0 or b_ <= r_
451
+ q_ = a_ / b_
452
+ break
453
+ end
454
+
455
+ rslt.push(q)
456
+ a , b = b , r
457
+ a_, b_ = b_, r_
458
+ end
459
+
460
+ if 0 == b
461
+ return rslt, [] if 0 == b_
462
+ return rslt, [a_ / b_, INFINITY]
463
+ end
464
+
465
+ return rslt, [a / b, INFINITY] if 0 == b_
466
+
467
+ q, q_ = q_, q if q > q_
468
+ return rslt, [q, q_]
469
+ end
470
+
471
+ # Param:: odd prime p
472
+ # Return:: primitive root modulo p
473
+ def primitive_root(p)
474
+ p_m1 = p - 1
475
+ check_order = factorize(p_m1)
476
+ check_order.shift
477
+ half_p_m1 = p_m1 >> 1
478
+ check_order.map!{|f| half_p_m1 / f.first}
479
+
480
+ a = 1
481
+ loop do
482
+ a += 1
483
+
484
+ next unless -1 == kronecker_symbol(a, p)
485
+ check = true
486
+ check_order.each do |e|
487
+ if p_m1 == power(a, e, p)
488
+ check = false
489
+ break
490
+ end
491
+ end
492
+
493
+ return a if check
494
+ end
495
+ end
496
+
497
+ # Param:: integer n, m
498
+ # Return:: kronecker symbol (n|m)
499
+ def kronecker_symbol(n, m)
500
+ if 0 == m
501
+ return (-1 == n or 1 == n) ? 1 : 0
502
+ end
503
+
504
+ return 0 if n.even? and m.even?
505
+
506
+ m8 = [0, 1, 0, -1, 0, -1, 0, 1]
507
+
508
+ # Remove 2's from m
509
+ count = 0
510
+ count += 1 while 0 == m[count]
511
+ m >>= count
512
+ rslt = count.even? ? 1 : m8[n & 7]
513
+
514
+ if m < 0
515
+ m = -m
516
+ rslt = -rslt if n < 0
517
+ end
518
+ n %= m
519
+
520
+ until 0 == n
521
+ count = 0
522
+ count += 1 while 0 == n[count]
523
+ n >>= count
524
+ rslt *= m8[m & 7] if count.odd?
525
+
526
+ # Apply reciprocity
527
+ rslt = -rslt if 1 == n[1] and 1 == m[1]
528
+ n, m = m % n, n
529
+ end
530
+
531
+ return (1 == m) ? rslt : 0
532
+ end
533
+ alias legendre_symbol kronecker_symbol
534
+ alias jacobi_symbol kronecker_symbol
535
+ module_function :jacobi_symbol, :legendre_symbol
536
+
537
+ # Param:: integer n
538
+ # odd prime p
539
+ # positive integer exp
540
+ # (if 1 < exp then n must be relatively prime with p)
541
+ # Return:: the square root of n mod (p ** exp) if exists else nil
542
+ def mod_sqrt(n, p, exp = 1, return_list = false)
543
+ if 1 < exp or return_list
544
+ x = mod_sqrt(n, p)
545
+ return x unless x
546
+ return [x] if 1 == exp
547
+ raise ArgumentError, "if 1 < exp then n must be relatively prime with p" if 0 == x
548
+
549
+ rslt = [x] if return_list
550
+ p_power = p
551
+ z = extended_lehmer_gcd(x << 1, p)[0]
552
+ (exp - 1).times do
553
+ x += (n - x ** 2) / p_power * z % p * p_power
554
+ p_power *= p
555
+ rslt.push(x) if return_list
556
+ end
557
+
558
+ return return_list ? rslt : x
559
+ end
560
+
561
+ unless (k = kronecker_symbol(n, p)) == 1
562
+ return nil if -1 == k
563
+ return 0
564
+ end
565
+
566
+ if 0 < p & 6
567
+ return power(n, (p >> 2) + 1, p) if p[1] == 1
568
+ n %= p
569
+ x = power(n, (p >> 3) + 1, p)
570
+ return x if x ** 2 % p == n
571
+ return x * power(2, p >> 2, p) % p
572
+ end
573
+
574
+ # get q and e s.t. p - 1 == 2**e * q with q odd
575
+ e = 0
576
+ q = p - 1
577
+ e += 1 while 0 == q[e]
578
+ q >>= e
579
+
580
+ # Find generator
581
+ g = 2
582
+ g += 1 until -1 == kronecker_symbol(g, p)
583
+ z = power(g, q, p) # |<z>| == 2 ** e
584
+
585
+ # Initialize
586
+ temp = power(n, q >> 1, p)
587
+ x = n * temp % p # n ** ((q + 1) / 2) mod p
588
+ b = x * temp % p # n ** q mod p
589
+
590
+ # always
591
+ # n * b == x ** 2
592
+ until 1 == b
593
+ # Find exponent f s.t. b ** (2 ** f) == 1 (mod p)
594
+ f = 0
595
+ b_ = b
596
+ until 1 == b_
597
+ b_ = b_ ** 2 % p
598
+ f += 1
599
+ end
600
+
601
+ # Reduce exponent
602
+ (e - f - 1).times { z = z ** 2 % p }
603
+ e = f
604
+ x = x * z % p
605
+ z = z ** 2 % p
606
+ b = b * z % p
607
+ end
608
+
609
+ return x
610
+ end
611
+
612
+ # Param:: positive integer d
613
+ # prime number p (d < p)
614
+ # Return:: integer solution (x, y) to the Diophantine equation
615
+ # x ** 2 + d * y ** 2 = p if exists else nil
616
+ def cornacchia(d, p)
617
+ return nil if -1 == kronecker_symbol(-d, p)
618
+
619
+ # Compute square root
620
+ x0 = mod_sqrt(-d, p)
621
+ x0 = p - x0 if x0 <= p >> 1
622
+ a = p
623
+ b = x0
624
+ border = isqrt(p)
625
+
626
+ # Euclidean algorithm
627
+ while border < b
628
+ a, b = b, a % b
629
+ end
630
+
631
+ # Test solution
632
+ c, r = (p - b ** 2).divmod(d)
633
+ return nil if 0 != r
634
+
635
+ q = c.square?
636
+ return nil unless q
637
+
638
+ return [b, q]
639
+ end
640
+
641
+ # Param:: d is a negative integer s.t. d = 0 or 1 mod 4
642
+ # prime number p (|d| < 4p)
643
+ # Return:: integer solution (x, y) to the Diophantine equation
644
+ # x ** 2 + |d| * y ** 2 = 4p if exists else nil
645
+ def modified_cornacchia(d, p)
646
+ # Case p == 2
647
+ if 2 == p
648
+ return nil unless q = (d + 8).square?
649
+ return q, 1
650
+ end
651
+
652
+ # Test if residue
653
+ return nil if -1 == kronecker_symbol(d, p)
654
+
655
+ # Compute square root
656
+ x0 = mod_sqrt(d, p)
657
+ x0 = p - x0 if 0 != x0 - d % 2
658
+
659
+ a = p << 1
660
+ b = x0
661
+ l = isqrt(p << 2)
662
+
663
+ # Euclidean algorithm
664
+ a, b = b, a % b while b < l
665
+
666
+ # Test solution
667
+ c, r = (4 * p - b**2).divmod(-d)
668
+ return nil if 0 != r
669
+ return nil unless q = c.square?
670
+ return b, q
671
+ end
672
+
673
+ # Integer Square Root
674
+ # Param:: positive integer n
675
+ # Return:: integer part of the square root of n
676
+ # i.e. the number m s.t. m ** 2 <= n < (m + 1) ** 2
677
+ def isqrt(n)
678
+ x = 1 << ((ilog2(n) >> 1) + 1)
679
+
680
+ loop do
681
+ # Newtonian step
682
+ next_x = (x + n / x) >> 1
683
+ return x if x <= next_x
684
+
685
+ x = next_x
686
+ end
687
+ end
688
+
689
+ # Integer Power Root
690
+ # Param:: positive integer n
691
+ # positive integer pow
692
+ # Return:: integer part of the power root of n
693
+ # i.e. the number m s.t. m ** pow <= n < (m + 1) ** pow
694
+ # if return_power is true then return n ** pow
695
+ def iroot(n, pow, return_power = false)
696
+ # get integer e s.t. (2 ** (e - 1)) ** pow <= n < (2 ** e) ** pow
697
+ e = ilog2(n) / pow + 1 # == Rational(ilog2(n) + 1, pow).ceil
698
+
699
+ x = 1 << e # == 2 ** e
700
+ z = nil
701
+ q = n >> (e * (pow - 1)) # == n / (x ** (pow - 1))
702
+
703
+ loop do
704
+ # Newtonian step
705
+ x += (q - x) / pow
706
+ z = x ** (pow - 1)
707
+ q = n / z
708
+
709
+ break if x <= q
710
+ end
711
+
712
+ return x, x * z if return_power
713
+ return x
714
+ end
715
+
716
+ # Param:: positive integer n > 1
717
+ # Return:: p if n is of the form p^k with p prime else false
718
+ def prime_power?(n)
719
+ if n.even?
720
+ return n.power_of?(2) ? 2 : false
721
+ end
722
+
723
+ p = n
724
+ loop do
725
+ rslt, witness = miller_rabin(p, 10, true)
726
+ if rslt
727
+ # Final test
728
+ redo unless prime?(p)
729
+ return n.power_of?(p) ? p : false
730
+ end
731
+
732
+ d = lehmer_gcd(power(witness, p, p) - witness, p)
733
+ return false if 1 == d or d == p
734
+ p = d
735
+ end
736
+ end
737
+
738
+ # Param:: positive integer n
739
+ # boolean largest_exp
740
+ # Return:: integer x, k s.t. n == x ** k
741
+ # if n == 1 then x, k == 1, 1
742
+ # (2 <= k if exist else x, k == n, 1)
743
+ # if largest_exp is true then return largest k
744
+ def power_detection(n, largest_exp = true)
745
+ x, k = n, 1
746
+
747
+ limit = ilog2(n)
748
+ (2..limit).each_prime do |exp|
749
+ break if limit < exp
750
+
751
+ root, pow = iroot(n, exp, true)
752
+ if pow == n
753
+ return root, exp unless largest_exp
754
+
755
+ n = x = root
756
+ k *= exp
757
+ limit = ilog2(n)
758
+ redo
759
+ end
760
+ end
761
+
762
+ return x, k
763
+ end
764
+
765
+ # Param:: positive integer n
766
+ # Return:: integer e s.t. 2 ** e <= n < 2 ** (e + 1)
767
+ def ilog2(n)
768
+ bits = (n.size - BASE_BYTE) << 3
769
+ return bits + Bisect.bisect_right(powers_of_2, n >> bits) - 1
770
+ end
771
+
772
+ $powers_of_2 = nil
773
+ # Return:: array power of 2 s.t. [1, 2, 4, 8, 16, 32, ...]
774
+ def powers_of_2
775
+ unless $powers_of_2
776
+ $powers_of_2 = [1]
777
+ ((BASE_BYTE << 3) - 1).times do |i|
778
+ $powers_of_2[i + 1] = $powers_of_2[i] << 1
779
+ end
780
+ end
781
+
782
+ return $powers_of_2
783
+ end
784
+
785
+ # Param:: positive integer m
786
+ # Return:: continued fraction of sqrt m
787
+ # [n, [a_1, a_2, ..., a_i]] s.t. sqrt m = n + frac{1}{a1 + frac{1}{a2 + ...}}
788
+ # n is integer part and a_1...a_i are repeating part
789
+ # Example::continued_fraction_of_sqrt(2) -> [1, [2]]
790
+ # continued_fraction_of_sqrt(3) -> [1, [1, 2]]
791
+ # continued_fraction_of_sqrt(4) -> [2, []]
792
+ def continued_fraction_of_sqrt(m)
793
+ if r = m.square?
794
+ return [r, []]
795
+ end
796
+
797
+ # Initialize
798
+ rslt = [isqrt(m), []]
799
+
800
+ a = 1
801
+ _B = b = -rslt[0]
802
+ c = 1
803
+
804
+ loop do
805
+ # inverse
806
+ a, b, c = a * c, -b * c, a**2 * m - b**2
807
+
808
+ # reduction
809
+ t = gcd(gcd(a, b), c)
810
+ a /= t
811
+ b /= t
812
+ c /= t
813
+
814
+ t = (isqrt(m * a ** 2) + b) / c
815
+ rslt[1].push(t)
816
+ b -= c * t
817
+
818
+ return rslt if 1 == a and _B == b and 1 == c
819
+ end
820
+ end
821
+
822
+ # Param:: positive non-square integer n
823
+ # Return:: least positive integer a, b s.t. a**2 - n * b**2 == 1 or -1
824
+ def bhaskara_brouncker(n)
825
+ t = sqrt = isqrt(n)
826
+ u, u1 = 0, sqrt
827
+ c, c1 = 1, n - sqrt ** 2
828
+ a, a1 = 1, sqrt
829
+ b, b1 = 0, 1
830
+
831
+ until 1 == c1
832
+ t = (sqrt + u1) / c1
833
+ u1, u = t * c1 - u1, u1
834
+ c1, c = c + t * (u - u1), c1
835
+ a1, a = a + t * a1, a1
836
+ b1, b = b + t * b1, b1
837
+ end
838
+
839
+ return a1, b1
840
+ end
841
+
842
+ # primitive Pythagorean number
843
+ # Param:: integer max_c
844
+ # Return:: array of primitive Pythagorean numbers s.t. [[a, b, c], ...]
845
+ # a**2 + b**2 == c**2 and a < b < c <= max_c
846
+ def pythagorean(max_c)
847
+ return Enumerator.new(self, :pythagorean, max_c) unless block_given?
848
+ return [] if max_c <= 4
849
+
850
+ 1.upto(isqrt(max_c - 1)) do |m|
851
+ mm = m ** 2
852
+ s = m.even? ? 1 : 2
853
+ s.step(m, 2) do |n|
854
+ next unless gcd(m, n) == 1
855
+
856
+ nn = n ** 2
857
+ c = mm + nn
858
+ break if max_c < c
859
+
860
+ a = mm - nn
861
+ b = (m * n) << 1
862
+ a, b = b, a if b < a
863
+
864
+ yield [a, b, c]
865
+ end
866
+ end
867
+ end
868
+
869
+ # Param:: positive integer n
870
+ # Return:: the value of moebius function for n
871
+ def mobius(n)
872
+ return 1 if 1 == n
873
+ return 0 unless n.squarefree?
874
+ return factorize(n).size.odd? ? -1 : 1
875
+ end
876
+ alias moebius mobius
877
+
878
+ # Param:: Integer base (2 <= base < p)
879
+ # Integer m (2 <= m < p)
880
+ # prime p
881
+ # Return:: Integer e s.t. base ** e == m (mod p)
882
+ def dlog_rho(base, m, p)
883
+ raise NotImplementedError
884
+ end
885
+
886
+ # Param:: Integer base (2 <= base < p)
887
+ # Integer m (2 <= m < p)
888
+ # prime p
889
+ # Return:: Integer e s.t. base ** e == m (mod p)
890
+ def dlog_icm(base, m, p)
891
+ # Select factor base
892
+
893
+ # Select smooth elements on factor base
894
+
895
+ # Solve DL of factor base for base
896
+
897
+ # Find smooth element h s.t. h == m * base ** f where f is integer
898
+
899
+ # Solve DL of h for factor base
900
+
901
+ raise NotImplementedError
902
+ end
903
+ end