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,875 @@
1
+ # Multivariate polynomial ring class over arbitary ring
2
+ #
3
+ # by Shin-ichiro Hara
4
+ #
5
+ # Version 1.6 (2002.02.05)
6
+
7
+ require "algebra/import-module-single-thread"
8
+ require "algebra/m-index"
9
+ require "algebra/algebraic-system"
10
+ module Algebra
11
+ autoload :Groebner, "algebra/groebner-basis"
12
+ def MPolynomial(ground, *vars)
13
+ Algebra::MPolynomial.create(ground, *vars)
14
+ end
15
+ module_function :MPolynomial
16
+
17
+ class MPolynomial
18
+ auto_req_init
19
+ auto_req(:value_on, "algebra/polynomial-converter"){
20
+ include MPolynomialConverter
21
+ }
22
+ auto_req_s_init
23
+ auto_req_s(:convert_to, "algebra/polynomial-converter"){
24
+ extend MPolynomialConvertTo
25
+ }
26
+
27
+ =begin
28
+ class MonomialOrder
29
+ def initialize(ord = :lex, t = nil)
30
+ # ord ||= :lex
31
+ case ord
32
+ when Symbol
33
+ @ord_str = ord.id2name
34
+ @ord_sym = ord
35
+ when String
36
+ @ord_sym = ord.intern
37
+ @ord_str = ord
38
+ else
39
+ raise "want Symbol or String"
40
+ end
41
+
42
+ if t
43
+ @t = t
44
+ instance_eval("alias cmp #{@ord_str}_t")
45
+ else
46
+ instance_eval("alias cmp #@ord_str")
47
+ end
48
+ end
49
+
50
+ def to_s; @ord_str; end
51
+ def to_sym; @ord_sym; end
52
+ def v_ord; @t; end
53
+
54
+ #standerd ordering
55
+ def lex(me, other)
56
+ me.to_a <=> other.to_a
57
+ end
58
+
59
+ def grlex(me, other)
60
+ s = (me.totdeg <=> other.totdeg)
61
+ return s unless s.zero?
62
+ lex(me, other)
63
+ end
64
+
65
+ def grevlex(me, other)
66
+ s = (me.totdeg <=> other.totdeg)
67
+ return s unless s.zero?
68
+ n = [me.size, other.size].max
69
+ (n-1).downto 0 do |i|
70
+ x = other[i] - me[i]
71
+ return x unless x.zero?
72
+ end
73
+ 0
74
+ end
75
+
76
+ #ordering by transition array
77
+ def lex_t(me, other)
78
+ n = [me.size, other.size].max
79
+ 0.upto (n-1) do |i|
80
+ x = me[@t[i]] - other[@t[i]]
81
+ return x unless x.zero?
82
+ end
83
+ 0
84
+ end
85
+
86
+ def grlex_t(me, other)
87
+ s = (me.totdeg <=> other.totdeg)
88
+ return s unless s.zero?
89
+ lex_t(me, other)
90
+ end
91
+
92
+ def grevlex_t(me, other)
93
+ s = (me.totdeg <=> other.totdeg)
94
+ return s unless s.zero?
95
+ n = [me.size, other.size].max
96
+ (n-1).downto 0 do |i|
97
+ x = other[@t[i]] - me[@t[i]]
98
+ return x unless x.zero?
99
+ end
100
+ 0
101
+ end
102
+ end
103
+ =end
104
+
105
+ include Enumerable
106
+ include Comparable
107
+ extend AlgebraCreator
108
+ include AlgebraBase
109
+ auto_req :factorize, "algebra/m-polynomial-factor"
110
+ auto_req :divmod_s, "algebra/groebner-basis"
111
+ auto_req :S_pair, "algebra/groebner-basis"
112
+ auto_req :S_pair_coeff, "algebra/groebner-basis"
113
+
114
+ def initialize(ha = {})
115
+ @bone = ha
116
+ method_cash_clear
117
+ end
118
+
119
+ def self.create(ground, *vars)
120
+ klass = super(ground)
121
+ klass.sysvar(:order, nil)
122
+ klass.sysvar(:v_order, nil)
123
+ klass.set_ord(:lex)
124
+ klass.sysvar(:variables, vars)
125
+ klass.sysvar(:display_type, :norm)
126
+ klass
127
+ end
128
+
129
+ def variables; self.class.variables; end
130
+ def vars; self.class.vars; end
131
+
132
+ def self.vars(*vs)
133
+ if vs.size > 0
134
+ vs = vs[0].scan(/[a-zA-Z]_?\d*/) if vs.size == 1 && vs[0].is_a?(String)
135
+ vs.collect{|var| indeterminate(var)}
136
+ else
137
+ variables.collect{|var| indeterminate(var) }
138
+ end
139
+ end
140
+
141
+ def self.to_ary
142
+ [self, *vars]
143
+ end
144
+
145
+ def self.indeterminate(obj)
146
+ ind = if i = variables.index(obj)
147
+ [0] * i + [1]
148
+ # Algebra::MIndex.monomial(i)
149
+ else
150
+ variables.push obj
151
+ # [0] * (variables.size-1) + [1]
152
+ Algebra::MIndex.monomial(variables.size-1)
153
+ end
154
+ monomial(ind)
155
+ end
156
+
157
+ def self.var(obj)
158
+ indeterminate(obj)
159
+ end
160
+
161
+ def self.mvar(*array)
162
+ if array.empty?
163
+ variables.collect{|var| indeterminate(var) }
164
+ else
165
+ array.collect{|var| indeterminate(var)}
166
+ end
167
+ end
168
+
169
+ def self.monomial(ind = [1], c = ground.unity)
170
+ new({Algebra::MIndex[*ind] => c})
171
+ end
172
+
173
+ def monomial(ind = [1], c = ground.unity)
174
+ self.class.monomial(ind, c)
175
+ end
176
+
177
+ def self.const(x)
178
+ new({Algebra::MIndex::Unity => x})
179
+ end
180
+
181
+ def self.regulate(x)
182
+ if x.is_a? self
183
+ x
184
+ elsif y = ground.regulate(x)
185
+ const(y)
186
+ else
187
+ nil
188
+ end
189
+ end
190
+
191
+ def self.[](*x)
192
+ new(Hash[*x])
193
+ end
194
+
195
+ def self.euclidian?
196
+ ground.euclidian? && variables.size <= 1
197
+ end
198
+
199
+ def self.ufd?
200
+ euclidian? || ground.field?
201
+ end
202
+
203
+ def each(&b); @bone.each(&b); end
204
+
205
+ def keys; @bone.keys; end
206
+
207
+ def values; @bone.values; end
208
+
209
+ def [](ind)
210
+ @bone[ind] || 0
211
+ end
212
+
213
+ def []=(ind, c)
214
+ @bone[ind] = c
215
+ end
216
+
217
+ def monomial?
218
+ flag = false
219
+ each do |m, c|
220
+ unless c.zero?
221
+ if flag
222
+ return false
223
+ else
224
+ flag = true
225
+ end
226
+ end
227
+ end
228
+ flag
229
+ end
230
+
231
+ def constant?
232
+ each do |m, c|
233
+ if m.totdeg > 0 && !c.zero?
234
+ return false
235
+ end
236
+ end
237
+ true
238
+ end
239
+
240
+ def unit?
241
+ constant? && lc.unit?
242
+ end
243
+
244
+ def constant_coeff
245
+ # we assume {[]=>2, [0]=>3} is not appeared.
246
+ # it must be reduced to {[]=>6}.
247
+ @bone[Algebra::MIndex::Unity]
248
+ # k = ground.unity
249
+ # @bone.each do |ind, c|
250
+ # unless c.zero?
251
+ # k *= c if ind.totdeg == 0
252
+ # end
253
+ # end
254
+ # k
255
+ end
256
+
257
+ def include?(k)
258
+ @bone.include?(k)
259
+ end
260
+
261
+ def self.zero; new; end
262
+
263
+ def self.unity; const(ground.unity); end
264
+
265
+ def zero?; !find{|m, c| !c.zero?}; end
266
+
267
+ def self.set_ord(ord = nil, v_ord = nil)
268
+ # @@order = MonomialOrder.new(ord, v_ord)
269
+ if ord.is_a? String
270
+ ord = ord.intern
271
+ elsif ord.is_a?(Symbol) || ord.nil?
272
+ else
273
+ raise "#{ord} must be String or Symbol"
274
+ end
275
+ if v_ord.is_a? String
276
+ v_ord = v_ord.intern
277
+ elsif v_ord.is_a?(Symbol) || v_ord.nil?
278
+ else
279
+ raise "#{v_ord} must be String or Symbol"
280
+ end
281
+
282
+ if ord.nil?
283
+ ord = get_ord
284
+ end
285
+ # self.order = MonomialOrder.new(ord, v_ord) #o
286
+ self.order = ord if ord #n
287
+ self.v_order = v_ord if v_ord #n
288
+
289
+ MIndex.set_ord(ord) if ord #n
290
+ MIndex.set_v_ord(v_ord) if v_ord #n
291
+ end
292
+
293
+ def self.ord=(ord)
294
+ self.set_ord(ord, nil)
295
+ end
296
+
297
+ def self.get_ord
298
+ order
299
+ end
300
+
301
+ def self.ord
302
+ get_ord
303
+ end
304
+
305
+ def self.get_v_ord
306
+ v_order
307
+ end
308
+
309
+ def self.with_ord_old(ord = nil, v_ord = nil, methods = [])
310
+ method_cash_clear(*methods)
311
+ o_ord, o_v_ord = get_ord, get_v_ord
312
+ result = nil
313
+ begin
314
+ set_ord(ord, v_ord)
315
+ result = yield
316
+ ensure
317
+ set_ord(o_ord, o_v_ord)
318
+ end
319
+ result
320
+ end
321
+
322
+ def self.with_ord(ord = nil, v_ord = nil, methods = [])
323
+ method_cash_clear(*methods)
324
+ o_ord, o_v_ord = get_ord, get_v_ord
325
+ ord = o_ord unless ord
326
+ result = nil
327
+
328
+ if v_ord
329
+ MIndex.set_v_ord(ord, v_ord)
330
+ MIndex.import_module(MIndex.get_module(ord || self.order, v_ord)) do
331
+ result = yield
332
+ end
333
+ MIndex.set_v_ord(o_ord, o_v_ord)
334
+ else
335
+ MIndex.import_module(MIndex.get_module(ord || self.order)) do
336
+ result = yield
337
+ end
338
+ end
339
+ result
340
+ end
341
+
342
+ def self.method_cash_clear(*m)
343
+ # $stderr.puts "method_cash_clear is given no parameter" if m.empty?
344
+ m.each do |x|
345
+ x.method_cash_clear
346
+ end
347
+ end
348
+
349
+ def method_cash_clear
350
+ @lc = @lm = @lt = @rt = @multideg = nil
351
+ end
352
+
353
+ def compact!
354
+ a = {}
355
+ each do |m, c|
356
+ a[m.compact] = c unless c.zero?
357
+ end
358
+ @bone = a
359
+ self
360
+ end
361
+
362
+ def multideg
363
+ if @multideg
364
+ @multideg
365
+ else
366
+ d = Algebra::MIndex::Unity
367
+ each do |m, c|
368
+ # d = m if !c.zero? && m > d
369
+ # d = m if !c.zero? && self.class.order.cmp(m, d) > 0 #o
370
+ d = m if !c.zero? && (m <=> d) > 0 #n
371
+ end
372
+ @multideg = d
373
+ end
374
+ end
375
+
376
+ def totdeg
377
+ if zero?
378
+ -1
379
+ else
380
+ max = 0
381
+ each do |ind, c|
382
+ unless c.zero?
383
+ t = ind.totdeg
384
+ max = t if t > max
385
+ end
386
+ end
387
+ max
388
+ end
389
+ end
390
+
391
+ def deg; multideg; end
392
+
393
+ def ==(other)
394
+ super{ |other|
395
+ each do |m, c|
396
+ return false unless c == other[m]
397
+ end
398
+ other.each do |m, c|
399
+ if !include? m
400
+ return false unless c.zero?
401
+ end
402
+ end
403
+ true
404
+ }
405
+ end
406
+
407
+ def <=>(other)
408
+ if o = regulate(other)
409
+ # THIS IS RATHER VAGUE
410
+ # lm.ind <=> o.lm.ind
411
+ # self.class.order.cmp(lm.ind, o.lm.ind) #o
412
+ lm.ind <=> o.lm.ind #n
413
+ else
414
+ x , y = other.coerce(self)
415
+ x <=> y
416
+ end
417
+ end
418
+
419
+ def +(other)
420
+ super{ |other|
421
+ a = zero
422
+ each do |m, c|
423
+ a[m] = c + other[m]
424
+ end
425
+ other.each do |m, c|
426
+ if !include? m
427
+ a[m] = self[m] + c
428
+ # a[m] = c + self[m]
429
+ end
430
+ end
431
+ a
432
+ }
433
+ end
434
+
435
+ def -(other)
436
+ super{ |other|
437
+ a = zero
438
+ each do |m, c|
439
+ a[m] = c - other[m]
440
+ end
441
+ other.each do |m, c|
442
+ if !include? m
443
+ a[m] = self[m] - c
444
+ end
445
+ end
446
+ a
447
+ }
448
+ end
449
+
450
+ def *(other)
451
+ super{ |other|
452
+ a = zero
453
+ each do |m0, c0|
454
+ other.each do |m1, c1|
455
+ a[m0 + m1] += c0 * c1
456
+ end
457
+ end
458
+ # a.compact!
459
+ a
460
+ }
461
+ end
462
+
463
+ def /(other) # other asume to be scalar
464
+ # if (o = regulate(other))
465
+ super{ |o|
466
+ if o.constant?
467
+ # self * (ground.unity / o.constant_coeff)
468
+ project{|c, ind|
469
+ c/o.constant_coeff
470
+ }
471
+ else
472
+ a, r = divmod(other)
473
+ if r.zero?
474
+ a.first
475
+ else
476
+ raise "#{other} not divides #{self}"
477
+ end
478
+ end
479
+ }
480
+ # else
481
+ # raise "other(#{o}, #{o.class}) must be monomial"
482
+ # end
483
+ end
484
+
485
+ def divmod(*f)
486
+ g = clone # not dup
487
+ f_lts = f.collect{|x| x.lt}
488
+ a = (0...f.size).collect{zero}
489
+ r = zero
490
+ until g.zero?
491
+ flag = false
492
+ f_lts.each_with_index do |f_lt, i|
493
+ g_lt = g.lt
494
+ if f_lt.divide? g_lt
495
+ d = g_lt / f_lt
496
+ if d == 0 then exit; end
497
+ a[i] += d
498
+ g = g.rt - (d * f[i]).rt
499
+ g.compact!
500
+ flag = true
501
+ break
502
+ end
503
+ end
504
+ unless flag
505
+ r += g.lt
506
+ g = g.rt #g.rt!
507
+ g.compact!
508
+ end
509
+ end
510
+ [a, r]
511
+ end
512
+
513
+ def divmod_variant(*f)
514
+ g = clone # not dup
515
+ f_lts = f.collect{|x| x.lt}
516
+ a = (0...f.size).collect{zero}
517
+ r = zero
518
+ until g.zero?
519
+ flag = false
520
+ f_lts.each_with_index do |f_lt, i|
521
+ g_lt = g.lt
522
+ if f_lt.divide? g_lt
523
+ d = g_lt / f_lt
524
+ a[i] += d
525
+ g = g.rt - (d * f[i]).rt
526
+ g.compact!
527
+ flag = true
528
+ g.zero? ? break : redo
529
+ end
530
+ end
531
+ unless flag
532
+ r += g.lt
533
+ g = g.rt #g.rt!
534
+ end
535
+ end
536
+ [a, r]
537
+ end
538
+
539
+ def %(others)
540
+ divmod(*others).last
541
+ end
542
+
543
+ def gcd(other)
544
+ fact = factorize
545
+ fact.gcd(other).pi
546
+ end
547
+
548
+ def lc
549
+ @lc ||= self[multideg]
550
+ end
551
+
552
+ def lm
553
+ #@lm ||= monomial(multideg).extend(Monomial)
554
+ monomial(multideg).extend(Monomial)
555
+ end
556
+
557
+ def lt
558
+ md = multideg
559
+ @lt ||= monomial(md, self[md]).extend(Monomial)
560
+ end
561
+
562
+ def rt
563
+ @rt ||= self - lt
564
+ end
565
+
566
+ def rt! # deepy destructive, do NOT use
567
+ @bone.delete(multideg)
568
+ method_cash_clear
569
+ self
570
+ end
571
+
572
+ def index_eval(ring, ary, ind)
573
+ e = ring.unity
574
+ ind.each_with_index do |n, i|
575
+ e *= ary[i]**n if n > 0
576
+ end
577
+ e
578
+ end
579
+
580
+ def project0(ring = self.class, ary = ring.vars)
581
+ e = ring.zero
582
+ each do |ind, c|
583
+ e += yield(c, ind)
584
+ end
585
+ e
586
+ end
587
+
588
+ alias map_to project0
589
+
590
+ def project(ring = self.class, ary = ring.vars)
591
+ e = ring.zero
592
+ each do |ind, c|
593
+ e += index_eval(ring, ary, ind) * yield(c, ind)
594
+ end
595
+ e
596
+ end
597
+
598
+ def evaluate(*ary)
599
+ project(ground, ary){|c, ind| c}
600
+ # project(self.class, ary){|c, ind| c}
601
+ end
602
+
603
+ def sub(var, value)
604
+ vs = self.class.vars
605
+ if i = vs.index(var)
606
+ vs = vs.dup
607
+ vs[i] = value
608
+ evaluate(*vs)
609
+ else
610
+ raise "#{var} is not a variable"
611
+ end
612
+ end
613
+
614
+ alias call evaluate
615
+
616
+ def derivate(v)
617
+ if an = self.class.variables.index(v) || vars.index(v)
618
+ derivate_at(an)
619
+ else
620
+ raise "#{var} is not a variable"
621
+ end
622
+ end
623
+
624
+ def derivate_at(an)
625
+ ary = vars
626
+ project0 {|c, ind|
627
+ if ind[an] < 1
628
+ zero
629
+ else
630
+ ind0 = ind - Algebra::MIndex.monomial(an)
631
+ index_eval(self.class, ary, ind0) * ind[an] * c
632
+ end
633
+ }
634
+ end
635
+
636
+ def move_const(pb, coef = ground.unity)
637
+ vs = self.class.vars.dup
638
+ a = []
639
+ vs.each_with_index do |x, i|
640
+ a << x + pb[i]*coef
641
+ end
642
+ evaluate(*a)
643
+ end
644
+
645
+ def convert_to(ring)
646
+ project(ring){|c, ind| c}
647
+ end
648
+
649
+ def need_paren_in_coeff?
650
+ if constant?
651
+ c = constant_coeff
652
+ if c.respond_to?(:need_paren_in_coeff?)
653
+ c.need_paren_in_coeff?
654
+ elsif c.is_a?(Numeric)
655
+ false
656
+ else
657
+ true
658
+ end
659
+ elsif !monomial?
660
+ true
661
+ else
662
+ false
663
+ end
664
+ end
665
+
666
+ def to_s
667
+ case self.class.display_type
668
+ when :code
669
+ pr, po = "*", "**"
670
+ when :tex
671
+ pr, po = "", "}^"
672
+ else
673
+ pr, po = "", "^"
674
+ end
675
+ a = []
676
+ # (k = keys).sort!
677
+ # k = keys.sort{|x, y| self.class.order.cmp(x, y)} #o
678
+ k = keys.sort{|x, y| x <=> y} #n
679
+ k.each do |m| c = self[m]
680
+ next if c.zero?
681
+ s = if m.unity?
682
+ c.to_s
683
+ else
684
+ case c
685
+ when Numeric
686
+ c = c == 1 ? "" : c == -1 ? "-" : c.to_s
687
+ when self.class
688
+ c = "(#{c})"
689
+ else
690
+ c = if c == 1
691
+ ""
692
+ elsif c == -1
693
+ "-"
694
+ elsif c.respond_to?(:need_paren_in_coeff?)
695
+ if c.need_paren_in_coeff?
696
+ "(#{c})"
697
+ else
698
+ c.to_s
699
+ end
700
+ elsif c.is_a?(Numeric)
701
+ c.to_s
702
+ else
703
+ "(#{c})"
704
+ end
705
+ end
706
+
707
+ ms = m.to_s(variables, pr, po)
708
+ c.empty? ? ms : c + pr + ms
709
+ end
710
+ a.unshift s
711
+ end
712
+ a.unshift "0" if a.empty?
713
+ a.join(" + ").gsub(/\+ -/, "- ")
714
+ end
715
+
716
+ alias inspect to_s unless $DEBUG
717
+
718
+ end
719
+
720
+ class MPolynomial
721
+ module Monomial# < MPolynomial
722
+ attr_reader :ind, :coeff
723
+
724
+ def self.extend_object(obj)
725
+ # p [obj, obj.class, obj.monomial?, obj == 0]
726
+ # exit unless obj.monomial?
727
+ raise "'#{obj}' must be monomial" unless obj.monomial?
728
+ super
729
+ obj.ind
730
+ obj.coeff
731
+ self
732
+ end
733
+
734
+ def ind
735
+ if defined? @ind
736
+ return @ind
737
+ else
738
+ each do |obj|
739
+ @ind = obj[0]
740
+ @coeff = obj[1]
741
+ end
742
+ return @ind
743
+ end
744
+ # return @ind if @ind
745
+ # each do |@ind, @coeff|
746
+ # return @ind
747
+ # end
748
+ raise "internal error"
749
+ end
750
+
751
+ def coeff
752
+ if @coeff
753
+ return @coeff
754
+ else
755
+ each do |obj|
756
+ @ind = obj[0]
757
+ @coeff = obj[1]
758
+ end
759
+ return @coeff
760
+ end
761
+ # return @coeff if @coeff
762
+ # each do |@ind, @coeff|
763
+ # return @coeff
764
+ # end
765
+ raise "internal error"
766
+ end
767
+
768
+ def <=>(other)
769
+ #@ind <=> other.ind
770
+ # self.class.order.cmp(@ind, other.ind) #o
771
+ @ind <=> other.ind #n
772
+ end
773
+
774
+ def divide?(other)
775
+ return true if other.zero?
776
+ case other
777
+ when Monomial
778
+ ind.devide?(other.ind) && (ground.field? ||
779
+ ground.euclidian? &&
780
+ coeff.devide?(other.coeff))
781
+ else
782
+ raise "unkown self.class #{other}(#{other.class})"
783
+ end
784
+ end
785
+
786
+ def divide_or?(other0, other1)
787
+ return true if other0.zero? && other1.zero?
788
+ if other0.is_a? Monomial and other1.is_a? Monomial
789
+ ind.devide_or?(other0.ind, other1.ind)
790
+ else
791
+ raise "unkown self.class #{other0.class}, #{other1.class}"
792
+ end
793
+ end
794
+
795
+ def prime_to?(other)
796
+ return false if other.zero?
797
+ case other
798
+ when Monomial
799
+ ind.prime_to?(other.ind)
800
+ else
801
+ raise "unkown self.class #{other}(#{other.class})"
802
+ end
803
+ end
804
+
805
+ def /(other)
806
+ case other
807
+ when self.class
808
+ self.class[(ind - other.ind), coeff / other.coeff]
809
+ else
810
+ super
811
+ end
812
+ end
813
+
814
+ def lcm(other)
815
+ monomial(ind.lcm(other.ind)).extend(Monomial)
816
+ end
817
+ end
818
+ end
819
+ end
820
+
821
+ if $0 == __FILE__
822
+ include Algebra
823
+ Foo = MPolynomial(Integer)
824
+ f = Foo[Algebra::MIndex[1,1]=>1, Algebra::MIndex[1,3]=>4, Algebra::MIndex[]=>9]
825
+ g = Foo[Algebra::MIndex[1,1]=>1, Algebra::MIndex[1,3]=>4, Algebra::MIndex[]=>9,
826
+ Algebra::MIndex[0,2,3]=>6, Algebra::MIndex[2,3]=>-1, Algebra::MIndex[2]=>-5,Algebra::MIndex[0,1]=>7]
827
+ $DEBUG = true
828
+
829
+ puts f, g, f*g
830
+
831
+ $DEBUG = false
832
+ puts
833
+
834
+ require "algebra/polynomial-converter"
835
+ require "algebra/mathn"
836
+ P = MPolynomial(Rational)
837
+ x, y, z = P.vars("xyz")
838
+ f = x**2*y + x*y**2 + y*2 + z**3
839
+ g = x*y-z**3
840
+ h = y*2-6*z
841
+
842
+ P.set_ord(:lex)
843
+ puts "LEX:"
844
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
845
+ fgh = f.divmod(g, h)
846
+ puts fgh
847
+ puts
848
+
849
+ P.method_cash_clear(f, g, h)
850
+ P.set_ord(:grlex)
851
+ puts "GRLEX:"
852
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
853
+ fgh = f.divmod(g, h)
854
+ puts fgh
855
+ puts
856
+
857
+ P.method_cash_clear(f, g, h)
858
+ P.set_ord(:grevlex)
859
+ puts "GREVLEX:"
860
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
861
+ fgh = f.divmod(g, h)
862
+ puts fgh
863
+ puts
864
+
865
+ P.variables.clear
866
+ z, y, x = P.vars("zyx")
867
+ f = x**2*y + x*y**2 + y*2 + z**3
868
+ g = x*y-z**3
869
+ h = y*2-6*z
870
+ puts "GREVLEX: order z, y, x"
871
+ puts "(#{f}).divmod([#{g}, #{h}]) =>"
872
+ fgh = f.divmod(g, h)
873
+ puts fgh
874
+ puts
875
+ end