The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.


=head1 Symbols


Symbolic Algebra in Pure Perl.

See user manual L</NAME>.

PhilipRBrenan@yahoo.com, 2004, Perl License.


=head2 Synopsis


This package delivers the public components of package B<sum>.


 
 
 package Math::Algebra::Symbols;
 $VERSION=1.21;
 use Math::Algebra::Symbols::Sum;
 use Carp;
 
 


=head2 import


Export components as requested by caller.

 use Math::Algebra::Symbols symbols=>'s' trig=>1 hyper=>1 complex=>0;

Valid options are:



=over






=item symbols=>'s'




Create a function with name B<s()> in the callers namespace to create
new symbols. The default is B<symbols()>.

item trig=>0

The default, no trigonometric functions  are exported.        

item trig=>1

Export trigonometric functions: tan, sec, csc, cot. sin, cos are created
by default by overloading the existing Perl sin and cos operators.



=item hyper=>0




The default, no hyperbolic functions         



=item hyper=>1




Export hyperbolic functions: sinh, cosh, tanh, sech, csch, coth.



=item complex=>0




The default, no complex functions         



=item complex=>1




Export complex functions:  conjugate, cross, dot, im, modulus, re,  unit.



=back




Trigonometric can be used instead of trig.

Hyperbolic can be used instead of hyper.



 
 
 sub import
  {my %P = (program=>@_);
   my %p; $p{lc()} = $P{$_} for(keys(%P));
 
 #_ Symbols _____________________________________________________________
 # New symbols term constructor - export to calling package.
 #_______________________________________________________________________
 
   my $s = "package XXXX;\n". <<'END';
 no warnings 'redefine';
 sub NNNN
  {return SSSSsum(@_);
  }
 END
 
 #_ Symbols _____________________________________________________________
 # Complex functions: re, im, dot, cross, conjugate, modulus              
 #_______________________________________________________________________
   
   if (exists($p{complex}))
    {$s .= <<'END';
 sub conjugate($)  {$_[0]->conjugate()}
 sub cross    ($$) {$_[0]->cross    ($_[1])}
 sub dot      ($$) {$_[0]->dot      ($_[1])}
 sub im       ($)  {$_[0]->im       ()}
 sub modulus  ($)  {$_[0]->modulus  ()}
 sub re       ($)  {$_[0]->re       ()}
 sub unit     ($)  {$_[0]->unit     ()}
 END
    }
 
 #_ Symbols _____________________________________________________________
 # Trigonometric functions: tan, sec, csc, cot              
 #_______________________________________________________________________
 
   if (exists($p{trig}) or exists($p{trigonometric}))
    {$s .= <<'END';
 sub tan($) {$_[0]->tan()}
 sub sec($) {$_[0]->sec()}
 sub csc($) {$_[0]->csc()}
 sub cot($) {$_[0]->cot()}
 END
    }
   if (exists($p{trig}) and exists($p{trigonometric}))
    {croak 'Please use specify just one of trig or trigonometric';
    }
 
 #_ Symbols _____________________________________________________________
 # Hyperbolic functions: sinh, cosh, tanh, sech, csch, coth              
 #_______________________________________________________________________
 
  if (exists($p{hyper}) or exists($p{hyperbolic}))
   {$s .= <<'END';
 sub sinh($) {$_[0]->sinh()}
 sub cosh($) {$_[0]->cosh()}
 sub tanh($) {$_[0]->tanh()}
 sub sech($) {$_[0]->sech()}
 sub csch($) {$_[0]->csch()}
 sub coth($) {$_[0]->coth()}
 END
   }
  if (exists($p{hyper}) and exists($p{hyperbolic}))
   {croak 'Please specify just one of hyper or hyperbolic';
   }
 
 #_ Symbols _____________________________________________________________
 # Export to calling package.
 #_______________________________________________________________________
 
     $s .= <<'END';
 use warnings 'redefine';
 END
  
   my $name   = 'symbols';
      $name   = $p{symbols} if exists($p{symbols});
   my ($main) = caller();
   my $pack   = __PACKAGE__. '::';   
 
   $s=~ s/XXXX/$main/g;
   $s=~ s/NNNN/$name/g;
   $s=~ s/SSSS/$pack/g;
   eval($s);
 
 #_ Symbols _____________________________________________________________
 # Check options supplied by user
 #_______________________________________________________________________
 
   delete @p{qw(
 symbols program trig trigonometric hyper hyperbolic complex
 )};
 
   croak "Unknown option(s): ". join(' ', keys(%p))."\n\n". <<'END' if keys(%p);
 
 Valid options are:
 
   symbols=>'symbols' Create a routine with this name in the callers
                   namespace to create new symbols. The default is
                   'symbols'.
 
 
   trig   =>0      The default, no trigonometric functions         
   trig   =>1      Export trigonometric functions: tan, sec, csc, cot.
                   sin, cos are created by default by overloading 
                   the existing Perl sin and cos operators.
 
   trigonometric can be used instead of trig.
 
 
   hyper  =>0      The default, no hyperbolic functions         
   hyper  =>1      Export hyperbolic functions:
                     sinh, cosh, tanh, sech, csch, coth.
 
   hyperbolic can be used instead of hyper.
 
 
   complex=>0      The default, no complex functions         
   complex=>1      Export complex functions:
                     conjugate, cross, dot, im, modulus, re,  unit
 
 END
  }
 
 #_ Symbols _____________________________________________________________
 # Package installed successfully
 #_______________________________________________________________________
 
 1;
 
 __DATA__
 
 
 #______________________________________________________________________
 # User guide.
 #______________________________________________________________________
 


=head1 NAME


Math::Algebra::Symbols - Symbolic Algebra in Pure Perl.

User guide.


=head1 SYNOPSIS


Example symbols.pl

 #!perl -w -I..
 #______________________________________________________________________
 # Symbolic algebra.
 # Perl License.
 # PhilipRBrenan@yahoo.com, 2004.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols hyper=>1;
 use Test::Simple tests=>5;
 
 ($n, $x, $y) = symbols(qw(n x y));
 
 $a     += ($x**8 - 1)/($x-1);
 $b     +=  sin($x)**2 + cos($x)**2; 
 $c     += (sin($n*$x) + cos($n*$x))->d->d->d->d / (sin($n*$x)+cos($n*$x));
 $d      =  tanh($x+$y) == (tanh($x)+tanh($y))/(1+tanh($x)*tanh($y));
 ($e,$f) =  @{($x**2 eq 5*$x-6) > $x};
 
 print "$a\n$b\n$c\n$d\n$e,$f\n";
 
 ok("$a"    eq '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1');
 ok("$b"    eq '1'); 
 ok("$c"    eq '$n**4'); 
 ok("$d"    eq '1'); 
 ok("$e,$f" eq '2,3');
 



=head1 DESCRIPTION


This package supplies a set of functions and operators to manipulate
operator expressions algebraically using the familiar Perl syntax.

These expressions are constructed
from L</Symbols>, L</Operators>, and L</Functions>, and processed via
L</Methods>.  For examples, see: L</Examples>.


=head2 Symbols


Symbols are created with the exported B<symbols()> constructor routine:

Example t/constants.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: constants.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>1;
 
 my ($x, $y, $i, $o, $pi) = symbols(qw(x y i 1 pi));
 
 ok( "$x $y $i $o $pi"   eq   '$x $y i 1 $pi'  );
 


The B<symbols()> routine constructs references to symbolic variables and
symbolic constants from a list of names and integer constants.

The special symbol B<i> is recognized as the square root of B<-1>.

The special symbol B<pi> is recognized as the smallest positive real
that satisfies:

Example t/ipi.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: constants.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
 
 my ($i, $pi) = symbols(qw(i pi));
 
 ok(  exp($i*$pi)  ==   -1  );
 ok(  exp($i*$pi) <=>  '-1' );
 



=head3 Constructor Routine Name


If you wish to use a different name for the constructor routine, say
B<S>:

Example t/ipi2.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: constants.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols symbols=>'S';
 use Test::Simple tests=>2;
 
 my ($i, $pi) = S(qw(i pi));
 
 ok(  exp($i*$pi)  ==   -1  );
 ok(  exp($i*$pi) <=>  '-1' );



=head3 Big Integers


Symbols automatically uses big integers if needed.

Example t/bigInt.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: bigInt.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>1;
 
 my $z = symbols('1234567890987654321/1234567890987654321');
 
 ok( eval $z eq '1');
 



=head2 Operators


L</Symbols> can be combined with L</Operators> to create symbolic expressions:


=head3 Arithmetic operators




=head4 Arithmetic Operators: B<+> B<-> B<*> B</> B<**> 

            
Example t/x2y2.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: simplification.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($x, $y) = symbols(qw(x y));
 
 ok(  ($x**2-$y**2)/($x-$y)  ==  $x+$y  );
 ok(  ($x**2-$y**2)/($x-$y)  !=  $x-$y  );
 ok(  ($x**2-$y**2)/($x-$y) <=> '$x+$y' );
 
 


The operators: B<+=> B<-=> B<*=> B</=> are overloaded to work
symbolically rather than numerically. If you need numeric results, you
can always B<eval()> the resulting symbolic expression.


=head4 Square root Operator: B<sqrt>       


Example t/ix.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: sqrt(-1).
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
 
 my ($x, $i) = symbols(qw(x i));
 
 ok(  sqrt(-$x**2)  ==  $i*$x  );
 ok(  sqrt(-$x**2)  <=> 'i*$x' );
 
 


The square root is represented by the symbol B<i>, which allows complex
expressions to be processed by Math::Complex.


=head4 Exponential Operator: B<exp>       


Example t/expd.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: exp.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
 
 my ($x, $i) = symbols(qw(x i));
 
 ok(   exp($x)->d($x)  ==   exp($x)  );
 ok(   exp($x)->d($x) <=>  'exp($x)' );
 
 


The exponential operator.


=head4 Logarithm Operator: B<log>       


Example t/logExp.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: log: need better example.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>1;
 
 my ($x) = symbols(qw(x));
 
 ok(   log($x) <=>  'log($x)' );
 
 


Logarithm to base B<e>.

Note: the above result is only true for x > 0.  B<Symbols> does not include domain and range
specifications of the functions it uses.


=head4 Sine and Cosine Operators: B<sin> and B<cos>       


Example t/sinCos.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: simplification.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($x) = symbols(qw(x));
 
 ok(  sin($x)**2 + cos($x)**2  ==  1  );
 ok(  sin($x)**2 + cos($x)**2  !=  0  );
 ok(  sin($x)**2 + cos($x)**2 <=> '1' );
 
 


This famous trigonometric identity is not preprogrammed into B<Symbols>
as it is in commercial products.

Instead: an expression for B<sin()> is constructed using the complex
exponential: L</exp>, said expression is algebraically multiplied out to
prove the identity. The proof steps involve large intermediate
expressions in each step, as yet I have not provided a means to neatly
lay out these intermediate steps and thus provide a more compelling
demonstration of the ability of B<Symbols> to verify such statements
from first principles.
 


=head3 Relational operators                                   



=head4 Relational operators: B<==>, B<!=> 


Example t/x2y2.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: simplification.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($x, $y) = symbols(qw(x y));
 
 ok(  ($x**2-$y**2)/($x-$y)  ==  $x+$y  );
 ok(  ($x**2-$y**2)/($x-$y)  !=  $x-$y  );
 ok(  ($x**2-$y**2)/($x-$y) <=> '$x+$y' );
 
 


The relational equality operator B<==> compares two symbolic expressions
and returns TRUE(1) or FALSE(0) accordingly. B<!=> produces the opposite
result.


=head4 Relational operator: B<eq> 


Example t/eq.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: solving.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($x, $v, $t) = symbols(qw(x v t));
 
 ok(  ($v eq $x / $t)->solve(qw(x in terms of v t))  ==  $v*$t  );
 ok(  ($v eq $x / $t)->solve(qw(x in terms of v t))  !=  $v+$t  );
 ok(  ($v eq $x / $t)->solve(qw(x in terms of v t)) <=> '$v*$t' );
 
 


The relational operator B<eq> is a synonym for the minus B<-> operator,
with the expectation that later on the L<solve()|/Solving equations>
function will be used to simplify and rearrange the equation. You may
prefer to use B<eq> instead of B<-> to enhance readability, there is no
functional difference.


=head3 Complex operators



=head4 Complex operators: the B<dot> operator: B<^>       


Example t/dot.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: dot operator.  Note the low priority
 # of the ^ operator.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($a, $b, $i) = symbols(qw(a b i));
 
 ok(  (($a+$i*$b)^($a-$i*$b))  ==  $a**2-$b**2  );
 ok(  (($a+$i*$b)^($a-$i*$b))  !=  $a**2+$b**2  );
 ok(  (($a+$i*$b)^($a-$i*$b)) <=> '$a**2-$b**2' );
 


Note the use of brackets:  The B<^> operator has low priority.

The B<^> operator treats its left hand and right hand arguments as
complex numbers, which in turn are regarded as two dimensional vectors
to which the vector dot product is applied.


=head4 Complex operators: the B<cross> operator: B<x>       


Example t/cross.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: cross operator.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($x, $i) = symbols(qw(x i));
 
 ok(  $i*$x x $x  ==  $x**2  );
 ok(  $i*$x x $x  !=  $x**3  );
 ok(  $i*$x x $x <=> '$x**2' );
 


The B<x> operator treats its left hand and right hand arguments as
complex numbers, which in turn are regarded as two dimensional vectors
defining the sides of a parallelogram. The B<x> operator returns the
area of this parallelogram.

Note the space before the B<x>, otherwise Perl is unable to disambiguate
the expression correctly.


=head4 Complex operators: the B<conjugate> operator: B<~>       


Example t/conjugate.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: dot operator.  Note the low priority
 # of the ^ operator.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($x, $y, $i) = symbols(qw(x y i));
 
 ok(  ~($x+$i*$y)  ==  $x-$i*$y  );
 ok(  ~($x-$i*$y)  ==  $x+$i*$y  );
 ok(  (($x+$i*$y)^($x-$i*$y)) <=> '$x**2-$y**2' );
 


The B<~> operator returns the complex conjugate of its right hand side.


=head4 Complex operators: the B<modulus> operator: B<abs>       


Example t/abs.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: dot operator.  Note the low priority
 # of the ^ operator.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my ($x, $i) = symbols(qw(x i));
 
 ok(  abs($x+$i*$x)  ==  sqrt(2*$x**2)  );
 ok(  abs($x+$i*$x)  !=  sqrt(2*$x**3)  );
 ok(  abs($x+$i*$x) <=> 'sqrt(2*$x**2)' );
 


The B<abs> operator returns the modulus (length) of its right hand side.


=head4 Complex operators: the B<unit> operator: B<!>       


Example t/unit.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: unit operator.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>4;
 
 my ($i) = symbols(qw(i));
 
 ok(  !$i      == $i                         );
 ok(  !$i     <=> 'i'                        );
 ok(  !($i+1) <=>  '1/(sqrt(2))+i/(sqrt(2))' );
 ok(  !($i-1) <=> '-1/(sqrt(2))+i/(sqrt(2))' );
 


The B<!> operator returns a complex number of unit length pointing in
the same direction as its right hand side.


=head3 Equation Manipulation Operators



=head4 Equation Manipulation Operators: B<Simplify> operator: B<+=>


Example t/simplify.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: simplify.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
  
 my ($x) = symbols(qw(x));
 
 ok(  ($x**8 - 1)/($x-1)  ==  $x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1  );      
 ok(  ($x**8 - 1)/($x-1) <=> '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1' );      
 


The simplify operator B<+=> is a synonym for the
L<simplify()|/"simplifying_equations:_simplify()"> method, if and only
if, the target on the left hand side initially has a value of undef.

Admittedly this is very strange behavior: it arises due to the shortage
of over-rideable operators in Perl: in particular it arises due to the
shortage of over-rideable unary operators in Perl. Never-the-less: this
operator is useful as can be seen in the L<Synopsis|/"synopsis">, and
the desired pre-condition can always achieved by using B<my>.


=head4 Equation Manipulation Operators: B<Solve> operator: B<E<gt>> 


Example t/solve2.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: simplify.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
  
 my ($t) = symbols(qw(t));
 
 my $rabbit  = 10 + 5 * $t;
 my $fox     = 7 * $t * $t;
 my ($a, $b) = @{($rabbit eq $fox) > $t};
 
 ok( "$a" eq  '1/14*sqrt(305)+5/14'  );      
 ok( "$b" eq '-1/14*sqrt(305)+5/14'  );      
 


The solve operator B<E<gt>> is a synonym for the
L<solve()|/"Solving_equations:_solve()"> method.

The priority of B<E<gt>> is higher than that of B<eq>, so the brackets
around the equation to be solved are necessary until Perl provides a
mechanism for adjusting operator priority (cf. Algol 68).

If the equation is in a single variable, the single variable
may be named after the B<E<gt>> operator without the use of [...]:

 use Math::Algebra::Symbols;

 my $rabbit  = 10 + 5 * $t;
 my $fox     = 7 * $t * $t;
 my ($a, $b) = @{($rabbit eq $fox) > $t};

 print "$a\n";

 # 1/14*sqrt(305)+5/14

If there are multiple solutions, (as in the case of polynomials), B<E<gt>>
returns an array of symbolic expressions containing the solutions.

This example was provided by Mike Schilli m@perlmeister.com.


=head2 Functions


Perl operator overloading is very useful for producing compact
representations of algebraic expressions. Unfortunately there are only a
small number of operators that Perl allows to be overloaded. The
following functions are used to provide capabilities not easily expressed
via Perl operator overloading.

These functions may either be called as methods from symbols constructed
by the L</Symbols> construction routine, or they may be exported into
the user's namespace as described in L</EXPORT>.


=head3 Trigonometric and Hyperbolic functions



=head4 Trigonometric functions


Example t/sinCos2.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: methods.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>1;
 
 my ($x, $y) = symbols(qw(x y));
 
 ok( (sin($x)**2 == (1-cos(2*$x))/2) );
 


The trigonometric functions B<cos>, B<sin>, B<tan>, B<sec>, B<csc>,
B<cot> are available, either as exports to the caller's name space, or
as methods.


=head4 Hyperbolic functions


Example t/tanh.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: methods.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols hyper=>1;
 use Test::Simple tests=>1;
 
 my ($x, $y) = symbols(qw(x y));
 
 ok( tanh($x+$y)==(tanh($x)+tanh($y))/(1+tanh($x)*tanh($y)));
 


The hyperbolic functions B<cosh>, B<sinh>, B<tanh>, B<sech>, B<csch>,
B<coth> are available, either as exports to the caller's name space, or
as methods.


=head3 Complex functions



=head4 Complex functions: B<re> and B<im>       


 use Math::Algebra::Symbols complex=>1;

Example t/reIm.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: methods.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
 
 my ($x, $i) = symbols(qw(x i));
 
 ok( ($i*$x)->re   <=>  0    );
 ok( ($i*$x)->im   <=>  '$x' );
 


The B<re> and B<im> functions return an expression which represents the
real and imaginary parts of the expression, assuming that symbolic
variables represent real numbers.


=head4 Complex functions: B<dot> and B<cross>       


Example t/dotCross.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: methods.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
 
 my $i = symbols(qw(i));
 
 ok( ($i+1)->cross($i-1)   <=>  2 );
 ok( ($i+1)->dot  ($i-1)   <=>  0 );
 


The B<dot> and B<cross> operators are available as functions, either as
exports to the caller's name space, or as methods.


=head4 Complex functions: B<conjugate>, B<modulus> and B<unit>       


Example t/conjugate2.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: methods.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
 
 my $i = symbols(qw(i));
 
 ok( ($i+1)->unit      <=>  '1/(sqrt(2))+i/(sqrt(2))' );
 ok( ($i+1)->modulus   <=>  'sqrt(2)'                 );
 ok( ($i+1)->conjugate <=>  '1-i'                     );
 


The B<conjugate>, B<abs> and B<unit> operators are available as
functions: B<conjugate>, B<modulus> and B<unit>, either as exports to
the caller's name space, or as methods. The confusion over the naming of:
the B<abs> operator being the same as the B<modulus> complex function;
arises over the limited set of Perl operator names available for
overloading.



=head2 Methods



=head3 Methods for manipulating Equations             



=head4 Simplifying equations: B<simplify()>


Example t/simplify2.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: simplify.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
  
 my ($x) = symbols(qw(x));
  
 my $y  = (($x**8 - 1)/($x-1))->simplify();  # Simplify method 
 my $z +=  ($x**8 - 1)/($x-1);               # Simplify via +=
 
 ok( "$y" eq '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1' );
 ok( "$z" eq '$x+$x**2+$x**3+$x**4+$x**5+$x**6+$x**7+1' );
 


B<Simplify()> attempts to simplify an expression. There is no general
simplification algorithm: consequently simplifications are carried out
on ad hoc basis. You may not even agree that the proposed simplification
for a given expressions is indeed any simpler than the original. It is
for these reasons that simplification has to be explicitly requested
rather than being performed automagically.

At the moment, simplifications consist of polynomial division: when the
expression consists, in essence, of one polynomial divided by another,
an attempt is made to perform polynomial division, the result is
returned if there is no remainder.

The B<+=> operator may be used to simplify and assign an expression to a
Perl variable. Perl operator overloading precludes the use of B<=> in this
manner. 



=head4 Substituting into equations: B<sub()>


Example t/sub.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: expression substitution for a variable.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>2;
 
 my ($x, $y) = symbols(qw(x y));
  
 my $e  = 1+$x+$x**2/2+$x**3/6+$x**4/24+$x**5/120;
 
 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'  );
 ok(  $e->sub(x=>1)            <=>  '163/60');          
 


The B<sub()> function example on line B<#1> demonstrates replacing
variables with expressions. The replacement specified for B<z> has no
effect as B<z> is not present in this equation.

Line B<#2> demonstrates the resulting rational fraction that arises when
all the variables have been replaced by constants. This package does not
convert fractions to decimal expressions in case there is a loss of
accuracy, however:

 my $e2 = $e->sub(x=>1);
 $result = eval "$e2";

or similar will produce approximate results.

At the moment only variables can be replaced by expressions. Mike
Schilli, m@perlmeister.com, has proposed that substitutions for
expressions should also be allowed, as in:

 $x/$y => $z



=head4 Solving equations: B<solve()>


Example t/solve1.t

 #!perl -w
 #______________________________________________________________________
 # Symbolic algebra: examples: simplify.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests=>3;
  
 my ($x, $v, $t) = symbols(qw(x v t));
 
 ok(   ($v eq $x / $t)->solve(qw(x in terms of v t))  ==  $v*$t  );      
 ok(   ($v eq $x / $t)->solve(qw(x in terms of v t))  !=  $v/$t  );      
 ok(   ($v eq $x / $t)->solve(qw(x in terms of v t)) <=> '$v*$t' );      
 


B<solve()> assumes that the equation on the left hand side is equal to
zero, applies various simplifications, then attempts to rearrange the
equation to obtain an equation for the first variable in the parameter
list assuming that the other terms mentioned in the parameter list are
known constants. There may of course be other unknown free variables in
the equation to be solved: the proposed solution is automatically tested
against the original equation to check that the proposed solution
removes these variables, an error is reported via B<die()> if it does not.

Example t/solve.t

 #!perl -w -I..
 #______________________________________________________________________
 # Symbolic algebra: quadratic equation.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::Simple tests => 2;
 
 my ($x) = symbols(qw(x));
 
 my  $p = $x**2-5*$x+6;        # Quadratic polynomial
 my ($a, $b) = @{($p > $x )};  # Solve for x
 
 print "x=$a,$b\n";            # Roots
 
 ok($a == 2);
 ok($b == 3);
 


If there are multiple solutions, (as in the case of polynomials), B<solve()>
returns an array of symbolic expressions containing the solutions.


=head3 Methods for performing Calculus



=head4 Differentiation: B<d()>


Example t/differentiation.t

 #!perl -w -I..
 #______________________________________________________________________
 # Symbolic algebra.
 # PhilipRBrenan@yahoo.com, 2004, Perl License.
 #______________________________________________________________________
 
 use Math::Algebra::Symbols;
 use Test::More tests => 5;
 
 $x = symbols(qw(x));
            
 ok(  sin($x)    ==  sin($x)->d->d->d->d);
 ok(  cos($x)    ==  cos($x)->d->d->d->d);
 ok(  exp($x)    ==  exp($x)->d($x)->d('x')->d->d);
 ok( (1/$x)->d   == -1/$x**2);
 ok(  exp($x)->d->d->d->d <=> 'exp($x)' );
 


B<d()> differentiates the equation on the left hand side by the named
variable.

The variable to be differentiated by may be explicitly specified,
either as a string or as single symbol; or it may be heuristically
guessed as follows:

If the equation to be differentiated refers to only one symbol, then
that symbol is used. If several symbols are present in the equation, but
only one of B<t>, B<x>, B<y>, B<z> is present, then that variable is
used in honor of Newton, Leibnitz, Cauchy.


=head2 Example of Equation Solving: the focii of a hyperbola:


 use Math::Algebra::Symbols;

 my ($a, $b, $x, $y, $i, $o) = symbols(qw(a b x y i 1));

 print
 "Hyperbola: Constant difference between distances from focii to locus of y=1/x",
 "\n  Assume by symmetry the focii are on ",
 "\n    the line y=x:                     ",  $f1 = $x + $i * $x,
 "\n  and equidistant from the origin:    ",  $f2 = -$f1,
 "\n  Choose a convenient point on y=1/x: ",  $a = $o+$i,
 "\n        and a general point on y=1/x: ",  $b = $y+$i/$y,
 "\n  Difference in distances from focii",
 "\n    From convenient point:            ",  $A = abs($a - $f2) - abs($a - $f1),  
 "\n    From general point:               ",  $B = abs($b - $f2) + abs($b - $f1),
 "\n\n  Solving for x we get:            x=", ($A - $B) > $x,
 "\n                         (should be: sqrt(2))",                        
 "\n  Which is indeed constant, as was to be demonstrated\n";

This example demonstrates the power of symbolic processing by finding the
focii of the curve B<y=1/x>, and incidentally, demonstrating that this curve
is a hyperbola.


=head1 EXPORTS


 use Math::Algebra::Symbols
   symbols=>'S',
   trig   => 1,
   hyper  => 1,
   complex=> 1;


=over



=item trig=>0


The default, do not export trigonometric functions. 


=item trig=>1


Export trigonometric functions: B<tan>, B<sec>, B<csc>, B<cot> to the
caller's namespace. B<sin>, B<cos> are created by default by overloading
the existing Perl B<sin> and B<cos> operators.


=item B<trigonometric>


Alias of B<trig>


=item hyperbolic=>0


The default, do not export hyperbolic functions. 


=item hyper=>1


Export hyperbolic functions: B<sinh>, B<cosh>, B<tanh>, B<sech>,
B<csch>, B<coth> to the caller's namespace.


=item B<hyperbolic>


Alias of B<hyper>


=item complex=>0


The default, do not export complex functions         


=item complex=>1


Export complex functions: B<conjugate>, B<cross>, B<dot>, B<im>,
B<modulus>, B<re>, B<unit> to the caller's namespace.


=back



=head1 PACKAGES


The B<Symbols> packages manipulate a sum of products representation of
an algebraic equation. The B<Symbols> package is the user interface to
the functionality supplied by the B<Symbols::Sum> and B<Symbols::Term>
packages.


=head2 Math::Algebra::Symbols::Term


B<Symbols::Term> represents a product term. A product term consists of the
number B<1>, optionally multiplied by:


=over



=item Variables


any number of variables raised to integer powers,


=item Coefficient


An integer coefficient optionally divided by a positive integer divisor,
both represented as BigInts if necessary. 


=item Sqrt


The sqrt of of any symbolic expression representable by the B<Symbols>
package, including minus one: represented as B<i>.


=item Reciprocal


The multiplicative inverse of any symbolic expression representable by
the B<Symbols> package: i.e. a B<SymbolsTerm> may be divided by any
symbolic expression representable by the B<Symbols> package.


=item Exp


The number B<e> raised to the power of any symbolic expression
representable by the B<Symbols> package.


=item Log


The logarithm to base B<e> of any symbolic expression representable by
the B<Symbols> package.


=back


Thus B<SymbolsTerm> can represent expressions like:

  2/3*$x**2*$y**-3*exp($i*$pi)*sqrt($z**3) / $x

but not:

  $x + $y

for which package B<Symbols::Sum> is required. 



=head2 Math::Algebra::Symbols::Sum


B<Symbols::Sum> represents a sum of product terms supplied by
B<Symbols::Term> and thus behaves as a polynomial. Operations such as
equation solving and differentiation are applied at this level.

The main benefit of programming B<Symbols::Term> and B<Symbols::Sum> as two
separate but related packages is Object Oriented Polymorphism. I.e. both
packages need to multiply items together: each package has its own B<multiply> method,
with Perl method lookup selecting the appropriate one as required. 


=head2 Math::Algebra::Symbols


Packaging the user functionality alone and separately in package
B<Symbols> allows the internal functions to be conveniently hidden from
user scripts.



=head1 AUTHOR


Philip R Brenan at B<philiprbrenan@yahoo.com>


 
 
 
 
 


=head2 Credits



=head3 Author


philiprbrenan@yahoo.com


=head3 Copyright


philiprbrenan@yahoo.com, 2004


=head3 License


Perl License.