\(\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¶
Example 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);
}
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_); }
}
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;
}
}