openpilot/external/cppad/include/cppad/core/discrete.hpp

307 lines
8.1 KiB
C++

# ifndef CPPAD_CORE_DISCRETE_HPP
# define CPPAD_CORE_DISCRETE_HPP
/* --------------------------------------------------------------------------
CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
CppAD is distributed under multiple licenses. This distribution is under
the terms of the
Eclipse 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$$
$mindex CPPAD_DISCRETE_FUNCTION$$
$head Syntax$$
$codei%CPPAD_DISCRETE_FUNCTION(%Base%, %name%)
%$$
$icode%y% = %name%(%x%)
%$$
$icode%ay% = %name%(%ax%)
%$$
$head Purpose$$
Record the evaluation of a discrete function as part
of an $codei%AD<%Base%>%$$
$cref/operation sequence/glossary/Operation/Sequence/$$.
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/$$ $icode 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 $icode name$$ with arguments of type
$codei%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 $icode name$$
where the argument has type $icode Base$$.
CppAD uses this to create a version of $icode name$$
where the argument has type $codei%AD<%Base%>%$$.
$head x$$
The argument $icode x$$ has prototype
$codei%
const %Base%& %x%
%$$
It is the value at which the user provided version of $icode name$$
is to be evaluated.
$head y$$
The result $icode y$$ has prototype
$codei%
%Base% %y%
%$$
It is the return value for the user provided version of $icode name$$.
$head ax$$
The argument $icode ax$$ has prototype
$codei%
const AD<%Base%>& %ax%
%$$
It is the value at which the CppAD provided version of $icode name$$
is to be evaluated.
$head ay$$
The result $icode ay$$ has prototype
$codei%
AD<%Base%> %ay%
%$$
It is the return value for the CppAD provided version of $icode name$$.
$head Create AD Version$$
The preprocessor macro invocation
$codei%
CPPAD_DISCRETE_FUNCTION(%Base%, %name%)
%$$
defines the $codei%AD<%Base%>%$$ version of $icode 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 $icode Base$$
$cref/atomic operation/glossary/Operation/Atomic/$$
and hence is part of the current
AD of $icode Base$$
$cref/operation sequence/glossary/Operation/Sequence/$$.
$head Derivatives$$
During a zero order $cref Forward$$ operation,
an $cref ADFun$$ object will compute the value of $icode name$$
using the user provided $icode Base$$ version of this routine.
All the derivatives of $icode name$$ will be evaluated as zero.
$head Parallel Mode$$
The first call to
$codei%
%ay% = %name%(%ax%)
%$$
must not be in $cref/parallel/ta_in_parallel/$$ execution mode.
$head Example$$
$children%
example/general/tape_index.cpp%
example/general/interp_onetape.cpp%
example/general/interp_retape.cpp
%$$
The file
$cref tape_index.cpp$$
contains an example and test that uses a discrete function
to vary an array index during $cref Forward$$ mode calculations.
The file
$cref interp_onetape.cpp$$
contains an example and test that uses discrete
functions to avoid retaping a calculation that requires interpolation.
(The file
$cref interp_retape.cpp$$
shows how interpolation can be done with retaping.)
$head CppADCreateDiscrete Deprecated 2007-07-28$$
The preprocessor symbol $code CppADCreateDiscrete$$
is defined to be the same as $code CPPAD_DISCRETE_FUNCTION$$
but its use is deprecated.
$end
------------------------------------------------------------------------------
*/
# include <vector>
# include <cppad/core/cppad_assert.hpp>
// needed before one can use CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL
# include <cppad/utility/thread_alloc.hpp>
namespace CppAD { // BEGIN_CPPAD_NAMESPACE
/*!
\file discrete.hpp
user define discrete functions
*/
/*!
\def CPPAD_DISCRETE_FUNCTION(Base, name)
Defines the function <code>name(ax, ay)</code>
where \c ax and \c ay are vectors with <code>AD<Base></code> elements.
\par Base
is the base type for the discrete function.
\par name
is the name of the user defined function that corresponding to this operation.
*/
# define CPPAD_DISCRETE_FUNCTION(Base, name) \
inline CppAD::AD<Base> name (const CppAD::AD<Base>& ax) \
{ \
static CppAD::discrete<Base> fun(#name, name); \
\
return fun.ad(ax); \
}
# define CppADCreateDiscrete CPPAD_DISCRETE_FUNCTION
/*
Class that acutally implemnets the <code>ay = name(ax)</code> call.
A new discrete function is generated for ech time the user invokes
the CPPAD_DISCRETE_FUNCTION macro; see static object in that macro.
*/
template <class Base>
class discrete {
/// parallel_ad needs to call List to initialize static
template <class Type>
friend void parallel_ad(void);
/// type for the user routine that computes function values
typedef Base (*F) (const Base& x);
private:
/// name of this user defined function
const std::string name_;
/// user's implementation of the function for Base operations
const F f_;
/// index of this objec in the vector of all objects for this class
const size_t index_;
/*!
List of all objects in this class.
If we use CppAD::vector for this vector, it will appear that
there is a memory leak because this list is not distroyed before
thread_alloc::free_available(thread) is called by the testing routines.
*/
static std::vector<discrete *>& List(void)
{ CPPAD_ASSERT_FIRST_CALL_NOT_PARALLEL;
static std::vector<discrete *> list;
return list;
}
public:
/*!
Constructor called for each invocation of CPPAD_DISCRETE_FUNCTION.
Put this object in the list of all objects for this class and set
the constant private data name_, f_, and index_.
\param Name
is the user's name for this discrete function.
\param f
user routine that implements this function for \c Base class.
\par
This constructor can ont be used in parallel mode because it changes
the static object \c List.
*/
discrete(const char* Name, F f) :
name_(Name)
, f_(f)
, index_( List().size() )
{
CPPAD_ASSERT_KNOWN(
! thread_alloc::in_parallel() ,
"discrete: First call the function *Name is in parallel mode."
);
List().push_back(this);
}
/*!
Implement the user call to <code>ay = name(ax)</code>.
\param ax
is the argument for this call.
\return
the return value is called \c ay above.
*/
AD<Base> ad(const AD<Base> &ax) const
{ AD<Base> ay;
ay.value_ = f_(ax.value_);
if( Variable(ax) )
{ local::ADTape<Base> *tape = ax.tape_this();
CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DisOp) == 1 );
CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DisOp) == 2 );
// put operand addresses in the tape
CPPAD_ASSERT_KNOWN(
std::numeric_limits<addr_t>::max() >= index_,
"discrete: cppad_tape_addr_type maximum not large enough"
);
tape->Rec_.PutArg(addr_t(index_), ax.taddr_);
// put operator in the tape
ay.taddr_ = tape->Rec_.PutOp(local::DisOp);
// make result a variable
ay.tape_id_ = tape->id_;
CPPAD_ASSERT_UNKNOWN( Variable(ay) );
}
return ay;
}
/// Name corresponding to a discrete object
static const char* name(size_t index)
{ return List()[index]->name_.c_str(); }
/*!
Link from forward mode sweep to users routine
\param index
index for this function in the list of all discrete object
\param x
argument value at which to evaluate this function
*/
static Base eval(size_t index, const Base& x)
{
CPPAD_ASSERT_UNKNOWN(index < List().size() );
return List()[index]->f_(x);
}
};
} // END_CPPAD_NAMESPACE
# endif