Пример #1
0
static ex atan_conjugate(const ex & x)
{
	// conjugate(atan(x))==atan(conjugate(x)) unless on the branch cuts which
	// run along the imaginary axis outside the interval [-I, +I].
	if (x.info(info_flags::real))
		return atan(x);
	if (is_exactly_a<numeric>(x)) {
		const numeric x_re = ex_to<numeric>(x.real_part());
		const numeric x_im = ex_to<numeric>(x.imag_part());
		if (!x_re.is_zero() ||
		    (x_im > *_num_1_p && x_im < *_num1_p))
			return atan(x.conjugate());
	}
	return conjugate_function(atan(x)).hold();
}
Пример #2
0
static ex binomial_sym(const ex & x, const numeric & y)
{
	if (y.is_integer()) {
		if (y.is_nonneg_integer()) {
			const unsigned N = y.to_int();
			if (N == 0) return _ex1;
			if (N == 1) return x;
			ex t = x.expand();
			for (unsigned i = 2; i <= N; ++i)
				t = (t * (x + i - y - 1)).expand() / i;
			return t;
		} else
			return _ex0;
	}

	return binomial(x, y).hold();
}
Пример #3
0
// These tests work with Python 2.2, but you must have Numeric installed.
object check_numeric_array_rich_slice(
    char const* module_name, char const* array_type_name, object all)
{
    using numeric::array;
    array::set_module_and_type(module_name, array_type_name);
    
    array original = array( make_tuple( make_tuple( 11, 12, 13, 14),
                                        make_tuple( 21, 22, 23, 24),
                                        make_tuple( 31, 32, 33, 34),
                                        make_tuple( 41, 42, 43, 44)));
    array upper_left_quadrant = array( make_tuple( make_tuple( 11, 12),
                                                   make_tuple( 21, 22)));
    array odd_cells = array( make_tuple( make_tuple( 11, 13),
                                          make_tuple( 31, 33)));
    array even_cells = array( make_tuple( make_tuple( 22, 24),
                                           make_tuple( 42, 44)));
    array lower_right_quadrant_reversed = array(
        make_tuple( make_tuple(44, 43),
                    make_tuple(34, 33)));

    // The following comments represent equivalent Python expressions used
    // to validate the array behavior.
    // original[::] == original
    ASSERT_EQUAL(original[slice()],original);
        
    // original[:2,:2] == array( [[11, 12], [21, 22]])
    ASSERT_EQUAL(original[make_tuple(slice(_,2), slice(_,2))],upper_left_quadrant);
        
    // original[::2,::2] == array( [[11, 13], [31, 33]])
    ASSERT_EQUAL(original[make_tuple( slice(_,_,2), slice(_,_,2))],odd_cells);
    
    // original[1::2, 1::2] == array( [[22, 24], [42, 44]])
    ASSERT_EQUAL(original[make_tuple( slice(1,_,2), slice(1,_,2))],even_cells);

    // original[:-3:-1, :-3,-1] == array( [[44, 43], [34, 33]])
    ASSERT_EQUAL(original[make_tuple( slice(_,-3,-1), slice(_,-3,-1))],lower_right_quadrant_reversed);

    return object(1);
}
Пример #4
0
// These tests work with Python 2.2, but you must have Numeric installed.
bool check_numeric_array_rich_slice()
{
    using numeric::array;
    array original = array( make_tuple( make_tuple( 11, 12, 13, 14),
                                        make_tuple( 21, 22, 23, 24),
                                        make_tuple( 31, 32, 33, 34),
                                        make_tuple( 41, 42, 43, 44)));
    array upper_left_quadrant = array( make_tuple( make_tuple( 11, 12),
                                                   make_tuple( 21, 22)));
    array odd_cells = array( make_tuple( make_tuple( 11, 13),
                                          make_tuple( 31, 33)));
    array even_cells = array( make_tuple( make_tuple( 22, 24),
                                           make_tuple( 42, 44)));
    array lower_right_quadrant_reversed = array(
        make_tuple( make_tuple(44, 43),
                    make_tuple(34, 33)));

    // The following comments represent equivalent Python expressions used
    // to validate the array behavior.
    // original[::] == original
    if (original[slice()] != original)
        return false;
    // original[:2,:2] == array( [[11, 12], [21, 22]])
    if (original[make_tuple(slice(_,2), slice(_,2))] != upper_left_quadrant)
        return false;
    // original[::2,::2] == array( [[11, 13], [31, 33]])
    if (original[make_tuple( slice(_,_,2), slice(_,_,2))] != odd_cells)
        return false;
    // original[1::2, 1::2] == array( [[22, 24], [42, 44]])
    if (original[make_tuple( slice(1,_,2), slice(1,_,2))] != even_cells)
        return false;
    // original[:-3:-1, :-3,-1] == array( [[44, 43], [34, 33]])
    if (original[make_tuple( slice(_,-3,-1), slice(_,-3,-1))] != lower_right_quadrant_reversed)
        return false;

    return true;
}
Пример #5
0
    inline Target numeric_cast(Source arg)
    {
        // typedefs abbreviating respective trait classes
        typedef detail::fixed_numeric_limits<Source> arg_traits;
        typedef detail::fixed_numeric_limits<Target> result_traits;

#if defined(BOOST_STRICT_CONFIG) \
    || (!defined(__HP_aCC) || __HP_aCC > 33900) \
         && (!defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) \
             || defined(BOOST_SGI_CPP_LIMITS))
        // typedefs that act as compile time assertions
        // (to be replaced by boost compile time assertions
        // as and when they become available and are stable)
        typedef bool argument_must_be_numeric[arg_traits::is_specialized];
        typedef bool result_must_be_numeric[result_traits::is_specialized];

        const bool arg_is_signed = arg_traits::is_signed;
        const bool result_is_signed = result_traits::is_signed;
        const bool same_sign = arg_is_signed == result_is_signed;

        if (less_than_type_min<arg_is_signed, result_is_signed>::check(arg, (result_traits::min)())
            || greater_than_type_max<same_sign, arg_is_signed>::check(arg, (result_traits::max)())
            )

#else // We need to use #pragma hacks if available

# if BOOST_MSVC
#  pragma warning(push)
#  pragma warning(disable : 4018)
#elif defined(__BORLANDC__)
#pragma option push -w-8012
# endif
        if ((arg < 0 && !result_traits::is_signed)  // loss of negative range
             || (arg_traits::is_signed && arg < (result_traits::min)())  // underflow
             || arg > (result_traits::max)())            // overflow
# if BOOST_MSVC
#  pragma warning(pop)
#elif defined(__BORLANDC__)
#pragma option pop
# endif
#endif
        {
            throw bad_numeric_cast();
        }
        return static_cast<Target>(arg);
    } // numeric_cast
Пример #6
0
static ex eta_eval(const ex &x, const ex &y)
{
	// trivial:  eta(x,c) -> 0  if c is real and positive
	if (x.info(info_flags::positive) || y.info(info_flags::positive))
		return _ex0;

	if (x.info(info_flags::numeric) &&	y.info(info_flags::numeric)) {
		// don't call eta_evalf here because it would call Pi.evalf()!
		const numeric nx = ex_to<numeric>(x);
		const numeric ny = ex_to<numeric>(y);
		const numeric nxy = ex_to<numeric>(x*y);
		int cut = 0;
		if (nx.is_real() && nx.is_negative())
			cut -= 4;
		if (ny.is_real() && ny.is_negative())
			cut -= 4;
		if (nxy.is_real() && nxy.is_negative())
			cut += 4;
		return (I/4)*Pi*((csgn(-imag(nx))+1)*(csgn(-imag(ny))+1)*(csgn(imag(nxy))+1)-
		                 (csgn(imag(nx))+1)*(csgn(imag(ny))+1)*(csgn(-imag(nxy))+1)+cut);
	}
	
	return eta(x,y).hold();
}
Пример #7
0
static ex eta_evalf(const ex &x, const ex &y)
{
	// It seems like we basically have to replicate the eval function here,
	// since the expression might not be fully evaluated yet.
	if (x.info(info_flags::positive) || y.info(info_flags::positive))
		return _ex0;

	if (x.info(info_flags::numeric) &&	y.info(info_flags::numeric)) {
		const numeric nx = ex_to<numeric>(x);
		const numeric ny = ex_to<numeric>(y);
		const numeric nxy = ex_to<numeric>(x*y);
		int cut = 0;
		if (nx.is_real() && nx.is_negative())
			cut -= 4;
		if (ny.is_real() && ny.is_negative())
			cut -= 4;
		if (nxy.is_real() && nxy.is_negative())
			cut += 4;
		return evalf(I/4*Pi)*((csgn(-imag(nx))+1)*(csgn(-imag(ny))+1)*(csgn(imag(nxy))+1)-
		                      (csgn(imag(nx))+1)*(csgn(imag(ny))+1)*(csgn(-imag(nxy))+1)+cut);
	}

	return eta(x,y).hold();
}
Пример #8
0
/** Numeric postfix decrement.  Returns the number and leaves the original
 *  decremented by 1. */
const numeric operator--(numeric & lh, int)
{
	numeric tmp(lh);
	lh = lh.add(*_num_1_p);
	return tmp;
}
Пример #9
0
/** 
 * Exact polynomial division of a, b \in Z_p[x_0, \ldots, x_n]
 * It doesn't check whether the inputs are proper polynomials, so be careful
 * of what you pass in.
 *  
 * @param a  first multivariate polynomial (dividend)
 * @param b  second multivariate polynomial (divisor)
 * @param q  quotient (returned)
 * @param var variables X iterator to first element of vector of symbols
 *
 * @return "true" when exact division succeeds (the quotient is returned in
 *          q), "false" otherwise.
 * @note @a p = 0 means the base ring is Z
 */
bool divide_in_z_p(const ex &a, const ex &b, ex &q, const exvector& vars, const long p)
{
	static const ex _ex1(1);
	if (b.is_zero())
		throw(std::overflow_error("divide_in_z: division by zero"));
	if (b.is_equal(_ex1)) {
		q = a;
		return true;
	}
	if (is_exactly_a<numeric>(a)) {
		if (is_exactly_a<numeric>(b)) {
			// p == 0 means division in Z
			if (p == 0) {
				const numeric tmp = ex_to<numeric>(a/b);
				if (tmp.is_integer()) {
					q = tmp;
					return true;
				} else
					return false;
			} else {
				q = (a*recip(ex_to<numeric>(b), p)).smod(numeric(p));
				return true;
			}
		} else
			return false;
	}
	if (a.is_equal(b)) {
		q = _ex1;
		return true;
	}

	// Main symbol
	const ex &x = vars.back();

	// Compare degrees
	int adeg = a.degree(x), bdeg = b.degree(x);
	if (bdeg > adeg)
		return false;

	// Polynomial long division (recursive)
	ex r = a.expand();
	if (r.is_zero())
		return true;
	int rdeg = adeg;
	ex eb = b.expand();
	ex blcoeff = eb.coeff(x, bdeg);
	exvector v;
	v.reserve(std::max(rdeg - bdeg + 1, 0));
	exvector rest_vars(vars);
	rest_vars.pop_back();
	while (rdeg >= bdeg) {
		ex term, rcoeff = r.coeff(x, rdeg);
		if (!divide_in_z_p(rcoeff, blcoeff, term, rest_vars, p))
			break;
		term = (term*power(x, rdeg - bdeg)).expand();
		v.push_back(term);
		r = (r - term*eb).expand();
		if (p != 0)
			r = r.smod(numeric(p));
		if (r.is_zero()) {
			q = (new add(v))->setflag(status_flags::dynallocated);
			return true;
		}
		rdeg = r.degree(x);
	}
	return false;
}
Пример #10
0
const numeric
fsolve(const ex& f_in, const symbol& x, const numeric& x1, const numeric& x2)
{
	if (!x1.is_real() || !x2.is_real()) {
		throw std::runtime_error("fsolve(): interval not bounded by real numbers");
	}
	if (x1==x2) {
		throw std::runtime_error("fsolve(): vanishing interval");
	}
	// xx[0] == left interval limit, xx[1] == right interval limit.
	// fx[0] == f(xx[0]), fx[1] == f(xx[1]).
	// We keep the root bracketed: xx[0]<xx[1] and fx[0]*fx[1]<0.
	numeric xx[2] = { x1<x2 ? x1 : x2,
	                  x1<x2 ? x2 : x1 };
	ex f;
	if (is_a<relational>(f_in)) {
		f = f_in.lhs()-f_in.rhs();
	} else {
		f = f_in;
	}
	const ex fx_[2] = { f.subs(x==xx[0]).evalf(),
	                    f.subs(x==xx[1]).evalf() };
	if (!is_a<numeric>(fx_[0]) || !is_a<numeric>(fx_[1])) {
		throw std::runtime_error("fsolve(): function does not evaluate numerically");
	}
	numeric fx[2] = { ex_to<numeric>(fx_[0]),
	                  ex_to<numeric>(fx_[1]) };
	if (!fx[0].is_real() || !fx[1].is_real()) {
		throw std::runtime_error("fsolve(): function evaluates to complex values at interval boundaries");
	}
	if (fx[0]*fx[1]>=0) {
		throw std::runtime_error("fsolve(): function does not change sign at interval boundaries");
	}

	// The Newton-Raphson method has quadratic convergence!  Simply put, it
	// replaces x with x-f(x)/f'(x) at each step.  -f/f' is the delta:
	const ex ff = normal(-f/f.diff(x));
	int side = 0;  // Start at left interval limit.
	numeric xxprev;
	numeric fxprev;
	do {
		xxprev = xx[side];
		fxprev = fx[side];
		ex dx_ = ff.subs(x == xx[side]).evalf();
		if (!is_a<numeric>(dx_))
			throw std::runtime_error("fsolve(): function derivative does not evaluate numerically");
		xx[side] += ex_to<numeric>(dx_);
		// Now check if Newton-Raphson method shot out of the interval 
		bool bad_shot = (side == 0 && xx[0] < xxprev) || 
				(side == 1 && xx[1] > xxprev) || xx[0] > xx[1];
		if (!bad_shot) {
			// Compute f(x) only if new x is inside the interval.
			// The function might be difficult to compute numerically
			// or even ill defined outside the interval. Also it's
			// a small optimization. 
			ex f_x = f.subs(x == xx[side]).evalf();
			if (!is_a<numeric>(f_x))
				throw std::runtime_error("fsolve(): function does not evaluate numerically");
			fx[side] = ex_to<numeric>(f_x);
		}
		if (bad_shot) {
			// Oops, Newton-Raphson method shot out of the interval.
			// Restore, and try again with the other side instead!
			xx[side] = xxprev;
			fx[side] = fxprev;
			side = !side;
			xxprev = xx[side];
			fxprev = fx[side];

			ex dx_ = ff.subs(x == xx[side]).evalf();
			if (!is_a<numeric>(dx_))
				throw std::runtime_error("fsolve(): function derivative does not evaluate numerically [2]");
			xx[side] += ex_to<numeric>(dx_);

			ex f_x = f.subs(x==xx[side]).evalf();
			if (!is_a<numeric>(f_x))
				throw std::runtime_error("fsolve(): function does not evaluate numerically [2]");
			fx[side] = ex_to<numeric>(f_x);
		}
		if ((fx[side]<0 && fx[!side]<0) || (fx[side]>0 && fx[!side]>0)) {
			// Oops, the root isn't bracketed any more.
			// Restore, and perform a bisection!
			xx[side] = xxprev;
			fx[side] = fxprev;

			// Ah, the bisection! Bisections converge linearly. Unfortunately,
			// they occur pretty often when Newton-Raphson arrives at an x too
			// close to the result on one side of the interval and
			// f(x-f(x)/f'(x)) turns out to have the same sign as f(x) due to
			// precision errors! Recall that this function does not have a
			// precision goal as one of its arguments but instead relies on
			// x converging to a fixed point. We speed up the (safe but slow)
			// bisection method by mixing in a dash of the (unsafer but faster)
			// secant method: Instead of splitting the interval at the
			// arithmetic mean (bisection), we split it nearer to the root as
			// determined by the secant between the values xx[0] and xx[1].
			// Don't set the secant_weight to one because that could disturb
			// the convergence in some corner cases!
			constexpr double secant_weight = 0.984375;  // == 63/64 < 1
			numeric xxmid = (1-secant_weight)*0.5*(xx[0]+xx[1])
			    + secant_weight*(xx[0]+fx[0]*(xx[0]-xx[1])/(fx[1]-fx[0]));
			ex fxmid_ = f.subs(x == xxmid).evalf();
			if (!is_a<numeric>(fxmid_))
				throw std::runtime_error("fsolve(): function does not evaluate numerically [3]");
			numeric fxmid = ex_to<numeric>(fxmid_);
			if (fxmid.is_zero()) {
				// Luck strikes...
				return xxmid;
			}
			if ((fxmid<0 && fx[side]>0) || (fxmid>0 && fx[side]<0)) {
				side = !side;
			}
			xxprev = xx[side];
			fxprev = fx[side];
			xx[side] = xxmid;
			fx[side] = fxmid;
		}
	} while (xxprev!=xx[side]);
	return xxprev;
}