--------------------------------------------------- lines 8-425 of file: example/general/base_alloc.hpp --------------------------------------------------- {xrst_begin base_alloc.hpp} {xrst_spell azmul isnan } Example AD 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 :ref:`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 :ref:`base_require-name` and :ref:`thread_alloc-name` . {xrst_spell_off} {xrst_code cpp} */ # include # include /* {xrst_code} {xrst_spell_on} Compound Assignment Macro ************************* This macro is used for the ``base_alloc`` compound assignment operators; to be specific, used with *op* equal to ``+=`` , ``-=`` , ``*=`` , ``/=`` . {xrst_spell_off} {xrst_code cpp} */ # define BASE_ALLOC_ASSIGN_OPERATOR(op) \ void operator op (const base_alloc& x) \ { *ptrdbl_ op *x.ptrdbl_; } /* {xrst_code} {xrst_spell_on} Binary Operator Macro ********************* This macro is used for the ``base_alloc`` binary operators (as member functions); to be specific, used with *op* equal to ``+`` , ``-`` , ``*`` , ``/`` . {xrst_spell_off} {xrst_code cpp} */ # 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; \ } /* {xrst_code} {xrst_spell_on} 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 ``>`` , {xrst_spell_off} {xrst_code cpp} */ # 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; \ } /* {xrst_code} {xrst_spell_on} Class Definition **************** The following example class defines the necessary :ref:`base_member-name` functions. It is made more complicated by storing a pointer to a ``double`` instead of the ``double`` value itself. {xrst_spell_off} {xrst_code cpp} */ 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(v); // // Avoid warning about possible use of uninitialized value *ptrdbl_ = CppAD::numeric_limits::quiet_NaN(); } base_alloc(double dbl) { size_t cap; void *v = CppAD::thread_alloc::get_memory(sizeof(double), cap); ptrdbl_ = static_cast(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(v); *ptrdbl_ = *x.ptrdbl_; } ~base_alloc(void) { void* v = static_cast(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(<=) }; /* {xrst_code} {xrst_spell_on} CondExpOp ********* The type ``base_alloc`` does not use :ref:`CondExp-name` operations. Hence its ``CondExpOp`` function is defined by {xrst_spell_off} {xrst_code cpp} */ 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(); } } /* {xrst_code} {xrst_spell_on} CondExpRel ********** The :ref:`CPPAD_COND_EXP_REL` macro invocation {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { CPPAD_COND_EXP_REL(base_alloc) } /* {xrst_code} {xrst_spell_on} 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 {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { inline bool EqualOpSeq(const base_alloc& x, const base_alloc& y) { return *x.ptrdbl_ == *y.ptrdbl_; } } /* {xrst_code} {xrst_spell_on} Identical ********* The type ``base_alloc`` is simple (in this respect) and so we define {xrst_spell_off} {xrst_code cpp} */ 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_); } } /* {xrst_code} {xrst_spell_on} Output Operator *************** {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { inline std::ostream& operator << (std::ostream &os, const base_alloc& x) { os << *x.ptrdbl_; return os; } } /* {xrst_code} {xrst_spell_on} Integer ******* {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { inline int Integer(const base_alloc& x) { return static_cast(*x.ptrdbl_); } } /* {xrst_code} {xrst_spell_on} azmul ***** {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { CPPAD_AZMUL( base_alloc ) } /* {xrst_code} {xrst_spell_on} Ordered ******* The ``base_alloc`` type supports ordered comparisons {xrst_spell_off} {xrst_code cpp} */ 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_); } } /* {xrst_code} {xrst_spell_on} Unary Standard Math ******************* The macro :ref:`base_std_math@CPPAD_STANDARD_MATH_UNARY` would not work with the type ``base_alloc`` so we define a special macro for this type: {xrst_spell_off} {xrst_code cpp} */ # define BASE_ALLOC_STD_MATH(fun) \ inline base_alloc fun (const base_alloc& x) \ { return std::fun(*x.ptrdbl_); } /* {xrst_code} {xrst_spell_on} The following invocations of the macro above define the :ref:`base_std_math@Unary Standard Math` functions (except for ``abs`` ): {xrst_spell_off} {xrst_code cpp} */ 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) } /* {xrst_code} {xrst_spell_on} The absolute value function is special because it ``std`` name is ``fabs`` {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { inline base_alloc abs(const base_alloc& x) { return fabs(*x.ptrdbl_); } } /* {xrst_code} {xrst_spell_on} The isnan function is special because it returns a bool {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { inline bool isnan(const base_alloc& x) { return *x.ptrdbl_ != *x.ptrdbl_; } } /* {xrst_code} {xrst_spell_on} sign **** The following defines the ``CppAD::sign`` function that is required to use ``AD`` : {xrst_spell_off} {xrst_code cpp} */ 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; } } /* {xrst_code} {xrst_spell_on} pow *** The following defines a ``CppAD::pow`` function that is required to use ``AD`` : {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { inline base_alloc pow(const base_alloc& x, const base_alloc& y) { return std::pow(*x.ptrdbl_, *y.ptrdbl_); } } /* {xrst_code} {xrst_spell_on} numeric_limits ************** The following defines the CppAD :ref:`numeric_limits-name` for the type ``base_alloc`` : {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { CPPAD_NUMERIC_LIMITS(double, base_alloc) } /* {xrst_code} {xrst_spell_on} to_string ********* The following defines the CppAD :ref:`to_string-name` function for the type ``base_alloc`` : {xrst_spell_off} {xrst_code cpp} */ namespace CppAD { CPPAD_TO_STRING(base_alloc) } /* {xrst_code} {xrst_spell_on} hash_code ********* The :ref:`base_hash@Default` hashing function does not work well for this case because two different pointers can have the same value. {xrst_spell_off} {xrst_code cpp} */ 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::max() ) is near 700 code = static_cast( (CPPAD_HASH_TABLE_SIZE / 700 + 1) * log_x ); code = code % CPPAD_HASH_TABLE_SIZE; return code; } } /* {xrst_code} {xrst_spell_on} {xrst_end base_alloc.hpp}