Math-Calculus-Differentiate-0.3/ 0040755 0001762 0001001 00000000000 10167102436 016004 5 ustar Jonathan None Math-Calculus-Differentiate-0.3/MANIFEST 0100644 0001762 0001001 00000000222 10167102434 017124 0 ustar Jonathan None Changes
Differentiate.pm
Makefile.PL
MANIFEST
README
test.pl
META.yml Module meta-data (added by MakeMaker)
Math-Calculus-Differentiate-0.3/Differentiate.pm 0100644 0001762 0001001 00000055263 10160672116 021123 0 ustar Jonathan None # ########################################################################################
# A CALCULUS DIFFERENTIATION OBJECT
# An implementation of algebraic differentiation by Jonathan Worthington.
# Copyright (C) Jonathan Worthington 2004
# This module may be used and distributed under the same terms as Perl.
# ########################################################################################
package Math::Calculus::Differentiate;
use 5.006;
use Math::Calculus::Expression;
use strict;
our $VERSION = '0.3';
our @ISA = qw/Math::Calculus::Expression/;
=head1 NAME
Math::Calculus::Differentiate - Algebraic Differentiation Engine
=head1 SYNOPSIS
use Math::Calculus::Differentiate;
# Create an object.
my $exp = Math::Calculus::Differentiate->new;
# Set a variable and expression.
$exp->addVariable('x');
$exp->setExpression('x^2 + 5*x') or die $exp->getError;
# Differentiate and simplify.
$exp->differentiate or die $exp->getError;;
$exp->simplify or die $exp->getError;;
# Print the result.
print $exp->getExpression; # Prints 2*x + 5
=head1 DESCRIPTION
This module can take an algebraic expression, parse it into a tree structure, modify
the tree to give a representation of the differentiated function, simplify the tree
and turn the tree back into an output of the same form as the input.
It supports differentiation of expressions including the +, -, *, / and ^ (raise to
power) operators, bracketed expressions to enable correct precedence and the functions
ln, exp, sin, cos, tan, sec, cosec, cot, sinh, cosh, tanh, sech, cosech, coth, asin,
acos, atan, asinh, acosh and atanh.
=head1 EXPORT
None by default.
=head1 METHODS
=item new
$exp = Math::Calculus::Differentiate->new;
Creates a new instance of the differentiation engine, which can hold an individual
expression.
=item addVariable
$exp->addVariable('x');
Sets a certain named value in the expression as being a variable. A named value must be
an alphabetic chracter.
=item setExpression
$exp->setExpression('x^2 + 5*x);
Takes an expression in human-readable form and stores it internally as a tree structure,
checking it is a valid expression that the module can understand in the process. Note that
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
# Differentiate.
# ##############
=item differentiate
$exp->differentiate('x');
Differentiates the expression that was stored with setExpression with respect to the variable
passed as a parameter. Returns undef on failure and a true value on success.
=cut
sub differentiate {
# Get invocant and variable.
my ($self, $variable) = @_;
# Check variable is in the list of variables.
return undef unless grep { $_ eq $variable } @{$self->{'variables'}};
# Clear error and traceback, and pass control to the differentiate routine.
$self->{'error'} = $self->{'traceback'} = undef;
eval {
$self->{'expression'} = $self->differentiateTree($variable, $self->{'expression'});
};
# Return an appropriate value (or lack thereof...).
if ($self->{'error'}) {
return undef;
} else {
return 1;
}
}
=item simplify
$exp->simplify;
Attempts to simplify the expression that is stored internally. It is a very good idea to call
this after calling differentiate, as the tree will often not be in the most compact possible
form, and this will affect the readability of output from getExpression and the performance
of future calls to differentiate if you are intending to obtain higher derivatives. Returns
undef on failure and a true value on success.
=item getTraceback
$exp->getTraceback;
When setExpression and differentiate are called, a traceback is generated to describe
what these functions did. If an error occurs, this traceback can be extremely useful
in helping track down the source of the error.
=item getError
$exp->getError;
When any method other than getTraceback is called, the error message stored is cleared, and
then any errors that occur during the execution of the method are stored. If failure occurs,
call this method to get a textual representation of the error.
=head1 SEE ALSO
The author of this module has a website at L, which has
the latest news about the module and a web-based frontend to allow you to test the module
out for yourself.
=head1 AUTHOR
Jonathan Worthington, Ejonathan@jwcs.netE
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2004 by Jonathan Worthington
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.1 or,
at your option, any later version of Perl 5 you may have available.
=cut
# ########################################################################################
# Private Methods
# ########################################################################################
# Differentiate Tree explores the current expression tree, recursively differentiating
# the branches of the tree.
# ########################################################################################
sub differentiateTree {
# Get invocant, variable and tree.
my ($self, $variable, $tree) = @_;
# Generate traceback.
$self->{'traceback'} .= "Parsing " . $self->prettyPrint($tree) . "\n";
# If we're at a node...
unless (ref $tree) {
# Is it the variable?
if ($tree eq $variable) {
# It goes to 1.
return 1;
# Or - the variable...
} elsif ($tree eq "-$variable") {
# It goes to -1.
return -1;
# Otherwise, it's a constant and goes to zero.
} else {
return 0;
}
} else {
# We've got a complex expression. Our actions from here depend on what the
# expression is.
# Addition or subtraction - just differentiate each operand.
if ($tree->{'operation'} eq '+' || $tree->{'operation'} eq '-') {
return {
operation => $tree->{'operation'},
operand1 => $self->differentiateTree($variable, $tree->{'operand1'}),
operand2 => $self->differentiateTree($variable, $tree->{'operand2'})
};
# Multiplication.
} elsif ($tree->{'operation'} eq '*') {
# Check if any branches are constant.
my $o1c = $self->isConstant($variable, $tree->{'operand1'});
my $o2c = $self->isConstant($variable, $tree->{'operand2'});
# If they're both constant, return the tree as it is.
if ($o1c && $o2c) {
return $tree;
# If the first is constant, only differentiate the second.
} elsif ($o1c) {
return {
operation => $tree->{'operation'},
operand1 => $tree->{'operand1'},
operand2 => $self->differentiateTree($variable, $tree->{'operand2'})
};
# If the second is constant, only differentiate the first.
} elsif ($o2c) {
return {
operation => $tree->{'operation'},
operand1 => $self->differentiateTree($variable, $tree->{'operand1'}),
operand2 => $tree->{'operand2'}
};
# Otherwise, it's the product rule. d[uv] = udv + vdu
} else {
return {
operation => '+',
operand1 =>
{
operation => '*',
operand1 => $tree->{'operand1'},
operand2 => $self->differentiateTree($variable, $tree->{'operand2'})
},
operand2 =>
{
operation => '*',
operand1 => $tree->{'operand2'},
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
}
};
}
# Division.
} elsif ($tree->{'operation'} eq '/') {
# Check if any branches are constant.
my $o1c = $self->isConstant($variable, $tree->{'operand1'});
my $o2c = $self->isConstant($variable, $tree->{'operand2'});
# If they're both constant, return the tree as it is.
if ($o1c && $o2c) {
return $tree;
# If the denominator is constant, just differentiate the top.
} elsif ($o2c) {
return {
operation => '/',
operand1 => $self->differentiateTree($variable, $tree->{'operand1'}),
operand2 => $tree->{'operand2'}
};
# If the numerator is constant, e.g. k/u, then return k * d[u^-1].
} elsif ($o1c) {
my $uinv = {
operation => '^',
operand1 => $tree->{'operand2'},
operand2 => -1
};
return {
operation => '*',
operand1 => $tree->{'operand1'},
operand2 => $self->differentiateTree($variable, $uinv)
}
# Otherwise, neither is constant. Use d[u/v] = (vdu - udv) / v^2.
} else {
my $vdu = {
operation => '*',
operand2 => $tree->{'operand2'},
operand1 => $self->differentiateTree($variable, $tree->{'operand1'})
};
my $udv = {
operation => '*',
operand2 => $tree->{'operand1'},
operand1 => $self->differentiateTree($variable, $tree->{'operand2'})
};
return {
operation => '/',
operand1 =>
{
operation => '-',
operand1 => $vdu,
operand2 => $udv
},
operand2 =>
{
operation => '^',
operand1 => $tree->{'operand2'},
operand2 => 2
}
};
}
# Powers.
} elsif ($tree->{'operation'} eq '^') {
# Check if any branches are constant.
my $o1c = $self->isConstant($variable, $tree->{'operand1'});
my $o2c = $self->isConstant($variable, $tree->{'operand2'});
# If they're both constant, return the tree as it is.
if ($o1c && $o2c) {
return $tree;
# If the power is constant...
} elsif ($o2c) {
# d[(f(x))^n] = n*f'(x)*f(x)^(n-1)
return {
operation => '*',
operand1 => $tree->{'operand2'},
operand2 =>
{
operation => '*',
operand1 => $self->differentiateTree($variable, $tree->{'operand1'}),
operand2 =>
{
operation => '^',
operand1 => $tree->{'operand1'},
operand2 =>
{
operation => '-',
operand1 => $tree->{'operand2'},
operand2 => 1
}
}
}
};
# If the value being raised to a power is constant...
} elsif ($o1c) {
# d[k^v] = dv * ln(k) * exp(ln(k) * v)
my $dv = $self->differentiateTree($variable, $tree->{'operand2'});
my $lnk = {
operation => 'ln',
operand1 => $tree->{'operand1'},
operand2 => undef
};
return {
operation => '*',
operand1 => $dv,
operand2 =>
{
operation => '*',
operand1 => $lnk,
operand2 =>
{
operation => 'exp',
operand1 =>
{
operation => '*',
operand1 => $lnk,
operand2 => $tree->{'operand2'}
},
operand2 => undef
}
}
};
# If it's a function of the variable raised to another function of the variable...
} else {
# d[u^v] = exp(ln(u) * v) * ((vdu)/u + ln(u)dv)
my $lnu = {
operation => 'ln',
operand1 => $tree->{'operand1'},
operand2 => undef
};
my $dv = $self->differentiateTree($variable, $tree->{'operand2'});
my $vdu = {
operation => '*',
operand1 => $tree->{'operand2'},
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
};
return {
operation => '*',
operand1 =>
{
operation => 'exp',
operand1 =>
{
operation => '*',
operand1 => $lnu,
operand2 => $tree->{'operand2'}
},
operand2 => undef
},
operand2 =>
{
operation => '+',
operand1 =>
{
operation => '/',
operand1 => $vdu,
operand2 => $tree->{'operand1'}
},
operand2 =>
{
operation => '*',
operand1 => $lnu,
operand2 => $dv
}
}
};
}
# Natural logarithm
} elsif ($tree->{'operation'} =~ /^(\-?)ln$/) {
# Stash negativity.
my $neg = $1;
# d[ln(u)] = du/u
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => "${neg}1",
operand2 =>
{
operation => '/',
operand1 => $du,
operand2 => $tree->{'operand1'}
}
};
# Exponential (e)
} elsif ($tree->{'operation'} =~ /^(\-?)exp$/) {
# Stash negativity.
my $neg = $1;
# d[exp(u)] = exp(u)du
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => $du,
operand2 => $tree
};
# sin
} elsif ($tree->{'operation'} =~ /^(\-?)sin$/) {
# Stash negativity.
my $neg = $1;
# d[sin(u)] = cos(u)du
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => $du,
operand2 =>
{
operation => "${neg}cos",
operand1 => $tree->{'operand1'},
operand2 => undef
}
};
# cos
} elsif ($tree->{'operation'} =~ /^(\-?)cos$/) {
# Stash negativity.
my $neg = $1 eq '-' ? '' : '-';
# d[cos(u)] = -sin(u)du
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => $du,
operand2 =>
{
operation => "${neg}sin",
operand1 => $tree->{'operand1'},
operand2 => undef
}
};
# tan
} elsif ($tree->{'operation'} =~ /^(\-?)tan$/) {
# Stash negativity.
my $neg = $1;
# d[tan(u)] = (sec(u))^2 * du
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => "${neg}1",
operand2 =>
{
operation => '*',
operand1 => $du,
operand2 =>
{
operation => '^',
operand1 =>
{
operation => "sec",
operand1 => $tree->{'operand1'},
operand2 => undef
},
operand2 => 2
}
}
};
# sec
} elsif ($tree->{'operation'} =~ /^(\-?)sec$/) {
# Stash negativity.
my $neg = $1;
# Convert to 1/cos and differentiate.
return $self->differentiateTree($variable, {
operation => '/',
operand1 => "${neg}1",
operand2 =>
{
operation => 'cos',
operand1 => $tree->{'operand1'},
operand2 => undef
}
});
# cosec
} elsif ($tree->{'operation'} =~ /^(\-?)cosec$/) {
# Stash negativity.
my $neg = $1;
# Convert to 1/sin and differentiate.
return $self->differentiateTree($variable, {
operation => '/',
operand1 => "${neg}1",
operand2 =>
{
operation => 'sin',
operand1 => $tree->{'operand1'},
operand2 => undef
}
});
# cot
} elsif ($tree->{'operation'} =~ /^(\-?)cot$/) {
# Stash negativity.
my $neg = $1;
# Convert to 1/tan and differentiate.
return $self->differentiateTree($variable, {
operation => '/',
operand1 => "${neg}1",
operand2 =>
{
operation => 'tan',
operand1 => $tree->{'operand1'},
operand2 => undef
}
});
# sinh
} elsif ($tree->{'operation'} =~ /^(\-?)sinh$/) {
# Stash negativity.
my $neg = $1;
# d[sinh(u)] = cosh(u)du
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => $du,
operand2 =>
{
operation => "${neg}cosh",
operand1 => $tree->{'operand1'},
operand2 => undef
}
};
# cosh
} elsif ($tree->{'operation'} =~ /^(\-?)cosh$/) {
# Stash negativity.
my $neg = $1;
# d[cosh(u)] = sinh(u)du
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => $du,
operand2 =>
{
operation => "${neg}sinh",
operand1 => $tree->{'operand1'},
operand2 => undef
}
};
# tanh
} elsif ($tree->{'operation'} =~ /^(\-?)tanh$/) {
# Stash negativity.
my $neg = $1;
# d[tanh(u)] = (sech(u))^2 * du
my $du = $self->differentiateTree($variable, $tree->{'operand1'});
return {
operation => '*',
operand1 => "${neg}1",
operand2 =>
{
operation => '*',
operand1 => $du,
operand2 =>
{
operation => '^',
operand1 =>
{
operation => "sech",
operand1 => $tree->{'operand1'},
operand2 => undef
},
operand2 => 2
}
}
};
# sech
} elsif ($tree->{'operation'} =~ /^(\-?)sech$/) {
# Stash negativity.
my $neg = $1;
# Convert to 1/cosh and differentiate.
return $self->differentiateTree($variable, {
operation => '/',
operand1 => "${neg}1",
operand2 =>
{
operation => 'cosh',
operand1 => $tree->{'operand1'},
operand2 => undef
}
});
# cosech
} elsif ($tree->{'operation'} =~ /^(\-?)cosech$/) {
# Stash negativity.
my $neg = $1;
# Convert to 1/sinh and differentiate.
return $self->differentiateTree($variable, {
operation => '/',
operand1 => "${neg}1",
operand2 =>
{
operation => 'sinh',
operand1 => $tree->{'operand1'},
operand2 => undef
}
});
# coth
} elsif ($tree->{'operation'} =~ /^(\-?)coth$/) {
# Stash negativity.
my $neg = $1;
# Convert to 1/tanh and differentiate.
return $self->differentiateTree($variable, {
operation => '/',
operand1 => "${neg}1",
operand2 =>
{
operation => 'tanh',
operand1 => $tree->{'operand1'},
operand2 => undef
}
});
# asin
} elsif ($tree->{'operation'} =~ /^(\-?)asin$/) {
# Stash negativity.
my $neg = $1;
# d[asin(u)] = du / (1 - u^2)^0.5
my $du;
if ($neg) {
$du = {
operation => '-',
operand1 => '0',
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
};
} else {
$du = $self->differentiateTree($variable, $tree->{'operand1'});
}
return {
operation => '/',
operand1 => $du,
operand2 =>
{
operation => '^',
operand1 =>
{
operation => '-',
operand1 => 1,
operand2 =>
{
operation => '^',
operand1 => $tree->{'operand1'},
operand2 => 2
}
},
operand2 => 0.5
}
};
# acos
} elsif ($tree->{'operation'} =~ /^(\-?)acos$/) {
# Stash negativity.
my $neg = $1;
# d[acos(u)] = -du / (1 - u^2)^0.5
my $du;
if ($neg) {
$du = $self->differentiateTree($variable, $tree->{'operand1'});
} else {
$du = {
operation => '-',
operand1 => '0',
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
};
}
return {
operation => '/',
operand1 => $du,
operand2 =>
{
operation => '^',
operand1 =>
{
operation => '-',
operand1 => 1,
operand2 =>
{
operation => '^',
operand1 => $tree->{'operand1'},
operand2 => 2
}
},
operand2 => 0.5
}
};
# atan
} elsif ($tree->{'operation'} =~ /^(\-?)atan$/) {
# Stash negativity.
my $neg = $1;
# d[atan(u)] = du / (1 + u^2)
my $du;
if ($neg) {
$du = {
operation => '-',
operand1 => '0',
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
};
} else {
$du = $self->differentiateTree($variable, $tree->{'operand1'});
}
return {
operation => '/',
operand1 => $du,
operand2 =>
{
operation => '+',
operand1 => 1,
operand2 =>
{
operation => '^',
operand1 => $tree->{'operand1'},
operand2 => 2
}
}
};
# asinh
} elsif ($tree->{'operation'} =~ /^(\-?)asinh$/) {
# Stash negativity.
my $neg = $1;
# d[asinh(u)] = du / (1 + u^2)^0.5
my $du;
if ($neg) {
$du = {
operation => '-',
operand1 => '0',
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
};
} else {
$du = $self->differentiateTree($variable, $tree->{'operand1'});
}
return {
operation => '/',
operand1 => $du,
operand2 =>
{
operation => '^',
operand1 =>
{
operation => '+',
operand1 => 1,
operand2 =>
{
operation => '^',
operand1 => $tree->{'operand1'},
operand2 => 2
}
},
operand2 => 0.5
}
};
# acosh
} elsif ($tree->{'operation'} =~ /^(\-?)acosh$/) {
# Stash negativity.
my $neg = $1;
# d[acosh(u)] = du / (u^2 - 1)^0.5
my $du;
if ($neg) {
$du = {
operation => '-',
operand1 => '0',
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
};
} else {
$du = $self->differentiateTree($variable, $tree->{'operand1'});
}
return {
operation => '/',
operand1 => $du,
operand2 =>
{
operation => '^',
operand1 =>
{
operation => '-',
operand1 =>
{
operation => '^',
operand1 => $tree->{'operand1'},
operand2 => 2
},
operand2 => 1
},
operand2 => 0.5
}
};
# atanh
} elsif ($tree->{'operation'} =~ /^(\-?)atanh$/) {
# Stash negativity.
my $neg = $1;
# d[atanh(u)] = du / (1 - u^2)
my $du;
if ($neg) {
$du = {
operation => '-',
operand1 => '0',
operand2 => $self->differentiateTree($variable, $tree->{'operand1'})
};
} else {
$du = $self->differentiateTree($variable, $tree->{'operand1'});
}
return {
operation => '/',
operand1 => $du,
operand2 =>
{
operation => '-',
operand1 => 1,
operand2 =>
{
operation => '^',
operand1 => $tree->{'operand1'},
operand2 => 2
}
}
};
# Otherwise, we don't know what it is.
} else {
$self->{'error'} = "Could not differentiate " . $self->prettyPrint($tree);
die;
}
}
}
1;
Math-Calculus-Differentiate-0.3/META.yml 0100644 0001762 0001001 00000000561 10167102434 017252 0 ustar Jonathan None # http://module-build.sourceforge.net/META-spec.html
#XXXXXXX This is a prototype!!! It will change in the future!!! XXXXX#
name: Math-Calculus-Differentiate
version: 0.3
version_from: Differentiate.pm
installdirs: site
requires:
Math::Calculus::Expression: 0.1
distribution_type: module
generated_by: ExtUtils::MakeMaker version 6.17
Math-Calculus-Differentiate-0.3/test.pl 0100644 0001762 0001001 00000003552 10160673640 017325 0 ustar Jonathan None # Before `make install' is performed this script should be runnable with
# `make test'. After `make install' it should work as `perl test.pl'
#########################
use Test;
BEGIN { plan tests => 12 }
my $res;
## BASIC MODULE TESTS
# Check include of module works.
use Math::Calculus::Differentiate;
ok(1);
# Create object.
my $exp = Math::Calculus::Differentiate->new;
ok($exp);
# Add a variable.
$res = $exp->addVariable('x');
ok($res);
## REGRESSION TESTS
# d[x] = 1
$exp->setExpression('x');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '1');
# d[-x] = -1
$exp->setExpression('-x');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '-1');
# d[x^2 + 4*x + 5] = 2*x + 4
$exp->setExpression('x^2 + 4*x + 5');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '2*x + 4');
# d[sin(-2 * x)] = -2*cos(-2*x)
$exp->setExpression('sin(-2 * x)');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '-2*cos(-2*x)');
# d[asin(x)] = 1/(1 - x^2)^0.5
$exp->setExpression('asin(x)');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '1/(1 - x^2)^0.5');
# d[ln(x^2)] = (2*x)/x^2
$exp->setExpression('ln(x^2)');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '(2*x)/x^2');
# d[x^x] = exp(ln(x)*x)*(1 + ln(x))
$exp->setExpression('x^x');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq 'exp(ln(x)*x)*(1 + ln(x))');
# d[x/x] = 0
$exp->setExpression('x/x');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '0');
# d[x - x] = 0
$exp->setExpression('x - x');
$exp->differentiate('x');
$exp->simplify;
$res = $exp->getExpression;
ok($res eq '0');
Math-Calculus-Differentiate-0.3/Changes 0100644 0001762 0001001 00000002077 10167102416 017300 0 ustar Jonathan None Revision history for Perl module Math::Calculus::Differentiate
==============================================================
VERSION 0.3
* Released to CPAN 5th January 2004
* Abstracted much code out to Math::Calculus::Expression,
which this module now inherits.
* Fixed an expression parser bug.
VERSION 0.2.1
* Released to CPAN on 4th September 2004.
* Fixed several bugs relating to handling of negation.
* Added support for differentiating inverse trigometric and
hyperbolic functions (asin, acos, atan, asinh, acosh and
atanh).
* Introduced several more rules to the simplifier.
* Included a handful of regression tests.
VERSION 0.2
* Released to CPAN on 1st September 2004.
* Completely re-written to use a tree structure internally.
* Precedence problems gone, and the / operator works.
* Interface changed from that of the 0.1 module.
* Documentation written. I didn't write any for 0.1, just in
case somebody tried to use it. ;-)
VERSION 0.1
* Released informally, badly written, never made it to CPAN,
eventually scrapped completely.
Math-Calculus-Differentiate-0.3/README 0100644 0001762 0001001 00000002213 10160673736 016670 0 ustar Jonathan None Math::Calculus::Differentiate version 0.3.0
===========================================
Math::Calculus::Differentiate takes an algebraic expression (e.g. in
the form x^2 + 5*x + sin(x)), differentiates it and returns the
derivative in the same format (e.g. 2*x + 5 + cos(x)). In understands
the operators +, -, *, / and ^ (raising to a power) as well as the
functions sin, cos, tan, sec, cosec, cot, sinh, cosh, tanh, sech,
cosech, coth, asin, acos, atan, asinh, acosh, atanh, ln and exp.
Functions are valid either side of all operators - that is, you can
differentiate a function raised to the power of another function.
Partial differentiation is supported to the extent that you can
differentiate with respect to a single variable.
INSTALLATION
To install this module type the following:
perl Makefile.PL
make
make test
make install
DEPENDENCIES
This module requires Perl 5.6.0 or greater and the module
Math::Calculus::Expression.
COPYRIGHT AND LICENCE
Copyright (C) 2004 Jonathan Worthington
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
Math-Calculus-Differentiate-0.3/Makefile.PL 0100644 0001762 0001001 00000001037 10160670204 017750 0 ustar Jonathan None use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
'NAME' => 'Math::Calculus::Differentiate',
'VERSION_FROM' => 'Differentiate.pm', # finds $VERSION
'PREREQ_PM' => {Math::Calculus::Expression => 0.1},
($] >= 5.005 ? ## Add these new keywords supported since 5.005
(ABSTRACT_FROM => 'Differentiate.pm', # retrieve abstract from module
AUTHOR => 'J. Worthington ') : ()),
);