algebra 0.2.1

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.
Files changed (199) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +53 -0
  3. data/.travis.yml +7 -0
  4. data/CODE_OF_CONDUCT.md +49 -0
  5. data/Gemfile +7 -0
  6. data/Gemfile.lock +28 -0
  7. data/LICENSE.txt +21 -0
  8. data/README-ja.txt +60 -0
  9. data/README.md +61 -0
  10. data/Rakefile +43 -0
  11. data/algebra.gemspec +33 -0
  12. data/bin/console +14 -0
  13. data/bin/setup +8 -0
  14. data/doc-ja/README-ja.html +69 -0
  15. data/doc-ja/README-ja.rd +60 -0
  16. data/doc-ja/README.html +0 -0
  17. data/doc-ja/README.rd +0 -0
  18. data/doc-ja/algebra-ja.html +66 -0
  19. data/doc-ja/algebra-ja.rd +60 -0
  20. data/doc-ja/algebraic-equation-ja.html +36 -0
  21. data/doc-ja/algebraic-equation-ja.rd +26 -0
  22. data/doc-ja/algebraic-extension-field-ja.html +122 -0
  23. data/doc-ja/algebraic-extension-field-ja.rd +118 -0
  24. data/doc-ja/algebraic-parser-ja.html +87 -0
  25. data/doc-ja/algebraic-parser-ja.rd +95 -0
  26. data/doc-ja/changes.html +161 -0
  27. data/doc-ja/changes.rd +119 -0
  28. data/doc-ja/elementary-divisor-ja.html +56 -0
  29. data/doc-ja/elementary-divisor-ja.rd +45 -0
  30. data/doc-ja/euclidian-ring-ja.html +78 -0
  31. data/doc-ja/euclidian-ring-ja.rd +69 -0
  32. data/doc-ja/finite-group-ja.html +285 -0
  33. data/doc-ja/finite-group-ja.rd +276 -0
  34. data/doc-ja/finite-map-ja.html +224 -0
  35. data/doc-ja/finite-map-ja.rd +227 -0
  36. data/doc-ja/finite-set-ja.html +393 -0
  37. data/doc-ja/finite-set-ja.rd +408 -0
  38. data/doc-ja/index-ja.html +113 -0
  39. data/doc-ja/index-ja.rd +112 -0
  40. data/doc-ja/jordan-form-ja.html +106 -0
  41. data/doc-ja/jordan-form-ja.rd +99 -0
  42. data/doc-ja/localized-ring-ja.html +121 -0
  43. data/doc-ja/localized-ring-ja.rd +131 -0
  44. data/doc-ja/m-polynomial-ja.html +542 -0
  45. data/doc-ja/m-polynomial-ja.rd +596 -0
  46. data/doc-ja/matrix-algebra-ja.html +686 -0
  47. data/doc-ja/matrix-algebra-ja.rd +727 -0
  48. data/doc-ja/matrix-algebra-triplet-ja.html +124 -0
  49. data/doc-ja/matrix-algebra-triplet-ja.rd +129 -0
  50. data/doc-ja/permutation-group-ja.html +159 -0
  51. data/doc-ja/permutation-group-ja.rd +151 -0
  52. data/doc-ja/polynomial-converter-ja.html +64 -0
  53. data/doc-ja/polynomial-converter-ja.rd +54 -0
  54. data/doc-ja/polynomial-ja.html +446 -0
  55. data/doc-ja/polynomial-ja.rd +473 -0
  56. data/doc-ja/residue-class-ring-ja.html +112 -0
  57. data/doc-ja/residue-class-ring-ja.rd +113 -0
  58. data/doc-ja/sample-algebraic-equation01.rb.v.rd +11 -0
  59. data/doc-ja/sample-algebraic-equation02.rb.v.rd +11 -0
  60. data/doc-ja/sample-algebraic-root01.rb.v.rd +20 -0
  61. data/doc-ja/sample-algebraicfield01.rb.v.rd +26 -0
  62. data/doc-ja/sample-algebraicfield02.rb.v.rd +15 -0
  63. data/doc-ja/sample-cayleyhamilton01.rb.v.rd +14 -0
  64. data/doc-ja/sample-diagonalization01.rb.v.rd +48 -0
  65. data/doc-ja/sample-divmod01.rb.v.rd +17 -0
  66. data/doc-ja/sample-elementary-divisor01.rb.v.rd +48 -0
  67. data/doc-ja/sample-factorize01.rb.v.rd +11 -0
  68. data/doc-ja/sample-factorize02.rb.v.rd +13 -0
  69. data/doc-ja/sample-factorize03.rb.v.rd +14 -0
  70. data/doc-ja/sample-factorize04.rb.v.rd +14 -0
  71. data/doc-ja/sample-factorize05.rb.v.rd +53 -0
  72. data/doc-ja/sample-galois-group01.rb.v.rd +27 -0
  73. data/doc-ja/sample-gaussian-elimination01.rb.v.rd +19 -0
  74. data/doc-ja/sample-geometry01.rb.v.rd +33 -0
  75. data/doc-ja/sample-geometry02.rb.v.rd +34 -0
  76. data/doc-ja/sample-geometry03.rb.v.rd +45 -0
  77. data/doc-ja/sample-geometry04.rb.v.rd +33 -0
  78. data/doc-ja/sample-geometry07.rb.v.rd +62 -0
  79. data/doc-ja/sample-groebner01.rb.v.rd +13 -0
  80. data/doc-ja/sample-groebner02.rb.v.rd +18 -0
  81. data/doc-ja/sample-groebner03.rb.v.rd +19 -0
  82. data/doc-ja/sample-group01.rb.v.rd +21 -0
  83. data/doc-ja/sample-jordan-form01.rb.v.rd +56 -0
  84. data/doc-ja/sample-jordanform01.rb.v.rd +55 -0
  85. data/doc-ja/sample-lagrange-multiplier01.rb.v.rd +35 -0
  86. data/doc-ja/sample-m-factorize01.rb.v.rd +15 -0
  87. data/doc-ja/sample-m-factorize02.rb.v.rd +12 -0
  88. data/doc-ja/sample-m-polynomial01.rb.v.rd +10 -0
  89. data/doc-ja/sample-map01.rb.v.rd +9 -0
  90. data/doc-ja/sample-polynomial01.rb.v.rd +9 -0
  91. data/doc-ja/sample-polynomial02.rb.v.rd +11 -0
  92. data/doc-ja/sample-primefield01.rb.v.rd +13 -0
  93. data/doc-ja/sample-quotientfield01.rb.v.rd +11 -0
  94. data/doc-ja/sample-quotientfield02.rb.v.rd +18 -0
  95. data/doc-ja/sample-quotientfield03.rb.v.rd +16 -0
  96. data/doc-ja/sample-quotientfield04.rb.v.rd +16 -0
  97. data/doc-ja/sample-set01.rb.v.rd +18 -0
  98. data/doc-ja/sample-splitting-field01.rb.v.rd +19 -0
  99. data/doc-ja/samples-ja.html +885 -0
  100. data/doc-ja/samples-ja.rd +221 -0
  101. data/doc-ja/style.css +85 -0
  102. data/doc-ja/todo.html +20 -0
  103. data/doc-ja/todo.rd +9 -0
  104. data/lib/algebra.rb +36 -0
  105. data/lib/algebra/algebraic-equation.rb +56 -0
  106. data/lib/algebra/algebraic-extension-field.rb +135 -0
  107. data/lib/algebra/algebraic-parser.rb +160 -0
  108. data/lib/algebra/algebraic-system.rb +224 -0
  109. data/lib/algebra/annihilate.rb +52 -0
  110. data/lib/algebra/array-supplement.rb +53 -0
  111. data/lib/algebra/auto-require.rb +84 -0
  112. data/lib/algebra/chinese-rem-th.rb +135 -0
  113. data/lib/algebra/combinatorial.rb +145 -0
  114. data/lib/algebra/elementary-divisor.rb +193 -0
  115. data/lib/algebra/euclidian-ring.rb +161 -0
  116. data/lib/algebra/factors.rb +305 -0
  117. data/lib/algebra/finite-group.rb +374 -0
  118. data/lib/algebra/finite-map.rb +201 -0
  119. data/lib/algebra/finite-set.rb +456 -0
  120. data/lib/algebra/galois-group.rb +129 -0
  121. data/lib/algebra/gaussian-elimination.rb +385 -0
  122. data/lib/algebra/groebner-basis-coeff.rb +228 -0
  123. data/lib/algebra/groebner-basis.rb +197 -0
  124. data/lib/algebra/import-module-single-thread.rb +86 -0
  125. data/lib/algebra/import-module.rb +491 -0
  126. data/lib/algebra/jordan-form.rb +114 -0
  127. data/lib/algebra/linear-algebra.rb +143 -0
  128. data/lib/algebra/localized-ring.rb +294 -0
  129. data/lib/algebra/m-index.rb +282 -0
  130. data/lib/algebra/m-polynomial-factor-int.rb +186 -0
  131. data/lib/algebra/m-polynomial-factor-zp.rb +114 -0
  132. data/lib/algebra/m-polynomial-factor.rb +315 -0
  133. data/lib/algebra/m-polynomial-gcd.rb +40 -0
  134. data/lib/algebra/m-polynomial.rb +875 -0
  135. data/lib/algebra/matrix-algebra-triplet.rb +292 -0
  136. data/lib/algebra/matrix-algebra.rb +929 -0
  137. data/lib/algebra/numeric-supplement.rb +123 -0
  138. data/lib/algebra/permutation-group.rb +257 -0
  139. data/lib/algebra/polynomial-converter.rb +193 -0
  140. data/lib/algebra/polynomial-factor-alg.rb +148 -0
  141. data/lib/algebra/polynomial-factor-int.rb +252 -0
  142. data/lib/algebra/polynomial-factor-zp.rb +165 -0
  143. data/lib/algebra/polynomial-factor.rb +140 -0
  144. data/lib/algebra/polynomial.rb +592 -0
  145. data/lib/algebra/powers.rb +31 -0
  146. data/lib/algebra/prime-gen.rb +32 -0
  147. data/lib/algebra/rational.rb +81 -0
  148. data/lib/algebra/residue-class-ring.rb +219 -0
  149. data/lib/algebra/sets-system.rb +43 -0
  150. data/lib/algebra/splitting-field.rb +103 -0
  151. data/lib/algebra/version.rb +3 -0
  152. data/sample/Makefile +10 -0
  153. data/sample/do-testscripts.rb +100 -0
  154. data/sample/sample-algebraic-equation01.rb +6 -0
  155. data/sample/sample-algebraic-equation02.rb +6 -0
  156. data/sample/sample-algebraic-root01.rb +15 -0
  157. data/sample/sample-algebraicfield01.rb +21 -0
  158. data/sample/sample-algebraicfield02.rb +10 -0
  159. data/sample/sample-cayleyhamilton01.rb +9 -0
  160. data/sample/sample-diagonalization01.rb +43 -0
  161. data/sample/sample-divmod01.rb +12 -0
  162. data/sample/sample-elementary-divisor01.rb +43 -0
  163. data/sample/sample-factorize01.rb +6 -0
  164. data/sample/sample-factorize02.rb +8 -0
  165. data/sample/sample-factorize03.rb +9 -0
  166. data/sample/sample-factorize04.rb +9 -0
  167. data/sample/sample-factorize05.rb +48 -0
  168. data/sample/sample-galois-group01.rb +22 -0
  169. data/sample/sample-gaussian-elimination01.rb +14 -0
  170. data/sample/sample-geometry01.rb +28 -0
  171. data/sample/sample-geometry02.rb +29 -0
  172. data/sample/sample-geometry03.rb +40 -0
  173. data/sample/sample-geometry04.rb +28 -0
  174. data/sample/sample-geometry07.rb +58 -0
  175. data/sample/sample-groebner01.rb +8 -0
  176. data/sample/sample-groebner02.rb +13 -0
  177. data/sample/sample-groebner03.rb +14 -0
  178. data/sample/sample-group01.rb +16 -0
  179. data/sample/sample-jordan-form01.rb +51 -0
  180. data/sample/sample-lagrange-multiplier01.rb +30 -0
  181. data/sample/sample-m-factorize01.rb +10 -0
  182. data/sample/sample-m-factorize02.rb +7 -0
  183. data/sample/sample-m-polynomial01.rb +5 -0
  184. data/sample/sample-map01.rb +4 -0
  185. data/sample/sample-polynomial01.rb +4 -0
  186. data/sample/sample-polynomial02.rb +6 -0
  187. data/sample/sample-primefield01.rb +8 -0
  188. data/sample/sample-quotientfield01.rb +6 -0
  189. data/sample/sample-quotientfield02.rb +13 -0
  190. data/sample/sample-quotientfield03.rb +11 -0
  191. data/sample/sample-quotientfield04.rb +11 -0
  192. data/sample/sample-set01.rb +13 -0
  193. data/sample/sample-splitting-field01.rb +14 -0
  194. data/sample/test-00-cayley-hamilton.rb +76 -0
  195. data/sample/test-00-groebner-basis.rb +274 -0
  196. data/sample/test-00-polynomial-factor-alg.rb +89 -0
  197. data/sample/test-00.list +4 -0
  198. data/sample/time-trial.rb +65 -0
  199. metadata +373 -0
@@ -0,0 +1,114 @@
1
+ # Jordan Canonical Forms
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.00 (2001.11.01)
6
+ require 'algebra/matrix-algebra'
7
+
8
+ module Algebra
9
+ class MatrixAlgebra
10
+ def jordan_form
11
+ Algebra::JordanForm.decompose(self).first
12
+ end
13
+
14
+ def jordan_form_info
15
+ Algebra::JordanForm.decompose(self)
16
+ end
17
+ end
18
+
19
+ class JordanForm
20
+ def initialize(body)
21
+ @body = body
22
+ end
23
+
24
+ def to_matrix(ring = Integer)
25
+ mat = nil
26
+ @body.each do |x, n|
27
+ mat = if mat
28
+ mat.dsum(jordan_block_u(ring, x, n))
29
+ else
30
+ jordan_block_u(ring, x, n)
31
+ end
32
+ end
33
+ mat
34
+ end
35
+
36
+ alias to_matrix_u to_matrix
37
+
38
+ def to_matrix_l
39
+ to_matrix_u.transpose
40
+ end
41
+
42
+ def jordan_block_u(ring, x, n)
43
+ a = Algebra.SquareMatrix(ring, n)
44
+ a.matrix do |i, j|
45
+ if i == j
46
+ x
47
+ elsif i == j - 1
48
+ ring.unity
49
+ else
50
+ ring.zero
51
+ end
52
+ end
53
+ end
54
+
55
+ def jordan_block_l(ring, x, n)
56
+ jordan_block_u(ring, x, n).transpose
57
+ end
58
+
59
+ def self.construct(elem_divs, facts, field, pfield)
60
+ a = []
61
+ elem_divs.each do |e|
62
+ facts.each do |f, n|
63
+ next if f.deg.zero? || n.zero?
64
+ f = f.convert_to(pfield)
65
+ g = e.convert_to(pfield)
66
+
67
+ raise 'insufficient decomposition' unless f.deg <= 1
68
+ k = 0
69
+ loop do
70
+ q, r = g.divmod f
71
+ break unless r.zero?
72
+ g = q
73
+ k += 1
74
+ end
75
+ a.push [-f[0], k] if k > 0
76
+ end
77
+ end
78
+ Algebra::JordanForm.new(a).to_matrix(field)
79
+ end
80
+
81
+ def self.decompose(m)
82
+ base_ring = m.ground
83
+ base_pring = Algebra.Polynomial(base_ring, 'x')
84
+ base_alg = Algebra.SquareMatrix(base_pring, m.size)
85
+
86
+ me = m._char_matrix(base_alg).to_quint.e_diagonalize
87
+ elem_divs = me.body.diag
88
+
89
+ facts = Algebra::ElementaryDivisor.factorize(elem_divs)
90
+ dl = facts.last
91
+ field, modulus, facts, roots, elms = dl.pi.decompose(dl)
92
+
93
+ pfield = Algebra.Polynomial(field, 'x')
94
+ pfm_alg = Algebra.SquareMatrix(pfield, m.size)
95
+
96
+ jm = Algebra::JordanForm.construct(elem_divs, facts, field, pfield)
97
+ jme = jm._char_matrix(pfm_alg).to_quint.e_diagonalize
98
+
99
+ mebody = pfm_alg.convert_from(me.body)
100
+ meright = pfm_alg.convert_from(me.right)
101
+ meleft = pfm_alg.convert_from(me.left)
102
+
103
+ sR = (meright * jme.righti).i2o.evaluateR(jm)
104
+ tL = (jme.lefti * meleft).i2o.evaluateL(jm)
105
+
106
+ [jm, tL, sR, field, modulus]
107
+ end
108
+ end
109
+ end
110
+
111
+ if $PROGRAM_NAME == __FILE__
112
+ j = Algebra::JordanForm.new([[2, 3], [-1, 2]])
113
+ j.to_matrix.display
114
+ end
@@ -0,0 +1,143 @@
1
+ # Linear Algebra
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.00 (2001.11.01)
6
+
7
+ require 'algebra/matrix-algebra'
8
+ require 'algebra/gaussian-elimination'
9
+ require 'algebra/polynomial'
10
+ require 'algebra/polynomial-factor'
11
+ require 'algebra/algebraic-equation'
12
+ require 'algebra/jordan-form'
13
+
14
+ module Algebra
15
+ module Orthogonalization
16
+ def orthogonalize
17
+ orth_basis = []
18
+ vectors.each_with_index do |b, i|
19
+ orth_basis.push b
20
+ next unless i > 0
21
+ orth_basis[0...i].each do |f|
22
+ orth_basis[i] -= b.inner_product(f) / f.norm2 * f
23
+ # orth_basis[i] = f.norm2*orth_basis[i] - b.inner_product(f)*f #also
24
+ end
25
+ end
26
+ self.class.collect_column { |j| orth_basis[j] }
27
+ end
28
+
29
+ def normalize
30
+ k = ground
31
+ orth_basis = []
32
+ vectors.each do |b|
33
+ k, n = Sqrt(k, b.norm2)
34
+ orth_basis.push Vector(k, size)**b / n
35
+ end
36
+ Algebra.SquareMatrix(k, size).collect_column { |j| orth_basis[j] }
37
+ end
38
+ end
39
+
40
+ class MatrixAlgebra
41
+ include Orthogonalization
42
+ # auto_req_init
43
+ # auto_req :e_diagonalize, "algebra/elementary-divisor"
44
+ # auto_req :elementary_divisor, "algebra/elementary-divisor"
45
+ require 'algebra/elementary-divisor'
46
+ end
47
+
48
+ class SquareMatrix < MatrixAlgebra
49
+ def self.symmetric(*a)
50
+ k = size * (size + 1) / 2
51
+ raise "the size of #{a.inspect} must be <= #{k}" if a.size > k
52
+ matrix do |i, j|
53
+ d = (i - j).abs
54
+ a[(i < j ? i : j) + (2 * size + 1 - d) * d / 2] || ground.zero
55
+ end
56
+ end
57
+
58
+ EigenSystem = Struct.new('EigenSystem',
59
+ :extfield,
60
+ :roots,
61
+ :tmatrix,
62
+ :evalues,
63
+ :addelms,
64
+ :evectors,
65
+ :espaces,
66
+ :chpoly,
67
+ :facts)
68
+
69
+ def diagonalize
70
+ chp = char_polynomial(Algebra.Polynomial(ground, 't'))
71
+
72
+ facts = chp.factorize
73
+ mdf, mods, fas, roots, proots = chp.decompose(facts)
74
+ nu = Algebra.SquareMatrix(mdf, size)
75
+
76
+ espaces = {}
77
+ evalues = []
78
+ evectors = []
79
+ roots0 = []
80
+ k = 0
81
+ facts.each do |f, _n|
82
+ dim = f.deg
83
+ if dim <= 0 # 0 might be occurred
84
+ next
85
+ elsif dim == 1
86
+ evs = [-f[0] / f[1]]
87
+ else
88
+ evs = roots[k, dim] # .reverse
89
+ roots0.push [f, evs]
90
+ end
91
+ k += dim
92
+
93
+ evs.each do |evalue|
94
+ ks = nu.const(evalue) - self
95
+ kb = ks.kernel_basis
96
+ espaces[evalue] = kb
97
+
98
+ kb.each do |v|
99
+ evalues.push evalue
100
+ evectors.push v
101
+ end
102
+ end
103
+ end
104
+
105
+ raise "can't Diagonalize" if evalues.size < size
106
+ ttype = Algebra.SquareMatrix(mdf, size)
107
+ r = ttype.collect_column { |i| evectors[i] }
108
+ # :extfield, :roots, :tmatrix, :evalues, :addelms, :evectors,
109
+ # :espaces, :chpoly, :facts
110
+ e = EigenSystem.new(mdf, roots0, r, evalues, proots, evectors,
111
+ espaces, chp, facts)
112
+ def e.to_ary
113
+ to_a
114
+ end
115
+ e
116
+ end
117
+
118
+ def solve_eigen_value_problem
119
+ puts 'A = '; display; puts
120
+
121
+ e = diagonalize
122
+ puts "Charactoristic Poly.: #{e.chpoly} => #{e.facts}"; puts
123
+ puts 'Algebraic Numbers:'
124
+ e.roots.each do |po, rs|
125
+ puts "#{rs.join(', ')} : roots of #{po} == 0"
126
+ end; puts
127
+
128
+ puts 'EigenSpaces: '
129
+ e.evalues.uniq.each do |ev|
130
+ puts "W_{#{ev}} = <#{e.espaces[ev].join(', ')}>"
131
+ end; puts
132
+
133
+ puts 'Trans. Matrix:'
134
+ puts 'P ='
135
+ e.tmatrix.display; puts
136
+
137
+ puts 'P^-1 * A * P = '; (e.tmatrix.inverse * self * e.tmatrix).display; puts
138
+ end
139
+ end
140
+ end
141
+
142
+ if __FILE__ == $PROGRAM_NAME
143
+ end
@@ -0,0 +1,294 @@
1
+ # Localization of Ring
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.1 (2001.04.10)
6
+
7
+ require 'algebra/euclidian-ring'
8
+ require 'algebra/algebraic-system'
9
+
10
+ module Algebra
11
+ def LocalizedRing(ring)
12
+ LocalizedRing.create(ring)
13
+ end
14
+
15
+ def RationalFunctionField(field, obj)
16
+ require 'algebra/polynomial'
17
+ k = LocalizedRing(Polynomial(field, obj))
18
+ def k.var
19
+ self[ground.var]
20
+ end
21
+
22
+ def k.to_ary
23
+ [self, var]
24
+ end
25
+ k
26
+ end
27
+
28
+ def MRationalFunctionField(field, *objs)
29
+ require 'algebra/m-polynomial'
30
+ k = LocalizedRing(MPolynomial(field, *objs))
31
+ def k.vars(*vs)
32
+ ground.vars(*vs).map { |v| self[v] }
33
+ end
34
+
35
+ def k.to_ary
36
+ [self, *vars]
37
+ end
38
+ k.reducible = false
39
+ k
40
+ end
41
+
42
+ module_function :LocalizedRing, :RationalFunctionField, :MRationalFunctionField
43
+
44
+ class LocalizedRing
45
+ extend AlgebraCreator
46
+ include AlgebraBase
47
+
48
+ def self.create(ground)
49
+ klass = super(ground)
50
+ klass.sysvar(:reducible, true)
51
+ klass
52
+ end
53
+
54
+ def self.reducible
55
+ @@reducible
56
+ end
57
+
58
+ def self.reducible=(sw)
59
+ @@reducible = sw
60
+ end
61
+
62
+ attr_reader :numerator
63
+ attr_reader :denominator
64
+
65
+ def monomial?
66
+ true
67
+ end
68
+
69
+ def self.[](num, den = nil)
70
+ den ? reduce(num, den) : unity * num
71
+ end
72
+
73
+ def self.reduce(num, den)
74
+ reducible ? simplify(num, den) : new(num, den)
75
+ end
76
+
77
+ def self.simplify(num, den)
78
+ raise ZeroDivisionError, 'denometor is 0' if den.zero?
79
+ return zero if num.zero?
80
+
81
+ if ground.field?
82
+ num /= den
83
+ den = ground.unit
84
+ elsif ground.ufd? # ground.euclidian?
85
+ gcd = num.gcd(den)
86
+ num /= gcd
87
+ den /= gcd
88
+ # num = num.div(gcd)
89
+ # den = den.div(gcd)
90
+ end
91
+
92
+ # regulate the leading coefficient of polynomil
93
+ if defined?(Polynomial) && ground <= Polynomial
94
+ if ground.ground.field?
95
+ m = den.lc
96
+ num /= m
97
+ den /= m
98
+ elsif ground.ground.euclidian? # high cost!
99
+ m = num.cont.gcd(den.cont)
100
+ num /= m
101
+ den /= m
102
+ end
103
+ # elsif defined?(MPolynomial) && ground <= MPolynomial
104
+ end
105
+
106
+ # if den.respond_to?(:<) and den < 0
107
+ # num = -num
108
+ # den = -den
109
+ # end
110
+ new(num, den)
111
+ end
112
+
113
+ def initialize(num, den = ground.unity)
114
+ if den.respond_to?(:<=>) && den < ground.zero
115
+ num = -num
116
+ den = -den
117
+ end
118
+ @numerator = num
119
+ @denominator = den
120
+ end
121
+
122
+ def simplify
123
+ self.class.simplify(@numerator, @denominator)
124
+ end
125
+
126
+ def ==(o)
127
+ super do |o|
128
+ @numerator * o.denominator == o.numerator * @denominator
129
+ end
130
+ end
131
+
132
+ def +(o)
133
+ super do |o|
134
+ num = @numerator * o.denominator
135
+ num_o = o.numerator * @denominator
136
+ self.class.reduce(num + num_o, @denominator * o.denominator)
137
+ end
138
+ end
139
+
140
+ def -(o)
141
+ super do |o|
142
+ num = @numerator * o.denominator
143
+ num_o = o.numerator * @denominator
144
+ self.class.reduce(num - num_o, @denominator * o.denominator)
145
+ end
146
+ end
147
+
148
+ def *(o)
149
+ super do |o|
150
+ num = @numerator * o.numerator
151
+ den = @denominator * o.denominator
152
+ self.class.reduce(num, den)
153
+ end
154
+ end
155
+
156
+ def /(o)
157
+ raise ZeroDivisionError, 'devided by 0' if o.zero?
158
+ super do |o|
159
+ num = @numerator * o.denominator
160
+ den = @denominator * o.numerator
161
+ self.class.reduce(num, den)
162
+ end
163
+ end
164
+
165
+ def unit?
166
+ !zero? # some about
167
+ end
168
+
169
+ def pdivmod(other)
170
+ [self / other, zero]
171
+ end
172
+
173
+ # def % (o)
174
+ # raise ZeroDivisionError, "devided by 0" if o.zero?
175
+ # den, a, = @denominator.gcd_coeff(o)
176
+ # num = (@numerator * a) % o
177
+ # q, r = num.divmod den
178
+ # raise "#@denominator can not divide #@numerator mod #{o}" unless r.zero?
179
+ # q
180
+ # end
181
+
182
+ def **(other)
183
+ case other
184
+ when Integer
185
+ if other > 0
186
+ num = @numerator**other
187
+ den = @denominator**other
188
+ self.class.new(num, den)
189
+ elsif other < 0
190
+ num = @denominator**-other
191
+ den = @numerator**-other
192
+ self.class.new(num, den)
193
+ elsif other.zero?
194
+ unity
195
+ end
196
+ else
197
+ x, y = other.coerce(self)
198
+ x**y
199
+ end
200
+ end
201
+
202
+ def need_paren_in_coeff?
203
+ if @denominator.unity?
204
+ if @numerator.respond_to?(:need_paren_in_coeff?)
205
+ @numerator.need_paren_in_coeff?
206
+ elsif @numerator.is_a?(Numeric)
207
+ false
208
+ else
209
+ true
210
+ end
211
+ else
212
+ false
213
+ end
214
+ end
215
+
216
+ def to_s
217
+ n = if @numerator.respond_to?(:need_paren_in_coeff?) &&
218
+ @numerator.need_paren_in_coeff? &&
219
+ !@denominator.unity?
220
+ "(#{@numerator})"
221
+ else
222
+ @numerator.to_s
223
+ end
224
+ d = if @denominator.respond_to?(:need_paren_in_coeff?) &&
225
+ @denominator.need_paren_in_coeff? &&
226
+ !@denominator.is_a?(Integer)
227
+ "(#{@denominator})"
228
+ else
229
+ @denominator.to_s
230
+ end
231
+ if @denominator.unity?
232
+ n.to_s
233
+ else
234
+ n + '/' + d
235
+ end
236
+ end
237
+
238
+ def inspect
239
+ to_s
240
+ # sprintf("%s(%s/%s)", self.class, @numerator.inspect, @denominator.inspect)
241
+ end
242
+
243
+ def hash
244
+ raise 'hash is undefined'
245
+ end
246
+ end
247
+ end
248
+
249
+ if __FILE__ == $PROGRAM_NAME
250
+ require 'algebra/polynomial'
251
+ require 'algebra/rational'
252
+ require 'algebra/residue-class-ring'
253
+ include Algebra
254
+
255
+ Q = LocalizedRing(Integer)
256
+ a = Q.new(3, 5)
257
+ b = Q.new(5, 3)
258
+ p [a + b, a - b, a * b, a / b, a + 3, 1 + a]
259
+
260
+ Z13 = ResidueClassRing(Integer, 13)
261
+
262
+ Z13x = Polynomial(Z13, 'x')
263
+ x = Z13x.var
264
+ QZ13x = LocalizedRing(Z13x)
265
+ a = QZ13x[x**2 + x + 1, x**2 - 1]
266
+ b = QZ13x[x + 1, x**2 + 3 * x + 2]
267
+ p a + b
268
+ p((a + b)**4)
269
+ puts
270
+
271
+ Rx = Polynomial(Rational, 'x')
272
+ # Rx = Polynomial(Z13, "x")
273
+ x = Rx.var
274
+ QRx = LocalizedRing(Rx)
275
+ x = QRx[x]
276
+ a = (x**2 + 1) / (x**3 + x + 1)
277
+ QRxy = Polynomial(QRx, 'y')
278
+ y = QRxy.var
279
+ AFF = ResidueClassRing(QRxy, y**3 + a * y + 1)
280
+ y = AFF[y]
281
+ p((y + x)**3)
282
+
283
+ F = RationalFunctionField(Rational, 'x')
284
+ x = F.var
285
+ p ( 1 / (x**2 - 1) - 1 / (x**3 - 1))
286
+
287
+ require 'algebra/mathn'
288
+ require 'algebra/algebraic-extension-field'
289
+ S = AlgebraicExtensionField(Rational, 'a') { |a| a**2 - 2 }
290
+ QSx = RationalFunctionField(S, 'x')
291
+ x = QSx.var
292
+ a = S.var
293
+ p((a / 4 * x + 1 / 2) / (x**2 + a * x + 1) + (-a / 4 * x + 1 / 2) / (x**2 - a * x + 1))
294
+ end