Ejemplo n.º 1
0
		/**
		 * Arguments merging in case of univariate monomial is meaningful only when extending a zero-arguments
		 * monomial to one argument. Therefore, this method will either throw or return a default-constructed monomial.
		 * 
		 * @param[in] orig_args original arguments.
		 * @param[in] new_args new arguments.
		 * 
		 * @return a default-constructed instance of piranha::univariate_monomial.
		 * 
		 * @throws std::invalid_argument if the size of \p new_args is different from 1 or the size of \p orig_args is not zero.
		 * @throws unspecified any exception thrown by the default constructor of piranha::univariate_monomial.
		 */
		univariate_monomial merge_args(const symbol_set &orig_args, const symbol_set &new_args) const
		{
			piranha_assert(std::is_sorted(orig_args.begin(),orig_args.end()));
			piranha_assert(std::is_sorted(new_args.begin(),new_args.end()));
			if (unlikely(new_args.size() != 1u || orig_args.size())) {
				piranha_throw(std::invalid_argument,"invalid symbol set");
			}
			piranha_assert(math::is_zero(m_value));
			// The only valid possibility here is that a monomial with zero args is extended
			// to one arg. Default construction is ok.
			return univariate_monomial();
		}
Ejemplo n.º 2
0
inline Uint ulshift(Uint n, Uint2 s)
{
	static_assert(std::is_integral<Uint>::value && std::is_unsigned<Uint>::value,"Invalid type.");
	static_assert(std::is_integral<Uint2>::value && std::is_unsigned<Uint2>::value,"Invalid type.");
	piranha_assert(s < unsigned(std::numeric_limits<Uint>::digits));
	return n << s;
}
Ejemplo n.º 3
0
    static void construct(::PyObject *obj_ptr, bp::converter::rvalue_from_python_stage1_data *data)
    {
        // NOTE: here we cannot construct directly from string, as we need to query the precision.
        piranha_assert(obj_ptr);
        // NOTE: here the handle is from borrowed because we are not responsible for the generation of obj_ptr:
        // borrowed will increase the refcount of obj_ptr, so that, when obj is destroyed, the refcount
        // for obj_ptr goes back to the original value instead of decreasing by 1.
        bp::handle<> obj_handle(bp::borrowed(obj_ptr));
        bp::object obj(obj_handle);
        const ::mpfr_prec_t prec
            = piranha::safe_cast<::mpfr_prec_t>(static_cast<long>(bp::extract<long>(obj.attr("context").attr("prec"))));
        // NOTE: here we use repr instead of str because the repr seems to give the most accurate representation
        // in base 10 for the object.
        ::PyObject *str_obj = ::PyObject_Repr(obj.ptr());
        if (!str_obj) {
            ::PyErr_SetString(PyExc_RuntimeError, "unable to extract string representation of real");
            bp::throw_error_already_set();
        }
        bp::handle<> str_rep(str_obj);
#if PY_MAJOR_VERSION < 3
        const char *s = ::PyString_AsString(str_rep.get());
#else
        ::PyObject *unicode_str_obj = ::PyUnicode_AsEncodedString(str_rep.get(), "ascii", "strict");
        if (!unicode_str_obj) {
            ::PyErr_SetString(PyExc_RuntimeError, "unable to extract string representation of real");
            bp::throw_error_already_set();
        }
        bp::handle<> unicode_str(unicode_str_obj);
        const char *s = ::PyBytes_AsString(unicode_str.get());
        if (!s) {
            ::PyErr_SetString(PyExc_RuntimeError, "unable to extract string representation of real");
            bp::throw_error_already_set();
        }
#endif
        // NOTE: the search for "'" is due to the string format of mpmath.mpf objects.
        while (*s != '\0' && *s != '\'') {
            ++s;
        }
        if (*s == '\0') {
            ::PyErr_SetString(PyExc_RuntimeError, "invalid string input converting to real");
            bp::throw_error_already_set();
        }
        ++s;
        auto start = s;
        while (*s != '\0' && *s != '\'') {
            ++s;
        }
        if (*s == '\0') {
            ::PyErr_SetString(PyExc_RuntimeError, "invalid string input converting to real");
            bp::throw_error_already_set();
        }
        void *storage
            = reinterpret_cast<bp::converter::rvalue_from_python_storage<piranha::real> *>(data)->storage.bytes;
        ::new (storage) piranha::real(std::string(start, s), prec);
        data->convertible = storage;
    }
Ejemplo n.º 4
0
		/**
		 * Partial degree of the monomial: only the symbols with names in \p active_args are considered during the computation
		 * of the degree. Symbols in \p active_args not appearing in \p args are not considered.
		 * 
		 * @param[in] active_args names of the symbols that will be considered in the computation of the partial degree of the monomial.
		 * @param[in] args reference set of piranha::symbol.
		 * 
		 * @return the summation of all the exponents of the monomial corresponding to the symbols in
		 * \p active_args, or <tt>value_type(0)</tt> if no symbols in \p active_args appear in \p args.
		 * 
		 * @throws std::invalid_argument if the size of \p args is greater than one or
		 * if the size is zero and the exponent is not zero.
		 * @throws unspecified any exception thrown by piranha::math::is_zero() or by constructing an instance of \p T from zero.
		 */
		T degree(const std::set<std::string> &active_args, const symbol_set &args) const
		{
			if (unlikely(args.size() > 1u || (!args.size() && !math::is_zero(m_value)))) {
				piranha_throw(std::invalid_argument,"invalid symbol set");
			}
			if (!args.size()) {
				return T(0);
			}
			piranha_assert(args.size() == 1u);
			// Look for the only symbol in active args, if we find it return its exponent.
			const bool is_present = std::binary_search(active_args.begin(),active_args.end(),args[0].get_name());
			if (is_present) {
				return m_value;
			} else {
				return T(0);
			}
		}
Ejemplo n.º 5
0
inline void construct_from_str(::PyObject *obj_ptr, bp::converter::rvalue_from_python_stage1_data *data,
                               const std::string &name)
{
    piranha_assert(obj_ptr);
    // NOTE: here we use str because for int and rational the string representations in Python
    // match the input format for the corresponding C++ objects. This is not true in general
    // for the repr() representations (e.g., in Python 2.x a trailing "L" is added to the repr() representation
    // for long integers).
    ::PyObject *str_obj = ::PyObject_Str(obj_ptr);
    if (!str_obj) {
        ::PyErr_SetString(PyExc_RuntimeError, ("unable to extract string representation of " + name).c_str());
        bp::throw_error_already_set();
    }
    bp::handle<> str_rep(str_obj);
#if PY_MAJOR_VERSION < 3
    const char *s = ::PyString_AsString(str_rep.get());
#else
    ::PyObject *unicode_str_obj = ::PyUnicode_AsEncodedString(str_rep.get(), "ascii", "strict");
    if (!unicode_str_obj) {
        ::PyErr_SetString(PyExc_RuntimeError, ("unable to extract string representation of " + name).c_str());
        bp::throw_error_already_set();
    }
    bp::handle<> unicode_str(unicode_str_obj);
    const char *s = ::PyBytes_AsString(unicode_str.get());
    if (!s) {
        ::PyErr_SetString(PyExc_RuntimeError, ("unable to extract string representation of " + name).c_str());
        bp::throw_error_already_set();
    }
#endif
    // NOTE: the use of reinterpret_cast here comes straight from the sources quoted at the beginning of the file.
    // reinterpret_cast
    // in general looks rather dangerous and unsafe, and it's not clear to me here if this is an idiomatic way of doing
    // things in Boost.Python
    // or instead this should be a static_cast to void * or something like that. Maybe a good question for the Boost
    // Python mailing list.
    void *storage = reinterpret_cast<bp::converter::rvalue_from_python_storage<T> *>(data)->storage.bytes;
    ::new (storage) T(s);
    data->convertible = storage;
}