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,140 @@
1
+ # Factorization of Polyomial
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.0 (2001.04.17)
6
+
7
+ require 'algebra/polynomial-factor-int'
8
+ require 'algebra/polynomial-factor-zp'
9
+ require 'algebra/polynomial-factor-alg'
10
+ require 'algebra/factors'
11
+
12
+ module Algebra
13
+ module PolynomialFactorization
14
+ def sqfree
15
+ f = self
16
+ g = gcd(derivate)
17
+ f / g * g.lc
18
+ end
19
+
20
+ def sqfree?
21
+ gcd(derivate).deg <= 0
22
+ end
23
+
24
+ def psqfree?
25
+ pgcd(derivate).deg <= 0
26
+ end
27
+
28
+ def monic_int(a = lc)
29
+ d = deg
30
+ project(self.class) do |c, n|
31
+ if n == d
32
+ ground.unity
33
+ elsif n < d
34
+ c * a**(d - 1 - n)
35
+ else
36
+ # p [self, d, n]; exit
37
+ raise
38
+ end
39
+ end
40
+ end
41
+
42
+ def monic_int_rev(a)
43
+ d = deg
44
+ project(self.class) do |c, n|
45
+ if n == d
46
+ a
47
+ elsif n < d
48
+ c / a**(d - 1 - n)
49
+ else
50
+ raise
51
+ end
52
+ end
53
+ end
54
+
55
+ def factorize
56
+ return Algebra::Factors.new([[zero, 1]]) if zero?
57
+ fact0 = if ground <= Integer
58
+ factorize_int
59
+ elsif defined?(Rational) && ground <= Rational ||
60
+ defined?(Algebra::LocalizedRing) && ground <= Algebra::LocalizedRing
61
+ factorize_rational
62
+ elsif defined?(Algebra::ResidueClassRing) && ground <= Algebra::ResidueClassRing
63
+ if ground.ground <= Integer
64
+ factorize_modp
65
+ else
66
+ factorize_alg
67
+ end
68
+ elsif ground <= Algebra::Polynomial
69
+ require 'algebra/m-polynomial-factor'
70
+ require 'algebra/polynomial-converter'
71
+ mp = self.class.convert_to(Algebra::MPolynomial)
72
+ f = value_on(mp)
73
+ fact = f.factorize
74
+ fact.map { |g| g.value_on(self.class) }
75
+ else
76
+ raise "(factor) unknown data type : #{self.class}"
77
+ end
78
+ fact0.normalize!
79
+ end
80
+
81
+ def irreducible?
82
+ factorize.size == 1
83
+ end
84
+ end
85
+
86
+ class Polynomial
87
+ include PolynomialFactorization
88
+
89
+ def self.reduction(ring, mod, var)
90
+ pfx = Algebra.Polynomial(Algebra.ResidueClassRing(ring, mod), var)
91
+ # def pfx.[](poly)
92
+ def pfx.reduce(poly)
93
+ poly.project(self) { |c, _i| ground[c] }
94
+ end
95
+ pfx
96
+ end
97
+ end
98
+ end
99
+
100
+ if __FILE__ == $PROGRAM_NAME
101
+ require 'algebra/polynomial'
102
+ require 'algebra/residue-class-ring'
103
+ require 'algebra/rational'
104
+ include Algebra
105
+
106
+ def test(f)
107
+ print "#{f}\n => "
108
+ a = f.factorize
109
+ sw = (f == a.pi)
110
+ puts "#{a.inspect}, #{sw}"
111
+ raise unless sw
112
+ end
113
+
114
+ P0 = Polynomial(Integer, 'x')
115
+ x = P0.var
116
+ # PQ = Polynomial(Rational, "x")
117
+ PQ = Polynomial(Integer, 'x')
118
+ x = PQ.var
119
+ f = (x**2 + x + 1) * (x + 1)**3
120
+
121
+ test(f)
122
+
123
+ n = 5
124
+ puts "mod = #{n}"
125
+
126
+ PF = Polynomial.reduction(Integer, n, 'y')
127
+ g = PF.reduce(f)
128
+ test(g)
129
+
130
+ # require "algebra/matrix-algebra"
131
+ # P3 = Polynomial(Integer, "x")
132
+ # x = P3.var
133
+ # f = 3 * x**3 + 5 * x**2 + 7 * x + 11
134
+ # g = x**4 - 3*x**2 + x - 7
135
+ # f.sylvester_matrix(g).display
136
+ # f.sylvester_matrix(g, 0).display
137
+ # f.sylvester_matrix(g, 1).display
138
+ # f.sylvester_matrix(g, 2).display
139
+ # p f.resultant(g)
140
+ end
@@ -0,0 +1,592 @@
1
+ # Univariate polynomial ring class over arbitary ring
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.4 (2001.04.20)
6
+
7
+ require "algebra/algebraic-system"
8
+ require "algebra/euclidian-ring"
9
+
10
+ module Algebra
11
+ def Polynomial(ground = Integer, *variables)
12
+ Polynomial.create(ground, *variables)
13
+ end
14
+ module_function :Polynomial
15
+
16
+ class Polynomial
17
+ include Enumerable
18
+ include Comparable
19
+ include EuclidianRing
20
+ extend AlgebraCreator
21
+ include AlgebraBase
22
+ auto_req_init
23
+ auto_req_s_init
24
+ auto_req :factorize, "algebra/polynomial-factor"
25
+ auto_req :sqfree, "algebra/polynomial-factor"
26
+ auto_req :sqfree?, "algebra/polynomial-factor"
27
+ auto_req :irreducible?, "algebra/polynomial-factor"
28
+ auto_req :MatrixAlgebra, "algebra/matrix-algebra"
29
+ auto_req :SquareMatrix, "algebra/matrix-algebra"
30
+ auto_req(:galois_group, "algebra/galois-group" ) {
31
+ include Galois
32
+ }
33
+ auto_req(:value_on, :var_swap, "algebra/polynomial-converter"){
34
+ include PolynomialConverter
35
+ }
36
+ auto_req_s(:convert_to, "algebra/polynomial-converter"){
37
+ extend PolynomialConvertTo
38
+ }
39
+
40
+ # auto_req(:decompose, :splitting_field, "algebra/splitting-field") {
41
+ # include SplittingField
42
+ # }
43
+ auto_req(:decompose, :splitting_field, "algebra/splitting-field"){
44
+ include Algebra::SplittingField
45
+ }
46
+
47
+ def initialize(*coeff)
48
+ @coeff = coeff
49
+ end
50
+
51
+ def self.create(ground, *vs)
52
+ if vs.empty?
53
+ #raise "parameter objects must be given"
54
+ vs = ["x"]
55
+ end
56
+ klass = super(vs.size > 1 ? create(ground, *vs[0..-2]) : ground)
57
+ klass.sysvar(:variable, vs.last)
58
+ klass.sysvar(:display_type, :norm)
59
+ klass
60
+ end
61
+
62
+ def self.vars; mvar; end
63
+
64
+ def self.mvar
65
+ g = self
66
+ a = []
67
+ while g <= Algebra::Polynomial
68
+ a.unshift g.var # regulate(g.var)
69
+ g = g.ground
70
+ end
71
+ a
72
+ end
73
+
74
+ def self.variables
75
+ g = self
76
+ a = []
77
+ while g <= Algebra::Polynomial
78
+ a.unshift g.variable
79
+ g = g.ground
80
+ end
81
+ a
82
+ end
83
+
84
+ def self.indeterminate(obj)
85
+ if obj == variable
86
+ new(ground.zero, ground.unity)
87
+ else
88
+ new(ground.indeterminate(obj))
89
+ end
90
+ end
91
+
92
+ def self.monomial(n = 1)
93
+ m = new(*([ground.zero] * n + [ground.unity]))
94
+ m
95
+ end
96
+
97
+ def self.to_ary
98
+ [self, *mvar]
99
+ end
100
+
101
+ def monomial(n = 1)
102
+ self.class.monomial(n)
103
+ end
104
+
105
+ def self.var
106
+ monomial
107
+ end
108
+
109
+ def var
110
+ self.class.monomial
111
+ end
112
+
113
+ def variable; self.class.variable; end
114
+
115
+ def variable=(bf); self.class.variable = bf; end
116
+
117
+ def self.const(c)
118
+ new(c)
119
+ end
120
+
121
+ def constant?
122
+ deg <= 0
123
+ end
124
+
125
+ # def self.[](obj)
126
+ # ground = obj
127
+ # monomial
128
+ # end
129
+
130
+ def each(&b)
131
+ @coeff.each(&b)
132
+ end
133
+
134
+ def reverse_each(&b)
135
+ @coeff.reverse_each(&b)
136
+ end
137
+
138
+ def size
139
+ @coeff.size
140
+ end
141
+
142
+ def [](x)
143
+ @coeff[x] || ground.zero
144
+ end
145
+
146
+ def []=(x, v)
147
+ @coeff[x]= v
148
+ end
149
+
150
+ def monomial?
151
+ flag = false
152
+ each do |x|
153
+ unless x.zero?
154
+ # if !flag && x.respond_to?(:monomial?) && x.monomial?
155
+ if !flag# && x.respond_to?(:monomial?) && x.monomial?
156
+ flag = true
157
+ else
158
+ return false
159
+ end
160
+ # if flag || !x.respond_to?(:monomial?) || !x.monomial?
161
+ # return false
162
+ # else
163
+ # flag = true
164
+ # end
165
+ end
166
+ end
167
+ flag
168
+ end
169
+
170
+ def self.euclidian?
171
+ # ground.euclidian? or ground.field?
172
+ ground.field?
173
+ end
174
+
175
+ def compact!
176
+ d = deg
177
+ @coeff.slice!((d+1)..-1) if d >= 0
178
+ self
179
+ end
180
+
181
+ def deg
182
+ i = size - 1
183
+ i -= 1 while i >= 0 && self[i].zero?
184
+ # i >= 0 ? i : nil
185
+ i
186
+ end
187
+
188
+ def ==(other)
189
+ super {|o|
190
+ d0, d1 = deg, o.deg
191
+ return false unless d0 == d1
192
+ d = d0
193
+ 0.upto d do |i|
194
+ return false unless self[i] == o[i]
195
+ end
196
+ true
197
+ }
198
+ end
199
+
200
+ def <=>(o)
201
+ d0, d1 = deg, o.deg
202
+ return d0 <=> d1 unless d0 == d1
203
+ d = d0
204
+ if ground.method_defined? :<=>
205
+ 0.upto d do |i|
206
+ c0, c1 = self[i], o[i]
207
+ unless (c = (c0 <=> c1)).zero?
208
+ return c
209
+ end
210
+ end
211
+ end
212
+ 0
213
+ end
214
+
215
+ def +(other)
216
+ super { |o|
217
+ d0, d1 = deg, o.deg
218
+ d = [d0, d1].max
219
+ a = []
220
+ # i = 0
221
+ 0.upto d do |i|
222
+ c = (i <= d0 ? self[i] : ground.zero)
223
+ d = (i <= d1 ? o[i] : ground.zero)
224
+ a.push( c + d )
225
+ end
226
+ self.class.new(*a)
227
+ }
228
+ end
229
+
230
+ def -(other)
231
+ super { |o|
232
+ d0, d1 = deg, o.deg
233
+ d = [d0, d1].max
234
+ a = []
235
+ # i = 0
236
+ 0.upto d do |i|
237
+ a.push( (i <= d0 ? self[i] : ground.zero) -
238
+ (i <= d1 ? o[i] : ground.zero))
239
+ end
240
+ self.class.new(*a)
241
+ }
242
+ end
243
+
244
+ def *(other)
245
+ super { |o|
246
+ d0, d1 = deg, o.deg
247
+ return zero if d0 < 0 or d1 < 0
248
+
249
+ # d = [d0, d1].max
250
+ a = (0..(d0+d1)).collect{ground.zero}
251
+ # i = j = 0
252
+ 0.upto d0 do |i|
253
+ 0.upto d1 do |j|
254
+ a[i+j] += self[i]*o[j]
255
+ end
256
+ end
257
+ self.class.new(*a)
258
+ }
259
+ end
260
+
261
+ def ground_div(n, d)
262
+ if ground.field?
263
+ n / d
264
+ elsif ground.euclidian?
265
+ q, r = n.divmod(d)
266
+ raise "devide #{n} by #{d} in #{n.class}" unless r.zero?
267
+ q
268
+ else
269
+ q = n / d
270
+ r = n - q*d
271
+ raise "devide #{n} by #{d} in #{n.class}" unless r.zero?
272
+ q
273
+ end
274
+ end
275
+
276
+ def divmod(o)
277
+ raise ZeroDivisionError, "divisor is zero" if o.zero?
278
+ d0, d1 = deg, o.deg
279
+ if d1 <= 0
280
+ [self.class.new(*collect{|c|
281
+ c / o.lc
282
+ }), zero
283
+ ]
284
+ elsif d0 < d1
285
+ [zero, self]
286
+ else
287
+ tk = monomial(d0 - d1) * ground_div(lc, o.lc)
288
+ e = rt - o.rt * tk
289
+ # e.compact!
290
+ q, r = e.divmod(o)
291
+ [q + tk, r]
292
+ end
293
+ end
294
+
295
+ def div(other)
296
+ if o = regulate(other)
297
+ divmod(o).first
298
+ else
299
+ raise "unknown divisor self.class #{other.class}"
300
+ end
301
+ end
302
+
303
+ alias / div
304
+
305
+ def rem(other)
306
+ if o = regulate(other)
307
+ divmod(o)[1]
308
+ else
309
+ raise "unknown divisor self.class #{other.class}"
310
+ end
311
+ end
312
+
313
+ alias % rem
314
+
315
+ def divide?(other)
316
+ _q, r = other.divmod(self)
317
+ r.zero?
318
+ end
319
+
320
+ def pdivmod(other)
321
+ if o = regulate(other)
322
+ deg0, deg1 = deg, o.deg
323
+ if deg0 < deg1
324
+ [zero, self]
325
+ else
326
+ ((o.lc)**(deg0 - deg1 + 1) * self).divmod(o)
327
+ end
328
+ else
329
+ raise "unknown divisor self.class #{other.class}"
330
+ end
331
+ end
332
+
333
+ def pdiv(other)
334
+ if o = regulate(other)
335
+ pdivmod(o).first
336
+ else
337
+ raise "unknown divisor self.class #{other.class}"
338
+ end
339
+ end
340
+
341
+ def prem(other)
342
+ if _o = regulate(other)
343
+ pdivmod(other).last
344
+ else
345
+ raise "unknown divisor self.class #{other.class}"
346
+ end
347
+ end
348
+
349
+ def lc
350
+ self[deg]
351
+ end
352
+
353
+ def lm
354
+ monomial(deg)
355
+ end
356
+
357
+ def lt
358
+ lc * lm
359
+ end
360
+
361
+ def rt
362
+ self - lt
363
+ end
364
+
365
+ def monic
366
+ self / lc
367
+ end
368
+
369
+ # def cont; @coeff.first.gcd_all(* @coeff[1..-1]); end
370
+ # def pp; self / cont; end
371
+
372
+ def need_paren_in_coeff?
373
+ if constant?
374
+ c = @coeff[0]
375
+ if c.respond_to?(:need_paren_in_coeff?)
376
+ c.need_paren_in_coeff?
377
+ elsif c.is_a?(Numeric)
378
+ false
379
+ else
380
+ true
381
+ end
382
+ elsif !monomial?
383
+ true
384
+ else
385
+ false
386
+ end
387
+ end
388
+
389
+ def to_s
390
+ a = []
391
+ case self.class.display_type
392
+ when :code
393
+ pr, po = "*", "**"
394
+ else
395
+ pr, po = "", "^"
396
+ end
397
+
398
+ x = variable ? variable.to_s : "x"
399
+ each_with_index do |c, i|
400
+ next if c.zero?
401
+ s = case i
402
+ when 0
403
+ c.to_s
404
+ else
405
+ c = if c == 1
406
+ ""
407
+ elsif c == -1
408
+ "-"
409
+ elsif c.respond_to?(:need_paren_in_coeff?)
410
+ if c.need_paren_in_coeff?
411
+ "(#{c})" + pr
412
+ else
413
+ c.to_s + pr
414
+ end
415
+ elsif c.is_a?(Numeric)
416
+ c.to_s + pr
417
+ else
418
+ "(#{c})" + pr
419
+ end
420
+ i == 1 ? c + x : c + x + "#{po}#{i}"
421
+ end
422
+ a.unshift s
423
+ end
424
+ a.unshift "0" if a.empty?
425
+ a.join(" + ").gsub(/\+ -/, "- ")
426
+ end
427
+
428
+ alias _inspect inspect
429
+ alias inspect to_s unless $DEBUG
430
+
431
+ def evaluate_old(obj)
432
+ e = ground.zero
433
+ reverse_each do |c|
434
+ e = e * obj + c
435
+ end
436
+ e
437
+ end
438
+
439
+ def project(ring, x = ring.var)
440
+ e = ring.zero
441
+ n = size
442
+ reverse_each do |c|
443
+ n -= 1
444
+ e = e * x + yield(c, n)
445
+ end
446
+ e
447
+ end
448
+
449
+ def evaluate(*a)
450
+ #project(self.class, x){|c, n| c}
451
+ x = a.last
452
+ if a.size > 1
453
+ project(ground, x){|c, n| c.evaluate(* a[0...-1])}
454
+ elsif a.size == 1
455
+ project(ground, x){|c, n| c}
456
+ else
457
+ raise "can't evaluate"
458
+ end
459
+ end
460
+
461
+ def to_proc
462
+ Proc.new{|*a| evaluate(*a)}
463
+ end
464
+
465
+ def sub(var, value)
466
+ vs = self.class.vars
467
+ if i = vs.index(var)
468
+ vs = vs.dup
469
+ vs[i] = value
470
+ evaluate(*vs)
471
+ else
472
+ raise "#{var} is not a variable"
473
+ end
474
+ end
475
+
476
+ alias evaluateR evaluate
477
+ alias call evaluate
478
+ alias callR evaluateR
479
+
480
+ def projectL(ring = self.class, x = ring.var)
481
+ e = ring.zero
482
+ n = size
483
+ reverse_each do |c|
484
+ n -= 1
485
+ e = x * e + yield(c, n)
486
+ end
487
+ e
488
+ end
489
+
490
+ def evaluateL(x)
491
+ projectL(ground, x){|c, n| c}
492
+ end
493
+
494
+ alias callL evaluateL
495
+
496
+ def move_const(a, coef = 1)
497
+ evaluate(self.class.var + a*coef)
498
+ end
499
+
500
+ def convert_to(ring)
501
+ project(ring){|c, n| c}
502
+ end
503
+
504
+ def derivate
505
+ e = zero
506
+ n = size - 1
507
+ reverse_each do |c|
508
+ e = e * var + c * n
509
+ break if n <= 1
510
+ n -= 1
511
+ end
512
+ e
513
+ end
514
+
515
+ def sylvester_matrix(o, k = 0)
516
+ m, n = deg, o.deg
517
+ if k.zero?
518
+ sm = Algebra.SquareMatrix(ground, m + n - 2*k)
519
+ else
520
+ sm = Algebra.MatrixAlgebra(ground, m + n - 2*k, m + n - k)
521
+ end
522
+ sm.matrix{|i, j|
523
+ if i < n - k
524
+ i0 = j - i
525
+ i0 >= 0 && i0 <= m ? self[m-i0] : ground.zero
526
+ else
527
+ i0 = j - i + n - k
528
+ i0 >= 0 && i0 <= n ? o[n-i0] : ground.zero
529
+ end
530
+ }
531
+ end
532
+
533
+ def resultant(other)
534
+ sylvester_matrix(other).determinant
535
+ end
536
+ end
537
+ end
538
+
539
+ if $0 == __FILE__
540
+ # include Algebra
541
+ require "algebra/residue-class-ring"
542
+ require "algebra/mathn"
543
+
544
+ Fx = Algebra::Polynomial.create(Integer, "x")
545
+ x = Fx.var
546
+
547
+ f = x**6 - 1
548
+ g = (x^4) -1
549
+
550
+ # p f.sylvester_matrix g
551
+ # p f.resultant g
552
+
553
+
554
+ d, t, u = f.gcd_coeff(g)
555
+ puts "(#{t})(#{f}) + (#{u})(#{g}) = #{t * f + u * g} = #{d}"
556
+
557
+ Fy = Algebra::Polynomial.create(Rational, "y")
558
+ y = Fy.var
559
+
560
+ f = y**3 - 3*y + 2
561
+ g = y**6 - 1
562
+ h = y**4 - 1
563
+
564
+ p f.gcd_all(g, h)
565
+ d, a, b, c = f.gcd_coeff_all(g, h)
566
+
567
+ p a*f+b*g+c*h == d
568
+
569
+ # Polynimial is a commutative multi-variable ring
570
+ Fxy = Algebra::Polynomial.create(Fx, "y")
571
+ x = Fx.var
572
+ y = Fxy.var
573
+ p x**2 * y**2 - y**2 * x**2 #=> 0
574
+
575
+ require "algebra/algebraic-parser"
576
+ p Algebra::AlgebraicParser.eval("(x + y)**10 - (y**2 + 2*x*y + x**2)**5)", Fxy) #=> 0
577
+
578
+ require "algebra/rational"
579
+ # A = Polynomial.create(Rational, "x")
580
+ # x = A.var
581
+ # B = Polynomial.create(A, "y")
582
+ # y = B.var
583
+ # C = Polynomial.create(B, "z")
584
+ # z = C.var
585
+ # D = Polynomial.create(C, "w")
586
+ # w = D.var
587
+ # p( (x+y+z+w)**4 )
588
+
589
+ K = Algebra::Polynomial.create(Integer, "x", "y", "z", "w")
590
+ x, y, z, w = K.vars
591
+ p( (x+y+z+w)**4 )
592
+ end