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 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
# ifndef CPPAD_INTRODUCTION_EXP_EPS_HPP
# define CPPAD_INTRODUCTION_EXP_EPS_HPP
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
// SPDX-FileCopyrightText: Bradley M. Bell <bradbell@seanet.com>
// SPDX-FileContributor: 2003-24 Bradley M. Bell
// ----------------------------------------------------------------------------
/*
{xrst_begin exp_eps}
{xrst_spell
apx
yyyymmdd
}
An Epsilon Accurate Exponential Approximation
#############################################
Syntax
******
| # ``include`` ``"exp_eps.hpp"``
| *y* = ``exp_eps`` ( *x* , *epsilon* )
Purpose
*******
This is a an example algorithm that is used to demonstrate
how Algorithmic Differentiation works with loops and
boolean decision variables
(see :ref:`exp_2-name` for a simpler example).
Mathematical Function
*********************
The exponential function can be defined by
.. math::
\exp (x) = 1 + x^1 / 1 ! + x^2 / 2 ! + \cdots
We define :math:`k ( x, \varepsilon )` as the smallest
non-negative integer such that :math:`\varepsilon \geq x^k / k !`; i.e.,
.. math::
k( x, \varepsilon ) =
\min \{ k \in {\rm Z}_+ \; | \; \varepsilon \geq x^k / k ! \}
The mathematical form for our approximation of the exponential function is
.. math::
:nowrap:
\begin{eqnarray}
{\rm exp\_eps} (x , \varepsilon ) & = & \left\{
\begin{array}{ll}
\frac{1}{ {\rm exp\_eps} (-x , \varepsilon ) }
& {\rm if} \; x < 0
\\
1 + x^1 / 1 ! + \cdots + x^{k( x, \varepsilon)} / k( x, \varepsilon ) !
& {\rm otherwise}
\end{array}
\right.
\end{eqnarray}
include
*******
The include command in the syntax is relative to
``cppad-`` *yyyymmdd* / ``introduction/exp_apx``
where ``cppad-`` *yyyymmdd* is the distribution directory
created during the beginning steps of the
:ref:`installation<Install-name>` of CppAD.
x
*
The argument *x* has prototype
``const`` *Type* & *x*
(see *Type* below).
It specifies the point at which to evaluate the
approximation for the exponential function.
epsilon
*******
The argument *epsilon* has prototype
``const`` *Type* & *epsilon*
It specifies the accuracy with which
to approximate the exponential function value; i.e.,
it is the value of :math:`\varepsilon` in the
exponential function approximation defined above.
y
*
The result *y* has prototype
*Type* *y*
It is the value of the exponential function
approximation defined above.
Type
****
If *u* and *v* are *Type* objects and *i*
is an ``int`` :
.. list-table::
:widths: auto
* - **Operation**
- **Result Type**
- **Description**
* - *Type* ( *i* )
- *Type*
- object with value equal to *i*
* - *Type u* = *v*
- *Type*
- construct *u* with value equal to *v*
* - *u* > *v*
- ``bool``
- true,
if *u* greater than *v* , an false otherwise
* - *u* = *v*
- *Type*
- new *u* (and result) is value of *v*
* - *u* * *v*
- *Type*
- result is value of :math:`u * v`
* - *u* / *v*
- *Type*
- result is value of :math:`u / v`
* - *u* + *v*
- *Type*
- result is value of :math:`u + v`
* - ``-`` *u*
- *Type*
- result is value of :math:`- u`
{xrst_toc_hidden
introduction/exp_eps.xrst
introduction/exp_eps_cppad.cpp
}
Implementation
**************
The file :ref:`exp_eps.hpp-name`
contains a C++ implementation of this function.
Test
****
The file :ref:`exp_eps.cpp-name`
contains a test of this implementation.
Exercises
*********
#. Using the definition of :math:`k( x, \varepsilon )` above,
what is the value of
:math:`k(.5, 1)`, :math:`k(.5, .1)`, and :math:`k(.5, .01)` ?
#. Suppose that we make the following call to ``exp_eps`` :
::
double x = 1.;
double epsilon = .01;
double y = exp_eps(x, epsilon);
What is the value assigned to
``k`` , ``temp`` , ``term`` , and ``sum``
the first time through the ``while`` loop in :ref:`exp_eps.hpp-name` ?
#. Continuing the previous exercise,
what is the value assigned to
``k`` , ``temp`` , ``term`` , and ``sum``
the second time through the ``while`` loop in :ref:`exp_eps.hpp-name` ?
{xrst_end exp_eps}
-----------------------------------------------------------------------------
*/
// BEGIN C++
template <class Type>
Type exp_eps(const Type &x, const Type &epsilon)
{ // abs_x = |x|
Type abs_x = x;
if( Type(0) > x )
abs_x = - x;
// initialize
int k = 0; // initial order
Type term = 1.; // term = |x|^k / k !
Type sum = term; // initial sum
while(term > epsilon)
{ k = k + 1; // order for next term
Type temp = term * abs_x; // term = |x|^k / (k-1)!
term = temp / Type(k); // term = |x|^k / k !
sum = sum + term; // sum = 1 + ... + |x|^k / k !
}
// In the case where x is negative, use exp(x) = 1 / exp(-|x|)
if( Type(0) > x )
sum = Type(1) / sum;
return sum;
}
// END C++
# endif
|