algebra 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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