# ifndef CPPAD_DISCRETE_INCLUDED
# define CPPAD_DISCRETE_INCLUDED
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-07 Bradley M. Bell
CppAD is distributed under multiple licenses. This distribution is under
the terms of the
Common Public License Version 1.0.
A copy of this license is included in the COPYING file of this distribution.
Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
-------------------------------------------------------------------------- */
/*
$begin Discrete$$
$spell
retaping
namespace
std
Eq
Cpp
const
inline
Geq
$$
$section Discrete AD Functions$$
$index discrete, AD function$$
$index function, discrete AD$$
$head Syntax$$
$syntax%CPPAD_DISCRETE_FUNCTION(%Base%, %name%)
%$$
$syntax%%v% = %name%(%u%)
%$$
$syntax%%y% = %name%(%x%)
%$$
$head Purpose$$
Record the evaluation of a discrete function as part
of an $syntax%AD<%Base%>%$$
$xref/glossary/Operation/Sequence/operation sequence/1/$$.
The value of a discrete function can depend on the
$cref/independent variables/glossary/Tape/Independent Variable/$$,
but its derivative is identically zero.
For example, suppose that the integer part of
a $cref/variable/glossary/Variable/$$ $italic x$$ is the
index into an array of values.
$head Base$$
This is the
$cref/base type/base_require/$$
corresponding to the operations sequence;
i.e., use of the $italic name$$ with arguments of type
$syntax%AD<%Base%>%$$ can be recorded in an operation sequence.
$head name$$
This is the name of the function (as it is used in the source code).
The user must provide a version of $italic name$$
where the argument has type $italic Base$$.
CppAD uses this to create a version of $italic name$$
where the argument has type $syntax%AD<%Base%>%$$.
$head u$$
The argument $italic u$$ has prototype
$syntax%
const %Base% &%u%
%$$
It is the value at which the user provided version of $italic name$$
is to be evaluated.
$head v$$
The result $italic v$$ has prototype
$syntax%
%Base% %v%
%$$
It is the return value for the user provided version of $italic name$$.
$head x$$
The argument $italic x$$ has prototype
$syntax%
const AD<%Base%> &%x%
%$$
It is the value at which the CppAD provided version of $italic name$$
is to be evaluated.
$head y$$
The result $italic y$$ has prototype
$syntax%
AD<%Base%> %v%
%$$
It is the return value for the CppAD provided version of $italic name$$.
$head Create AD Version$$
$index CPPAD_DISCRETE_FUNCTION$$
The preprocessor macro invocation
$syntax%
CPPAD_DISCRETE_FUNCTION(%Base%, %name%)
%$$
defines the $syntax%AD<%Base%>%$$ version of $italic name$$.
This can be with in a namespace (not the $code CppAD$$ namespace)
but must be outside of any routine.
$head Operation Sequence$$
This is an AD of $italic Base$$
$xref/glossary/Operation/Atomic/atomic operation/1/$$
and hence is part of the current
AD of $italic Base$$
$xref/glossary/Operation/Sequence/operation sequence/1/$$.
$head Derivatives$$
During a zero order $xref/Forward//Forward/$$ operation,
an $xref/ADFun/$$ object will compute the value of $italic name$$
using the user provided $italic Base$$ version of this routine.
All the derivatives of $italic name$$ will be evaluated as zero.
$head Example$$
$children%
example/tape_index.cpp%
example/interp_onetape.cpp%
example/interp_retape.cpp
%$$
The file
$xref/TapeIndex.cpp/$$
contains an example and test that uses a discrete function
to vary an array index during $cref/Forward/$$ mode calculations.
The file
$xref/interp_onetape.cpp/$$
contains an example and test that uses discrete
functions to avoid retaping a calculation that requires interpolation.
(The file
$xref/interp_retape.cpp/$$
shows how interpolation can be done with retaping.)
$head Deprecated$$
$index CppADCreateDiscrete, deprecated$$
$index deprecated, CppADCreateDiscrete$$
The preprocessor symbol $code CppADCreateDiscrete$$
is defined to be the same as $code CPPAD_DISCRETE_FUNCTION$$
but its use is deprecated.
$end
------------------------------------------------------------------------------
*/
# define CPPAD_DISCRETE_FUNCTION(Base, FunName) \
inline CppAD::AD FunName (const CppAD::AD &x) \
{ \
static CppAD::ADDiscrete Fun(FunName); \
\
return Fun.Eval(x); \
}
# define CppADCreateDiscrete CPPAD_DISCRETE_FUNCTION
# include
// Begin CppAD namespace
namespace CppAD {
template
class ADDiscrete {
typedef Base (*F) (const Base &x);
public:
ADDiscrete(F f) : f_(f), f_index_( List()->size() )
{ List()->push_back(this); }
// used during the recording process
AD Eval(const AD &x) const
{ AD result;
result.value_ = f_(x.value_);
if( Variable(x) )
{ ADTape *tape = x.tape_this();
CPPAD_ASSERT_UNKNOWN( NumVar(DisOp) == 1 );
CPPAD_ASSERT_UNKNOWN( NumInd(DisOp) == 2 );
// put operand addresses in the tape
tape->Rec_.PutInd(x.taddr_, f_index_);
// put operator in the tape
result.taddr_ = tape->Rec_.PutOp(DisOp);
// make result a variable
result.id_ = tape->id_;
CPPAD_ASSERT_UNKNOWN( Variable(result) );
}
return result;
}
// used to evaluate from the recording
static Base Eval(size_t f_index, const Base &x)
{
CPPAD_ASSERT_UNKNOWN(f_index < List()->size() );
return (*List())[f_index]->f_(x);
}
private:
const F f_;
const size_t f_index_;
static std::vector *List(void)
{ static std::vector list;
return &list;
}
};
} // END CppAD namespace
# endif