File Coverage

blib/lib/Math/MVPoly/Monomial.pm
Criterion Covered Total %
statement 202 256 78.9
branch 48 54 88.8
condition 3 3 100.0
subroutine 21 21 100.0
pod 18 19 94.7
total 292 353 82.7


line stmt bran cond sub pod time code
1             package Math::MVPoly::Monomial;
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   5 use strict;
  1         2  
  1         29  
8 1     1   745 use Math::MVPoly::Integer;
  1         3  
  1         2927  
9            
10             sub
11             new
12             {
13 120     120 1 134 my $self;
14            
15 120         164 $self = {};
16            
17 120         231 $self->{COEFFICIENT} = undef;
18 120         203 $self->{VARIABLES} = {};
19 120         191 $self->{VARORDER} = [];
20 120         158 $self->{VERBOSE} = 1;
21            
22 120         128 bless($self);
23 120         223 return $self;
24             }
25            
26             sub
27             copy
28             {
29 88     88 1 119 my $self = shift;
30 88         141 my $m = shift;
31 88         94 my $vars;
32             my $f;
33 0         0 my $copy_vars;
34 0         0 my $varOrder;
35 0         0 my $copy_varOrder;
36            
37 88         136 $self->coefficient($m->coefficient());
38            
39 88         151 $vars = $m->variables();
40 88         231 $copy_vars = {%$vars};
41 88         181 $self->variables($copy_vars);
42            
43 88         149 $varOrder = $m->varOrder();
44 88         221 $copy_varOrder = [@$varOrder];
45 88         154 $self->varOrder($copy_varOrder);
46             }
47            
48             sub
49             coefficient
50             {
51 601     601 1 720 my $self = shift;
52 601 100       1065 if (@_) { $self->{COEFFICIENT} = shift }
  167         254  
53 601         1051 return $self->{COEFFICIENT};
54             }
55            
56             sub
57             variables
58             {
59 1181     1181 1 1400 my $self = shift;
60 1181 100       2247 if (@_) { $self->{VARIABLES} = shift }
  120         175  
61 1181         1896 return $self->{VARIABLES};
62             }
63            
64             sub
65             varOrder
66             {
67 456     456 1 539 my $self = shift;
68 456 100       908 if (@_) { $self->{VARORDER} = shift }
  111         166  
69 456         859 return $self->{VARORDER};
70             }
71            
72             sub
73             verbose
74             {
75 98     98 0 116 my $self = shift;
76 98 100       217 if (@_) { $self->{VERBOSE} = shift }
  49         105  
77 98         217 return $self->{VERBOSE};
78             }
79            
80             sub
81             fromString
82             {
83 32     32 1 39 my $self = shift();
84 32         33 my $string = shift();
85 32         39 my $i;
86             my $c;
87 0         0 my $h;
88 0         0 my $p;
89 0         0 my $f;
90 0         0 my @ve;
91 0         0 my @parts;
92 0         0 my $buildVarOrder;
93            
94 32         237 @parts = grep {/\S/} ($string =~ /(^[+-]?\d+\.\d+)|(^[+-]?\d+)|(^[+-])|([A-Za-z]\^\d+)|([A-Za-z])/g);
  330         615  
95            
96             # determine the coefficient
97 32         59 $c = $parts[0];
98 32         44 $i = 1;
99            
100             # see if $c is numeric, otherwise deduce the coefficient
101 32 100       112 if ($c !~ /^[+-]?\d+/g)
102             {
103 19 100       49 if ($c eq "-")
    100          
104             {
105 6         9 $c = -1;
106             }
107             elsif ($c eq "+")
108             {
109 7         8 $c = 1;
110             }
111             else
112             {
113 6         6 $i = 0;
114 6         11 $c = 1;
115             }
116             }
117            
118 32         110 $self->coefficient($c*1);
119            
120             # build the variable/exponent pairs
121 32         55 $h = {};
122            
123 32         82 foreach $p (@parts[$i..$#parts])
124             {
125             # if there is an exponent, extract it, otherwise default to 1
126 40 100       100 if ($p =~ /\^/)
127             {
128 22         62 @ve = split(/\^/,$p);
129 22         66 $h->{$ve[0]} = $ve[1];
130             }
131             else
132             {
133 18         44 $h->{$p} = 1;
134             }
135             }
136            
137 32         70 $self->variables($h);
138             }
139            
140             sub
141             toString
142             {
143 49     49 1 66 my $self = shift();
144 49         51 my $s;
145             my $myVars;
146 0         0 my $varOrder;
147 0         0 my $f;
148 0         0 my $varsExist;
149 0         0 my @nd;
150 0         0 my $c;
151            
152 49         85 @nd = $self->coeff_to_ND();
153            
154 49         87 $c = $nd[0]/$nd[1];
155            
156 49 100       103 if ($c > 0)
157             {
158 27         40 $s = "+";
159             }
160            
161 49         81 $myVars = $self->variables();
162 49         91 $varOrder = $self->varOrder();
163            
164 49 50       85 if ($self->verbose())
165             {
166 0         0 $s .= $self->coefficient();
167            
168 0         0 foreach $f (@$varOrder)
169             {
170 0 0       0 if (exists($myVars->{$f}))
171             {
172 0         0 $s .= "$f^".$myVars->{$f};
173             }
174             }
175             }
176             else
177             {
178 49 100       121 if (abs($c) != 1)
    100          
179             {
180 4         9 $s .= $self->coefficient();
181             }
182             elsif ($self->coefficient() == -1)
183             {
184 20         29 $s = "-";
185             }
186            
187 49         74 $varsExist = 0;
188            
189 49         76 foreach $f (@$varOrder)
190             {
191 127 100       298 if (exists($myVars->{$f}))
192             {
193 94         130 $varsExist = 1;
194 94         115 $s .= "$f";
195 94 100       221 if ($myVars->{$f} > 1)
196             {
197 48         112 $s .= "^".$myVars->{$f};
198             }
199             }
200             }
201            
202 49 100       109 if (! $varsExist)
203             {
204 4         8 $s .= "1";
205             }
206             }
207            
208 49         179 return $s;
209             }
210            
211             sub
212             getSignature
213             {
214 154     154 1 248 my $self = shift();
215 154         436 my $s;
216             my $myVars;
217 0         0 my $varOrder;
218 0         0 my $f;
219            
220 154 100       293 if ($self->getTotalDegree() == 0)
221             {
222 19         30 $s = "CONST";
223             }
224             else
225             {
226 135         241 $myVars = $self->variables();
227 135         258 $varOrder = $self->varOrder();
228            
229 135         307 foreach $f (@$varOrder)
230             {
231 331 100       711 if (exists($myVars->{$f}))
232             {
233 227         494 $s .= "$f^".$myVars->{$f};
234             }
235             }
236             }
237            
238 154         429 return $s;
239             }
240            
241             sub
242             getTotalDegree
243             {
244 514     514 1 906 my $self = shift();
245 514         692 my $deg;
246             my $vars;
247 0         0 my $f;
248            
249 514         772 $vars = $self->variables();
250            
251 514         583 $deg = 0;
252 514         977 foreach $f (keys %$vars)
253             {
254 959         1634 $deg += $vars->{$f};
255             }
256            
257 514         1296 return $deg;
258             }
259            
260             sub
261             canDivide
262             {
263 7     7 1 11 my $self = shift;
264 7         9 my $m = shift;
265 7         9 my $flag;
266             my $myVars;
267 0         0 my $vars;
268 0         0 my $f;
269            
270             # does $m have a subset of vars?
271             # Is each corresponding exponent <=?
272            
273 7         9 $flag = 1;
274            
275 7         14 $myVars = $self->variables();
276 7         15 $vars = $m->variables();
277            
278 7         20 foreach $f (keys %$myVars)
279             {
280 7 100 100     38 if (! exists($vars->{$f}) || $myVars->{$f} > $vars->{$f})
281             {
282 4         4 $flag = 0;
283 4         8 last;
284             }
285             }
286            
287 7         27 return $flag;
288             }
289            
290             sub
291             add
292             {
293 10     10 1 15 my $self = shift;
294 10         13 my $m = shift;
295 10         12 my $nm;
296             my @pa;
297 0         0 my @qa;
298 0         0 my $numer;
299 0         0 my $denom;
300 0         0 my $x;
301 0         0 my $y;
302 0         0 my $k;
303 0         0 my $j;
304            
305 10         24 $nm = Math::MVPoly::Monomial->new();
306 10         22 $nm->copy($self);
307            
308             #
309             # calc. the coefficient
310             #
311 10         20 @qa = $self->coeff_to_ND();
312 10         22 @pa = $m->coeff_to_ND();
313            
314             # x/y + k/j = (yk+jx)/yj
315            
316 10         15 $x = $qa[0];
317 10         12 $y = $qa[1];
318 10         10 $k = $pa[0];
319 10         13 $j = $pa[1];
320            
321 10         15 $numer = $y*$k + $j*$x;
322 10         14 $denom = $y*$j;
323            
324 10         20 $nm->coeff_from_ND($numer,$denom);
325            
326 10         28 return $nm;
327             }
328            
329             sub
330             divide
331             {
332 7     7 1 11 my $self = shift;
333 7         9 my $m = shift;
334 7         9 my $nm;
335             my $nmVars;
336 0         0 my $vars;
337 0         0 my $f;
338 0         0 my @pa;
339 0         0 my @qa;
340 0         0 my $numer;
341 0         0 my $denom;
342            
343 7         16 $nm = Math::MVPoly::Monomial->new();
344 7         16 $nm->copy($self);
345            
346             #
347             # calc. the coefficient
348             #
349 7         14 @qa = $self->coeff_to_ND();
350 7         15 @pa = $m->coeff_to_ND();
351            
352 7         11 $numer = $qa[0]*$pa[1];
353 7         10 $denom = $qa[1]*$pa[0];
354            
355 7         14 $nm->coeff_from_ND($numer,$denom);
356            
357             #
358             # determine the variables and exponents
359             #
360 7         12 $nmVars = $nm->variables();
361 7         14 $vars = $m->variables();
362            
363 7         20 foreach $f (keys %$vars)
364             {
365 11 50       22 if (! exists($nmVars->{$f}))
366             {
367 0         0 $nmVars->{$f} = $vars->{$f};;
368             }
369             else
370             {
371 11         22 $nmVars->{$f} -= $vars->{$f};
372             }
373             }
374            
375             # at this point, new variables may be present in the monomial
376             # and/or one or more exponents may now be 0, so reduce.
377 7         19 $nm->reduceVariables();
378            
379 7         23 return $nm;
380             }
381            
382             sub
383             mult
384             {
385 30     30 1 38 my $self = shift;
386 30         36 my $m = shift;
387 30         32 my $nm;
388             my $nmVars;
389 0         0 my $vars;
390 0         0 my $f;
391 0         0 my @pa;
392 0         0 my @qa;
393 0         0 my $numer;
394 0         0 my $denom;
395            
396 30         61 $nm = Math::MVPoly::Monomial->new();
397 30         56 $nm->copy($self);
398            
399             #
400             # calc. the coefficient
401             #
402 30         58 @qa = $self->coeff_to_ND();
403 30         60 @pa = $m->coeff_to_ND();
404            
405 30         45 $numer = $qa[0]*$pa[0];
406 30         32 $denom = $qa[1]*$pa[1];
407            
408 30         58 $nm->coeff_from_ND($numer,$denom);
409            
410             #
411             # determine the variables and exponents
412             #
413 30         54 $nmVars = $nm->variables();
414 30         51 $vars = $m->variables();
415            
416 30         63 foreach $f (keys %$vars)
417             {
418 16 100       79 if (! exists($nmVars->{$f}))
419             {
420 2         11 $nmVars->{$f} = $vars->{$f};;
421             }
422             else
423             {
424 14         35 $nmVars->{$f} += $vars->{$f};
425             }
426             }
427            
428             # at this point, new variables may be present in the monomial
429             # and/or one or more exponents may now be 0, so reduce.
430 30         94 $nm->reduceVariables();
431            
432 30         90 return $nm;
433             }
434            
435             sub
436             coeff_to_ND
437             {
438 287     287 1 323 my $self = shift;
439 287         280 my $x;
440             my @xa;
441            
442 287         455 $x = $self->coefficient();
443            
444 287         516 @xa = ($x,1);
445            
446 287 100       1152 if ($x =~ /\//)
447             {
448 14         39 @xa = split('\/',$x);
449             }
450            
451 287         716 return (@xa);
452             }
453            
454             sub
455             coeff_from_ND
456             {
457 47     47 1 55 my $self = shift;
458 47         50 my $numer = shift;
459 47         50 my $denom = shift;
460 47         49 my $c;
461            
462 47 100       113 if ($numer/$denom != int($numer/$denom))
463             {
464 6         12 $c = "$numer/$denom";
465             }
466             else
467             {
468 41         46 $c = $numer/$denom;
469             }
470            
471 47         85 $self->coefficient($c);
472             }
473            
474             sub
475             reduceCoefficient
476             {
477 144     144 1 160 my $self = shift;
478 144         149 my $i;
479             my $j;
480 0         0 my $r;
481            
482 144         277 ($i,$j) = $self->coeff_to_ND();
483 144 50       336 if ($i != 0)
484             {
485 144         331 $r = Math::MVPoly::Integer::gcd($i,$j);
486             }
487 144 50       680 if ($r > 1)
488             {
489 0         0 $i /= $r;
490 0         0 $j /= $r;
491 0         0 $self->coeff_from_ND($i,$j);
492             }
493             }
494            
495             sub
496             reduceVariables
497             {
498 37     37 1 42 my $self = shift;
499 37         45 my $vars;
500             my $k;
501            
502 37         66 $vars = $self->variables();
503            
504 37         83 foreach $k (keys %$vars)
505             {
506 47 100       127 if ($vars->{$k} == 0)
507             {
508 4         13 delete($vars->{$k});
509             }
510             }
511             }
512            
513             sub
514             getLCM
515             {
516 4     4 1 4 my $self = shift;
517 4         6 my $b = shift;
518 4         5 my $varOrder;
519             my $f;
520 0         0 my $lcm;
521 0         0 my $a_vars;
522 0         0 my $b_vars;
523 0         0 my $lcm_vars;
524 0         0 my $ea;
525 0         0 my $eb;
526 0         0 my $e;
527            
528 4         19 $lcm = Math::MVPoly::Monomial->new();
529 4         9 $lcm->copy($self);
530            
531 4         8 $a_vars = $self->variables();
532 4         9 $b_vars = $b->variables();
533 4         5 $lcm_vars = $lcm->variables();
534            
535 4         9 $varOrder = $self->varOrder();
536            
537 4         8 foreach $f (@$varOrder)
538             {
539 8         10 $ea = $a_vars->{$f};
540 8         11 $eb = $b_vars->{$f};
541 8 100       20 $lcm_vars->{$f} = ($ea > $eb ? $ea : $eb);
542             }
543            
544 4         11 return $lcm;
545             }
546            
547             1;
548            
549             __END__