1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
#!perl
use strict;
use warnings;
use Carp qw/croak/;
use Test::More tests => 12;
BEGIN {
use_ok('Math::Symbolic');
}
use Math::Symbolic qw/:all/;
use Math::Symbolic::Derivative qw/partial_derivative/;
if ($ENV{TEST_YAPP_PARSER}) {
require Math::Symbolic::Parser::Yapp;
$Math::Symbolic::Parser = Math::Symbolic::Parser::Yapp->new();
}
my @f = (
[
q{-a+b*x},
q{b}
],
[
q{a+b*x+c*x^2},
q{b+2*c*x}
],
[
q{a+x+}.join('+', map {"x^$_"} 2..10),
'1+'.join('+', map {"$_*x^".($_-1)} 2..10)
],
[
q{sin(2*x)*cos(3*x)},
q{2*cos(2*x)*cos(3*x)-3*sin(3*x)*sin(2*x)},
],
[
q{log(a, 2*x)},
q{2/(log(2.71828182845905, a)*2*x)},
{ x => sub {$_[0] > 0}, a => sub {$_[0] > 0}, }
],
[
q{x/x^2},
q{-1/x^2},
{ x => sub {$_[0] > 0} },
],
[
q{2/x},
q{-2/x^2},
{ x => sub {$_[0] > 0} },
],
[
q{c/x},
q{-c/x^2},
{ x => sub {$_[0] > 0} },
],
);
foreach my $ref (@f) {
my ($f, $deriv) = map { parse_from_string($_) } @{$ref}[0,1];
my $limits = $ref->[2];
die "parse of '$ref->[0]' failed" if not defined $f;
die "parse of '$ref->[1]' failed" if not defined $deriv;
my $d = partial_derivative($f, 'x');
ok($d->test_num_equiv($deriv, limits => $limits), "$d == $deriv");
}
# Test for regression RT #43783
{
my $formula1 = parse_from_string('K-C*exp(-L*x)');
my $formula2 = parse_from_string('K+-C*exp(-L*x)');
my %parameters = ( C => 0.8, K => 1., L => 1. );
my $deriv1 = partial_derivative($formula1, 'C')->apply_derivatives()->simplify();
my $deriv2 = partial_derivative($formula2, 'C')->apply_derivatives()->simplify();
foreach (1, 2, 3) {
ok(
float_eq(
$deriv1->value(%parameters, x => $_),
$deriv2->value(%parameters, x => $_)
),
"Derivatives of semantically equivalent formulas equivalent at x=$_"
);
}
}
sub float_eq {
$_[0] + 1.e-6 > $_[1] and $_[0] - 1.e-6 < $_[1]
}
|