\(\newcommand{\W}[1]{ \; #1 \; }\) \(\newcommand{\R}[1]{ {\rm #1} }\) \(\newcommand{\B}[1]{ {\bf #1} }\) \(\newcommand{\D}[2]{ \frac{\partial #1}{\partial #2} }\) \(\newcommand{\DD}[3]{ \frac{\partial^2 #1}{\partial #2 \partial #3} }\) \(\newcommand{\Dpow}[2]{ \frac{\partial^{#1}}{\partial {#2}^{#1}} }\) \(\newcommand{\dpow}[2]{ \frac{ {\rm d}^{#1}}{{\rm d}\, {#2}^{#1}} }\)
base_alloc.hpp¶
View page sourceExample AD<Base> Where Base Constructor Allocates Memory¶
Purpose¶
Demonstrate use of AD
< Base >
where memory is allocated for each element of the type Base .
In addition, this is a complete example where all the
required Base type
operations are defined (as apposed to other examples where
some of the operations for the Base type are already defined).
Include File¶
This file uses some of the definitions in base_require and thread_alloc .
# include <cppad/base_require.hpp>
# include <cppad/utility/thread_alloc.hpp>
Compound Assignment Macro¶
This macro is used for the
base_alloc
compound assignment operators; to be specific,
used with op equal to
+=
,
-=
,
*=
,
/=
.
# define BASE_ALLOC_ASSIGN_OPERATOR(op) \
void operator op (const base_alloc& x) \
{ *ptrdbl_ op *x.ptrdbl_; }
Binary Operator Macro¶
This macro is used for the
base_alloc
binary operators (as member functions); to be specific,
used with op equal to
+
,
-
,
*
,
/
.
# define BASE_ALLOC_BINARY_OPERATOR(op) const \
base_alloc operator op (const base_alloc& x) const \
{ base_alloc result; \
double dbl = *ptrdbl_; \
double x_dbl = *x.ptrdbl_; \
*result.ptrdbl_ = dbl op x_dbl; \
return result; \
}
Boolean Operator Macro¶
This macro can be used for the
base_alloc
binary operators that have a
bool
result; to be specific,
used with op equal to
==
,
!=
,
<
,
<=
,
>=
, and
>
,
# define BASE_ALLOC_BOOL_OPERATOR(op) const \
bool operator op (const base_alloc& x) const \
{ double dbl = *ptrdbl_; \
double x_dbl = *x.ptrdbl_; \
return dbl op x_dbl; \
}
Class Definition¶
The following example class
defines the necessary base_member functions.
It is made more complicated by storing a pointer to a double
instead of the double
value itself.
class base_alloc {
public:
double* ptrdbl_;
base_alloc(void)
{ size_t cap;
void* v = CppAD::thread_alloc::get_memory(sizeof(double), cap);
ptrdbl_ = static_cast<double*>(v);
//
// Avoid warning about possible use of uninitialized value
*ptrdbl_ = CppAD::numeric_limits<double>::quiet_NaN();
}
base_alloc(double dbl)
{ size_t cap;
void *v = CppAD::thread_alloc::get_memory(sizeof(double), cap);
ptrdbl_ = static_cast<double*>(v);
*ptrdbl_ = dbl;
}
base_alloc(const base_alloc& x)
{ size_t cap;
void *v = CppAD::thread_alloc::get_memory(sizeof(double), cap);
ptrdbl_ = static_cast<double*>(v);
*ptrdbl_ = *x.ptrdbl_;
}
~base_alloc(void)
{ void* v = static_cast<void*>(ptrdbl_);
CppAD::thread_alloc::return_memory(v);
}
base_alloc operator-(void) const
{ base_alloc result;
*result.ptrdbl_ = - *ptrdbl_;
return result;
}
base_alloc operator+(void) const
{ return *this; }
void operator=(const base_alloc& x)
{ *ptrdbl_ = *x.ptrdbl_; }
BASE_ALLOC_ASSIGN_OPERATOR(+=)
BASE_ALLOC_ASSIGN_OPERATOR(-=)
BASE_ALLOC_ASSIGN_OPERATOR(*=)
BASE_ALLOC_ASSIGN_OPERATOR(/=)
BASE_ALLOC_BINARY_OPERATOR(+)
BASE_ALLOC_BINARY_OPERATOR(-)
BASE_ALLOC_BINARY_OPERATOR(*)
BASE_ALLOC_BINARY_OPERATOR(/)
BASE_ALLOC_BOOL_OPERATOR(==)
BASE_ALLOC_BOOL_OPERATOR(!=)
// The <= operator is not necessary for the base type requirements
// (needed so we can use NearEqual with base_alloc arguments).
BASE_ALLOC_BOOL_OPERATOR(<=)
};
CondExpOp¶
The type base_alloc
does not use CondExp operations.
Hence its CondExpOp
function is defined by
namespace CppAD {
inline base_alloc CondExpOp(
enum CompareOp cop ,
const base_alloc& left ,
const base_alloc& right ,
const base_alloc& exp_if_true ,
const base_alloc& exp_if_false )
{ // not used
assert(false);
// to void compiler error
return base_alloc();
}
}
CondExpRel¶
The CPPAD_COND_EXP_REL macro invocation
namespace CppAD {
CPPAD_COND_EXP_REL(base_alloc)
}
uses CondExpOp
above to
define CondExp
Rel for base_alloc
arguments
and Rel equal to
Lt
, Le
, Eq
, Ge
, and Gt
.
EqualOpSeq¶
The type base_alloc
is simple (in this respect) and so we define
namespace CppAD {
inline bool EqualOpSeq(const base_alloc& x, const base_alloc& y)
{ return *x.ptrdbl_ == *y.ptrdbl_; }
}
Identical¶
The type base_alloc
is simple (in this respect) and so we define
namespace CppAD {
inline bool IdenticalCon(const base_alloc& x)
{ return true; }
inline bool IdenticalZero(const base_alloc& x)
{ return (*x.ptrdbl_ == 0.0); }
inline bool IdenticalOne(const base_alloc& x)
{ return (*x.ptrdbl_ == 1.0); }
inline bool IdenticalEqualCon(const base_alloc& x, const base_alloc& y)
{ return (*x.ptrdbl_ == *y.ptrdbl_); }
}
Output Operator¶
namespace CppAD {
inline std::ostream& operator << (std::ostream &os, const base_alloc& x)
{ os << *x.ptrdbl_;
return os;
}
}
Integer¶
namespace CppAD {
inline int Integer(const base_alloc& x)
{ return static_cast<int>(*x.ptrdbl_); }
}
azmul¶
namespace CppAD {
CPPAD_AZMUL( base_alloc )
}
Ordered¶
The base_alloc
type supports ordered comparisons
namespace CppAD {
inline bool GreaterThanZero(const base_alloc& x)
{ return *x.ptrdbl_ > 0.0; }
inline bool GreaterThanOrZero(const base_alloc& x)
{ return *x.ptrdbl_ >= 0.0; }
inline bool LessThanZero(const base_alloc& x)
{ return *x.ptrdbl_ < 0.0; }
inline bool LessThanOrZero(const base_alloc& x)
{ return *x.ptrdbl_ <= 0.f; }
inline bool abs_geq(const base_alloc& x, const base_alloc& y)
{ return std::fabs(*x.ptrdbl_) >= std::fabs(*y.ptrdbl_); }
}
Unary Standard Math¶
The macro
CPPAD_STANDARD_MATH_UNARY
would not work with the type base_alloc
so we define
a special macro for this type:
# define BASE_ALLOC_STD_MATH(fun) \
inline base_alloc fun (const base_alloc& x) \
{ return std::fun(*x.ptrdbl_); }
The following invocations of the macro above define the
Unary Standard Math functions
(except for abs
):
namespace CppAD {
BASE_ALLOC_STD_MATH(acos)
BASE_ALLOC_STD_MATH(acosh)
BASE_ALLOC_STD_MATH(asin)
BASE_ALLOC_STD_MATH(asinh)
BASE_ALLOC_STD_MATH(atan)
BASE_ALLOC_STD_MATH(atanh)
BASE_ALLOC_STD_MATH(cos)
BASE_ALLOC_STD_MATH(cosh)
BASE_ALLOC_STD_MATH(erf)
BASE_ALLOC_STD_MATH(erfc)
BASE_ALLOC_STD_MATH(exp)
BASE_ALLOC_STD_MATH(expm1)
BASE_ALLOC_STD_MATH(fabs)
BASE_ALLOC_STD_MATH(log)
BASE_ALLOC_STD_MATH(log1p)
BASE_ALLOC_STD_MATH(log10)
BASE_ALLOC_STD_MATH(sin)
BASE_ALLOC_STD_MATH(sinh)
BASE_ALLOC_STD_MATH(sqrt)
BASE_ALLOC_STD_MATH(tan)
BASE_ALLOC_STD_MATH(tanh)
}
The absolute value function is special because it std
name is
fabs
namespace CppAD {
inline base_alloc abs(const base_alloc& x)
{ return fabs(*x.ptrdbl_); }
}
The isnan function is special because it returns a bool
namespace CppAD {
inline bool isnan(const base_alloc& x)
{ return *x.ptrdbl_ != *x.ptrdbl_; }
}
sign¶
The following defines the CppAD::sign
function that
is required to use AD<base_alloc>
:
namespace CppAD {
inline base_alloc sign(const base_alloc& x)
{ if( *x.ptrdbl_ > 0.0 )
return 1.0;
if( *x.ptrdbl_ == 0.0 )
return 0.0;
return -1.0;
}
}
pow¶
The following defines a CppAD::pow
function that
is required to use AD<base_alloc>
:
namespace CppAD {
inline base_alloc pow(const base_alloc& x, const base_alloc& y)
{ return std::pow(*x.ptrdbl_, *y.ptrdbl_); }
}
numeric_limits¶
The following defines the CppAD numeric_limits
for the type base_alloc
:
namespace CppAD {
CPPAD_NUMERIC_LIMITS(double, base_alloc)
}
to_string¶
The following defines the CppAD to_string function
for the type base_alloc
:
namespace CppAD {
CPPAD_TO_STRING(base_alloc)
}
hash_code¶
The Default hashing function does not work well for this case because two different pointers can have the same value.
namespace CppAD {
inline unsigned short hash_code(const base_alloc& x)
{ unsigned short code = 0;
if( *x.ptrdbl_ == 0.0 )
return code;
double log_x = log( std::fabs( *x.ptrdbl_ ) );
// assume log( std::numeric_limits<double>::max() ) is near 700
code = static_cast<unsigned short>(
(CPPAD_HASH_TABLE_SIZE / 700 + 1) * log_x
);
code = code % CPPAD_HASH_TABLE_SIZE;
return code;
}
}