File Coverage

blib/lib/Math/Algebra/Symbols.pm
Criterion Covered Total %
statement 46 49 93.8
branch 10 14 71.4
condition 8 12 66.6
subroutine 15 15 100.0
pod n/a
total 79 90 87.7


line stmt bran cond sub pod time code
1             =pod
2            
3             =head1 Name
4            
5             Math::Algebra::Symbols
6            
7             =head1 Synopsis
8            
9             Symbolic Algebra in Pure Perl
10            
11             use Math::Algebra::Symbols hyper=>1;
12             use Test::Simple tests=>5;
13            
14             ($n, $x, $y) = symbols(qw(n x y));
15            
16             $a += ($x**8 - 1)/($x-1);
17             $b += sin($x)**2 + cos($x)**2;
18             $c += (sin($n*$x) + cos($n*$x))->d->d->d->d / (sin($n*$x)+cos($n*$x));
19             $d = tanh($x+$y) == (tanh($x)+tanh($y))/(1+tanh($x)*tanh($y));
20             ($e,$f) = @{($x**2 eq 5*$x-6) > $x};
21            
22             print "$a\n$b\n$c\n$d\n$e,$f\n";
23            
24             ok("$a" eq '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1');
25             ok("$b" eq '1');
26             ok("$c" eq '$n**4');
27             ok("$d" eq '1');
28             ok("$e,$f" eq '2,3');
29            
30             The focii to locus round trip of an ellipse has a length of twice the
31             major radius:
32            
33             use Math::Algebra::Symbols;
34             use Test::More tests => 1;
35             my ($R, $f, $x, $i) = symbols(qw(R f x i)); # Major radius, focii
36            
37             my $y = sqrt($R*$R-$f*$f - $x*$x +$f*$f*$x*$x / ($R*$R)); # Ellipse: rr=RR-ff
38             my $a = $x+$i*$y - $f; # Vector from focus1 to a point on the locus
39             my $b = $x+$i*$y + $f; # Vector from focus2 to same point on the locus
40            
41             ok(abs($a) + abs($b) == 2*$R, 'Focus trip is constant 2R');
42            
43             Floating point calculations on a triangle with angles of 22.5, 45, 112.5
44             degrees to determine whether two of the diameters of the nine point circle
45             are at right angles yield (on my computer) the following inconclusive result
46             when the dot product between the diameters is formed numerically:
47            
48             my $o = 1;
49             my $a = sqrt($o/2); # X position of apex
50             my $b = $o - $a; # Y position of apex
51             my $s = ($a*$a+$b*$b-$a)/2/$b;
52             my ($nx, $ny) = ($o/4 + $a/2, $b/2 - $s/2); # Nine point centre
53             my ($px, $py) = ($o/2, 0); # Diameter from mid point
54             my ($qx, $qy) = ($o/2 + $a/2, $b/2); # Diameter from mid point
55            
56             my $d = ($px-$nx)*($qx-$nx)+($py-$ny)*($qy-$ny); # Dot product should be zero
57             print +($d == 0)||0, "\n$d\n"; # Definitively zero if 1
58            
59             # 0 # Not exactly zero
60             # -6.93889390390723e-18 # Is this significant or not?
61            
62             By contrast with Math::Algebra::Symbols I get the much more convincing:
63            
64             my ($o, $i) = symbols(qw(1 i)); # Units in x,y
65             my $a = sqrt($o/2); # X position of apex
66             my $b = $o - $a; # Y position of apex
67             my $s = ($a*$a+$b*$b-$a)/2/$b;
68             my $n = $o/4 + $a/2 +$i*($b/2 - $s/2); # Nine point centre
69             my $p = $o/2; # Diameter from mid point
70             my $q = $o/2 + $a/2 +$i* $b/2; # Diameter from mid point
71            
72             my $d = (($p-$n) ^ ($q-$n)); # Dot product should be zero
73             print +($d == 0)||0, "\n$d\n"; # Definitively zero if 1
74            
75             # 1
76             # 17/32/(-2*sqrt(1/2)+3/2)-3/4/(-2*sqrt(1/2)+3/2)*sqrt(1/2)-7/16/(-sqrt(1/2)+1)
77             # +5/8/(-sqrt(1/2)+1)*sqrt(1/2)-1/8*sqrt(1/2)+1/16
78            
79             =head1 Description
80            
81             This package supplies a set of functions and operators to manipulate operator
82             expressions algebraically using the familiar Perl syntax.
83            
84             These expressions are constructed from L, L, and
85             L, and processed via L. For examples, see:
86             L.
87            
88             =head2 Symbols
89            
90             Symbols are created with the exported B constructor routine:
91            
92             use Math::Algebra::Symbols;
93             use Test::Simple tests=>1;
94            
95             my ($x, $y, $i, $o, $pi) = symbols(qw(x y i 1 pi));
96            
97             ok( "$x $y $i $o $pi" eq '$x $y i 1 $pi' );
98            
99             The B routine constructs references to symbolic variables and
100             symbolic constants from a list of names and integer constants.
101            
102             It is often useful to declare a variable B<$o> to contain the unit B<1> with
103             which to start symbolic expressions, thus:
104            
105             $o/2 is a symbolic expression for one half where-as:
106            
107             1/2 == 0.5 is merely the numeric representation of one half.
108            
109             The special symbol B is recognized as the square root of B<-1>.
110            
111             The special symbol B is recognized as the smallest positive real that
112             satisfies:
113            
114             use Math::Algebra::Symbols;
115             use Test::Simple tests=>2;
116            
117             my ($i, $pi) = symbols(qw(i pi));
118            
119             ok( exp($i*$pi) == -1 );
120             ok( exp($i*$pi) <=> '-1' );
121            
122             =head3 Constructor Routine Name
123            
124             If you wish to use a different name for the constructor routine, say
125             B:
126            
127             use Math::Algebra::Symbols symbols=>'S';
128             use Test::Simple tests=>2;
129            
130             my ($i, $pi) = S(qw(i pi));
131            
132             ok( exp($i*$pi) == -1 );
133             ok( exp($i*$pi) <=//> '-1' );
134            
135            
136             =head3 Big Integers
137            
138             Symbols automatically uses big integers if needed.
139            
140             use Math::Algebra::Symbols;
141             use Test::Simple tests=>1;
142            
143             my $z = symbols('1234567890987654321/1234567890987654321');
144            
145             ok( eval $z eq '1');
146            
147             =head2 Operators
148            
149             L can be combined with L to create symbolic
150             expressions:
151            
152             =head3 Arithmetic operators
153            
154            
155             =head4 Arithmetic Operators: B<+> B<-> B<*> B B<**>
156            
157             use Math::Algebra::Symbols;
158             use Test::Simple tests=>3;
159            
160             my ($x, $y) = symbols(qw(x y));
161            
162             ok( ($x**2-$y**2)/($x-$y) == $x+$y );
163             ok( ($x**2-$y**2)/($x-$y) != $x-$y );
164             ok( ($x**2-$y**2)/($x-$y) <=> '$x+$y' );
165            
166             The operators: B<+=> B<-=> B<*=> B are overloaded to work symbolically
167             rather than numerically. If you need numeric results, you can always
168             B the resulting symbolic expression.
169            
170             =head4 Square root Operator: B
171            
172             use Math::Algebra::Symbols;
173             use Test::Simple tests=>2;
174            
175             my ($x, $i) = symbols(qw(x i));
176            
177             ok( sqrt(-$x**2) == $i*$x );
178             ok( sqrt(-$x**2) <=> 'i*$x' );
179            
180             The square root is represented by the symbol B, which allows complex
181             expressions to be processed by Math::Complex.
182            
183             =head4 Exponential Operator: B
184            
185             use Math::Algebra::Symbols;
186             use Test::Simple tests=>2;
187            
188             my ($x, $i) = symbols(qw(x i));
189            
190             ok( exp($x)->d($x) == exp($x) );
191             ok( exp($x)->d($x) <=> 'exp($x)' );
192            
193             The exponential operator.
194            
195             =head4 Logarithm Operator: B
196            
197             use Math::Algebra::Symbols;
198             use Test::Simple tests=>1;
199            
200             my ($x) = symbols(qw(x));
201            
202             ok( log($x) <=> 'log($x)' );
203            
204             Logarithm to base B.
205            
206             Note: the above result is only true for x > 0. B does not include
207             domain and range specifications of the functions it uses.
208            
209             =head4 Sine and Cosine Operators: B and B
210            
211             use Math::Algebra::Symbols;
212             use Test::Simple tests=>3;
213            
214             my ($x) = symbols(qw(x));
215            
216             ok( sin($x)**2 + cos($x)**2 == 1 );
217             ok( sin($x)**2 + cos($x)**2 != 0 );
218             ok( sin($x)**2 + cos($x)**2 <=> '1' );
219            
220             This famous trigonometric identity is not preprogrammed into B as it
221             is in commercial products.
222            
223             Instead: an expression for B is constructed using the complex
224             exponential: L, said expression is algebraically multiplied out to
225             prove the identity. The proof steps involve large intermediate expressions in
226             each step, as yet I have not provided a means to neatly lay out these
227             intermediate steps and thus provide a more compelling demonstration of the
228             ability of B to verify such statements from first principles.
229            
230             =head3 Relational operators
231            
232             =head4 Relational operators: B<==>, B
233            
234             use Math::Algebra::Symbols;
235             use Test::Simple tests=>3;
236            
237             my ($x, $y) = symbols(qw(x y));
238            
239             ok( ($x**2-$y**2)/($x-$y) == $x+$y );
240             ok( ($x**2-$y**2)/($x-$y) != $x-$y );
241             ok( ($x**2-$y**2)/($x-$y) <=> '$x+$y' );
242            
243             The relational equality operator B<==> compares two symbolic expressions and
244             returns TRUE(1) or FALSE(0) accordingly. B produces the opposite result.
245            
246             =head4 Relational operator: B
247            
248             my ($x, $v, $t) = symbols(qw(x v t));
249            
250             ok( ($v eq $x / $t)->solve(qw(x in terms of v t)) == $v*$t );
251             ok( ($v eq $x / $t)->solve(qw(x in terms of v t)) != $v+$t );
252             ok( ($v eq $x / $t)->solve(qw(x in terms of v t)) <=> '$t*$v' );
253            
254             The relational operator B is a synonym for the minus B<-> operator, with
255             the expectation that later on the L function will
256             be used to simplify and rearrange the equation. You may prefer to use B
257             instead of B<-> to enhance readability, there is no functional difference.
258            
259             =head3 Complex operators
260            
261             =head4 Complex operators: the B operator: B<^>
262            
263             use Math::Algebra::Symbols;
264             use Test::Simple tests=>3;
265            
266             my ($a, $b, $i) = symbols(qw(a b i));
267            
268             ok( (($a+$i*$b)^($a-$i*$b)) == $a**2-$b**2 );
269             ok( (($a+$i*$b)^($a-$i*$b)) != $a**2+$b**2 );
270             ok( (($a+$i*$b)^($a-$i*$b)) <=> '$a**2-$b**2' );
271            
272             Please note the use of brackets: The B<^> operator has low priority.
273            
274             The B<^> operator treats its left hand and right hand arguments as complex
275             numbers, which in turn are regarded as two dimensional vectors to which the
276             vector dot product is applied.
277            
278             =head4 Complex operators: the B operator: B
279            
280             use Math::Algebra::Symbols;
281             use Test::Simple tests=>3;
282            
283             my ($x, $i) = symbols(qw(x i));
284            
285             ok( $i*$x x $x == $x**2 );
286             ok( $i*$x x $x != $x**3 );
287             ok( $i*$x x $x <=> '$x**2' );
288            
289             The B operator treats its left hand and right hand arguments as complex
290             numbers, which in turn are regarded as two dimensional vectors defining the
291             sides of a parallelogram. The B operator returns the area of this
292             parallelogram.
293            
294             Note the space before the B, otherwise Perl is unable to disambiguate the
295             expression correctly.
296            
297             =head4 Complex operators: the B operator: B<~>
298            
299             use Math::Algebra::Symbols;
300             use Test::Simple tests=>3;
301            
302             my ($x, $y, $i) = symbols(qw(x y i));
303            
304             ok( ~($x+$i*$y) == $x-$i*$y );
305             ok( ~($x-$i*$y) == $x+$i*$y );
306             ok( (($x+$i*$y)^($x-$i*$y)) <=> '$x**2-$y**2' );
307            
308             The B<~> operator returns the complex conjugate of its right hand side.
309            
310             =head4 Complex operators: the B operator: B
311            
312             use Math::Algebra::Symbols;
313             use Test::Simple tests=>3;
314            
315             my ($x, $i) = symbols(qw(x i));
316            
317             ok( abs($x+$i*$x) == sqrt(2*$x**2) );
318             ok( abs($x+$i*$x) != sqrt(2*$x**3) );
319             ok( abs($x+$i*$x) <=> 'sqrt(2*$x**2)' );
320            
321             The B operator returns the modulus (length) of its right hand side.
322            
323             =head4 Complex operators: the B operator: B
324            
325             use Math::Algebra::Symbols;
326             use Test::Simple tests=>4;
327            
328             my ($i) = symbols(qw(i));
329            
330             ok( !$i == $i );
331             ok( !$i <=> 'i' );
332             ok( !($i+1) <=> '1/(sqrt(2))+i/(sqrt(2))' );
333             ok( !($i-1) <=> '-1/(sqrt(2))+i/(sqrt(2))' );
334            
335             The B operator returns a complex number of unit length pointing in the
336             same direction as its right hand side.
337            
338             =head3 Equation Manipulation Operators
339            
340             =head4 Equation Manipulation Operators: B operator: B<+=>
341            
342             use Math::Algebra::Symbols;
343             use Test::Simple tests=>2;
344            
345             my ($x) = symbols(qw(x));
346            
347             ok( ($x**8 - 1)/($x-1) == $x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1 );
348             ok( ($x**8 - 1)/($x-1) <=> '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1' );
349            
350             The simplify operator B<+=> is a synonym for the
351             L method, if and only if,
352             the target on the left hand side initially has a value of undef.
353            
354             Admittedly this is very strange behaviour: it arises due to the shortage of
355             over-ride-able operators in Perl: in particular it arises due to the shortage
356             of over-ride-able unary operators in Perl. Never-the-less: this operator is
357             useful as can be seen in the L, and the desired
358             pre-condition can always achieved by using B.
359            
360             =head4 Equation Manipulation Operators: B operator: B>
361            
362             use Math::Algebra::Symbols;
363             use Test::Simple tests=>2;
364            
365             my ($t) = symbols(qw(t));
366            
367             my $rabbit = 10 + 5 * $t;
368             my $fox = 7 * $t * $t;
369             my ($a, $b) = @{($rabbit eq $fox) > $t};
370            
371             ok( "$a" eq '1/14*sqrt(305)+5/14' );
372             ok( "$b" eq '-1/14*sqrt(305)+5/14' );
373            
374             The solve operator B> is a synonym for the
375             L method.
376            
377             The priority of B> is higher than that of B, so the brackets around
378             the equation to be solved are necessary until Perl provides a mechanism for
379             adjusting operator priority (cf. Algol 68).
380            
381             If the equation is in a single variable, the single variable may be named
382             after the B> operator without the use of [...]:
383            
384             use Math::Algebra::Symbols;
385            
386             my $rabbit = 10 + 5 * $t;
387             my $fox = 7 * $t * $t;
388             my ($a, $b) = @{($rabbit eq $fox) > $t};
389            
390             print "$a\n";
391            
392             # 1/14*sqrt(305)+5/14
393            
394             If there are multiple solutions, (as in the case of polynomials), B>
395             returns an array of symbolic expressions containing the solutions.
396            
397             This example was provided by Mike Schilli m@perlmeister.com.
398            
399             =head2 Functions
400            
401             Perl operator overloading is very useful for producing compact
402             representations of algebraic expressions. Unfortunately there are only a
403             small number of operators that Perl allows to be overloaded. The following
404             functions are used to provide capabilities not easily expressed via Perl
405             operator overloading.
406            
407             These functions may either be called as methods from symbols constructed by
408             the L construction routine, or they may be exported into the user's
409             name space as described in L.
410            
411             =head3 Trigonometric and Hyperbolic functions
412            
413             =head4 Trigonometric functions
414            
415             use Math::Algebra::Symbols;
416             use Test::Simple tests=>1;
417            
418             my ($x, $y) = symbols(qw(x y));
419            
420             ok( (sin($x)**2 == (1-cos(2*$x))/2) );
421            
422             The trigonometric functions B, B, B, B, B, B
423             are available, either as exports to the caller's name space, or as methods.
424            
425             =head4 Hyperbolic functions
426            
427             use Math::Algebra::Symbols hyper=>1;
428             use Test::Simple tests=>1;
429            
430             my ($x, $y) = symbols(qw(x y));
431            
432             ok( tanh($x+$y)==(tanh($x)+tanh($y))/(1+tanh($x)*tanh($y)));
433            
434             The hyperbolic functions B, B, B, B, B, B
435             are available, either as exports to the caller's name space, or as methods.
436            
437             =head3 Complex functions
438            
439             =head4 Complex functions: B and B
440            
441             use Math::Algebra::Symbols;
442             use Test::Simple tests=>2;
443            
444             my ($x, $i) = symbols(qw(x i));
445            
446             ok( ($i*$x)->re <=> 0 );
447             ok( ($i*$x)->im <=> '$x' );
448            
449             The B and B functions return an expression which represents the real
450             and imaginary parts of the expression, assuming that symbolic variables
451             represent real numbers.
452            
453             =head4 Complex functions: B and B
454            
455             use Math::Algebra::Symbols;
456             use Test::Simple tests=>2;
457            
458             my $i = symbols(qw(i));
459            
460             ok( ($i+1)->cross($i-1) <=> 2 );
461             ok( ($i+1)->dot ($i-1) <=> 0 );
462            
463             The B and B operators are available as functions, either as
464             exports to the caller's name space, or as methods.
465            
466             =head4 Complex functions: B, B and B
467            
468             use Math::Algebra::Symbols;
469             use Test::Simple tests=>3;
470            
471             my $i = symbols(qw(i));
472            
473             ok( ($i+1)->unit <=> '1/(sqrt(2))+i/(sqrt(2))' );
474             ok( ($i+1)->modulus <=> 'sqrt(2)' );
475             ok( ($i+1)->conjugate <=> '1-i' );
476            
477             The B, B and B operators are available as functions:
478             B, B and B, either as exports to the caller's name
479             space, or as methods. The confusion over the naming of: the B operator
480             being the same as the B complex function; arises over the limited
481             set of Perl operator names available for overloading.
482            
483             =head2 Methods
484            
485             =head3 Methods for manipulating Equations
486            
487             =head4 Simplifying equations: B
488            
489             Example t/simplify2.t
490            
491             use Math::Algebra::Symbols;
492             use Test::Simple tests=>2;
493            
494             my ($x) = symbols(qw(x));
495            
496             my $y = (($x**8 - 1)/($x-1))->simplify(); # Simplify method
497             my $z += ($x**8 - 1)/($x-1); # Simplify via +=
498            
499             ok( "$y" eq '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1' );
500             ok( "$z" eq '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1' );
501            
502             B attempts to simplify an expression. There is no general
503             simplification algorithm: consequently simplifications are carried out on
504             ad-hoc basis. You may not even agree that the proposed simplification for a
505             given expressions is indeed any simpler than the original. It is for these
506             reasons that simplification has to be explicitly requested rather than being
507             performed auto-magically.
508            
509             At the moment, simplifications consist of polynomial division: when the
510             expression consists, in essence, of one polynomial divided by another, an
511             attempt is made to perform polynomial division, the result is returned if
512             there is no remainder.
513            
514             The B<+=> operator may be used to simplify and assign an expression to a Perl
515             variable. Perl operator overloading precludes the use of B<=> in this manner.
516            
517             =head4 Substituting into equations: B
518            
519             use Math::Algebra::Symbols;
520             use Test::Simple tests=>2;
521            
522             my ($x, $y) = symbols(qw(x y));
523            
524             my $e = 1+$x+$x**2/2+$x**3/6+$x**4/24+$x**5/120;
525            
526             ok( $e->sub(x=>$y**2, z=>2) <=> '$y**2+1/2*$y**4+1/6*$y**6+1/24*$y**8+1/120*$y**10+1' );
527             ok( $e->sub(x=>1) <=> '163/60');
528            
529             The B function example on line B<#1> demonstrates replacing variables
530             with expressions. The replacement specified for B has no effect as B is
531             not present in this equation.
532            
533             Line B<#2> demonstrates the resulting rational fraction that arises when all
534             the variables have been replaced by constants. This package does not convert
535             fractions to decimal expressions in case there is a loss of accuracy,
536             however:
537            
538             my $e2 = $e->sub(x=>1);
539             $result = eval "$e2";
540            
541             or similar will produce approximate results.
542            
543             At the moment only variables can be replaced by expressions. Mike Schilli,
544             m@perlmeister.com, has proposed that substitutions for expressions should
545             also be allowed, as in:
546            
547             $x/$y => $z
548            
549            
550             =head4 Solving equations: B
551            
552             use Math::Algebra::Symbols;
553             use Test::Simple tests=>3;
554            
555             my ($x, $v, $t) = symbols(qw(x v t));
556            
557             ok( ($v eq $x / $t)->solve(qw(x in terms of v t)) == $v*$t );
558             ok( ($v eq $x / $t)->solve(qw(x in terms of v t)) != $v/$t );
559             ok( ($v eq $x / $t)->solve(qw(x in terms of v t)) <=> '$t*$v' );
560            
561             B assumes that the equation on the left hand side is equal to zero,
562             applies various simplifications, then attempts to rearrange the equation to
563             obtain an equation for the first variable in the parameter list assuming that
564             the other terms mentioned in the parameter list are known constants. There
565             may of course be other unknown free variables in the equation to be solved:
566             the proposed solution is automatically tested against the original equation
567             to check that the proposed solution removes these variables, an error is
568             reported via B if it does not.
569            
570             use Math::Algebra::Symbols;
571             use Test::Simple tests => 2;
572            
573             my ($x) = symbols(qw(x));
574            
575             my $p = $x**2-5*$x+6; # Quadratic polynomial
576             my ($a, $b) = @{($p > $x )}; # Solve for x
577            
578             print "x=$a,$b\n"; # Roots
579            
580             ok($a == 2);
581             ok($b == 3);
582            
583             If there are multiple solutions, (as in the case of polynomials), B
584             returns an array of symbolic expressions containing the solutions.
585            
586             =head3 Methods for performing Calculus
587            
588             =head4 Differentiation: B
589            
590             use Math::Algebra::Symbols;
591             use Test::More tests => 5;
592            
593             $x = symbols(qw(x));
594            
595             ok( sin($x) == sin($x)->d->d->d->d);
596             ok( cos($x) == cos($x)->d->d->d->d);
597             ok( exp($x) == exp($x)->d($x)->d('x')->d->d);
598             ok( (1/$x)->d == -1/$x**2);
599             ok( exp($x)->d->d->d->d <=> 'exp($x)' );
600            
601             B differentiates the equation on the left hand side by the named
602             variable.
603            
604             The variable to be differentiated by may be explicitly specified, either as a
605             string or as single symbol; or it may be heuristically guessed as follows:
606            
607             If the equation to be differentiated refers to only one symbol, then that
608             symbol is used. If several symbols are present in the equation, but only one
609             of B, B, B, B is present, then that variable is used in honour of
610             Newton, Leibnitz, Cauchy.
611            
612             =head2 Example of Equation Solving: the focii of a hyperbola:
613            
614             use Math::Algebra::Symbols;
615            
616             my ($a, $b, $x, $y, $i, $o) = symbols(qw(a b x y i 1));
617            
618             print
619             "Hyperbola: Constant difference between distances from focii to locus of y=1/x",
620             "\n Assume by symmetry the focii are on ",
621             "\n the line y=x: ", $f1 = $x + $i * $x,
622             "\n and equidistant from the origin: ", $f2 = -$f1,
623             "\n Choose a convenient point on y=1/x: ", $a = $o+$i,
624             "\n and a general point on y=1/x: ", $b = $y+$i/$y,
625             "\n Difference in distances from focii",
626             "\n From convenient point: ", $A = abs($a - $f2) - abs($a - $f1),
627             "\n From general point: ", $B = abs($b - $f2) + abs($b - $f1),
628             "\n\n Solving for x we get: x=", ($A - $B) > $x,
629             "\n (should be: sqrt(2))",
630             "\n Which is indeed constant, as was to be demonstrated\n";
631            
632             This example demonstrates the power of symbolic processing by finding the
633             focii of the curve B, and incidentally, demonstrating that this curve
634             is a hyperbola.
635            
636             =head1 Exports
637            
638             use Math::Algebra::Symbols
639             symbols=>'s',
640             trig => 1,
641             hyper => 1,
642             complex=> 1;
643            
644             =over
645            
646             =item symbols=>'s'
647            
648             Create a function with name B in the callers name space to create new
649             symbols. The default is B.
650            
651             =item trig=>0
652            
653             The default, do not export trigonometric functions.
654            
655             =item trig=>1
656            
657             Export trigonometric functions: B, B, B, B to the
658             caller's name space. B, B are created by default by overloading the
659             existing Perl B and B operators.
660            
661             =item B
662            
663             Alias of B
664            
665             =item hyperbolic=>0
666            
667             The default, do not export hyperbolic functions.
668            
669             =item hyper=>1
670            
671             Export hyperbolic functions: B, B, B, B,
672             B, B to the caller's name space.
673            
674             =item B
675            
676             Alias of B
677            
678             =item complex=>0
679            
680             The default, do not export complex functions
681            
682             =item complex=>1
683            
684             Export complex functions: B, B, B, B, B,
685             B, B to the caller's name space.
686            
687             =back
688            
689             =cut
690            
691             package Math::Algebra::Symbols;
692 45     45   35749 use strict;
  45         50  
  45         1580  
693             our $VERSION=1.27;
694 45     45   20201 use Math::Algebra::Symbols::Sum;
  45         84  
  45         158  
695 45     45   152 use Carp;
  45         46  
  45         15210  
696            
697             sub import
698 45     45   340 {my %P = (program=>@_);
699 45         49 my %p; $p{lc()} = $P{$_} for(keys(%P));
  45         198  
700            
701             #_ Symbols _____________________________________________________________
702             # New symbols term constructor - export to calling package.
703             #_______________________________________________________________________
704            
705 45         80 my $s = "package XXXX;\n". <<'END';
706             no warnings 'redefine';
707             sub NNNN
708             {return SSSSsum(@_);
709             }
710             END
711            
712             #_ Symbols _____________________________________________________________
713             # Complex functions: re, im, dot, cross, conjugate, modulus
714             #_______________________________________________________________________
715            
716 45 50       142 if (exists($p{complex}))
717 0         0 {$s .= <<'END';
718             sub conjugate($) {$_[0]->conjugate()}
719             sub cross ($$) {$_[0]->cross ($_[1])}
720             sub dot ($$) {$_[0]->dot ($_[1])}
721             sub im ($) {$_[0]->im ()}
722             sub modulus ($) {$_[0]->modulus ()}
723             sub re ($) {$_[0]->re ()}
724             sub unit ($) {$_[0]->unit ()}
725             END
726             }
727            
728             #_ Symbols _____________________________________________________________
729             # Trigonometric functions: tan, sec, csc, cot
730             #_______________________________________________________________________
731            
732 45 100 66     224 if (exists($p{trig}) or exists($p{trigonometric}))
733 2         4 {$s .= <<'END';
734             sub tan($) {$_[0]->tan()}
735             sub sec($) {$_[0]->sec()}
736             sub csc($) {$_[0]->csc()}
737             sub cot($) {$_[0]->cot()}
738             END
739             }
740 45 50 66     118 if (exists($p{trig}) and exists($p{trigonometric}))
741 0         0 {croak 'Please use specify just one of trig or trigonometric';
742             }
743            
744             #_ Symbols _____________________________________________________________
745             # Hyperbolic functions: sinh, cosh, tanh, sech, csch, coth
746             #_______________________________________________________________________
747            
748 45 100 66     329 if (exists($p{hyper}) or exists($p{hyperbolic}))
749 3         4 {$s .= <<'END';
750             sub sinh($) {$_[0]->sinh()}
751             sub cosh($) {$_[0]->cosh()}
752             sub tanh($) {$_[0]->tanh()}
753             sub sech($) {$_[0]->sech()}
754             sub csch($) {$_[0]->csch()}
755             sub coth($) {$_[0]->coth()}
756             END
757             }
758 45 50 66     101 if (exists($p{hyper}) and exists($p{hyperbolic}))
759 0         0 {croak 'Please specify just one of hyper or hyperbolic';
760             }
761            
762             #_ Symbols _____________________________________________________________
763             # Export to calling package.
764             #_______________________________________________________________________
765            
766 45         68 $s .= <<'END';
767             use warnings 'redefine';
768             END
769            
770 45         50 my $name = 'symbols';
771 45 100       103 $name = $p{symbols} if exists($p{symbols});
772 45         97 my ($main) = caller();
773 45         64 my $pack = __PACKAGE__. '::';
774            
775 45         164 $s=~ s/XXXX/$main/g;
776 45         126 $s=~ s/NNNN/$name/g;
777 45         116 $s=~ s/SSSS/$pack/g;
778 45     45   180 eval($s);
  45     45   52  
  45     65   2490  
  45     40   148  
  45     25   44  
  45     4   850  
  45     11   2508  
  65     4   4680  
  40     11   193  
  25     4   87  
  4     12   15  
  11         45  
  4         14  
  11         40  
  4         15  
  12         35  
779            
780             #_ Symbols _____________________________________________________________
781             # Check options supplied by user
782             #_______________________________________________________________________
783            
784 45         127 delete @p{qw(
785             symbols program trig trigonometric hyper hyperbolic complex
786             )};
787            
788 45 50       2210 croak "Unknown option(s): ". join(' ', keys(%p))."\n\n". <<'END' if keys(%p);
789            
790             Valid options are:
791            
792             symbols=>'symbols' Create a routine with this name in the callers
793             name space to create new symbols. The default is
794             'symbols'.
795            
796            
797             trig =>0 The default, no trigonometric functions
798             trig =>1 Export trigonometric functions: tan, sec, csc, cot.
799             sin, cos are created by default by overloading
800             the existing Perl sin and cos operators.
801            
802             trigonometric can be used instead of trig.
803            
804            
805             hyper =>0 The default, no hyperbolic functions
806             hyper =>1 Export hyperbolic functions:
807             sinh, cosh, tanh, sech, csch, coth.
808            
809             hyperbolic can be used instead of hyper.
810            
811            
812             complex=>0 The default, no complex functions
813             complex=>1 Export complex functions:
814             conjugate, cross, dot, im, modulus, re, unit
815            
816             END
817             }
818            
819             #_ Symbols _____________________________________________________________
820             # Package installed successfully
821             #_______________________________________________________________________
822            
823             1;
824            
825             =pod
826            
827             =head1 Packages
828            
829             The B packages manipulate a sum of products representation of an
830             algebraic equation. The B package is the user interface to the
831             functionality supplied by the B and B packages.
832            
833             =head2 Math::Algebra::Symbols::Term
834            
835             B represents a product term. A product term consists of the
836             number B<1>, optionally multiplied by:
837            
838             =over
839            
840             =item Variables
841            
842             Any number of variables raised to integer powers.
843            
844             =item Coefficient
845            
846             An integer coefficient optionally divided by a positive integer divisor, both
847             represented as BigInts if necessary.
848            
849             =item Sqrt
850            
851             The sqrt of of any symbolic expression representable by the B
852             package, including minus one: represented as B.
853            
854             =item Reciprocal
855            
856             The multiplicative inverse of any symbolic expression representable by the
857             B package: i.e. a B may be divided by any symbolic
858             expression representable by the B package.
859            
860             =item Exp
861            
862             The number B raised to the power of any symbolic expression representable
863             by the B package.
864            
865             =item Log
866            
867             The logarithm to base B of any symbolic expression representable by the
868             B package.
869            
870             =back
871            
872             Thus B can represent expressions like:
873            
874             2/3*$x**2*$y**-3*exp($i*$pi)*sqrt($z**3) / $x
875            
876             but not:
877            
878             $x + $y
879            
880             for which package B is required.
881            
882            
883             =head2 Math::Algebra::Symbols::Sum
884            
885             B represents a sum of product terms supplied by
886             B and thus behaves as a polynomial. Operations such as
887             equation solving and differentiation are applied at this level.
888            
889             =head1 Installation
890            
891             Standard Module::Build process for building and installing modules:
892            
893             perl Build.PL
894             ./Build
895             ./Build test
896             ./Build install
897            
898             =head1 Copyright
899            
900             Philip R Brenan at B 2004-2016
901            
902             =head1 License
903            
904             Perl License.
905            
906             =cut