line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Math::MVPoly::Polynomial;
|
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
# Copyright (c) 1998 by Brian Guarraci. All rights reserved.
|
4
|
|
|
|
|
|
|
# This program is free software; you can redistribute it and/or modify it
|
5
|
|
|
|
|
|
|
# under the same terms as Perl itself.
|
6
|
|
|
|
|
|
|
|
7
|
1
|
|
|
1
|
|
6
|
use strict;
|
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
30
|
|
8
|
1
|
|
|
1
|
|
655
|
use Math::MVPoly::Monomial;
|
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
30
|
|
9
|
1
|
|
|
1
|
|
9
|
use Math::MVPoly::Integer;
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
3371
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
$Math::MVPoly::VERSION = '0.2b';
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
sub
|
14
|
|
|
|
|
|
|
new
|
15
|
|
|
|
|
|
|
{
|
16
|
69
|
|
|
69
|
1
|
79
|
my $self;
|
17
|
|
|
|
|
|
|
my $m;
|
18
|
|
|
|
|
|
|
|
19
|
69
|
|
|
|
|
93
|
$self = {};
|
20
|
|
|
|
|
|
|
|
21
|
69
|
|
|
|
|
155
|
$self->{MONOMIALS} = [];
|
22
|
69
|
|
|
|
|
113
|
$self->{MONORDER} = 'grlex';
|
23
|
69
|
|
|
|
|
97
|
$self->{VARORDER} = [];
|
24
|
69
|
|
|
|
|
93
|
$self->{VERBOSE} = 0;
|
25
|
|
|
|
|
|
|
|
26
|
69
|
|
|
|
|
81
|
bless($self); # but see below
|
27
|
69
|
|
|
|
|
114
|
return $self;
|
28
|
|
|
|
|
|
|
}
|
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
sub
|
31
|
|
|
|
|
|
|
copy
|
32
|
|
|
|
|
|
|
{
|
33
|
26
|
|
|
26
|
1
|
35
|
my $self = shift;
|
34
|
26
|
|
|
|
|
29
|
my $p = shift;
|
35
|
26
|
|
|
|
|
27
|
my $monomials;
|
36
|
|
|
|
|
|
|
my $varOrder;
|
37
|
0
|
|
|
|
|
0
|
my $copy_monomials;
|
38
|
0
|
|
|
|
|
0
|
my $copy_varOrder;
|
39
|
0
|
|
|
|
|
0
|
my $copy_order;
|
40
|
0
|
|
|
|
|
0
|
my $m;
|
41
|
0
|
|
|
|
|
0
|
my $f;
|
42
|
|
|
|
|
|
|
|
43
|
26
|
|
|
|
|
49
|
$copy_order = $p->monOrder();
|
44
|
26
|
|
|
|
|
54
|
$self->monOrder($copy_order);
|
45
|
|
|
|
|
|
|
|
46
|
26
|
|
|
|
|
47
|
$monomials = $p->monomials();
|
47
|
26
|
|
|
|
|
44
|
$copy_monomials = [@$monomials];
|
48
|
26
|
|
|
|
|
45
|
$self->monomials($copy_monomials);
|
49
|
|
|
|
|
|
|
|
50
|
26
|
|
|
|
|
51
|
$varOrder = $p->varOrder();
|
51
|
26
|
|
|
|
|
47
|
$copy_varOrder = [@$varOrder];
|
52
|
26
|
|
|
|
|
52
|
$self->varOrder($copy_varOrder);
|
53
|
|
|
|
|
|
|
|
54
|
26
|
|
|
|
|
42
|
return $self;
|
55
|
|
|
|
|
|
|
}
|
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
sub
|
58
|
|
|
|
|
|
|
monOrder
|
59
|
|
|
|
|
|
|
{
|
60
|
302
|
|
|
302
|
1
|
525
|
my $self = shift;
|
61
|
302
|
100
|
|
|
|
542
|
if (@_)
|
62
|
|
|
|
|
|
|
{
|
63
|
64
|
|
|
|
|
124
|
$self->{MONORDER} = shift;
|
64
|
|
|
|
|
|
|
}
|
65
|
302
|
|
|
|
|
766
|
return($self->{MONORDER});
|
66
|
|
|
|
|
|
|
}
|
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
sub
|
69
|
|
|
|
|
|
|
verbose
|
70
|
|
|
|
|
|
|
{
|
71
|
83
|
|
|
83
|
0
|
97
|
my $self = shift;
|
72
|
83
|
100
|
|
|
|
153
|
if (@_)
|
73
|
|
|
|
|
|
|
{
|
74
|
17
|
|
|
|
|
28
|
$self->{VERBOSE} = shift;
|
75
|
|
|
|
|
|
|
}
|
76
|
83
|
|
|
|
|
232
|
return($self->{VERBOSE});
|
77
|
|
|
|
|
|
|
}
|
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub
|
80
|
|
|
|
|
|
|
varOrder
|
81
|
|
|
|
|
|
|
{
|
82
|
108
|
|
|
108
|
1
|
128
|
my $self = shift;
|
83
|
108
|
100
|
|
|
|
213
|
if (@_)
|
84
|
|
|
|
|
|
|
{
|
85
|
54
|
|
|
|
|
82
|
$self->{VARORDER} = shift;
|
86
|
|
|
|
|
|
|
}
|
87
|
108
|
|
|
|
|
216
|
return($self->{VARORDER});
|
88
|
|
|
|
|
|
|
}
|
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
sub
|
91
|
|
|
|
|
|
|
monomials
|
92
|
|
|
|
|
|
|
{
|
93
|
733
|
|
|
733
|
1
|
857
|
my $self = shift;
|
94
|
733
|
100
|
|
|
|
1304
|
if (@_)
|
95
|
|
|
|
|
|
|
{
|
96
|
336
|
|
|
|
|
504
|
$self->{MONOMIALS} = shift;
|
97
|
|
|
|
|
|
|
}
|
98
|
733
|
|
|
|
|
1565
|
return($self->{MONOMIALS});
|
99
|
|
|
|
|
|
|
}
|
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
sub
|
102
|
|
|
|
|
|
|
insertMonomial
|
103
|
|
|
|
|
|
|
{
|
104
|
84
|
|
|
84
|
1
|
106
|
my $self = shift;
|
105
|
84
|
|
|
|
|
90
|
my $m = shift;
|
106
|
84
|
|
|
|
|
73
|
my $monomials;
|
107
|
|
|
|
|
|
|
|
108
|
84
|
|
|
|
|
131
|
$monomials = $self->monomials();
|
109
|
|
|
|
|
|
|
|
110
|
84
|
|
|
|
|
134
|
push(@$monomials, $m);
|
111
|
|
|
|
|
|
|
|
112
|
84
|
|
|
|
|
156
|
$self->simplify();
|
113
|
84
|
|
|
|
|
183
|
$self->applyOrder();
|
114
|
|
|
|
|
|
|
}
|
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub
|
117
|
|
|
|
|
|
|
simplify
|
118
|
|
|
|
|
|
|
{
|
119
|
84
|
|
|
84
|
1
|
88
|
my $self = shift;
|
120
|
84
|
|
|
|
|
80
|
my $monomials;
|
121
|
|
|
|
|
|
|
my %hash;
|
122
|
0
|
|
|
|
|
0
|
my $m;
|
123
|
0
|
|
|
|
|
0
|
my $hm;
|
124
|
0
|
|
|
|
|
0
|
my $f;
|
125
|
0
|
|
|
|
|
0
|
my $sig;
|
126
|
|
|
|
|
|
|
|
127
|
84
|
|
|
|
|
121
|
$monomials = $self->monomials();
|
128
|
|
|
|
|
|
|
|
129
|
84
|
|
|
|
|
128
|
foreach $m (@$monomials)
|
130
|
|
|
|
|
|
|
{
|
131
|
154
|
|
|
|
|
429
|
$sig = $m->getSignature();
|
132
|
|
|
|
|
|
|
|
133
|
154
|
100
|
|
|
|
299
|
if (exists($hash{$sig}))
|
134
|
|
|
|
|
|
|
{
|
135
|
10
|
|
|
|
|
16
|
$hm = $hash{$sig};
|
136
|
10
|
|
|
|
|
32
|
$hm = $hm->add($m);
|
137
|
10
|
|
|
|
|
20
|
$hash{$sig} = $hm;
|
138
|
|
|
|
|
|
|
|
139
|
10
|
50
|
|
|
|
26
|
if ($hm->coefficient() == 0)
|
140
|
|
|
|
|
|
|
{
|
141
|
10
|
|
|
|
|
24
|
delete $hash{$sig};
|
142
|
10
|
|
|
|
|
26
|
next;
|
143
|
|
|
|
|
|
|
}
|
144
|
|
|
|
|
|
|
else
|
145
|
|
|
|
|
|
|
{
|
146
|
|
|
|
|
|
|
}
|
147
|
|
|
|
|
|
|
}
|
148
|
|
|
|
|
|
|
else
|
149
|
|
|
|
|
|
|
{
|
150
|
144
|
|
|
|
|
272
|
$hash{$sig} = $m;
|
151
|
|
|
|
|
|
|
}
|
152
|
|
|
|
|
|
|
|
153
|
144
|
|
|
|
|
328
|
$m->reduceCoefficient();
|
154
|
|
|
|
|
|
|
}
|
155
|
|
|
|
|
|
|
|
156
|
84
|
|
|
|
|
180
|
$monomials = [values %hash];
|
157
|
|
|
|
|
|
|
|
158
|
84
|
|
|
|
|
206
|
$self->monomials($monomials);
|
159
|
|
|
|
|
|
|
}
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub
|
162
|
|
|
|
|
|
|
fromString
|
163
|
|
|
|
|
|
|
{
|
164
|
9
|
|
|
9
|
1
|
11
|
my $self = shift;
|
165
|
9
|
|
|
|
|
13
|
my $eq = shift;
|
166
|
9
|
|
|
|
|
36
|
my $m;
|
167
|
|
|
|
|
|
|
my $pat;
|
168
|
0
|
|
|
|
|
0
|
my @parts;
|
169
|
0
|
|
|
|
|
0
|
my $f;
|
170
|
0
|
|
|
|
|
0
|
my $varOrder;
|
171
|
|
|
|
|
|
|
|
172
|
9
|
|
|
|
|
13
|
$_ = $eq;
|
173
|
|
|
|
|
|
|
|
174
|
9
|
|
|
|
|
16
|
s/\s//g; # remove all white space
|
175
|
9
|
|
|
|
|
23
|
s/\+/\ \+/g; # move a space in front of all +'s
|
176
|
9
|
|
|
|
|
22
|
s/\-/\ \-/g; # move a space in front of all -'s
|
177
|
|
|
|
|
|
|
|
178
|
9
|
|
|
|
|
26
|
@parts = grep {/\S/} split();
|
|
23
|
|
|
|
|
136
|
|
179
|
|
|
|
|
|
|
|
180
|
9
|
|
|
|
|
20
|
$varOrder = $self->varOrder();
|
181
|
|
|
|
|
|
|
|
182
|
9
|
|
|
|
|
16
|
foreach $f (@parts)
|
183
|
|
|
|
|
|
|
{
|
184
|
23
|
|
|
|
|
72
|
$m = Math::MVPoly::Monomial->new();
|
185
|
23
|
|
|
|
|
97
|
$m->varOrder([@$varOrder]);
|
186
|
23
|
|
|
|
|
56
|
$m->fromString($f);
|
187
|
23
|
|
|
|
|
52
|
$self->insertMonomial($m);
|
188
|
|
|
|
|
|
|
}
|
189
|
|
|
|
|
|
|
}
|
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
sub
|
192
|
|
|
|
|
|
|
toString
|
193
|
|
|
|
|
|
|
{
|
194
|
17
|
|
|
17
|
1
|
22
|
my $self = shift;
|
195
|
17
|
|
|
|
|
20
|
my $s;
|
196
|
|
|
|
|
|
|
my $m;
|
197
|
0
|
|
|
|
|
0
|
my $sig;
|
198
|
0
|
|
|
|
|
0
|
my $monomials;
|
199
|
|
|
|
|
|
|
|
200
|
17
|
|
|
|
|
32
|
$monomials = $self->monomials();
|
201
|
|
|
|
|
|
|
|
202
|
17
|
|
|
|
|
23
|
$s = "";
|
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
205
|
17
|
50
|
|
|
|
41
|
if ($#$monomials < 0)
|
206
|
|
|
|
|
|
|
{
|
207
|
0
|
|
|
|
|
0
|
$s .= "0";
|
208
|
|
|
|
|
|
|
}
|
209
|
|
|
|
|
|
|
else
|
210
|
|
|
|
|
|
|
{
|
211
|
17
|
|
|
|
|
29
|
foreach $m (@$monomials)
|
212
|
|
|
|
|
|
|
{
|
213
|
49
|
|
|
|
|
101
|
$m->verbose($self->verbose());
|
214
|
49
|
|
|
|
|
124
|
$s .= $m->toString();
|
215
|
|
|
|
|
|
|
}
|
216
|
|
|
|
|
|
|
|
217
|
17
|
50
|
|
|
|
39
|
if (! $self->verbose())
|
218
|
|
|
|
|
|
|
{
|
219
|
17
|
100
|
|
|
|
72
|
if ($s =~ /^\+/)
|
220
|
|
|
|
|
|
|
{
|
221
|
15
|
|
|
|
|
34
|
$s = substr($s,1);
|
222
|
|
|
|
|
|
|
}
|
223
|
|
|
|
|
|
|
}
|
224
|
|
|
|
|
|
|
}
|
225
|
|
|
|
|
|
|
|
226
|
17
|
|
|
|
|
58
|
return $s;
|
227
|
|
|
|
|
|
|
}
|
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub
|
230
|
|
|
|
|
|
|
applyOrder
|
231
|
|
|
|
|
|
|
{
|
232
|
113
|
|
|
113
|
1
|
122
|
my $self = shift;
|
233
|
113
|
|
|
|
|
141
|
my $monomials;
|
234
|
|
|
|
|
|
|
my @list;
|
235
|
0
|
|
|
|
|
0
|
my $f;
|
236
|
0
|
|
|
|
|
0
|
my $m;
|
237
|
|
|
|
|
|
|
|
238
|
113
|
|
|
|
|
189
|
$monomials = $self->monomials();
|
239
|
|
|
|
|
|
|
|
240
|
113
|
|
|
|
|
203
|
$self->monomials($monomials);
|
241
|
|
|
|
|
|
|
|
242
|
113
|
100
|
|
|
|
202
|
if ($self->monOrder() eq 'lex')
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
243
|
|
|
|
|
|
|
{
|
244
|
19
|
|
|
|
|
60
|
$monomials = [sort SortByLexOrder @$monomials];
|
245
|
|
|
|
|
|
|
}
|
246
|
|
|
|
|
|
|
elsif ($self->monOrder() eq 'grlex')
|
247
|
|
|
|
|
|
|
{
|
248
|
89
|
|
|
|
|
273
|
$monomials = [sort SortByGrLex @$monomials];
|
249
|
|
|
|
|
|
|
}
|
250
|
|
|
|
|
|
|
elsif ($self->monOrder() eq 'grevlex')
|
251
|
|
|
|
|
|
|
{
|
252
|
5
|
|
|
|
|
16
|
$monomials = [sort SortByGrevLex @$monomials];
|
253
|
|
|
|
|
|
|
}
|
254
|
|
|
|
|
|
|
elsif ($self->monOrder() eq 'tdeg')
|
255
|
|
|
|
|
|
|
{
|
256
|
0
|
|
|
|
|
0
|
$monomials = [sort SortByTotalDegree @$monomials];
|
257
|
|
|
|
|
|
|
}
|
258
|
|
|
|
|
|
|
|
259
|
113
|
|
|
|
|
257
|
$self->monomials($monomials);
|
260
|
|
|
|
|
|
|
}
|
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
sub
|
263
|
|
|
|
|
|
|
SortByLexOrder
|
264
|
|
|
|
|
|
|
{
|
265
|
48
|
|
|
48
|
1
|
49
|
my $left;
|
266
|
|
|
|
|
|
|
my $right;
|
267
|
0
|
|
|
|
|
0
|
my $varOrder;
|
268
|
0
|
|
|
|
|
0
|
my $a_vars;
|
269
|
0
|
|
|
|
|
0
|
my $b_vars;
|
270
|
0
|
|
|
|
|
0
|
my $f;
|
271
|
|
|
|
|
|
|
|
272
|
|
|
|
|
|
|
# proceed down the variable order to perform lex order
|
273
|
48
|
|
|
|
|
122
|
$varOrder = $a->varOrder();
|
274
|
|
|
|
|
|
|
|
275
|
48
|
|
|
|
|
116
|
$a_vars = $a->variables();
|
276
|
48
|
|
|
|
|
104
|
$b_vars = $b->variables();
|
277
|
|
|
|
|
|
|
|
278
|
48
|
|
|
|
|
53
|
$left = 0;
|
279
|
48
|
|
|
|
|
56
|
$right = 0;
|
280
|
|
|
|
|
|
|
|
281
|
48
|
|
|
|
|
59
|
foreach $f (@$varOrder)
|
282
|
|
|
|
|
|
|
{
|
283
|
64
|
100
|
|
|
|
153
|
if ($a_vars->{$f} != $b_vars->{$f})
|
284
|
|
|
|
|
|
|
{
|
285
|
48
|
100
|
|
|
|
95
|
if ($a_vars->{$f} > $b_vars->{$f})
|
286
|
|
|
|
|
|
|
{
|
287
|
25
|
|
|
|
|
28
|
$right = 1;
|
288
|
|
|
|
|
|
|
}
|
289
|
|
|
|
|
|
|
else
|
290
|
|
|
|
|
|
|
{
|
291
|
23
|
|
|
|
|
28
|
$left = 1;
|
292
|
|
|
|
|
|
|
}
|
293
|
48
|
|
|
|
|
55
|
last;
|
294
|
|
|
|
|
|
|
}
|
295
|
|
|
|
|
|
|
}
|
296
|
|
|
|
|
|
|
|
297
|
48
|
|
|
|
|
95
|
$left <=> $right;
|
298
|
|
|
|
|
|
|
}
|
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
sub
|
301
|
|
|
|
|
|
|
SortByGrevLex
|
302
|
|
|
|
|
|
|
{
|
303
|
17
|
|
|
17
|
1
|
16
|
my $left;
|
304
|
|
|
|
|
|
|
my $right;
|
305
|
0
|
|
|
|
|
0
|
my $varOrder;
|
306
|
0
|
|
|
|
|
0
|
my $a_vars;
|
307
|
0
|
|
|
|
|
0
|
my $b_vars;
|
308
|
0
|
|
|
|
|
0
|
my $f;
|
309
|
|
|
|
|
|
|
|
310
|
17
|
|
|
|
|
39
|
$left = $b->getTotalDegree();
|
311
|
17
|
|
|
|
|
39
|
$right = $a->getTotalDegree();
|
312
|
|
|
|
|
|
|
|
313
|
17
|
100
|
|
|
|
40
|
if ($b->getTotalDegree() == $a->getTotalDegree())
|
314
|
|
|
|
|
|
|
{
|
315
|
|
|
|
|
|
|
# proceed down the variable order to perform lex order
|
316
|
4
|
|
|
|
|
14
|
$varOrder = $a->varOrder();
|
317
|
|
|
|
|
|
|
|
318
|
4
|
|
|
|
|
14
|
$a_vars = $a->variables();
|
319
|
4
|
|
|
|
|
11
|
$b_vars = $b->variables();
|
320
|
|
|
|
|
|
|
|
321
|
4
|
|
|
|
|
5
|
$left = 0;
|
322
|
4
|
|
|
|
|
6
|
$right = 0;
|
323
|
|
|
|
|
|
|
|
324
|
4
|
|
|
|
|
8
|
foreach $f (@$varOrder)
|
325
|
|
|
|
|
|
|
{
|
326
|
6
|
100
|
|
|
|
17
|
if ($a_vars->{$f} != $b_vars->{$f})
|
327
|
|
|
|
|
|
|
{
|
328
|
4
|
100
|
|
|
|
11
|
if ($a_vars->{$f} < $b_vars->{$f})
|
329
|
|
|
|
|
|
|
{
|
330
|
2
|
|
|
|
|
4
|
$right = 1;
|
331
|
|
|
|
|
|
|
}
|
332
|
|
|
|
|
|
|
else
|
333
|
|
|
|
|
|
|
{
|
334
|
2
|
|
|
|
|
3
|
$left = 1;
|
335
|
|
|
|
|
|
|
}
|
336
|
4
|
|
|
|
|
7
|
last;
|
337
|
|
|
|
|
|
|
}
|
338
|
|
|
|
|
|
|
}
|
339
|
|
|
|
|
|
|
}
|
340
|
|
|
|
|
|
|
|
341
|
17
|
|
|
|
|
32
|
$left <=> $right;
|
342
|
|
|
|
|
|
|
}
|
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
sub
|
345
|
|
|
|
|
|
|
SortByGrLex
|
346
|
|
|
|
|
|
|
{
|
347
|
73
|
|
|
73
|
1
|
76
|
my $left;
|
348
|
|
|
|
|
|
|
my $right;
|
349
|
0
|
|
|
|
|
0
|
my $varOrder;
|
350
|
0
|
|
|
|
|
0
|
my $a_vars;
|
351
|
0
|
|
|
|
|
0
|
my $b_vars;
|
352
|
0
|
|
|
|
|
0
|
my $f;
|
353
|
|
|
|
|
|
|
|
354
|
73
|
|
|
|
|
175
|
$left = $b->getTotalDegree();
|
355
|
73
|
|
|
|
|
163
|
$right = $a->getTotalDegree();
|
356
|
|
|
|
|
|
|
|
357
|
73
|
100
|
|
|
|
209
|
if ($b->getTotalDegree() == $a->getTotalDegree())
|
358
|
|
|
|
|
|
|
{
|
359
|
|
|
|
|
|
|
# proceed down the variable order to perform lex order
|
360
|
17
|
|
|
|
|
42
|
$varOrder = $a->varOrder();
|
361
|
|
|
|
|
|
|
|
362
|
17
|
|
|
|
|
39
|
$a_vars = $a->variables();
|
363
|
17
|
|
|
|
|
40
|
$b_vars = $b->variables();
|
364
|
|
|
|
|
|
|
|
365
|
17
|
|
|
|
|
19
|
$left = 0;
|
366
|
17
|
|
|
|
|
16
|
$right = 0;
|
367
|
|
|
|
|
|
|
|
368
|
17
|
|
|
|
|
26
|
foreach $f (@$varOrder)
|
369
|
|
|
|
|
|
|
{
|
370
|
21
|
100
|
|
|
|
49
|
if ($a_vars->{$f} != $b_vars->{$f})
|
371
|
|
|
|
|
|
|
{
|
372
|
17
|
100
|
|
|
|
37
|
if ($a_vars->{$f} > $b_vars->{$f})
|
373
|
|
|
|
|
|
|
{
|
374
|
11
|
|
|
|
|
14
|
$right = 1;
|
375
|
|
|
|
|
|
|
}
|
376
|
|
|
|
|
|
|
else
|
377
|
|
|
|
|
|
|
{
|
378
|
6
|
|
|
|
|
8
|
$left = 1;
|
379
|
|
|
|
|
|
|
}
|
380
|
17
|
|
|
|
|
25
|
last;
|
381
|
|
|
|
|
|
|
}
|
382
|
|
|
|
|
|
|
}
|
383
|
|
|
|
|
|
|
}
|
384
|
|
|
|
|
|
|
|
385
|
73
|
|
|
|
|
253
|
$left <=> $right;
|
386
|
|
|
|
|
|
|
}
|
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
sub
|
389
|
|
|
|
|
|
|
SortByTotalDegree
|
390
|
|
|
|
|
|
|
{
|
391
|
0
|
|
|
0
|
1
|
0
|
$b->getTotalDegree() <=> $a->getTotalDegree();
|
392
|
|
|
|
|
|
|
}
|
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
sub
|
395
|
|
|
|
|
|
|
getLT
|
396
|
|
|
|
|
|
|
{
|
397
|
26
|
|
|
26
|
1
|
35
|
my $self = shift;
|
398
|
26
|
|
|
|
|
27
|
my $m;
|
399
|
|
|
|
|
|
|
my $monomials;
|
400
|
|
|
|
|
|
|
|
401
|
26
|
|
|
|
|
45
|
$monomials = $self->monomials();
|
402
|
26
|
|
|
|
|
78
|
$m = Math::MVPoly::Monomial->new();
|
403
|
26
|
|
|
|
|
71
|
$m->copy($$monomials[0]);
|
404
|
|
|
|
|
|
|
|
405
|
26
|
|
|
|
|
47
|
return($m);
|
406
|
|
|
|
|
|
|
}
|
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub
|
409
|
|
|
|
|
|
|
isNotZero
|
410
|
|
|
|
|
|
|
{
|
411
|
12
|
|
|
12
|
1
|
17
|
my $self = shift;
|
412
|
12
|
|
|
|
|
15
|
my $g = shift;
|
413
|
12
|
|
|
|
|
10
|
my $flag;
|
414
|
|
|
|
|
|
|
my $monomials;
|
415
|
|
|
|
|
|
|
|
416
|
12
|
|
|
|
|
24
|
$monomials = $self->monomials();
|
417
|
|
|
|
|
|
|
|
418
|
12
|
|
|
|
|
15
|
$flag = 0;
|
419
|
|
|
|
|
|
|
|
420
|
12
|
100
|
|
|
|
49
|
if ($#$monomials >= 0)
|
421
|
|
|
|
|
|
|
{
|
422
|
8
|
|
|
|
|
11
|
$flag = 1;
|
423
|
|
|
|
|
|
|
}
|
424
|
|
|
|
|
|
|
|
425
|
12
|
|
|
|
|
35
|
return($flag);
|
426
|
|
|
|
|
|
|
}
|
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
sub
|
429
|
|
|
|
|
|
|
mult
|
430
|
|
|
|
|
|
|
{
|
431
|
8
|
|
|
8
|
1
|
14
|
my $self = shift;
|
432
|
8
|
|
|
|
|
8
|
my $q = shift;
|
433
|
8
|
|
|
|
|
10
|
my $myMonomials;
|
434
|
|
|
|
|
|
|
my $monomials;
|
435
|
0
|
|
|
|
|
0
|
my $f;
|
436
|
0
|
|
|
|
|
0
|
my $p;
|
437
|
0
|
|
|
|
|
0
|
my $z;
|
438
|
0
|
|
|
|
|
0
|
my $m;
|
439
|
|
|
|
|
|
|
|
440
|
8
|
|
|
|
|
20
|
$p = Math::MVPoly::Polynomial->new();
|
441
|
|
|
|
|
|
|
|
442
|
8
|
|
|
|
|
17
|
$myMonomials = $self->monomials();
|
443
|
|
|
|
|
|
|
|
444
|
8
|
100
|
|
|
|
23
|
if (ref($q) eq "Math::MVPoly::Monomial")
|
445
|
|
|
|
|
|
|
{
|
446
|
7
|
|
|
|
|
12
|
$f = $q;
|
447
|
7
|
|
|
|
|
14
|
$q = Math::MVPoly::Polynomial->new();
|
448
|
7
|
|
|
|
|
12
|
$q->insertMonomial($f);
|
449
|
|
|
|
|
|
|
}
|
450
|
|
|
|
|
|
|
|
451
|
8
|
|
|
|
|
26
|
$monomials = $q->monomials();
|
452
|
|
|
|
|
|
|
|
453
|
8
|
|
|
|
|
15
|
foreach $f (@$myMonomials)
|
454
|
|
|
|
|
|
|
{
|
455
|
16
|
|
|
|
|
26
|
foreach $m (@$monomials)
|
456
|
|
|
|
|
|
|
{
|
457
|
17
|
|
|
|
|
46
|
$z = $f->mult($m);
|
458
|
17
|
|
|
|
|
35
|
$p->insertMonomial($z);
|
459
|
|
|
|
|
|
|
}
|
460
|
|
|
|
|
|
|
}
|
461
|
|
|
|
|
|
|
|
462
|
8
|
|
|
|
|
30
|
return $p;
|
463
|
|
|
|
|
|
|
}
|
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
sub
|
466
|
|
|
|
|
|
|
add
|
467
|
|
|
|
|
|
|
{
|
468
|
10
|
|
|
10
|
1
|
17
|
my $self = shift;
|
469
|
10
|
|
|
|
|
72
|
my $q = shift;
|
470
|
10
|
|
|
|
|
13
|
my $p;
|
471
|
|
|
|
|
|
|
my $monomials;
|
472
|
0
|
|
|
|
|
0
|
my $f;
|
473
|
0
|
|
|
|
|
0
|
my $m;
|
474
|
|
|
|
|
|
|
|
475
|
10
|
|
|
|
|
23
|
$p = Math::MVPoly::Polynomial->new();
|
476
|
10
|
|
|
|
|
23
|
$p->copy($self);
|
477
|
|
|
|
|
|
|
|
478
|
10
|
100
|
|
|
|
28
|
if (ref($q) eq "Math::MVPoly::Monomial")
|
479
|
|
|
|
|
|
|
{
|
480
|
9
|
|
|
|
|
11
|
$f = $q;
|
481
|
9
|
|
|
|
|
18
|
$q = Math::MVPoly::Polynomial->new();
|
482
|
9
|
|
|
|
|
20
|
$q->insertMonomial($f);
|
483
|
|
|
|
|
|
|
}
|
484
|
|
|
|
|
|
|
|
485
|
10
|
|
|
|
|
22
|
$monomials = $q->monomials();
|
486
|
|
|
|
|
|
|
|
487
|
10
|
|
|
|
|
18
|
foreach $f (@$monomials)
|
488
|
|
|
|
|
|
|
{
|
489
|
11
|
|
|
|
|
30
|
$m = Math::MVPoly::Monomial->new();
|
490
|
11
|
|
|
|
|
30
|
$m->copy($f);
|
491
|
11
|
|
|
|
|
23
|
$p->insertMonomial($f);
|
492
|
|
|
|
|
|
|
}
|
493
|
|
|
|
|
|
|
|
494
|
10
|
|
|
|
|
54
|
return $p;
|
495
|
|
|
|
|
|
|
}
|
496
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
sub
|
498
|
|
|
|
|
|
|
subtract
|
499
|
|
|
|
|
|
|
{
|
500
|
9
|
|
|
9
|
1
|
13
|
my $self = shift;
|
501
|
9
|
|
|
|
|
9
|
my $q = shift;
|
502
|
9
|
|
|
|
|
12
|
my $p;
|
503
|
|
|
|
|
|
|
my $monomials;
|
504
|
0
|
|
|
|
|
0
|
my $f;
|
505
|
0
|
|
|
|
|
0
|
my $neg;
|
506
|
0
|
|
|
|
|
0
|
my $m;
|
507
|
|
|
|
|
|
|
|
508
|
9
|
|
|
|
|
21
|
$p = Math::MVPoly::Polynomial->new();
|
509
|
9
|
|
|
|
|
19
|
$p->copy($self);
|
510
|
|
|
|
|
|
|
|
511
|
9
|
100
|
|
|
|
26
|
if (ref($q) eq "Math::MVPoly::Monomial")
|
512
|
|
|
|
|
|
|
{
|
513
|
4
|
|
|
|
|
7
|
$f = $q;
|
514
|
4
|
|
|
|
|
11
|
$q = Math::MVPoly::Polynomial->new();
|
515
|
4
|
|
|
|
|
9
|
$q->insertMonomial($f);
|
516
|
|
|
|
|
|
|
}
|
517
|
|
|
|
|
|
|
|
518
|
9
|
|
|
|
|
17
|
$monomials = $q->monomials();
|
519
|
|
|
|
|
|
|
|
520
|
9
|
|
|
|
|
32
|
$neg = Math::MVPoly::Monomial->new();
|
521
|
9
|
|
|
|
|
26
|
$neg->fromString("-1");
|
522
|
|
|
|
|
|
|
|
523
|
9
|
|
|
|
|
20
|
foreach $f (@$monomials)
|
524
|
|
|
|
|
|
|
{
|
525
|
13
|
|
|
|
|
64
|
$m = $f->mult($neg);
|
526
|
13
|
|
|
|
|
37
|
$p->insertMonomial($m);
|
527
|
|
|
|
|
|
|
}
|
528
|
|
|
|
|
|
|
|
529
|
9
|
|
|
|
|
51
|
return($p);
|
530
|
|
|
|
|
|
|
}
|
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
sub
|
533
|
|
|
|
|
|
|
divide
|
534
|
|
|
|
|
|
|
{
|
535
|
3
|
|
|
3
|
1
|
4
|
my $self = shift;
|
536
|
3
|
|
|
|
|
5
|
my $ft = shift;
|
537
|
3
|
|
|
|
|
5
|
my $divisionOccured;
|
538
|
|
|
|
|
|
|
my $lt_p;
|
539
|
0
|
|
|
|
|
0
|
my $lt_fi;
|
540
|
0
|
|
|
|
|
0
|
my $at;
|
541
|
0
|
|
|
|
|
0
|
my $m;
|
542
|
0
|
|
|
|
|
0
|
my $z;
|
543
|
0
|
|
|
|
|
0
|
my $q;
|
544
|
0
|
|
|
|
|
0
|
my $r;
|
545
|
0
|
|
|
|
|
0
|
my $p;
|
546
|
0
|
|
|
|
|
0
|
my $s;
|
547
|
0
|
|
|
|
|
0
|
my $i;
|
548
|
|
|
|
|
|
|
|
549
|
3
|
50
|
|
|
|
10
|
if (ref($ft) ne "ARRAY")
|
550
|
|
|
|
|
|
|
{
|
551
|
3
|
|
|
|
|
6
|
$ft = [$ft];
|
552
|
|
|
|
|
|
|
}
|
553
|
|
|
|
|
|
|
|
554
|
3
|
|
|
|
|
5
|
$s = $#$ft;
|
555
|
3
|
|
|
|
|
5
|
$at = [];
|
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
# initialize the output variables
|
558
|
3
|
|
|
|
|
6
|
foreach $i (0..$s)
|
559
|
|
|
|
|
|
|
{
|
560
|
3
|
|
|
|
|
10
|
push(@$at, Math::MVPoly::Polynomial->new());
|
561
|
|
|
|
|
|
|
}
|
562
|
3
|
|
|
|
|
8
|
$r = Math::MVPoly::Polynomial->new();
|
563
|
|
|
|
|
|
|
|
564
|
3
|
|
|
|
|
8
|
$p = Math::MVPoly::Polynomial->new();
|
565
|
3
|
|
|
|
|
8
|
$p->copy($self); # f is $self
|
566
|
|
|
|
|
|
|
|
567
|
3
|
|
|
|
|
8
|
while($p->isNotZero())
|
568
|
|
|
|
|
|
|
{
|
569
|
7
|
|
|
|
|
11
|
$i = 0;
|
570
|
7
|
|
|
|
|
9
|
$divisionOccured = 0;
|
571
|
|
|
|
|
|
|
|
572
|
7
|
|
100
|
|
|
40
|
while($i <= $s && !$divisionOccured)
|
573
|
|
|
|
|
|
|
{
|
574
|
7
|
|
|
|
|
23
|
$lt_fi = $$ft[$i]->getLT();
|
575
|
7
|
|
|
|
|
24
|
$lt_p = $p->getLT();
|
576
|
7
|
100
|
|
|
|
25
|
if ($lt_fi->canDivide($lt_p))
|
577
|
|
|
|
|
|
|
{
|
578
|
3
|
|
|
|
|
12
|
$m = $lt_p->divide($lt_fi);
|
579
|
3
|
|
|
|
|
11
|
$$at[$i] = $$at[$i]->add($m);
|
580
|
3
|
|
|
|
|
11
|
$z = $$ft[$i]->mult($m);
|
581
|
3
|
|
|
|
|
9
|
$p = $p->subtract($z);
|
582
|
3
|
|
|
|
|
22
|
$divisionOccured = 1;
|
583
|
|
|
|
|
|
|
}
|
584
|
|
|
|
|
|
|
else
|
585
|
|
|
|
|
|
|
{
|
586
|
4
|
|
|
|
|
12
|
$i++;
|
587
|
|
|
|
|
|
|
}
|
588
|
|
|
|
|
|
|
}
|
589
|
7
|
100
|
|
|
|
19
|
if (! $divisionOccured)
|
590
|
|
|
|
|
|
|
{
|
591
|
4
|
|
|
|
|
8
|
$z = $p->getLT();
|
592
|
4
|
|
|
|
|
15
|
$r = $r->add($z);
|
593
|
4
|
|
|
|
|
14
|
$p = $p->subtract($z);
|
594
|
|
|
|
|
|
|
}
|
595
|
|
|
|
|
|
|
}
|
596
|
|
|
|
|
|
|
|
597
|
3
|
|
|
|
|
28
|
return [@$at,$r];
|
598
|
|
|
|
|
|
|
}
|
599
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
sub
|
601
|
|
|
|
|
|
|
gcd
|
602
|
|
|
|
|
|
|
{
|
603
|
1
|
|
|
1
|
1
|
2
|
my $self = shift;
|
604
|
1
|
|
|
|
|
2
|
my $g = shift;
|
605
|
1
|
|
|
|
|
1
|
my $h;
|
606
|
|
|
|
|
|
|
my $e;
|
607
|
0
|
|
|
|
|
0
|
my $s;
|
608
|
0
|
|
|
|
|
0
|
my $i;
|
609
|
0
|
|
|
|
|
0
|
my $r;
|
610
|
|
|
|
|
|
|
|
611
|
1
|
|
|
|
|
4
|
$h = Math::MVPoly::Polynomial->new();
|
612
|
1
|
|
|
|
|
3
|
$h->copy($self);
|
613
|
|
|
|
|
|
|
|
614
|
1
|
|
|
|
|
3
|
$s = Math::MVPoly::Polynomial->new();
|
615
|
1
|
|
|
|
|
3
|
$s->copy($g);
|
616
|
|
|
|
|
|
|
|
617
|
1
|
|
|
|
|
4
|
while($s->isNotZero())
|
618
|
|
|
|
|
|
|
{
|
619
|
1
|
|
|
|
|
4
|
$e = $h->divide($s);
|
620
|
1
|
|
|
|
|
3
|
$r = $$e[1];
|
621
|
1
|
|
|
|
|
4
|
$h->copy($s);
|
622
|
1
|
|
|
|
|
3
|
$s->copy($r);
|
623
|
|
|
|
|
|
|
}
|
624
|
|
|
|
|
|
|
|
625
|
1
|
|
|
|
|
7
|
return ($h)
|
626
|
|
|
|
|
|
|
}
|
627
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
sub
|
629
|
|
|
|
|
|
|
reduce
|
630
|
|
|
|
|
|
|
{
|
631
|
0
|
|
|
0
|
1
|
0
|
my $self = shift;
|
632
|
0
|
|
|
|
|
0
|
my $monomials;
|
633
|
|
|
|
|
|
|
my $m;
|
634
|
0
|
|
|
|
|
0
|
my $numerGCD;
|
635
|
0
|
|
|
|
|
0
|
my $denomGCD;
|
636
|
0
|
|
|
|
|
0
|
my $i;
|
637
|
0
|
|
|
|
|
0
|
my $j;
|
638
|
0
|
|
|
|
|
0
|
my $r;
|
639
|
0
|
|
|
|
|
0
|
my $z;
|
640
|
0
|
|
|
|
|
0
|
my $np;
|
641
|
0
|
|
|
|
|
0
|
my $np2;
|
642
|
0
|
|
|
|
|
0
|
my $n;
|
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
# reduction goals:
|
645
|
|
|
|
|
|
|
#
|
646
|
|
|
|
|
|
|
# try to get as many 1's as coefficients as possible
|
647
|
|
|
|
|
|
|
# make the coefficient of the first monomial (if more than one) > 0
|
648
|
|
|
|
|
|
|
#
|
649
|
|
|
|
|
|
|
# ASIDE: there is a lot of work being done here...but this is no trivial task
|
650
|
|
|
|
|
|
|
# to reduce a polynomial into a simpler form
|
651
|
|
|
|
|
|
|
#
|
652
|
|
|
|
|
|
|
|
653
|
0
|
|
|
|
|
0
|
$monomials = $self->monomials();
|
654
|
|
|
|
|
|
|
|
655
|
|
|
|
|
|
|
# determine the gcd for the numerators and denominators
|
656
|
0
|
|
|
|
|
0
|
$m = $$monomials[0];
|
657
|
0
|
|
|
|
|
0
|
($i,$j) = $m->coeff_to_ND();
|
658
|
0
|
|
|
|
|
0
|
$numerGCD = $i;
|
659
|
0
|
|
|
|
|
0
|
$denomGCD = $j;
|
660
|
|
|
|
|
|
|
|
661
|
0
|
|
|
|
|
0
|
foreach $m (@$monomials[1..$#$monomials])
|
662
|
|
|
|
|
|
|
{
|
663
|
0
|
|
|
|
|
0
|
($i,$j) = $m->coeff_to_ND();
|
664
|
0
|
|
|
|
|
0
|
$numerGCD = Integer::gcd($numerGCD, $i);
|
665
|
0
|
|
|
|
|
0
|
$denomGCD = Integer::gcd($denomGCD, $j);
|
666
|
|
|
|
|
|
|
}
|
667
|
|
|
|
|
|
|
|
668
|
0
|
|
|
|
|
0
|
$z = Math::MVPoly::Monomial->new();
|
669
|
0
|
|
|
|
|
0
|
$z->coeff_from_ND(1,$numerGCD);
|
670
|
0
|
|
|
|
|
0
|
$np = Math::MVPoly::Polynomial->new();
|
671
|
|
|
|
|
|
|
|
672
|
|
|
|
|
|
|
# divide through by the numerator gcd
|
673
|
0
|
|
|
|
|
0
|
foreach $m (@$monomials)
|
674
|
|
|
|
|
|
|
{
|
675
|
0
|
|
|
|
|
0
|
$n = $m->mult($z);
|
676
|
0
|
|
|
|
|
0
|
$np = $np->add($n);
|
677
|
|
|
|
|
|
|
}
|
678
|
|
|
|
|
|
|
|
679
|
0
|
|
|
|
|
0
|
$z = Math::MVPoly::Monomial->new();
|
680
|
0
|
|
|
|
|
0
|
$z->coefficient($denomGCD);
|
681
|
|
|
|
|
|
|
|
682
|
0
|
|
|
|
|
0
|
$np2 = Math::MVPoly::Polynomial->new();
|
683
|
|
|
|
|
|
|
|
684
|
0
|
|
|
|
|
0
|
$monomials = $np->monomials();
|
685
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
# multiply through by the denominator gcd
|
687
|
0
|
|
|
|
|
0
|
foreach $m (@$monomials)
|
688
|
|
|
|
|
|
|
{
|
689
|
0
|
|
|
|
|
0
|
$n = $m->mult($z);
|
690
|
0
|
|
|
|
|
0
|
$np2 = $np2->add($n);
|
691
|
|
|
|
|
|
|
}
|
692
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
# see if the first coefficient is > 0
|
694
|
0
|
|
|
|
|
0
|
$m = $np2->getLT();
|
695
|
|
|
|
|
|
|
|
696
|
0
|
0
|
|
|
|
0
|
if ($m->coefficient() < 0)
|
697
|
|
|
|
|
|
|
{
|
698
|
0
|
|
|
|
|
0
|
$z = Math::MVPoly::Monomial->new();
|
699
|
0
|
|
|
|
|
0
|
$z->fromString("-1");
|
700
|
0
|
|
|
|
|
0
|
$np2 = $np2->mult($z);
|
701
|
|
|
|
|
|
|
}
|
702
|
|
|
|
|
|
|
|
703
|
0
|
|
|
|
|
0
|
$self->copy($np2);
|
704
|
|
|
|
|
|
|
}
|
705
|
|
|
|
|
|
|
|
706
|
|
|
|
|
|
|
sub
|
707
|
|
|
|
|
|
|
spoly
|
708
|
|
|
|
|
|
|
{
|
709
|
2
|
|
|
2
|
1
|
4
|
my $self = shift;
|
710
|
2
|
|
|
|
|
4
|
my $g = shift;
|
711
|
2
|
|
|
|
|
3
|
my $lcm;
|
712
|
|
|
|
|
|
|
my $q;
|
713
|
0
|
|
|
|
|
0
|
my $p1;
|
714
|
0
|
|
|
|
|
0
|
my $p2;
|
715
|
0
|
|
|
|
|
0
|
my $spoly;
|
716
|
0
|
|
|
|
|
0
|
my $lt_g;
|
717
|
0
|
|
|
|
|
0
|
my $lt_f;
|
718
|
0
|
|
|
|
|
0
|
my $f;
|
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
#
|
721
|
|
|
|
|
|
|
# S(f,g) = (x^l/LT(f))*f - (x^l/LT(g))*g
|
722
|
|
|
|
|
|
|
#
|
723
|
|
|
|
|
|
|
# where x is a monomial with coefficients l, the LCM of LT(g) and LT(f) where
|
724
|
|
|
|
|
|
|
#
|
725
|
|
|
|
|
|
|
# l(i) = max(a(i), B(i)), a = LT(f), B = LT(g), and i is the ith exponent
|
726
|
|
|
|
|
|
|
#
|
727
|
|
|
|
|
|
|
|
728
|
2
|
|
|
|
|
4
|
$f = $self;
|
729
|
|
|
|
|
|
|
|
730
|
2
|
|
|
|
|
5
|
$lt_f = $f->getLT();
|
731
|
2
|
|
|
|
|
4
|
$lt_g = $g->getLT();
|
732
|
|
|
|
|
|
|
|
733
|
2
|
|
|
|
|
6
|
$lcm = $lt_f->getLCM($lt_g);
|
734
|
|
|
|
|
|
|
|
735
|
2
|
|
|
|
|
9
|
$q = $lcm->divide($lt_f);
|
736
|
2
|
|
|
|
|
12
|
$p1 = $f->mult($q);
|
737
|
|
|
|
|
|
|
|
738
|
2
|
|
|
|
|
5
|
$q = $lcm->divide($lt_g);
|
739
|
2
|
|
|
|
|
8
|
$p2 = $g->mult($q);
|
740
|
|
|
|
|
|
|
|
741
|
2
|
|
|
|
|
8
|
$spoly = $p1->subtract($p2);
|
742
|
|
|
|
|
|
|
|
743
|
2
|
|
|
|
|
38
|
return $spoly;
|
744
|
|
|
|
|
|
|
}
|
745
|
|
|
|
|
|
|
|
746
|
|
|
|
|
|
|
1;
|
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
__END__
|