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 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-22 Bradley M. Bell
// ----------------------------------------------------------------------------
/*
Test higher order derivatives for tan(x) function.
*/
# include <cppad/cppad.hpp>
namespace {
bool tan_two(void)
{ bool ok = true;
using CppAD::AD;
using CppAD::NearEqual;
double eps = 10. * std::numeric_limits<double>::epsilon();
// domain space vector
size_t n = 1;
CPPAD_TESTVECTOR(AD<double>) ax(n);
ax[0] = 0.5;
// declare independent variables and starting recording
CppAD::Independent(ax);
// range space vector
size_t m = 1;
CPPAD_TESTVECTOR(AD<double>) ay(m);
ay[0] = tan( ax[0] );
// create f: x -> y and stop tape recording
CppAD::ADFun<double> f(ax, ay);
// first order Taylor coefficient
CPPAD_TESTVECTOR(double) x1(n), y1;
x1[0] = 2.0;
y1 = f.Forward(1, x1);
ok &= size_t( y1.size() ) == m;
// secondorder Taylor coefficients
CPPAD_TESTVECTOR(double) x2(n), y2;
x2[0] = 0.0;
y2 = f.Forward(2, x2);
ok &= size_t( y2.size() ) == m;
//
// Y (t) = F[X_0(t)]
// = tan(0.5 + 2t )
// Y' (t) = 2 * cos(0.5 + 2t )^(-2)
double sec_sq = 1.0 / ( cos(0.5) * cos(0.5) );
double check = 2.0 * sec_sq;
ok &= NearEqual(y1[0] , check, eps, eps);
//
// Y''(0) = 8*cos(0.5)^(-3)*sin(0.5)
check = 8.0 * tan(0.5) * sec_sq / 2.0;
ok &= NearEqual(y2[0] , check, eps, eps);
//
return ok;
}
bool tan_case(bool tan_first)
{ bool ok = true;
double eps = 100. * std::numeric_limits<double>::epsilon();
using CppAD::AD;
using CppAD::NearEqual;
// independent variable vector, indices, values, and declaration
size_t n = 1;
CPPAD_TESTVECTOR(AD<double>) ax(n);
ax[0] = .7;
Independent(ax);
// dependent variable vector and indices
size_t m = 1;
CPPAD_TESTVECTOR(AD<double>) ay(m);
if( tan_first )
ay[0] = atan( tan( ax[0] ) );
else
ay[0] = tan( atan( ax[0] ) );
// check value
ok &= NearEqual(ax[0] , ay[0], eps, eps);
// create f: x -> y and vectors used for derivative calculations
CppAD::ADFun<double> f(ax, ay);
CPPAD_TESTVECTOR(double) dx(n), dy(m);
// forward computation of partials w.r.t. x
dx[0] = 1.;
dy = f.Forward(1, dx);
ok &= NearEqual(dy[0], 1e0, eps, eps);
size_t p, order = 5;
dx[0] = 0.;
for(p = 2; p < order; p++)
{ dy = f.Forward(p, dx);
ok &= NearEqual(dy[0], 0e0, eps, eps);
}
// reverse computation of order partial
CPPAD_TESTVECTOR(double) w(m), dw(n * order);
w[0] = 1.;
dw = f.Reverse(order, w);
ok &= NearEqual(dw[0], 1e0, eps, eps);
for(p = 1; p < order; p++)
ok &= NearEqual(dw[p], 0e0, eps, eps);
return ok;
}
bool tanh_case(bool tanh_first)
{ bool ok = true;
double eps = 100. * std::numeric_limits<double>::epsilon();
using CppAD::AD;
using CppAD::NearEqual;
// independent variable vector, indices, values, and declaration
size_t n = 1;
CPPAD_TESTVECTOR(AD<double>) ax(n);
ax[0] = .5;
Independent(ax);
// dependent variable vector and indices
size_t m = 1;
CPPAD_TESTVECTOR(AD<double>) ay(m);
AD<double> z;
if( tanh_first )
{ z = tanh( ax[0] );
ay[0] = .5 * log( (1. + z) / (1. - z) );
}
else
{ z = .5 * log( (1. + ax[0]) / (1. - ax[0]) );
ay[0] = tanh(z);
}
// check value
ok &= NearEqual(ax[0] , ay[0], eps, eps);
// create f: x -> y and vectors used for derivative calculations
CppAD::ADFun<double> f(ax, ay);
CPPAD_TESTVECTOR(double) dx(n), dy(m);
// forward computation of partials w.r.t. x
dx[0] = 1.;
dy = f.Forward(1, dx);
ok &= NearEqual(dy[0], 1e0, eps, eps);
size_t p, order = 5;
dx[0] = 0.;
for(p = 2; p < order; p++)
{ dy = f.Forward(p, dx);
ok &= NearEqual(dy[0], 0e0, eps, eps);
}
// reverse computation of order partial
CPPAD_TESTVECTOR(double) w(m), dw(n * order);
w[0] = 1.;
dw = f.Reverse(order, w);
ok &= NearEqual(dw[0], 1e0, eps, eps);
for(p = 1; p < order; p++)
ok &= NearEqual(dw[p], 0e0, eps, eps);
return ok;
}
}
bool tan(void)
{ bool ok = true;
//
ok &= tan_case(true);
ok &= tan_case(false);
ok &= tanh_case(true);
ok &= tanh_case(false);
//
ok &= tan_two();
return ok;
}
|