abst 0.2.0
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/lib/abst.rb +38 -0
- data/lib/config.rb +21 -0
- data/lib/include/array.rb +45 -0
- data/lib/include/bisect.rb +95 -0
- data/lib/include/cache.rb +60 -0
- data/lib/include/compatibility.rb +3 -0
- data/lib/include/complex.rb +10 -0
- data/lib/include/float.rb +19 -0
- data/lib/include/fundamental.rb +903 -0
- data/lib/include/graph.rb +11 -0
- data/lib/include/group.rb +35 -0
- data/lib/include/integer.rb +385 -0
- data/lib/include/matrix.rb +143 -0
- data/lib/include/polynomial.rb +137 -0
- data/lib/include/prime.rb +556 -0
- data/lib/include/prime_mpqs.rb +483 -0
- data/lib/include/rational.rb +155 -0
- data/lib/include/residue.rb +27 -0
- data/lib/include/ring.rb +21 -0
- data/lib/include/sequence.rb +54 -0
- data/lib/include/set.rb +67 -0
- data/lib/include/vector.rb +90 -0
- data/test/test_all.rb +15 -0
- data/test/test_array.rb +10 -0
- data/test/test_bisect.rb +43 -0
- data/test/test_combination.rb +6 -0
- data/test/test_float.rb +13 -0
- data/test/test_fundamental.rb +406 -0
- data/test/test_group.rb +10 -0
- data/test/test_integer.rb +161 -0
- data/test/test_matrix.rb +54 -0
- data/test/test_polynomial.rb +107 -0
- data/test/test_prime.rb +153 -0
- data/test/test_prime_mpqs.rb +24 -0
- data/test/test_rational.rb +33 -0
- data/test/test_sequence.rb +55 -0
- data/test/test_set.rb +36 -0
- data/test/test_vector.rb +37 -0
- metadata +98 -0
@@ -0,0 +1,155 @@
|
|
1
|
+
class Rational
|
2
|
+
def self.one
|
3
|
+
return Rational(1, 1)
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.zero
|
7
|
+
return Rational(0, 1)
|
8
|
+
end
|
9
|
+
|
10
|
+
def inverse
|
11
|
+
return 1 / self
|
12
|
+
end
|
13
|
+
|
14
|
+
# to repeating decimal string
|
15
|
+
def to_rds(base = 10)
|
16
|
+
raise ArgumentError, "invalid radix #{base}" if base < 2 or 36 < base
|
17
|
+
|
18
|
+
# initialize
|
19
|
+
quotient = []
|
20
|
+
|
21
|
+
n = numerator.to_s(base).split('').map(&:to_i)
|
22
|
+
exp = 0
|
23
|
+
while 0 == n.last
|
24
|
+
n.pop
|
25
|
+
exp += 1
|
26
|
+
end
|
27
|
+
d = denominator
|
28
|
+
loop do
|
29
|
+
q, r = d.divmod(base)
|
30
|
+
break unless 0 == r
|
31
|
+
d = q
|
32
|
+
exp -= 1
|
33
|
+
end
|
34
|
+
t = n[0]
|
35
|
+
|
36
|
+
# division loop
|
37
|
+
i = 1
|
38
|
+
loop do
|
39
|
+
q, r = t.divmod(d)
|
40
|
+
t = r * base + n[i].to_i
|
41
|
+
|
42
|
+
quotient.push([q, nil])
|
43
|
+
|
44
|
+
unless n[i]
|
45
|
+
if 0 == t
|
46
|
+
quotient.last[1] = 0
|
47
|
+
break
|
48
|
+
end
|
49
|
+
break if quotient.map(&:last).include?(t)
|
50
|
+
quotient.last[1] = t
|
51
|
+
end
|
52
|
+
|
53
|
+
i += 1
|
54
|
+
end
|
55
|
+
|
56
|
+
# format
|
57
|
+
rslt = "0."
|
58
|
+
|
59
|
+
zero_count = 0
|
60
|
+
while 0 == quotient[0][0]
|
61
|
+
zero_count += 1
|
62
|
+
if t == quotient.shift[1]
|
63
|
+
rslt += '('
|
64
|
+
|
65
|
+
# rotate 0
|
66
|
+
while 0 == quotient[0][0]
|
67
|
+
quotient.push(quotient.shift)
|
68
|
+
zero_count += 1
|
69
|
+
end
|
70
|
+
break
|
71
|
+
end
|
72
|
+
end
|
73
|
+
exp += n.size - zero_count
|
74
|
+
|
75
|
+
convert = "0123456789abcdefghijklmnopqrstuvwxyz"
|
76
|
+
if 0 == quotient.last[1]
|
77
|
+
rslt += quotient.map{|q| convert[q[0]]}.inject(&:+)
|
78
|
+
else
|
79
|
+
quotient.each do |q|
|
80
|
+
rslt += convert[q[0]]
|
81
|
+
rslt += '(' if t == q[1]
|
82
|
+
end
|
83
|
+
rslt += ")"
|
84
|
+
end
|
85
|
+
rslt += "e" + exp.to_s unless 0 == exp
|
86
|
+
|
87
|
+
return rslt
|
88
|
+
end
|
89
|
+
|
90
|
+
# to decimal string
|
91
|
+
def to_ds(length = 64, base = 10)
|
92
|
+
raise ArgumentError, "invalid radix #{base}" if base < 2 or 36 < base
|
93
|
+
|
94
|
+
# initialize
|
95
|
+
quotient = []
|
96
|
+
|
97
|
+
n = numerator.to_s(base).split('').map(&:to_i)
|
98
|
+
exp = 0
|
99
|
+
while 0 == n.last
|
100
|
+
n.pop
|
101
|
+
exp += 1
|
102
|
+
end
|
103
|
+
d = denominator
|
104
|
+
loop do
|
105
|
+
q, r = d.divmod(base)
|
106
|
+
break unless 0 == r
|
107
|
+
d = q
|
108
|
+
exp -= 1
|
109
|
+
end
|
110
|
+
t = n[0]
|
111
|
+
|
112
|
+
# division loop
|
113
|
+
i = 1
|
114
|
+
s = nil
|
115
|
+
loop do
|
116
|
+
q, r = t.divmod(d)
|
117
|
+
t = r * base + n[i].to_i
|
118
|
+
|
119
|
+
s = i - 1 if nil == s and q != 0
|
120
|
+
quotient.push([q, nil])
|
121
|
+
|
122
|
+
unless n[i]
|
123
|
+
if 0 == t
|
124
|
+
quotient.last[1] = 0
|
125
|
+
break
|
126
|
+
end
|
127
|
+
break if s and i - s == length
|
128
|
+
quotient.last[1] = t
|
129
|
+
end
|
130
|
+
|
131
|
+
i += 1
|
132
|
+
end
|
133
|
+
|
134
|
+
# format
|
135
|
+
zero_count = 0
|
136
|
+
while 0 == quotient[0][0]
|
137
|
+
zero_count += 1
|
138
|
+
if t == quotient.shift[1]
|
139
|
+
# rotate 0
|
140
|
+
while 0 == quotient[0][0]
|
141
|
+
quotient.push(quotient.shift)
|
142
|
+
zero_count += 1
|
143
|
+
end
|
144
|
+
break
|
145
|
+
end
|
146
|
+
end
|
147
|
+
exp += n.size - zero_count
|
148
|
+
|
149
|
+
convert = "0123456789abcdefghijklmnopqrstuvwxyz"
|
150
|
+
rslt = "0." + quotient.map{|q| convert[q[0]]}.inject(&:+)
|
151
|
+
rslt += "e" + exp.to_s unless 0 == exp
|
152
|
+
|
153
|
+
return rslt
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Abst
|
2
|
+
module_function
|
3
|
+
|
4
|
+
def residue_class(ideal)
|
5
|
+
if prime?(ideal.n)
|
6
|
+
return residue_class_field(ideal)
|
7
|
+
else
|
8
|
+
return residue_class_ring(ideal)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def residue_class_ring(ideal)
|
13
|
+
residue_class = Class.new(IntegerResidueRing) do
|
14
|
+
@mod = ideal.n
|
15
|
+
end
|
16
|
+
|
17
|
+
return residue_class
|
18
|
+
end
|
19
|
+
|
20
|
+
def residue_class_field(maximal_ideal)
|
21
|
+
residue_class = Class.new(IntegerResidueField) do
|
22
|
+
@mod = maximal_ideal.n
|
23
|
+
end
|
24
|
+
|
25
|
+
return residue_class
|
26
|
+
end
|
27
|
+
end
|
data/lib/include/ring.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Abst
|
2
|
+
module Ring
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
include Abst::Group
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def /(other)
|
10
|
+
return self.divmod(other)[0]
|
11
|
+
end
|
12
|
+
|
13
|
+
def %(other)
|
14
|
+
return self.divmod(other)[1]
|
15
|
+
end
|
16
|
+
|
17
|
+
def **(e)
|
18
|
+
return Abst.power(self, e)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Abst
|
2
|
+
module_function
|
3
|
+
|
4
|
+
$fibonacci = {0 => 0, 1 => 1}
|
5
|
+
|
6
|
+
# Param:: non-negative integer n
|
7
|
+
# Return:: the n-th Fibonacci number
|
8
|
+
# effect $fibonacci[n] = fibonacci(n)
|
9
|
+
def fibonacci(n)
|
10
|
+
return $fibonacci[n] if $fibonacci.include?(n)
|
11
|
+
|
12
|
+
m = n >> 1
|
13
|
+
if n.even?
|
14
|
+
f1 = fibonacci(m - 1)
|
15
|
+
f2 = fibonacci(m)
|
16
|
+
$fibonacci[n] = (f1 + f1 + f2) * f2
|
17
|
+
else
|
18
|
+
f1 = fibonacci(m)
|
19
|
+
f2 = fibonacci(m + 1)
|
20
|
+
$fibonacci[n] = f1 ** 2 + f2 ** 2
|
21
|
+
end
|
22
|
+
|
23
|
+
return $fibonacci[n]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Triangle numbers are generated by the formula, T_n = n * (n + 1) / 2.
|
27
|
+
# The first ten triangle numbers are:
|
28
|
+
# 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
|
29
|
+
def triangle(n)
|
30
|
+
return n * (n + 1) >> 1
|
31
|
+
end
|
32
|
+
|
33
|
+
# Pentagonal numbers are generated by the formula, P_n = n * (3 * n - 1) / 2.
|
34
|
+
# The first ten pentagonal numbers are:
|
35
|
+
# 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...
|
36
|
+
def pentagonal(n)
|
37
|
+
return n * (3 * n - 1) >> 1
|
38
|
+
end
|
39
|
+
|
40
|
+
# Hexagonal numbers are generated by the formula, H_n = n * (2 * n - 1)
|
41
|
+
# The first ten hexagonal numbers are:
|
42
|
+
# 1, 6, 15, 28, 45, 66, 91, 120, 153, 190, ...
|
43
|
+
def hexagonal(n)
|
44
|
+
return n * ((n << 1) - 1)
|
45
|
+
end
|
46
|
+
|
47
|
+
def heptagonal(n)
|
48
|
+
return n * (5 * n - 3) >> 1
|
49
|
+
end
|
50
|
+
|
51
|
+
def octagonal(n)
|
52
|
+
return n * (3 * n - 2)
|
53
|
+
end
|
54
|
+
end
|
data/lib/include/set.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
class Set
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
def initialize(ary = [])
|
5
|
+
@set = ary.uniq
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(*items)
|
9
|
+
items.each do |i|
|
10
|
+
@set.push(i) unless @set.include?(i)
|
11
|
+
end
|
12
|
+
return self
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other)
|
16
|
+
return false unless self.size == other.size
|
17
|
+
@set.each do |i|
|
18
|
+
return false unless other.include?(i)
|
19
|
+
end
|
20
|
+
|
21
|
+
return true
|
22
|
+
end
|
23
|
+
|
24
|
+
def each(&block)
|
25
|
+
@set.each(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def size
|
29
|
+
@set.size
|
30
|
+
end
|
31
|
+
|
32
|
+
def dup
|
33
|
+
self.class.new(@set.dup)
|
34
|
+
end
|
35
|
+
|
36
|
+
def include?(a)
|
37
|
+
@set.include?(a)
|
38
|
+
end
|
39
|
+
|
40
|
+
def inspect
|
41
|
+
str = @set.inspect[1..-2]
|
42
|
+
return "{" + str + "}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_a
|
46
|
+
return @set
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class SortableSet < Set
|
51
|
+
def initialize(ary = [], &compare)
|
52
|
+
@set = ary.uniq.sort(&compare)
|
53
|
+
@compare = compare
|
54
|
+
end
|
55
|
+
|
56
|
+
def add(*items)
|
57
|
+
items.each do |i|
|
58
|
+
j = Bisect.bisect_left(@set, i, &@compare)
|
59
|
+
@set.insert(j, i) unless @set[j] == i
|
60
|
+
end
|
61
|
+
return self
|
62
|
+
end
|
63
|
+
|
64
|
+
def dup
|
65
|
+
self.class.new(@set.dup, &@compare)
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Abst
|
2
|
+
module_function
|
3
|
+
|
4
|
+
class Vector
|
5
|
+
class << self
|
6
|
+
attr_reader :coef_class, :size
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
return "#{size} length #{self.coef_class} Vector"
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
return to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :coef
|
18
|
+
protected :coef
|
19
|
+
|
20
|
+
def initialize(coef)
|
21
|
+
raise VectorSizeError unless coef.size == self.class.size
|
22
|
+
@coef = coef.to_a
|
23
|
+
end
|
24
|
+
|
25
|
+
def +(other)
|
26
|
+
raise VectorSizeError unless self.size == other.size
|
27
|
+
return self.class.new(self.coef.zip(other.coef).map{|a, b| a + b})
|
28
|
+
end
|
29
|
+
|
30
|
+
def -(other)
|
31
|
+
raise VectorSizeError unless self.size == other.size
|
32
|
+
return self.class.new(self.coef.zip(other.coef).map{|a, b| a - b})
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(other)
|
36
|
+
return @coef == other.to_a
|
37
|
+
end
|
38
|
+
|
39
|
+
def size
|
40
|
+
return self.class.size
|
41
|
+
end
|
42
|
+
|
43
|
+
def each
|
44
|
+
return Enumerator.new(self) unless block_given?
|
45
|
+
|
46
|
+
@coef.each do |i|
|
47
|
+
yield i
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def squared_length
|
52
|
+
return self.coef.map{|i| i ** 2}.inject(&:+)
|
53
|
+
end
|
54
|
+
|
55
|
+
def [](index)
|
56
|
+
return @coef[index]
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_a
|
60
|
+
return @coef.dup
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
return @coef.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
def inspect
|
68
|
+
return "#{self.class}\n#{self}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def create_vector_space(coef_class, size)
|
73
|
+
if size.kind_of?(Array)
|
74
|
+
elems = size
|
75
|
+
size = size.size
|
76
|
+
end
|
77
|
+
|
78
|
+
vector = Class.new(Vector) do
|
79
|
+
@coef_class = coef_class
|
80
|
+
@size = size
|
81
|
+
end
|
82
|
+
|
83
|
+
return vector.new(elems) if elems
|
84
|
+
return vector
|
85
|
+
end
|
86
|
+
alias Vector create_vector_space
|
87
|
+
module_function :Vector
|
88
|
+
|
89
|
+
class VectorSizeError < Exception; end
|
90
|
+
end
|
data/test/test_all.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require_relative 'test_array'
|
2
|
+
require_relative 'test_bisect'
|
3
|
+
require_relative 'test_combination'
|
4
|
+
require_relative 'test_float'
|
5
|
+
require_relative 'test_fundamental'
|
6
|
+
require_relative 'test_group'
|
7
|
+
require_relative 'test_integer'
|
8
|
+
require_relative 'test_matrix'
|
9
|
+
require_relative 'test_polynomial'
|
10
|
+
require_relative 'test_prime'
|
11
|
+
require_relative 'test_prime_mpqs'
|
12
|
+
require_relative 'test_rational'
|
13
|
+
require_relative 'test_sequence'
|
14
|
+
require_relative 'test_set'
|
15
|
+
require_relative 'test_vector'
|
data/test/test_array.rb
ADDED