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
|
// 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 that reverse mode handles conditional expressions properly
// in that infinity and nans do not propagate thouh un-used case.
# include <cppad/cppad.hpp>
bool cond_exp_rev(void)
{ bool ok = true;
using CppAD::vector;
using CppAD::AD;
AD<double> anan = std::numeric_limits<double>::quiet_NaN();
AD<double> azero = 0.0;
size_t n = 2;
vector< AD<double> > ax(n), ay;
ax[0] = 1.0;
ax[1] = anan;
Independent(ax);
// AbsOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], fabs(ax[1]) ));
// AcosOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], acos(ax[1]) ));
// AddvvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] + ax[1] ));
// AddpvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], 1.0 + ax[1] ));
// AsinOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], asin(ax[1]) ));
// AtanOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], atan(ax[1]) ));
// CosOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], cos(ax[1]) ));
// CoshOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], cosh(ax[1]) ));
// DivvvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] / ax[1] ));
// DivpvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], 1.0 / ax[1] ));
// DivvpOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[1] / 2.0 ));
// ErfOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], erf(ax[1]) ));
// ExpOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], exp(ax[1]) ));
// LogOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], log(ax[1]) ));
// MulvvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] * ax[1] ));
// MulpvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], 2.0 * ax[1] ));
// PowvvOP
// uses check in log, mul, and exp
ay.push_back( CondExpGt(ax[0], azero, ax[0], pow(ax[1], ax[1]) ));
// PowvpOP
// uses check in log, mul, and exp
ay.push_back( CondExpGt(ax[0], azero, ax[0], pow(ax[1], 2.0) ));
// PowpvOP
// uses check in log, mul, and exp
ay.push_back( CondExpGt(ax[0], azero, ax[0], pow(2.0, ax[1]) ));
// SignOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], sign(ax[1]) ));
// SinOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], sin(ax[1]) ));
// SinhOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], sinh(ax[1]) ));
// SqrtOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], sqrt(ax[1]) ));
// SubvvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[0] - ax[1] ));
// SubpvOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], 1.0 - ax[1] ));
// SubvpOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], ax[1] - 1.0 ));
// TanOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], tan(ax[1]) ));
// TanhOp
ay.push_back( CondExpGt(ax[0], azero, ax[0], tanh(ax[1]) ));
// create f : x -> y
size_t m = ay.size();
CppAD::ADFun<double> f(ax, ay);
// weighting vector and reverse mode derivative
vector<double> w(m), dw(n);
for(size_t i = 0; i < m; i++)
w[i] = 0.0;
// check DivvOp
for(size_t i = 0; i < m; i++)
{ w[i] = 1.0;
dw = f.Reverse(1, w);
ok &= dw[0] == 1.0;
ok &= dw[1] == 0.0;
w[i] = 0.0;
}
return ok;
}
|