Prev Next base_alloc.hpp

@(@\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}} }@)@This is cppad-20221105 documentation. Here is a link to its current documentation .
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 CondExpRel 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;
    }
}

Input File: example/general/base_alloc.hpp