예제 #1
0
파일: atan_op.hpp 프로젝트: ZiiCee/OPTI
inline void reverse_atan_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      cap_order    ,
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(AtanOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(AtanOp) == 2 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	const Base* x  = taylor  + i_x * cap_order;
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to first result
	const Base* z  = taylor  + i_z * cap_order;
	Base* pz       = partial + i_z * nc_partial;

	// Taylor coefficients and partials corresponding to auxillary result
	const Base* b  = z  - cap_order; // called y in documentation
	Base* pb       = pz - nc_partial;

	// If pz is zero, make sure this operation has no effect
	// (zero times infinity or nan would be non-zero).
	bool skip(true);
	for(size_t i_d = 0; i_d <= d; i_d++)
		skip &= IdenticalZero(pz[i_d]);
	if( skip )
		return;

	// number of indices to access
	size_t j = d;
	size_t k;
	while(j)
	{	// scale partials w.r.t z[j] and b[j]
		pz[j] /= b[0];
		pb[j] *= Base(2);

		pb[0] -= pz[j] * z[j];
		px[j] += pz[j] + pb[j] * x[0];
		px[0] += pb[j] * x[j];

		// more scaling of partials w.r.t z[j]
		pz[j] /= Base(j);

		for(k = 1; k < j; k++)
		{	pb[j-k] -= pz[j] * Base(k) * z[k];
			pz[k]   -= pz[j] * Base(k) * b[j-k];
			px[k]   += pb[j] * x[j-k];
		}
		--j;
	}
	px[0] += pz[0] / b[0] + pb[0] * Base(2) * x[0];
}
예제 #2
0
inline void reverse_cosh_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      cap_order    ,
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(CoshOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(CoshOp) == 2 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	const Base* x  = taylor  + i_x * cap_order;
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to first result
	const Base* c  = taylor  + i_z * cap_order; // called z in doc
	Base* pc       = partial + i_z * nc_partial;

	// Taylor coefficients and partials corresponding to auxillary result
	const Base* s  = c  - cap_order; // called y in documentation
	Base* ps       = pc - nc_partial;

	// If pc is zero, make sure this operation has no effect
	// (zero times infinity or nan would be non-zero).
	bool skip(true);
	for(size_t i_d = 0; i_d <= d; i_d++)
		skip &= IdenticalZero(pc[i_d]);
	if( skip )
		return;

	// rest of this routine is identical for the following cases:
	// reverse_sin_op, reverse_cos_op, reverse_sinh_op, reverse_cosh_op.
	size_t j = d;
	size_t k;
	while(j)
	{
		ps[j]   /= Base(j);
		pc[j]   /= Base(j);
		for(k = 1; k <= j; k++)
		{
			px[k]   += ps[j] * Base(k) * c[j-k];
			px[k]   += pc[j] * Base(k) * s[j-k];

			ps[j-k] += pc[j] * Base(k) * x[k];
			pc[j-k] += ps[j] * Base(k) * x[k];

		}
		--j;
	}
	px[0] += ps[0] * c[0];
	px[0] += pc[0] * s[0];
}
예제 #3
0
파일: tan_op.hpp 프로젝트: ZiiCee/OPTI
inline void reverse_tan_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      cap_order    ,
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(TanOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(TanOp) == 2 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	const Base* x  = taylor  + i_x * cap_order;
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to first result
	const Base* z  = taylor  + i_z * cap_order; // called z in doc
	Base* pz       = partial + i_z * nc_partial;

	// Taylor coefficients and partials corresponding to auxillary result
	const Base* y  = z  - cap_order; // called y in documentation
	Base* py       = pz - nc_partial;

	// If pz is zero, make sure this operation has no effect
	// (zero times infinity or nan would be non-zero).
	bool skip(true);
	for(size_t i_d = 0; i_d <= d; i_d++)
		skip &= IdenticalZero(pz[i_d]);
	if( skip )
		return;

	size_t j = d;
	size_t k;
	Base base_two(2);
	while(j)
	{
		px[j]   += pz[j];
		pz[j]   /= Base(j);
		for(k = 1; k <= j; k++)
		{	px[k]   += pz[j] * y[j-k] * Base(k);
			py[j-k] += pz[j] * x[k] * Base(k);
		}
		for(k = 0; k < j; k++)
			pz[k] += py[j-1] * z[j-k-1] * base_two;

		--j;
	}
	px[0] += pz[0] * (Base(1) + y[0]);
}
예제 #4
0
inline void reverse_divvv_op(
	size_t        d           ,
	size_t        i_z         ,
	const addr_t* arg         ,
	const Base*   parameter   ,
	size_t        cap_order   ,
	const Base*   taylor      ,
	size_t        nc_partial  ,
	Base*         partial     )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );
	CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Arguments
	const Base* y  = taylor + arg[1] * cap_order;
	const Base* z  = taylor + i_z    * cap_order;

	// Partial derivatives corresponding to arguments and result
	Base* px = partial + arg[0] * nc_partial;
	Base* py = partial + arg[1] * nc_partial;
	Base* pz = partial + i_z    * nc_partial;

	// If pz is zero, make sure this operation has no effect
	// (zero times infinity or nan would be non-zero).
	bool skip(true);
	for(size_t i_d = 0; i_d <= d; i_d++)
		skip &= IdenticalZero(pz[i_d]);
	if( skip )
		return;

	// Using CondExp, it can make sense to divide by zero
	// so do not make it an error.

	size_t k;
	// number of indices to access
	size_t j = d + 1;
	while(j)
	{	--j;
		// scale partial w.r.t. z[j]
		pz[j] /= y[0];

		px[j] += pz[j];
		for(k = 1; k <= j; k++)
		{	pz[j-k] -= pz[j] * y[k];
			py[k]   -= pz[j] * z[j-k];
		}
		py[0] -= pz[j] * z[j];
	}
}
예제 #5
0
inline void reverse_sqrt_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      cap_order    ,
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(SqrtOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(SqrtOp) == 1 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to result
	const Base* z  = taylor  + i_z * cap_order;
	Base* pz       = partial + i_z * nc_partial;

	// If pz is zero, make sure this operation has no effect
	// (zero times infinity or nan would be non-zero).
	bool skip(true);
	for(size_t i_d = 0; i_d <= d; i_d++)
		skip &= IdenticalZero(pz[i_d]);
	if( skip )
		return;

	CPPAD_ASSERT_KNOWN(
		z[0] != Base(0),
		"Reverse: attempt to take derivatve of square root of zero"
	)

	// number of indices to access
	size_t j = d;
	size_t k;
	while(j)
	{

		// scale partial w.r.t. z[j]
		pz[j]   /= z[0];

		pz[0]   -= pz[j] * z[j];
		px[j]   += pz[j] / Base(2);
		for(k = 1; k < j; k++)
			pz[k]   -= pz[j] * z[j-k];
		--j;
	}
	px[0] += pz[0] / (Base(2) * z[0]);
}
예제 #6
0
파일: expm1_op.hpp 프로젝트: CSCsw/CppAD
inline void reverse_expm1_op(
	size_t      d            ,
	size_t      i_z          ,
	size_t      i_x          ,
	size_t      cap_order    ,
	const Base* taylor       ,
	size_t      nc_partial   ,
	Base*       partial      )
{
	// check assumptions
	CPPAD_ASSERT_UNKNOWN( NumArg(Expm1Op) == 1 );
	CPPAD_ASSERT_UNKNOWN( NumRes(Expm1Op) == 1 );
	CPPAD_ASSERT_UNKNOWN( d < cap_order );
	CPPAD_ASSERT_UNKNOWN( d < nc_partial );

	// Taylor coefficients and partials corresponding to argument
	const Base* x  = taylor  + i_x * cap_order;
	Base* px       = partial + i_x * nc_partial;

	// Taylor coefficients and partials corresponding to result
	const Base* z  = taylor  + i_z * cap_order;
	Base* pz       = partial + i_z * nc_partial;

	// If pz is zero, make sure this operation has no effect
	// (zero times infinity or nan would be non-zero).
	bool skip(true);
	for(size_t i_d = 0; i_d <= d; i_d++)
		skip &= IdenticalZero(pz[i_d]);
	if( skip )
		return;

	// loop through orders in reverse
	size_t j, k;
	j = d;
	while(j)
	{	px[j] += pz[j];

		// scale partial w.r.t z[j]
		pz[j] /= Base(j);

		for(k = 1; k <= j; k++)
		{	px[k]   += pz[j] * Base(k) * z[j-k];
			pz[j-k] += pz[j] * Base(k) * x[k];
		}
		--j;
	}
	px[0] += pz[0] + pz[0] * z[0];
}
예제 #7
0
파일: sub.hpp 프로젝트: jnorthrup/jmodelica
AD<Base> operator - (const AD<Base> &left , const AD<Base> &right)
{	ADTape<Base> *tape = AD<Base>::tape_ptr();
	bool var_left, var_right;
# ifdef NDEBUG
	if( tape == CPPAD_NULL )
	{	var_left =  false;
		var_right = false;
	}
	else
	{
		var_left  = left.id_  == tape->id_;
		var_right = right.id_ == tape->id_;
	}
# else
	var_left  = Variable(left);
	var_right = Variable(right);
	CPPAD_ASSERT_KNOWN(
		(! var_left) || left.id_ == tape->id_ ,
		"- left operand is a variable for a different thread"
	);
	CPPAD_ASSERT_KNOWN(
		(! var_right) || right.id_ == tape->id_ ,
		"- right operand is a variable for a different thread"
	);
# endif

	AD<Base> result;
	result.value_  = left.value_ - right.value_;
	CPPAD_ASSERT_UNKNOWN( Parameter(result) );

	if( var_left )
	{	if( var_right )
		{	// result = variable - variable
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(left.taddr_, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(SubvvOp);
			// make result a variable
			result.id_ = tape->id_;
		}
		else if( IdenticalZero(right.value_) )
		{	// result = variable - 0
			result.make_variable(left.id_, left.taddr_);
		}
		else
		{	// result = variable - parameter
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );

			// put operand addresses in tape
			size_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(left.taddr_, p);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(SubvpOp);
			// make result a variable
			result.id_ = tape->id_;
		}
	}
	else if( var_right )
	{	// result = parameter - variable
		CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
		CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );

		// put operand addresses in tape
		size_t p = tape->Rec_.PutPar(left.value_);
		tape->Rec_.PutArg(p, right.taddr_);
		// put operator in the tape
		result.taddr_ = tape->Rec_.PutOp(SubpvOp);
		// make result a variable
		result.id_ = tape->id_;
	}
	return result;
}
예제 #8
0
파일: div.hpp 프로젝트: GodinA/adcomp
AD<Base> operator / (const AD<Base> &left , const AD<Base> &right)
{
	// compute the Base part
	AD<Base> result;
	result.value_  = left.value_ / right.value_;
	CPPAD_ASSERT_UNKNOWN( Parameter(result) );

	// check if there is a recording in progress
	ADTape<Base>* tape = AD<Base>::tape_ptr();
	if( tape == CPPAD_NULL )
		return result;
	tape_id_t tape_id = tape->id_;

	// tape_id cannot match the default value for tape_id_; i.e., 0
	CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
	bool var_left  = left.tape_id_  == tape_id;
	bool var_right = right.tape_id_ == tape_id;

	if( var_left )
	{	if( var_right )
		{	// result = variable / variable
			CPPAD_ASSERT_KNOWN(
				left.tape_id_ == right.tape_id_,
				"Dividing AD objects that are"
				" variables on different tapes."
			);
			CPPAD_ASSERT_UNKNOWN( NumRes(DivvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(DivvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(left.taddr_, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(DivvvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
		else if( IdenticalOne(right.value_) )
		{	// result = variable / 1
			result.make_variable(left.tape_id_, left.taddr_);
		}
		else
		{	// result = variable / parameter
			CPPAD_ASSERT_UNKNOWN( NumRes(DivvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(DivvpOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(left.taddr_, p);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(DivvpOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	else if( var_right )
	{	if( IdenticalZero(left.value_) )
		{	// result = 0 / variable
		}
		else
		{	// result = parameter / variable
			CPPAD_ASSERT_UNKNOWN( NumRes(DivpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(DivpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(left.value_);
			tape->Rec_.PutArg(p, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(DivpvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	return result;
}
예제 #9
0
파일: azmul.hpp 프로젝트: barak/CppAD-1
// case where x and y are AD<Base> -------------------------------------------
template <class Base> AD<Base>
azmul(const AD<Base>& x, const AD<Base>& y)
{
	// compute the Base part
	AD<Base> result;
	result.value_ = azmul(x.value_, y.value_);

	// check if there is a recording in progress
	ADTape<Base>* tape = AD<Base>::tape_ptr();
	if( tape == CPPAD_NULL )
		return result;
	tape_id_t tape_id = tape->id_;

	// tape_id cannot match the default value for tape_id_; i.e., 0
	CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
	bool var_x = x.tape_id_ == tape_id;
	bool var_y = y.tape_id_ == tape_id;

	if( var_x )
	{	if( var_y )
		{	// result = azmul(variable, variable)
			CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(x.taddr_, y.taddr_);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(ZmulvvOp);

			// make result a variable
			result.tape_id_ = tape_id;
		}
		else if( IdenticalZero( y.value_ ) )
		{	// result = variable * 0
		}
		else if( IdenticalOne( y.value_ ) )
		{	// result = variable * 1
			result.make_variable(x.tape_id_, x.taddr_);
		}
		else
		{	// result = zmul(variable, parameter)
			CPPAD_ASSERT_UNKNOWN( NumRes(ZmulvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(ZmulvpOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(y.value_);
			tape->Rec_.PutArg(x.taddr_, p);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(ZmulvpOp);

			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	else if( var_y )
	{	if( IdenticalZero(x.value_) )
		{	// result = 0 * variable
		}
		else if( IdenticalOne( x.value_ ) )
		{	// result = 1 * variable
			result.make_variable(y.tape_id_, y.taddr_);
		}
		else
		{	// result = zmul(parameter, variable)
			CPPAD_ASSERT_UNKNOWN( NumRes(ZmulpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(ZmulpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(x.value_);
			tape->Rec_.PutArg(p, y.taddr_);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(ZmulpvOp);

			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	return result;
}
예제 #10
0
파일: div.hpp 프로젝트: barak/cppad
AD<Base> operator / (const AD<Base> &left , const AD<Base> &right)
{
    // compute the Base part
    AD<Base> result;
    result.value_  = left.value_ / right.value_;
    CPPAD_ASSERT_UNKNOWN( Parameter(result) );

    // check if there is a recording in progress
    local::ADTape<Base>* tape = AD<Base>::tape_ptr();
    if( tape == CPPAD_NULL )
        return result;
    tape_id_t tape_id = tape->id_;
    // tape_id cannot match the default value for tape_id_; i.e., 0
    CPPAD_ASSERT_UNKNOWN( tape_id > 0 );

    // check if left and right tapes match
    bool match_left  = left.tape_id_  == tape_id;
    bool match_right = right.tape_id_ == tape_id;

    // check if left and right are dynamic parameters
    bool dyn_left  = match_left  & (left.ad_type_ == dynamic_enum);
    bool dyn_right = match_right & (right.ad_type_ == dynamic_enum);

    // check if left and right are variables
    bool var_left  = match_left  & (left.ad_type_ != dynamic_enum);
    bool var_right = match_right & (right.ad_type_ != dynamic_enum);

    CPPAD_ASSERT_KNOWN(
        left.tape_id_ == right.tape_id_ || ! match_left || ! match_right ,
        "Divide: AD variables or dynamic parameters on different threads."
    );
    if( var_left )
    {   if( var_right )
        {   // result = variable / variable
            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvvOp) == 1 );
            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvvOp) == 2 );

            // put operand addresses in tape
            tape->Rec_.PutArg(left.taddr_, right.taddr_);
            // put operator in the tape
            result.taddr_ = tape->Rec_.PutOp(local::DivvvOp);
            // make result a variable
            result.tape_id_ = tape_id;
            result.ad_type_ = variable_enum;
        }
        else if( (! dyn_right) & IdenticalOne(right.value_) )
        {   // result = variable / 1
            result.make_variable(left.tape_id_, left.taddr_);
        }
        else
        {   // result = variable / parameter
            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivvpOp) == 1 );
            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivvpOp) == 2 );

            // put operand addresses in tape
            addr_t p = right.taddr_;
            if( ! dyn_right )
                p = tape->Rec_.put_con_par(right.value_);
            tape->Rec_.PutArg(left.taddr_, p);
            // put operator in the tape
            result.taddr_ = tape->Rec_.PutOp(local::DivvpOp);
            // make result a variable
            result.tape_id_ = tape_id;
            result.ad_type_ = variable_enum;
        }
    }
    else if( var_right )
    {   if( (! dyn_left) & IdenticalZero(left.value_) )
        {   // result = 0 / variable
        }
        else
        {   // result = parameter / variable
            CPPAD_ASSERT_UNKNOWN( local::NumRes(local::DivpvOp) == 1 );
            CPPAD_ASSERT_UNKNOWN( local::NumArg(local::DivpvOp) == 2 );

            // put operand addresses in tape
            addr_t p = left.taddr_;
            if( ! dyn_left )
                p = tape->Rec_.put_con_par(left.value_);
            tape->Rec_.PutArg(p, right.taddr_);
            // put operator in the tape
            result.taddr_ = tape->Rec_.PutOp(local::DivpvOp);
            // make result a variable
            result.tape_id_ = tape_id;
            result.ad_type_ = variable_enum;
        }
    }
    else if( dyn_left | dyn_right )
    {   addr_t arg0 = left.taddr_;
        addr_t arg1 = right.taddr_;
        if( ! dyn_left )
            arg0 = tape->Rec_.put_con_par(left.value_);
        if( ! dyn_right )
            arg1 = tape->Rec_.put_con_par(right.value_);
        //
        // parameters with a dynamic parameter result
        result.taddr_   = tape->Rec_.put_dyn_par(
            result.value_, local::div_dyn,   arg0, arg1
        );
        result.tape_id_ = tape_id;
        result.ad_type_ = dynamic_enum;
    }
    return result;
}
예제 #11
0
inline void reverse_erf_op(
    size_t        d           ,
    size_t        i_z         ,
    const addr_t* arg         ,
    const Base*   parameter   ,
    size_t        cap_order   ,
    const Base*   taylor      ,
    size_t        nc_partial  ,
    Base*         partial     )
{
    // check assumptions
    CPPAD_ASSERT_UNKNOWN( NumArg(ErfOp) == 3 );
    CPPAD_ASSERT_UNKNOWN( NumRes(ErfOp) == 5 );
    CPPAD_ASSERT_UNKNOWN( d < cap_order );

    // array used to pass parameter values for sub-operations
    addr_t addr[2];

    // If pz is zero, make sure this operation has no effect
    // (zero times infinity or nan would be non-zero).
    Base* pz  = partial + i_z * nc_partial;
    bool skip(true);
    for(size_t i_d = 0; i_d <= d; i_d++)
        skip &= IdenticalZero(pz[i_d]);
    if( skip )
        return;

    // convert from final result to first result
    i_z -= 4; // 4 = NumRes(ErfOp) - 1;

    // Taylor coefficients and partials corresponding to x
    const Base* x  = taylor  + arg[0]  * cap_order;
    Base* px       = partial + arg[0] * nc_partial;

    // Taylor coefficients and partials corresponding to z_3
    const Base* z_3  = taylor  + (i_z+3) * cap_order;
    Base* pz_3       = partial + (i_z+3) * nc_partial;

    // Taylor coefficients and partials corresponding to z_4
    Base* pz_4 = partial + (i_z+4) * nc_partial;

    // Reverse z_4
    size_t j = d;
    while(j)
    {   pz_4[j] /= Base(j);
        for(size_t k = 1; k <= j; k++)
        {   px[k]     += pz_4[j] * z_3[j-k] * Base(k);
            pz_3[j-k] += pz_4[j] * x[k] * Base(k);
        }
        j--;
    }
    px[0] += pz_4[0] * z_3[0];

    // z_3 = (2 / sqrt(pi)) * exp( - x * x )
    addr[0] = arg[2];  // 2 / sqrt(pi)
    addr[1] = i_z + 2; // z_2
    reverse_mulpv_op(
        d, i_z+3, addr, parameter, cap_order, taylor, nc_partial, partial
    );

    // z_2 = exp( - x * x )
    reverse_exp_op(
        d, i_z+2, i_z+1, cap_order, taylor, nc_partial, partial
    );

    // z_1 = - x * x
    addr[0] = arg[1]; // zero
    addr[1] = i_z;    // z_0
    reverse_subpv_op(
        d, i_z+1, addr, parameter, cap_order, taylor, nc_partial, partial
    );

    // z_0 = x * x
    addr[0] = arg[0]; // x
    addr[1] = arg[0]; // x
    reverse_mulvv_op(
        d, i_z+0, addr, parameter, cap_order, taylor, nc_partial, partial
    );

}
예제 #12
0
AD<Base>& AD<Base>::operator -= (const AD<Base> &right)
{	ADTape<Base> *tape = AD<Base>::tape_ptr();
	size_t tape_id = 0;
	if( tape != CPPAD_NULL )
		tape_id = tape->id_;

	// id_ setting for parameters cannot match 0
	bool var_left  = id_       == tape_id;
	bool var_right = right.id_ == tape_id;
	CPPAD_ASSERT_KNOWN(
		Parameter(*this) || var_left ,
		"-=: left operand is a variable for a different thread"
	);
	CPPAD_ASSERT_KNOWN(
		Parameter(right) || var_right ,
		"-=: right operand is a variable for a different thread"
	);

	Base left;
	left    = value_;
	value_ -= right.value_;

	if( var_left )
	{	if( var_right )
		{	// this = variable - variable
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(taddr_, right.taddr_);
			// put operator in the tape
			taddr_ = tape->Rec_.PutOp(SubvvOp);
			// make this a variable
			CPPAD_ASSERT_UNKNOWN( id_ == tape_id );
		}
		else if( IdenticalZero( right.value_ ) )
		{	// this = variable - 0
		}
		else
		{	// this = variable - parameter
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(taddr_, p);
			// put operator in the tape
			taddr_ = tape->Rec_.PutOp(SubvpOp);
			// make this a variable
			CPPAD_ASSERT_UNKNOWN( id_ == tape_id );
		}
	}
	else if( var_right  )
	{	// this = parameter - variable
		CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
		CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );

		// put operand addresses in tape
		addr_t p = tape->Rec_.PutPar(left);
		tape->Rec_.PutArg(p, right.taddr_);
		// put operator in the tape
		taddr_ = tape->Rec_.PutOp(SubpvOp);
		// make this a variable
		id_ = tape_id;
	}
	return *this;
}
예제 #13
0
파일: add.hpp 프로젝트: GodinA/adcomp
AD<Base> operator + (const AD<Base> &left , const AD<Base> &right)
{
	// compute the Base part of this AD object
	AD<Base> result;
	result.value_  = left.value_ + right.value_;
	CPPAD_ASSERT_UNKNOWN( Parameter(result) );

	// check if there is a recording in progress
	ADTape<Base>* tape = AD<Base>::tape_ptr();
	if( tape == CPPAD_NULL )
		return result;
	tape_id_t tape_id = tape->id_;

	// tape_id cannot match the default value for tape_id_; i.e., 0
	CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
	bool var_left  = left.tape_id_  == tape_id;
	bool var_right = right.tape_id_ == tape_id;

	if( var_left )
	{	if( var_right )
		{	// result = variable + variable
			CPPAD_ASSERT_UNKNOWN( NumRes(AddvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(AddvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(left.taddr_, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(AddvvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
		else if( IdenticalZero(right.value_) )
		{	// result = variable + 0
			result.make_variable(left.tape_id_, left.taddr_);
		}
		else
		{	// result = variable  + parameter
			//        = parameter + variable
			CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(p, left.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(AddpvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	else if( var_right )
	{	if( IdenticalZero(left.value_) )
		{	// result = 0 + variable
			result.make_variable(right.tape_id_, right.taddr_);
		}
		else
		{	// result = parameter + variable
			CPPAD_ASSERT_UNKNOWN( NumRes(AddpvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(AddpvOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(left.value_);
			tape->Rec_.PutArg(p, right.taddr_);
			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(AddpvOp);
			// make result a variable
			result.tape_id_ = tape_id;
		}
	}
	return result;
}
예제 #14
0
파일: pow.hpp 프로젝트: jnorthrup/jmodelica
// case where x and y are AD<Base> -----------------------------------------
template <class Base> AD<Base> 
pow(const AD<Base> &x, const AD<Base> &y)
{	ADTape<Base> *tape = AD<Base>::tape_ptr();
	bool var_x, var_y;
# ifdef NDEBUG
	if( tape == CPPAD_NULL )
	{	var_x =  false;
		var_y = false;
	}
	else
	{
		var_x = x.id_ == tape->id_;
		var_y = y.id_ == tape->id_;
	}
# else
	var_x  = Variable(x);
	var_y = Variable(y);
	CPPAD_ASSERT_KNOWN(
		(! var_x) || x.id_ == tape->id_ ,
		"pow first operand is a variable for a different thread"
	);
	CPPAD_ASSERT_KNOWN(
		(! var_y) || y.id_ == tape->id_ ,
		"pow second operand is a variable for a different thread"
	);
# endif
	AD<Base> result;
	result.value_  = pow(x.value_, y.value_);
	CPPAD_ASSERT_UNKNOWN( Parameter(result) );

	if( var_x )
	{	if( var_y )
		{	// result = variable^variable
			CPPAD_ASSERT_UNKNOWN( NumRes(PowvvOp) == 3 );
			CPPAD_ASSERT_UNKNOWN( NumArg(PowvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(x.taddr_, y.taddr_);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(PowvvOp);

			// make result a variable
			result.id_ = tape->id_;
		}
		else if( IdenticalZero( y.value_ ) )
		{	// result = variable^0
		}
		else
		{	// result = variable^parameter 
			CPPAD_ASSERT_UNKNOWN( NumRes(PowvpOp) == 3 );
			CPPAD_ASSERT_UNKNOWN( NumArg(PowvpOp) == 2 );

			// put operand addresses in tape
			size_t p = tape->Rec_.PutPar(y.value_);
			tape->Rec_.PutArg(x.taddr_, p);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(PowvpOp);

			// make result a variable
			result.id_ = tape->id_;
		}
	}
	else if( var_y )
	{	if( IdenticalZero(x.value_) )
		{	// result = 0^variable 
		}
		else
		{	// result = variable^parameter 
			CPPAD_ASSERT_UNKNOWN( NumRes(PowpvOp) == 3 );
			CPPAD_ASSERT_UNKNOWN( NumArg(PowpvOp) == 2 );

			// put operand addresses in tape
			size_t p = tape->Rec_.PutPar(x.value_);
			tape->Rec_.PutArg(p, y.taddr_);

			// put operator in the tape
			result.taddr_ = tape->Rec_.PutOp(PowpvOp);

			// make result a variable
			result.id_ = tape->id_;
		}
	}
	return result;
}
예제 #15
0
파일: cskip_op.hpp 프로젝트: barak/cppad
void forward_cskip_op_0(
    size_t               i_z            ,
    const addr_t*        arg            ,
    size_t               num_par        ,
    const Base*          parameter      ,
    size_t               cap_order      ,
    Base*                taylor         ,
    bool*                cskip_op       )
{
    CPPAD_ASSERT_UNKNOWN( size_t(arg[0]) < size_t(CompareNe) );
    CPPAD_ASSERT_UNKNOWN( arg[1] != 0 );

    Base left, right;
    if( arg[1] & 1 )
    {   // If variable arg[2] <= i_z, it has already been computed,
        // but it will be skipped for higher orders.
        CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) <= i_z );
        left = taylor[ size_t(arg[2]) * cap_order + 0 ];
    }
    else
    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[2]) < num_par );
        left = parameter[ arg[2] ];
    }
    if( arg[1] & 2 )
    {   // If variable arg[3] <= i_z, it has already been computed,
        // but it will be skipped for higher orders.
        CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) <= i_z );
        right = taylor[ size_t(arg[3]) * cap_order + 0 ];
    }
    else
    {   CPPAD_ASSERT_UNKNOWN( size_t(arg[3]) < num_par );
        right = parameter[ arg[3] ];
    }
    bool ok_to_skip = IdenticalCon(left) & IdenticalCon(right);
    if( ! ok_to_skip )
        return;

    // initialize to avoid compiler warning
    bool true_case = false;
    Base diff      = left - right;
    switch( CompareOp( arg[0] ) )
    {
        case CompareLt:
        true_case = LessThanZero(diff);
        break;

        case CompareLe:
        true_case = LessThanOrZero(diff);
        break;

        case CompareEq:
        true_case = IdenticalZero(diff);
        break;

        case CompareGe:
        true_case = GreaterThanOrZero(diff);
        break;

        case CompareGt:
        true_case = GreaterThanZero(diff);
        break;

        case CompareNe:
        true_case = ! IdenticalZero(diff);
        break;

        default:
        CPPAD_ASSERT_UNKNOWN(false);
    }
    if( true_case )
    {   for(addr_t i = 0; i < arg[4]; i++)
            cskip_op[ arg[6+i] ] = true;
    }
    else
    {   for(addr_t i = 0; i < arg[5]; i++)
            cskip_op[ arg[6+arg[4]+i] ] = true;
    }
    return;
}
예제 #16
0
파일: identical.hpp 프로젝트: barak/CppAD-1
CPPAD_INLINE_FRIEND_TEMPLATE_FUNCTION
bool IdenticalZero(const AD<Base> &x)
{	return Parameter(x) && IdenticalZero(x.value_); }
예제 #17
0
AD<Base>& AD<Base>::operator -= (const AD<Base> &right)
{
	// compute the Base part
	Base left;
	left    = value_;
	value_ -= right.value_;

	// check if there is a recording in progress
	ADTape<Base>* tape = AD<Base>::tape_ptr();
	if( tape == CPPAD_NULL )
		return *this;
	tape_id_t tape_id = tape->id_;

	// tape_id cannot match the default value for tape_id_; i.e., 0
	CPPAD_ASSERT_UNKNOWN( tape_id > 0 );
	bool var_left  = tape_id_       == tape_id;
	bool var_right = right.tape_id_ == tape_id;

	if( var_left )
	{	if( var_right )
		{	// this = variable - variable
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvvOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvvOp) == 2 );

			// put operand addresses in tape
			tape->Rec_.PutArg(taddr_, right.taddr_);
			// put operator in the tape
			taddr_ = tape->Rec_.PutOp(SubvvOp);
			// make this a variable
			CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
		}
		else if( IdenticalZero( right.value_ ) )
		{	// this = variable - 0
		}
		else
		{	// this = variable - parameter
			CPPAD_ASSERT_UNKNOWN( NumRes(SubvpOp) == 1 );
			CPPAD_ASSERT_UNKNOWN( NumArg(SubvpOp) == 2 );

			// put operand addresses in tape
			addr_t p = tape->Rec_.PutPar(right.value_);
			tape->Rec_.PutArg(taddr_, p);
			// put operator in the tape
			taddr_ = tape->Rec_.PutOp(SubvpOp);
			// make this a variable
			CPPAD_ASSERT_UNKNOWN( tape_id_ == tape_id );
		}
	}
	else if( var_right  )
	{	// this = parameter - variable
		CPPAD_ASSERT_UNKNOWN( NumRes(SubpvOp) == 1 );
		CPPAD_ASSERT_UNKNOWN( NumArg(SubpvOp) == 2 );

		// put operand addresses in tape
		addr_t p = tape->Rec_.PutPar(left);
		tape->Rec_.PutArg(p, right.taddr_);
		// put operator in the tape
		taddr_ = tape->Rec_.PutOp(SubpvOp);
		// make this a variable
		tape_id_ = tape_id;
	}
	return *this;
}