inline void safe_integral_subber(T &a, const T &b) { if (b <= T(0)) { if (unlikely(a > std::numeric_limits<T>::max() + b)) { piranha_throw(std::overflow_error,"overflow in the subtraction of two signed integrals"); } } else { if (unlikely(a < std::numeric_limits<T>::min() + b)) { piranha_throw(std::overflow_error,"overflow in the subtraction of two signed integrals"); } } a = static_cast<T>(a - b); }
/** * @param[in] n the minimum work per thread. * * @throws std::invalid_argument if \n is zero. */ static void set_min_work_per_thread(unsigned long long n) { if (unlikely(n == 0u)) { piranha_throw(std::invalid_argument,"the minimum work per thread value must be strictly positive"); } return s_min_work_per_thread.store(n); }
inline void safe_integral_adder(T &a, const T &b) { if (unlikely(a > std::numeric_limits<T>::max() - b)) { piranha_throw(std::overflow_error,"overflow in the addition of two unsigned integrals"); } a = static_cast<T>(a + b); }
/** * @param[in] args reference set of piranha::symbol. * * @return degree of the monomial. * * @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(). */ T degree(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"); } return m_value; }
inline void safe_integral_subber(T &a, const T &b) { if (unlikely(a < b)) { piranha_throw(std::overflow_error,"overflow in the subtraction of two unsigned integrals"); } a = static_cast<T>(a - b); }
static void ip_inc(U &x) { if (unlikely(x == std::numeric_limits<U>::max())) { piranha_throw(std::invalid_argument,"positive overflow error in the calculation of the " "integral of a monomial"); } x = static_cast<U>(x + U(1)); }
void multiply(univariate_monomial &retval, const univariate_monomial<U> &other, const symbol_set &args) const { if (unlikely(args.size() > 1u || (!args.size() && (!math::is_zero(m_value) || !math::is_zero(other.m_value))))) { piranha_throw(std::invalid_argument,"invalid symbol set"); } retval.m_value = m_value; retval.m_value += other.m_value; }
/** * A monomial is unitary if piranha::math::is_zero() on its exponent returns \p true. * * @param[in] args reference set of piranha::symbol. * * @return \p true if the monomial is unitary, \p false otherwise. * * @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(). */ bool is_unitary(const symbol_set &args) const { const bool is_zero = math::is_zero(m_value); if (unlikely(args.size() > 1u || (!args.size() && !is_zero))) { piranha_throw(std::invalid_argument,"invalid symbol set"); } return is_zero; }
static void ip_dec(U &x) { if (unlikely(x == std::numeric_limits<U>::min())) { piranha_throw(std::invalid_argument,"negative overflow error in the calculation of the " "partial derivative of a monomial"); } x = static_cast<U>(x - U(1)); }
explicit univariate_monomial(std::initializer_list<U> list):m_value(0) { if (unlikely(list.size() > 1u)) { piranha_throw(std::invalid_argument,"excessive number of symbols for univariate monomial"); } if (list.size()) { m_value = *list.begin(); } }
explicit array_key(const array_key<U, Derived2, S2> &other, const symbol_fset &args) { if (unlikely(other.size() != args.size())) { piranha_throw(std::invalid_argument, "inconsistent sizes in the generic array_key constructor: the size of the array (" + std::to_string(other.size()) + ") differs from the size of the symbol set (" + std::to_string(args.size()) + ")"); } std::transform(other.begin(), other.end(), std::back_inserter(m_container), [](const U &x) { return piranha::safe_cast<value_type>(x); }); }
/** * 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(); }
/** * This method is used in piranha::series::trim(). The input mask \p trim_mask * is a vector of boolean flags signalling (with nonzero values) elements * of \p this to be removed. The method will return a copy of \p this in which * the specified elements have been removed. * * For instance, if \p this contains the values <tt>[0,5,3,0,4]</tt> and \p trim_mask contains * the values <tt>[false,false,false,true,false]</tt>, then the output of this method will be * the array of values <tt>[0,5,3,4]</tt> (that is, the fourth element has been removed as indicated * by a \p true value in <tt>trim_mask</tt>'s fourth element). * * @param trim_mask a mask indicating which elements will be removed. * @param args the reference piranha::symbol_fset. * * @return a trimmed copy of \p this. * * @throws std::invalid_argument if the sizes of \p this or \p trim_mask differ from the size of \p args. * @throws unspecified any exception thrown by push_back(). */ Derived trim(const std::vector<char> &trim_mask, const symbol_fset &args) const { auto sbe = size_begin_end(); if (unlikely(std::get<0>(sbe) != args.size())) { piranha_throw(std::invalid_argument, "invalid arguments set for trim(): the size of the array (" + std::to_string(std::get<0>(sbe)) + ") differs from the size of the reference symbol set (" + std::to_string(args.size()) + ")"); } if (unlikely(std::get<0>(sbe) != trim_mask.size())) { piranha_throw(std::invalid_argument, "invalid mask for trim(): the size of the array (" + std::to_string(std::get<0>(sbe)) + ") differs from the size of the mask (" + std::to_string(trim_mask.size()) + ")"); } Derived retval; for (decltype(trim_mask.size()) i = 0; std::get<1>(sbe) != std::get<2>(sbe); ++i, ++std::get<1>(sbe)) { if (!trim_mask[i]) { retval.push_back(*std::get<1>(sbe)); } } return retval; }
/** * This method is used in piranha::series::trim(). The input parameter \p trim_mask * is a vector of boolean flags (i.e., a mask) which signals which elements in \p args are candidates * for trimming: a nonzero value means that the symbol at the corresponding position is a candidate for trimming, * while a zero value means that the symbol is not a candidate for trimming. This method will set to zero those * values in \p trim_mask for which the corresponding element in \p this is nonzero. * * For instance, if \p this contains the values <tt>[0,5,3,0,4]</tt> and \p trim_mask originally contains * the values <tt>[1,1,0,1,0]</tt>, after a call to this method \p trim_mask will contain * <tt>[1,0,0,1,0]</tt> (that is, the second element was set from 1 to 0 as the corresponding element * in \p this has a value of 5 and thus it must not be trimmed). * * @param trim_mask a mask signalling candidate elements for trimming. * @param args the reference piranha::symbol_fset. * * @throws std::invalid_argument if the sizes of \p this or \p trim_mask differ from the size of \p args. * @throws unspecified any exception thrown by piranha::is_zero(). */ void trim_identify(std::vector<char> &trim_mask, const symbol_fset &args) const { auto sbe = size_begin_end(); if (unlikely(std::get<0>(sbe) != args.size())) { piranha_throw(std::invalid_argument, "invalid symbol set for trim_identify(): the size of the array (" + std::to_string(std::get<0>(sbe)) + ") differs from the size of the reference symbol set (" + std::to_string(args.size()) + ")"); } if (unlikely(std::get<0>(sbe) != trim_mask.size())) { piranha_throw(std::invalid_argument, "invalid mask for trim_identify(): the size of the array (" + std::to_string(std::get<0>(sbe)) + ") differs from the size of the mask (" + std::to_string(trim_mask.size()) + ")"); } for (decltype(trim_mask.size()) i = 0; std::get<1>(sbe) != std::get<2>(sbe); ++i, ++std::get<1>(sbe)) { if (!piranha::is_zero(*std::get<1>(sbe))) { // The current element of the array is nonzero, set the // corresponding element in the mask to zero. trim_mask[i] = 0; } } }
/** * Will print to stream a human-readable representation of the monomial. * * @param[in] os target stream. * @param[in] args reference set of piranha::symbol. * * @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(), * - construction of the exponent type from \p int, * - comparison of exponents, * - printing exponents to stream. */ void print(std::ostream &os, 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"); } const value_type zero(0), one(1); if (args.size() && m_value != zero) { os << args[0u].get_name(); if (m_value != one) { os << "**" << m_value; } } }
/** * 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); } }
/** * Will print to stream a TeX representation of the monomial. * * @param[in] os target stream. * @param[in] args reference set of piranha::symbol. * * @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() and piranha::math::negate(), * - construction of the exponent type, * - comparison of exponents, * - printing exponents to stream. */ void print_tex(std::ostream &os, 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"); } const value_type zero(0), one(1); value_type copy(m_value); bool sign_change = false; if (args.size() && copy != zero) { if (copy < zero) { math::negate(copy); os << "\\frac{1}{"; sign_change = true; } os << "{" << args[0u].get_name() << "}"; if (copy != one) { os << "^{" << copy << "}"; } if (sign_change) { os << "}"; } } }
/** * This constructor is for use when converting from one term type to another in piranha::series. It will * set the internal integer instance to the same value of \p m, after having checked that * \p m is compatible with \p args. * * @param[in] m construction argument. * @param[in] args reference set of piranha::symbol. * * @throws std::invalid_argument if \p m is not compatible with \p args. */ explicit univariate_monomial(const univariate_monomial &m, const symbol_set &args):m_value(m.m_value) { if (unlikely(!m.is_compatible(args))) { piranha_throw(std::invalid_argument,"incompatible arguments set"); } }
/** * This constructor will initialise the value of the exponent to 0. * * @param[in] args set of symbols used for construction. * * @throws std::invalid_argument if the size of \p args is greater than 1. * @throws unspecified any exception thrown by the construction of an instance of \p T from 0. */ explicit univariate_monomial(const symbol_set &args):m_value(0) { if (unlikely(args.size() > 1u)) { piranha_throw(std::invalid_argument,"excessive number of symbols for univariate monomial"); } }