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.
@@ -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
@@ -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
@@ -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
@@ -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'
@@ -0,0 +1,10 @@
1
+ require 'minitest/unit'
2
+ require 'minitest/autorun'
3
+ require 'abst'
4
+
5
+ class TC_Array < MiniTest::Unit::TestCase
6
+ def test_each_coefficient
7
+ assert_equal([[0, 0], [0, 1], [1, 0], [1, 1]].sort,
8
+ [1, 1].each_coefficient.to_a.sort)
9
+ end
10
+ end