Math-Calculus-TaylorSeries
view release on metacpan or search on metacpan
TaylorSeries.pm view on Meta::CPAN
the engine is strict about syntax. For example, note above that you must write 5*x and not
just 5x. Whitespace is allowed in the expression, but does not have any effect on precedence.
If you require control of precedence, use brackets; bracketed expressions will always be
evaluated first, as you would normally expect. The module follows the BODMAS precedence
convention. Returns undef on failure and a true value on success.
=item getExpression
$expr = $exp->getExpression;
Returns a textaul, human readable representation of the expression that is being stored.
=cut
# Taylor Series.
# ##############
=item taylorSeries
$result = $exp->taylorSeries($variable, $terms, $about);
Finds the first $terms non-zero terms of the Taylor series of the expression object
for the variable $variable evaluated about the value $about and returns a new
expression object that represents it.
=cut
sub taylorSeries {
# Get invocant and variable.
my ($self, $variable, $terms, $about) = @_;
# Clear error and traceback.
$self->{'error'} = $self->{'traceback'} = '';
# Check variable is in the list of variables.
unless (grep { $_ eq $variable } @{$self->{'variables'}})
{
$self->{'error'} = 'Function variable was not declared.';
return undef;
}
# Check number of terms is sane.
unless ($terms =~ /^\d+$/ && $terms > 1)
{
$self->{'error'} = 'Attempt to evaluate Taylor series with an invalid number of terms.';
return undef;
}
# Check about value is sane.
unless ($about =~ /^[\-\d\.]+$/)
{
$self->{'error'} = 'Attempt to evaluate Taylor series about an invalid value.';
return undef;
}
# Create a clone of the expression object that we'll differentiate and prepare to find co-efficients.
my $diffExp = $self->clone;
my @coeffs = ();
my $coeffsFound = 0;
# Loop until we've found enough terms or we hit our maximum number of iterations.
my $numIters = 0;
while ($coeffsFound < $terms) {
# Evaluate.
my $coeff = $diffExp->evaluate($variable => $about);
return undef unless defined($coeff);
# Put in co-effs list, and if it's non-zero then state we've found a term.
push @coeffs, $coeff;
$coeffsFound++ if $coeff != 0;
# Differentiate for next round.
return undef unless $diffExp->differentiate($variable);
$diffExp->simplify;
# Sanity check - we may run out of terms.
last if ++$numIters == $MAXITERATIONS;
}
# Now we need to generate the expression with the real co-efficients.
my @termList = ();
for (my $i = 0; $i < @coeffs; $i++) {
# If the co-efficient is non-zero, create the term and put it on the list.
if ($coeffs[$i] != 0) {
my $term = $coeffs[$i];
$term .= '*' . $variable if $i > 0;
$term .= '^' . $i if $i > 1;
$term .= '/' . $self->fact($i);
push @termList, $term;
}
}
# Create a new expression object containing the term, and simplify.
my $newExp = Math::Calculus::Expression->new;
unless ($newExp->setExpression(join '+', @termList)) {
$self->{'error'} = "Could not parse generated taylor series expression.";
}
$newExp->simplify;
# Return the Taylor series, if no errors.
if ($self->{'error'}) {
return undef;
} else {
return $newExp;
}
}
# Taylor Series Co-efficients.
# ############################
=item taylorSeries_coeffs
$result = $exp->taylorSeries($variable, $numcoeffs, $about);
Returns an array containing the first $numcoeffs terms when the Taylor series for
the variable $variable is found about $about.
=cut
sub taylorSeries_coeffs {
# Get invocant and variable.
( run in 0.449 second using v1.01-cache-2.11-cpan-71847e10f99 )