package Math::Symbolic::Custom::Simplification; use 5.006001; use strict; use warnings; use Carp qw/cluck confess/; use Math::Symbolic; our $VERSION = '1.01'; our @Simplification_Stack; our %Registered; _reset(); sub _reset { @Simplification_Stack = ( ['Math::Symbolic::Operator', \&Math::Symbolic::Operator::simplify] ); %Registered = ( 'Math::Symbolic::Operator' => 1 ); } sub register { my $class = shift; confess("Cannot register simplification routine when not called as class method.") if not defined $class; my $simp = eval "\\&${class}::simplify"; if ($@ or not defined $simp or not ref $simp eq 'CODE') { my $msg = $@? "Error: $@" : ''; confess("Could not find simplification routine as '${class}::simplify'."); } $Registered{$class}++; push @Simplification_Stack, [$class, $simp]; no strict; no warnings qw/redefine/; *Math::Symbolic::Operator::simplify = $simp; return 1; } sub unregister { my $class = shift; confess("Cannot unregister simplification routine when not called as class method.") if not defined $class; return 0 if not $Registered{$class}; while (@Simplification_Stack and $class ne $Simplification_Stack[-1][0]) { my $this = pop @Simplification_Stack; $Registered{$this->[0]}--; }; my $this = pop @Simplification_Stack; $Registered{$this->[0]}--; if (not @Simplification_Stack) { _reset(); return 0; } no strict; no warnings qw/redefine/; *Math::Symbolic::Operator::simplify = $Simplification_Stack[-1][1]; return 1; } 1; __END__ =head1 NAME Math::Symbolic::Custom::Simplification - User defined simplification routines =head1 SYNOPSIS package Math::Symbolic::Custom::MySimplification; use base 'Math::Symbolic::Custom::Simplification'; sub simplify { my $tree = shift; # ... simplify tree ... return $simplified; } 1; # Then, in another portion of your code. Math::Symbolic::Custom::MySimplification->register(); # Code that uses MySimplification: # $tree->simplify() invokes # Math::Symbolic::Custom::MySimplification::simplify($tree). Math::Symbolic::Custom::MySimplification->unregister(); # Code that uses the default simplification routines or whichever # simplification routines where registered before. =head1 DESCRIPTION This module is an extension to the Math::Symbolic module. A basic familiarity with that module is required. Math::Symbolic offers some builtin simplification routines. These, however, are not capable of complex simplifications. This extension offers facilities to override the default simplification routines through means of subclassing this module. A subclass of this module is required to define a C object method that implements a simplification of Math::Symbolic trees. There are two class methods to inherit: I and I. Calling the C method on your subclass registers your class as providing the I method that is invoked whenever C is called on a Math::Symbolic::Operator object. Calling C on your subclass restores whichever simplification routines where in place before. Several subsequent C and c calls on different subclasses can be used to localize simplification routines. The old routines are saved to a stack. If there are several subclasses of this module, say C and C, calling Cregister()>, then Cregister()> will finally provide the simplification routines of I. Unregistering I revert to the routine from I. If you unregister out of order (i.e. in the above example if you unregistered I instead of I), all simplification routines up to and including the one you're unregistering are removed and the one that was in effect before I (here: the default C) is restored. =head2 EXPORT This module does not export anything. =head2 METHODS =over 2 =item register A class method to register the C subroutine of the class as the new Math::Symbolic simplification rotuine. =item unregister A class method to unregister the aformentioned simplification routine. =back =head1 SEE ALSO New versions of this module can be found on http://steffen-mueller.net or CPAN. L L which contains the default simplification routines. L and L for details on enhancing Math::Symbolic. =head1 AUTHOR Steffen Müller, Esymbolic-module at steffen-mueller dot net =head1 COPYRIGHT AND LICENSE Copyright (C) 2005 by Steffen Müller This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.4 or, at your option, any later version of Perl 5 you may have available. =cut