/** * 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(); }
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; }
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; }
/** * 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); } }
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; }