--- /dev/null
+/* Polynomial integer classes.
+ Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This file provides a representation of sizes and offsets whose exact
+ values depend on certain runtime properties. The motivating example
+ is the Arm SVE ISA, in which the number of vector elements is only
+ known at runtime. See doc/poly-int.texi for more details.
+
+ Tests for poly-int.h are located in testsuite/gcc.dg/plugin,
+ since they are too expensive (in terms of binary size) to be
+ included as selftests. */
+
+#ifndef HAVE_POLY_INT_H
+#define HAVE_POLY_INT_H
+
+template<unsigned int N, typename T> class poly_int_pod;
+template<unsigned int N, typename T> class poly_int;
+
+/* poly_coeff_traiits<T> describes the properties of a poly_int
+ coefficient type T:
+
+ - poly_coeff_traits<T1>::rank is less than poly_coeff_traits<T2>::rank
+ if T1 can promote to T2. For C-like types the rank is:
+
+ (2 * number of bytes) + (unsigned ? 1 : 0)
+
+ wide_ints don't have a normal rank and so use a value of INT_MAX.
+ Any fixed-width integer should be promoted to wide_int if possible
+ and lead to an error otherwise.
+
+ - poly_coeff_traits<T>::int_type is the type to which an integer
+ literal should be cast before comparing it with T.
+
+ - poly_coeff_traits<T>::precision is the number of bits that T can hold.
+
+ - poly_coeff_traits<T>::signedness is:
+ 0 if T is unsigned
+ 1 if T is signed
+ -1 if T has no inherent sign (as for wide_int).
+
+ - poly_coeff_traits<T>::max_value, if defined, is the maximum value of T.
+
+ - poly_coeff_traits<T>::result is a type that can hold results of
+ operations on T. This is different from T itself in cases where T
+ is the result of an accessor like wi::to_offset. */
+template<typename T, wi::precision_type = wi::int_traits<T>::precision_type>
+struct poly_coeff_traits;
+
+template<typename T>
+struct poly_coeff_traits<T, wi::FLEXIBLE_PRECISION>
+{
+ typedef T result;
+ typedef T int_type;
+ static const int signedness = (T (0) >= T (-1));
+ static const int precision = sizeof (T) * CHAR_BIT;
+ static const T max_value = (signedness
+ ? ((T (1) << (precision - 2))
+ + ((T (1) << (precision - 2)) - 1))
+ : T (-1));
+ static const int rank = sizeof (T) * 2 + !signedness;
+};
+
+template<typename T>
+struct poly_coeff_traits<T, wi::VAR_PRECISION>
+{
+ typedef T result;
+ typedef int int_type;
+ static const int signedness = -1;
+ static const int precision = WIDE_INT_MAX_PRECISION;
+ static const int rank = INT_MAX;
+};
+
+template<typename T>
+struct poly_coeff_traits<T, wi::CONST_PRECISION>
+{
+ typedef WI_UNARY_RESULT (T) result;
+ typedef int int_type;
+ /* These types are always signed. */
+ static const int signedness = 1;
+ static const int precision = wi::int_traits<T>::precision;
+ static const int rank = precision * 2 / CHAR_BIT;
+};
+
+/* Information about a pair of coefficient types. */
+template<typename T1, typename T2>
+struct poly_coeff_pair_traits
+{
+ /* True if T1 can represent all the values of T2.
+
+ Either:
+
+ - T1 should be a type with the same signedness as T2 and no less
+ precision. This allows things like int16_t -> int16_t and
+ uint32_t -> uint64_t.
+
+ - T1 should be signed, T2 should be unsigned, and T1 should be
+ wider than T2. This allows things like uint16_t -> int32_t.
+
+ This rules out cases in which T1 has less precision than T2 or where
+ the conversion would reinterpret the top bit. E.g. int16_t -> uint32_t
+ can be dangerous and should have an explicit cast if deliberate. */
+ static const bool lossless_p = (poly_coeff_traits<T1>::signedness
+ == poly_coeff_traits<T2>::signedness
+ ? (poly_coeff_traits<T1>::precision
+ >= poly_coeff_traits<T2>::precision)
+ : (poly_coeff_traits<T1>::signedness == 1
+ && poly_coeff_traits<T2>::signedness == 0
+ && (poly_coeff_traits<T1>::precision
+ > poly_coeff_traits<T2>::precision)));
+
+ /* 0 if T1 op T2 should promote to HOST_WIDE_INT,
+ 1 if T1 op T2 should promote to unsigned HOST_WIDE_INT,
+ 2 if T1 op T2 should use wide-int rules. */
+#define RANK(X) poly_coeff_traits<X>::rank
+ static const int result_kind
+ = ((RANK (T1) <= RANK (HOST_WIDE_INT)
+ && RANK (T2) <= RANK (HOST_WIDE_INT))
+ ? 0
+ : (RANK (T1) <= RANK (unsigned HOST_WIDE_INT)
+ && RANK (T2) <= RANK (unsigned HOST_WIDE_INT))
+ ? 1 : 2);
+#undef RANK
+};
+
+/* SFINAE class that makes T3 available as "type" if T2 can represent all the
+ values in T1. */
+template<typename T1, typename T2, typename T3,
+ bool lossless_p = poly_coeff_pair_traits<T1, T2>::lossless_p>
+struct if_lossless;
+template<typename T1, typename T2, typename T3>
+struct if_lossless<T1, T2, T3, true>
+{
+ typedef T3 type;
+};
+
+/* poly_int_traits<T> describes an integer type T that might be polynomial
+ or non-polynomial:
+
+ - poly_int_traits<T>::is_poly is true if T is a poly_int-based type
+ and false otherwise.
+
+ - poly_int_traits<T>::num_coeffs gives the number of coefficients in T
+ if T is a poly_int and 1 otherwise.
+
+ - poly_int_traits<T>::coeff_type gives the coefficent type of T if T
+ is a poly_int and T itself otherwise
+
+ - poly_int_traits<T>::int_type is a shorthand for
+ typename poly_coeff_traits<coeff_type>::int_type. */
+template<typename T>
+struct poly_int_traits
+{
+ static const bool is_poly = false;
+ static const unsigned int num_coeffs = 1;
+ typedef T coeff_type;
+ typedef typename poly_coeff_traits<T>::int_type int_type;
+};
+template<unsigned int N, typename C>
+struct poly_int_traits<poly_int_pod<N, C> >
+{
+ static const bool is_poly = true;
+ static const unsigned int num_coeffs = N;
+ typedef C coeff_type;
+ typedef typename poly_coeff_traits<C>::int_type int_type;
+};
+template<unsigned int N, typename C>
+struct poly_int_traits<poly_int<N, C> > : poly_int_traits<poly_int_pod<N, C> >
+{
+};
+
+/* SFINAE class that makes T2 available as "type" if T1 is a non-polynomial
+ type. */
+template<typename T1, typename T2 = T1,
+ bool is_poly = poly_int_traits<T1>::is_poly>
+struct if_nonpoly {};
+template<typename T1, typename T2>
+struct if_nonpoly<T1, T2, false>
+{
+ typedef T2 type;
+};
+
+/* SFINAE class that makes T3 available as "type" if both T1 and T2 are
+ non-polynomial types. */
+template<typename T1, typename T2, typename T3,
+ bool is_poly1 = poly_int_traits<T1>::is_poly,
+ bool is_poly2 = poly_int_traits<T2>::is_poly>
+struct if_nonpoly2 {};
+template<typename T1, typename T2, typename T3>
+struct if_nonpoly2<T1, T2, T3, false, false>
+{
+ typedef T3 type;
+};
+
+/* SFINAE class that makes T2 available as "type" if T1 is a polynomial
+ type. */
+template<typename T1, typename T2 = T1,
+ bool is_poly = poly_int_traits<T1>::is_poly>
+struct if_poly {};
+template<typename T1, typename T2>
+struct if_poly<T1, T2, true>
+{
+ typedef T2 type;
+};
+
+/* poly_result<T1, T2> describes the result of an operation on two
+ types T1 and T2, where at least one of the types is polynomial:
+
+ - poly_result<T1, T2>::type gives the result type for the operation.
+ The intention is to provide normal C-like rules for integer ranks,
+ except that everything smaller than HOST_WIDE_INT promotes to
+ HOST_WIDE_INT.
+
+ - poly_result<T1, T2>::cast is the type to which an operand of type
+ T1 should be cast before doing the operation, to ensure that
+ the operation is done at the right precision. Casting to
+ poly_result<T1, T2>::type would also work, but casting to this
+ type is more efficient. */
+template<typename T1, typename T2 = T1,
+ int result_kind = poly_coeff_pair_traits<T1, T2>::result_kind>
+struct poly_result;
+
+/* Promote pair to HOST_WIDE_INT. */
+template<typename T1, typename T2>
+struct poly_result<T1, T2, 0>
+{
+ typedef HOST_WIDE_INT type;
+ /* T1 and T2 are primitive types, so cast values to T before operating
+ on them. */
+ typedef type cast;
+};
+
+/* Promote pair to unsigned HOST_WIDE_INT. */
+template<typename T1, typename T2>
+struct poly_result<T1, T2, 1>
+{
+ typedef unsigned HOST_WIDE_INT type;
+ /* T1 and T2 are primitive types, so cast values to T before operating
+ on them. */
+ typedef type cast;
+};
+
+/* Use normal wide-int rules. */
+template<typename T1, typename T2>
+struct poly_result<T1, T2, 2>
+{
+ typedef WI_BINARY_RESULT (T1, T2) type;
+ /* Don't cast values before operating on them; leave the wi:: routines
+ to handle promotion as necessary. */
+ typedef const T1 &cast;
+};
+
+/* The coefficient type for the result of a binary operation on two
+ poly_ints, the first of which has coefficients of type C1 and the
+ second of which has coefficients of type C2. */
+#define POLY_POLY_COEFF(C1, C2) typename poly_result<C1, C2>::type
+
+/* Enforce that T2 is non-polynomial and provide the cofficient type of
+ the result of a binary operation in which the first operand is a
+ poly_int with coefficients of type C1 and the second operand is
+ a constant of type T2. */
+#define POLY_CONST_COEFF(C1, T2) \
+ POLY_POLY_COEFF (C1, typename if_nonpoly<T2>::type)
+
+/* Likewise in reverse. */
+#define CONST_POLY_COEFF(T1, C2) \
+ POLY_POLY_COEFF (typename if_nonpoly<T1>::type, C2)
+
+/* The result type for a binary operation on poly_int<N, C1> and
+ poly_int<N, C2>. */
+#define POLY_POLY_RESULT(N, C1, C2) poly_int<N, POLY_POLY_COEFF (C1, C2)>
+
+/* Enforce that T2 is non-polynomial and provide the result type
+ for a binary operation on poly_int<N, C1> and T2. */
+#define POLY_CONST_RESULT(N, C1, T2) poly_int<N, POLY_CONST_COEFF (C1, T2)>
+
+/* Enforce that T1 is non-polynomial and provide the result type
+ for a binary operation on T1 and poly_int<N, C2>. */
+#define CONST_POLY_RESULT(N, T1, C2) poly_int<N, CONST_POLY_COEFF (T1, C2)>
+
+/* Enforce that T1 and T2 are non-polynomial and provide the result type
+ for a binary operation on T1 and T2. */
+#define CONST_CONST_RESULT(N, T1, T2) \
+ POLY_POLY_COEFF (typename if_nonpoly<T1>::type, \
+ typename if_nonpoly<T2>::type)
+
+/* The type to which a coefficient of type C1 should be cast before
+ using it in a binary operation with a coefficient of type C2. */
+#define POLY_CAST(C1, C2) typename poly_result<C1, C2>::cast
+
+/* Provide the coefficient type for the result of T1 op T2, where T1
+ and T2 can be polynomial or non-polynomial. */
+#define POLY_BINARY_COEFF(T1, T2) \
+ typename poly_result<typename poly_int_traits<T1>::coeff_type, \
+ typename poly_int_traits<T2>::coeff_type>::type
+
+/* The type to which an integer constant should be cast before
+ comparing it with T. */
+#define POLY_INT_TYPE(T) typename poly_int_traits<T>::int_type
+
+/* RES is a poly_int result that has coefficients of type C and that
+ is being built up a coefficient at a time. Set coefficient number I
+ to VALUE in the most efficient way possible.
+
+ For primitive C it is better to assign directly, since it avoids
+ any further calls and so is more efficient when the compiler is
+ built at -O0. But for wide-int based C it is better to construct
+ the value in-place. This means that calls out to a wide-int.cc
+ routine can take the address of RES rather than the address of
+ a temporary.
+
+ The dummy comparison against a null C * is just a way of checking
+ that C gives the right type. */
+#define POLY_SET_COEFF(C, RES, I, VALUE) \
+ ((void) (&(RES).coeffs[0] == (C *) 0), \
+ wi::int_traits<C>::precision_type == wi::FLEXIBLE_PRECISION \
+ ? (void) ((RES).coeffs[I] = VALUE) \
+ : (void) ((RES).coeffs[I].~C (), new (&(RES).coeffs[I]) C (VALUE)))
+
+/* A base POD class for polynomial integers. The polynomial has N
+ coefficients of type C. */
+template<unsigned int N, typename C>
+class poly_int_pod
+{
+public:
+ template<typename Ca>
+ poly_int_pod &operator = (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator = (const Ca &);
+
+ template<typename Ca>
+ poly_int_pod &operator += (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator += (const Ca &);
+
+ template<typename Ca>
+ poly_int_pod &operator -= (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator -= (const Ca &);
+
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int_pod>::type &operator *= (const Ca &);
+
+ poly_int_pod &operator <<= (unsigned int);
+
+ bool is_constant () const;
+
+ template<typename T>
+ typename if_lossless<T, C, bool>::type is_constant (T *) const;
+
+ C to_constant () const;
+
+ template<typename Ca>
+ static poly_int<N, C> from (const poly_int_pod<N, Ca> &, unsigned int,
+ signop);
+ template<typename Ca>
+ static poly_int<N, C> from (const poly_int_pod<N, Ca> &, signop);
+
+ bool to_shwi (poly_int_pod<N, HOST_WIDE_INT> *) const;
+ bool to_uhwi (poly_int_pod<N, unsigned HOST_WIDE_INT> *) const;
+ poly_int<N, HOST_WIDE_INT> force_shwi () const;
+ poly_int<N, unsigned HOST_WIDE_INT> force_uhwi () const;
+
+#if POLY_INT_CONVERSION
+ operator C () const;
+#endif
+
+ C coeffs[N];
+};
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator = (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator = (const Ca &a)
+{
+ POLY_SET_COEFF (C, *this, 0, a);
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator += (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] += a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator += (const Ca &a)
+{
+ this->coeffs[0] += a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator -= (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] -= a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator -= (const Ca &a)
+{
+ this->coeffs[0] -= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
+poly_int_pod<N, C>::operator *= (const Ca &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] *= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+inline poly_int_pod<N, C>&
+poly_int_pod<N, C>::operator <<= (unsigned int a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] <<= a;
+ return *this;
+}
+
+/* Return true if the polynomial value is a compile-time constant. */
+
+template<unsigned int N, typename C>
+inline bool
+poly_int_pod<N, C>::is_constant () const
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (this->coeffs[i] != 0)
+ return false;
+ return true;
+}
+
+/* Return true if the polynomial value is a compile-time constant,
+ storing its value in CONST_VALUE if so. */
+
+template<unsigned int N, typename C>
+template<typename T>
+inline typename if_lossless<T, C, bool>::type
+poly_int_pod<N, C>::is_constant (T *const_value) const
+{
+ if (is_constant ())
+ {
+ *const_value = this->coeffs[0];
+ return true;
+ }
+ return false;
+}
+
+/* Return the value of a polynomial that is already known to be a
+ compile-time constant.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the value is constant in that context. */
+
+template<unsigned int N, typename C>
+inline C
+poly_int_pod<N, C>::to_constant () const
+{
+ gcc_checking_assert (is_constant ());
+ return this->coeffs[0];
+}
+
+/* Convert X to a wide_int-based polynomial in which each coefficient
+ has BITSIZE bits. If X's coefficients are smaller than BITSIZE,
+ extend them according to SGN. */
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>
+poly_int_pod<N, C>::from (const poly_int_pod<N, Ca> &a,
+ unsigned int bitsize, signop sgn)
+{
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, C::from (a.coeffs[i], bitsize, sgn));
+ return r;
+}
+
+/* Convert X to a fixed_wide_int-based polynomial, extending according
+ to SGN. */
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>
+poly_int_pod<N, C>::from (const poly_int_pod<N, Ca> &a, signop sgn)
+{
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, C::from (a.coeffs[i], sgn));
+ return r;
+}
+
+/* Return true if the coefficients of this generic_wide_int-based
+ polynomial can be represented as signed HOST_WIDE_INTs without loss
+ of precision. Store the HOST_WIDE_INT representation in *R if so. */
+
+template<unsigned int N, typename C>
+inline bool
+poly_int_pod<N, C>::to_shwi (poly_int_pod<N, HOST_WIDE_INT> *r) const
+{
+ for (unsigned int i = 0; i < N; i++)
+ if (!wi::fits_shwi_p (this->coeffs[i]))
+ return false;
+ for (unsigned int i = 0; i < N; i++)
+ r->coeffs[i] = this->coeffs[i].to_shwi ();
+ return true;
+}
+
+/* Return true if the coefficients of this generic_wide_int-based
+ polynomial can be represented as unsigned HOST_WIDE_INTs without
+ loss of precision. Store the unsigned HOST_WIDE_INT representation
+ in *R if so. */
+
+template<unsigned int N, typename C>
+inline bool
+poly_int_pod<N, C>::to_uhwi (poly_int_pod<N, unsigned HOST_WIDE_INT> *r) const
+{
+ for (unsigned int i = 0; i < N; i++)
+ if (!wi::fits_uhwi_p (this->coeffs[i]))
+ return false;
+ for (unsigned int i = 0; i < N; i++)
+ r->coeffs[i] = this->coeffs[i].to_uhwi ();
+ return true;
+}
+
+/* Force a generic_wide_int-based constant to HOST_WIDE_INT precision,
+ truncating if necessary. */
+
+template<unsigned int N, typename C>
+inline poly_int<N, HOST_WIDE_INT>
+poly_int_pod<N, C>::force_shwi () const
+{
+ poly_int_pod<N, HOST_WIDE_INT> r;
+ for (unsigned int i = 0; i < N; i++)
+ r.coeffs[i] = this->coeffs[i].to_shwi ();
+ return r;
+}
+
+/* Force a generic_wide_int-based constant to unsigned HOST_WIDE_INT precision,
+ truncating if necessary. */
+
+template<unsigned int N, typename C>
+inline poly_int<N, unsigned HOST_WIDE_INT>
+poly_int_pod<N, C>::force_uhwi () const
+{
+ poly_int_pod<N, unsigned HOST_WIDE_INT> r;
+ for (unsigned int i = 0; i < N; i++)
+ r.coeffs[i] = this->coeffs[i].to_uhwi ();
+ return r;
+}
+
+#if POLY_INT_CONVERSION
+/* Provide a conversion operator to constants. */
+
+template<unsigned int N, typename C>
+inline
+poly_int_pod<N, C>::operator C () const
+{
+ gcc_checking_assert (this->is_constant ());
+ return this->coeffs[0];
+}
+#endif
+
+/* The main class for polynomial integers. The class provides
+ constructors that are necessarily missing from the POD base. */
+template<unsigned int N, typename C>
+class poly_int : public poly_int_pod<N, C>
+{
+public:
+ poly_int () {}
+
+ template<typename Ca>
+ poly_int (const poly_int<N, Ca> &);
+ template<typename Ca>
+ poly_int (const poly_int_pod<N, Ca> &);
+ template<typename C0>
+ poly_int (const C0 &);
+ template<typename C0, typename C1>
+ poly_int (const C0 &, const C1 &);
+
+ template<typename Ca>
+ poly_int &operator = (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator = (const Ca &);
+
+ template<typename Ca>
+ poly_int &operator += (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator += (const Ca &);
+
+ template<typename Ca>
+ poly_int &operator -= (const poly_int_pod<N, Ca> &);
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator -= (const Ca &);
+
+ template<typename Ca>
+ typename if_nonpoly<Ca, poly_int>::type &operator *= (const Ca &);
+
+ poly_int &operator <<= (unsigned int);
+};
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline
+poly_int<N, C>::poly_int (const poly_int<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline
+poly_int<N, C>::poly_int (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
+}
+
+template<unsigned int N, typename C>
+template<typename C0>
+inline
+poly_int<N, C>::poly_int (const C0 &c0)
+{
+ POLY_SET_COEFF (C, *this, 0, c0);
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
+}
+
+template<unsigned int N, typename C>
+template<typename C0, typename C1>
+inline
+poly_int<N, C>::poly_int (const C0 &c0, const C1 &c1)
+{
+ STATIC_ASSERT (N >= 2);
+ POLY_SET_COEFF (C, *this, 0, c0);
+ POLY_SET_COEFF (C, *this, 1, c1);
+ for (unsigned int i = 2; i < N; i++)
+ POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>&
+poly_int<N, C>::operator = (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] = a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator = (const Ca &a)
+{
+ this->coeffs[0] = a;
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ this->coeffs[i] = wi::ints_for<C>::zero (this->coeffs[0]);
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>&
+poly_int<N, C>::operator += (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] += a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator += (const Ca &a)
+{
+ this->coeffs[0] += a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline poly_int<N, C>&
+poly_int<N, C>::operator -= (const poly_int_pod<N, Ca> &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] -= a.coeffs[i];
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator -= (const Ca &a)
+{
+ this->coeffs[0] -= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+template<typename Ca>
+inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
+poly_int<N, C>::operator *= (const Ca &a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] *= a;
+ return *this;
+}
+
+template<unsigned int N, typename C>
+inline poly_int<N, C>&
+poly_int<N, C>::operator <<= (unsigned int a)
+{
+ for (unsigned int i = 0; i < N; i++)
+ this->coeffs[i] <<= a;
+ return *this;
+}
+
+/* Return true if every coefficient of A is in the inclusive range [B, C]. */
+
+template<typename Ca, typename Cb, typename Cc>
+inline typename if_nonpoly<Ca, bool>::type
+coeffs_in_range_p (const Ca &a, const Cb &b, const Cc &c)
+{
+ return a >= b && a <= c;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cc>
+inline typename if_nonpoly<Ca, bool>::type
+coeffs_in_range_p (const poly_int_pod<N, Ca> &a, const Cb &b, const Cc &c)
+{
+ for (unsigned int i = 0; i < N; i++)
+ if (a.coeffs[i] < b || a.coeffs[i] > c)
+ return false;
+ return true;
+}
+
+namespace wi {
+/* Poly version of wi::shwi, with the same interface. */
+
+template<unsigned int N>
+inline poly_int<N, hwi_with_prec>
+shwi (const poly_int_pod<N, HOST_WIDE_INT> &a, unsigned int precision)
+{
+ poly_int<N, hwi_with_prec> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (hwi_with_prec, r, i, wi::shwi (a.coeffs[i], precision));
+ return r;
+}
+
+/* Poly version of wi::uhwi, with the same interface. */
+
+template<unsigned int N>
+inline poly_int<N, hwi_with_prec>
+uhwi (const poly_int_pod<N, unsigned HOST_WIDE_INT> &a, unsigned int precision)
+{
+ poly_int<N, hwi_with_prec> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (hwi_with_prec, r, i, wi::uhwi (a.coeffs[i], precision));
+ return r;
+}
+
+/* Poly version of wi::sext, with the same interface. */
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+sext (const poly_int_pod<N, Ca> &a, unsigned int precision)
+{
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sext (a.coeffs[i], precision));
+ return r;
+}
+
+/* Poly version of wi::zext, with the same interface. */
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+zext (const poly_int_pod<N, Ca> &a, unsigned int precision)
+{
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::zext (a.coeffs[i], precision));
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+operator + (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) + b.coeffs[i]);
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+operator + (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, NCa (a.coeffs[0]) + b);
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+operator + (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef CONST_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, a + NCb (b.coeffs[0]));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCb (b.coeffs[i]));
+ return r;
+}
+
+namespace wi {
+/* Poly versions of wi::add, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i], b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::add (a.coeffs[0], b));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i],
+ wi::ints_for<Cb>::zero (b)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::add (a, b.coeffs[0]));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::add (wi::ints_for<Ca>::zero (a),
+ b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+add (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
+ signop sgn, bool *overflow)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::add (a.coeffs[0], b.coeffs[0], sgn, overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ bool suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i], b.coeffs[i], sgn,
+ &suboverflow));
+ *overflow |= suboverflow;
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+operator - (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) - b.coeffs[i]);
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+operator - (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, NCa (a.coeffs[0]) - b);
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+operator - (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef CONST_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, a - NCb (b.coeffs[0]));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, -NCb (b.coeffs[i]));
+ return r;
+}
+
+namespace wi {
+/* Poly versions of wi::sub, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sub (a.coeffs[i], b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::sub (a.coeffs[0], b));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sub (a.coeffs[i],
+ wi::ints_for<Cb>::zero (b)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::sub (a, b.coeffs[0]));
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::sub (wi::ints_for<Ca>::zero (a),
+ b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+sub (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
+ signop sgn, bool *overflow)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::sub (a.coeffs[0], b.coeffs[0], sgn, overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ bool suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::sub (a.coeffs[i], b.coeffs[i], sgn,
+ &suboverflow));
+ *overflow |= suboverflow;
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+operator - (const poly_int_pod<N, Ca> &a)
+{
+ typedef POLY_CAST (Ca, Ca) NCa;
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, -NCa (a.coeffs[i]));
+ return r;
+}
+
+namespace wi {
+/* Poly version of wi::neg, with the same interface. */
+
+template<unsigned int N, typename Ca>
+inline poly_int<N, WI_UNARY_RESULT (Ca)>
+neg (const poly_int_pod<N, Ca> &a)
+{
+ typedef WI_UNARY_RESULT (Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::neg (a.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca>
+inline poly_int<N, WI_UNARY_RESULT (Ca)>
+neg (const poly_int_pod<N, Ca> &a, bool *overflow)
+{
+ typedef WI_UNARY_RESULT (Ca) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::neg (a.coeffs[0], overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ bool suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::neg (a.coeffs[i], &suboverflow));
+ *overflow |= suboverflow;
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+operator ~ (const poly_int_pod<N, Ca> &a)
+{
+ if (N >= 2)
+ return -1 - a;
+ return ~a.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+operator * (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) * b);
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+operator * (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef CONST_POLY_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a) * b.coeffs[i]);
+ return r;
+}
+
+namespace wi {
+/* Poly versions of wi::mul, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+mul (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::mul (a.coeffs[i], b));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+mul (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::mul (a, b.coeffs[i]));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
+mul (const poly_int_pod<N, Ca> &a, const Cb &b,
+ signop sgn, bool *overflow)
+{
+ typedef WI_BINARY_RESULT (Ca, Cb) C;
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, wi::mul (a.coeffs[0], b, sgn, overflow));
+ for (unsigned int i = 1; i < N; i++)
+ {
+ bool suboverflow;
+ POLY_SET_COEFF (C, r, i, wi::mul (a.coeffs[i], b, sgn, &suboverflow));
+ *overflow |= suboverflow;
+ }
+ return r;
+}
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Ca)
+operator << (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Ca) NCa;
+ typedef POLY_POLY_COEFF (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) << b);
+ return r;
+}
+
+namespace wi {
+/* Poly version of wi::lshift, with the same interface. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, WI_BINARY_RESULT (Ca, Ca)>
+lshift (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef WI_BINARY_RESULT (Ca, Ca) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, wi::lshift (a.coeffs[i], b));
+ return r;
+}
+}
+
+/* Return true if a0 + a1 * x might equal b0 + b1 * x for some nonnegative
+ integer x. */
+
+template<typename Ca, typename Cb>
+inline bool
+maybe_eq_2 (const Ca &a0, const Ca &a1, const Cb &b0, const Cb &b1)
+{
+ if (a1 != b1)
+ /* a0 + a1 * x == b0 + b1 * x
+ ==> (a1 - b1) * x == b0 - a0
+ ==> x == (b0 - a0) / (a1 - b1)
+
+ We need to test whether that's a valid value of x.
+ (b0 - a0) and (a1 - b1) must not have opposite signs
+ and the result must be integral. */
+ return (a1 < b1
+ ? b0 <= a0 && (a0 - b0) % (b1 - a1) == 0
+ : b0 >= a0 && (b0 - a0) % (a1 - b1) == 0);
+ return a0 == b0;
+}
+
+/* Return true if a0 + a1 * x might equal b for some nonnegative
+ integer x. */
+
+template<typename Ca, typename Cb>
+inline bool
+maybe_eq_2 (const Ca &a0, const Ca &a1, const Cb &b)
+{
+ if (a1 != 0)
+ /* a0 + a1 * x == b
+ ==> x == (b - a0) / a1
+
+ We need to test whether that's a valid value of x.
+ (b - a0) and a1 must not have opposite signs and the
+ result must be integral. */
+ return (a1 < 0
+ ? b <= a0 && (a0 - b) % a1 == 0
+ : b >= a0 && (b - a0) % a1 == 0);
+ return a0 == b;
+}
+
+/* Return true if A might equal B for some indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_eq (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ STATIC_ASSERT (N <= 2);
+ if (N == 2)
+ return maybe_eq_2 (a.coeffs[0], a.coeffs[1], b.coeffs[0], b.coeffs[1]);
+ return a.coeffs[0] == b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_eq (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ STATIC_ASSERT (N <= 2);
+ if (N == 2)
+ return maybe_eq_2 (a.coeffs[0], a.coeffs[1], b);
+ return a.coeffs[0] == b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_eq (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ STATIC_ASSERT (N <= 2);
+ if (N == 2)
+ return maybe_eq_2 (b.coeffs[0], b.coeffs[1], a);
+ return a == b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_eq (const Ca &a, const Cb &b)
+{
+ return a == b;
+}
+
+/* Return true if A might not equal B for some indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_ne (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] != b.coeffs[i])
+ return true;
+ return a.coeffs[0] != b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_ne (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] != 0)
+ return true;
+ return a.coeffs[0] != b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_ne (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (0 != b.coeffs[i])
+ return true;
+ return a != b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_ne (const Ca &a, const Cb &b)
+{
+ return a != b;
+}
+
+/* Return true if A is known to be equal to B. */
+#define known_eq(A, B) (!maybe_ne (A, B))
+
+/* Return true if A is known to be unequal to B. */
+#define known_ne(A, B) (!maybe_eq (A, B))
+
+/* Return true if A might be less than or equal to B for some
+ indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_le (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < b.coeffs[i])
+ return true;
+ return a.coeffs[0] <= b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_le (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < 0)
+ return true;
+ return a.coeffs[0] <= b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_le (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (0 < b.coeffs[i])
+ return true;
+ return a <= b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_le (const Ca &a, const Cb &b)
+{
+ return a <= b;
+}
+
+/* Return true if A might be less than B for some indeterminate values. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+maybe_lt (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < b.coeffs[i])
+ return true;
+ return a.coeffs[0] < b.coeffs[0];
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+maybe_lt (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (a.coeffs[i] < 0)
+ return true;
+ return a.coeffs[0] < b;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+maybe_lt (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if (0 < b.coeffs[i])
+ return true;
+ return a < b.coeffs[0];
+}
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+maybe_lt (const Ca &a, const Cb &b)
+{
+ return a < b;
+}
+
+/* Return true if A may be greater than or equal to B. */
+#define maybe_ge(A, B) maybe_le (B, A)
+
+/* Return true if A may be greater than B. */
+#define maybe_gt(A, B) maybe_lt (B, A)
+
+/* Return true if A is known to be less than or equal to B. */
+#define known_le(A, B) (!maybe_gt (A, B))
+
+/* Return true if A is known to be less than B. */
+#define known_lt(A, B) (!maybe_ge (A, B))
+
+/* Return true if A is known to be greater than B. */
+#define known_gt(A, B) (!maybe_le (A, B))
+
+/* Return true if A is known to be greater than or equal to B. */
+#define known_ge(A, B) (!maybe_lt (A, B))
+
+/* Return true if A and B are ordered by the partial ordering known_le. */
+
+template<typename T1, typename T2>
+inline bool
+ordered_p (const T1 &a, const T2 &b)
+{
+ return ((poly_int_traits<T1>::num_coeffs == 1
+ && poly_int_traits<T2>::num_coeffs == 1)
+ || known_le (a, b)
+ || known_le (b, a));
+}
+
+/* Assert that A and B are known to be ordered and return the minimum
+ of the two.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the values are ordered in that context. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+ordered_min (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return a;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return b;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+ordered_min (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return a;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return b;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+ordered_min (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (known_le (a, b))
+ return a;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return b;
+ }
+}
+
+/* Assert that A and B are known to be ordered and return the maximum
+ of the two.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the values are ordered in that context. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+ordered_max (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return b;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return a;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+ordered_max (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ if (known_le (a, b))
+ return b;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return a;
+ }
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+ordered_max (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ if (known_le (a, b))
+ return b;
+ else
+ {
+ if (N > 1)
+ gcc_checking_assert (known_le (b, a));
+ return a;
+ }
+}
+
+/* Return a constant lower bound on the value of A, which is known
+ to be nonnegative. */
+
+template<unsigned int N, typename Ca>
+inline Ca
+constant_lower_bound (const poly_int_pod<N, Ca> &a)
+{
+ gcc_checking_assert (known_ge (a, POLY_INT_TYPE (Ca) (0)));
+ return a.coeffs[0];
+}
+
+/* Return a value that is known to be no greater than A and B. This
+ will be the greatest lower bound for some indeterminate values but
+ not necessarily for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+lower_bound (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, MIN (NCa (a.coeffs[0]), NCb (b)));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MIN (NCa (a.coeffs[i]), ICb (0)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+lower_bound (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ return lower_bound (b, a);
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+lower_bound (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MIN (NCa (a.coeffs[i]), NCb (b.coeffs[i])));
+ return r;
+}
+
+template<typename Ca, typename Cb>
+inline CONST_CONST_RESULT (N, Ca, Cb)
+lower_bound (const Ca &a, const Cb &b)
+{
+ return a < b ? a : b;
+}
+
+/* Return a value that is known to be no less than A and B. This will
+ be the least upper bound for some indeterminate values but not
+ necessarily for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+upper_bound (const poly_int_pod<N, Ca> &a, const Cb &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ POLY_SET_COEFF (C, r, 0, MAX (NCa (a.coeffs[0]), NCb (b)));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MAX (NCa (a.coeffs[i]), ICb (0)));
+ return r;
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+upper_bound (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ return upper_bound (b, a);
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+upper_bound (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_POLY_COEFF (Ca, Cb) C;
+
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (C, r, i, MAX (NCa (a.coeffs[i]), NCb (b.coeffs[i])));
+ return r;
+}
+
+/* Return the greatest common divisor of all nonzero coefficients, or zero
+ if all coefficients are zero. */
+
+template<unsigned int N, typename Ca>
+inline POLY_BINARY_COEFF (Ca, Ca)
+coeff_gcd (const poly_int_pod<N, Ca> &a)
+{
+ /* Find the first nonzero coefficient, stopping at 0 whatever happens. */
+ unsigned int i;
+ for (i = N - 1; i > 0; --i)
+ if (a.coeffs[i] != 0)
+ break;
+ typedef POLY_BINARY_COEFF (Ca, Ca) C;
+ C r = a.coeffs[i];
+ for (unsigned int j = 0; j < i; ++j)
+ if (a.coeffs[j] != 0)
+ r = gcd (r, C (a.coeffs[j]));
+ return r;
+}
+
+/* Return a value that is a multiple of both A and B. This will be the
+ least common multiple for some indeterminate values but necessarily
+ for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+POLY_CONST_RESULT (N, Ca, Cb)
+common_multiple (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ POLY_BINARY_COEFF (Ca, Ca) xgcd = coeff_gcd (a);
+ return a * (least_common_multiple (xgcd, b) / xgcd);
+}
+
+template<unsigned int N, typename Ca, typename Cb>
+inline CONST_POLY_RESULT (N, Ca, Cb)
+common_multiple (const Ca &a, const poly_int_pod<N, Cb> &b)
+{
+ return common_multiple (b, a);
+}
+
+/* Return a value that is a multiple of both A and B, asserting that
+ such a value exists. The result will be the least common multiple
+ for some indeterminate values but necessarily for all.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the values have a common multiple (which might
+ for example be because we know A / B is rational). */
+
+template<unsigned int N, typename Ca, typename Cb>
+POLY_POLY_RESULT (N, Ca, Cb)
+force_common_multiple (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b)
+{
+ if (b.is_constant ())
+ return common_multiple (a, b.coeffs[0]);
+ if (a.is_constant ())
+ return common_multiple (a.coeffs[0], b);
+
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+ typedef POLY_INT_TYPE (Ca) ICa;
+
+ for (unsigned int i = 1; i < N; ++i)
+ if (a.coeffs[i] != ICa (0))
+ {
+ C lcm = least_common_multiple (NCa (a.coeffs[i]), NCb (b.coeffs[i]));
+ C amul = lcm / a.coeffs[i];
+ C bmul = lcm / b.coeffs[i];
+ for (unsigned int j = 0; j < N; ++j)
+ gcc_checking_assert (a.coeffs[j] * amul == b.coeffs[j] * bmul);
+ return a * amul;
+ }
+ gcc_unreachable ();
+}
+
+/* Compare A and B for sorting purposes, returning -1 if A should come
+ before B, 0 if A and B are identical, and 1 if A should come after B.
+ This is a lexicographical compare of the coefficients in reverse order.
+
+ A consequence of this is that all constant sizes come before all
+ non-constant ones, regardless of magnitude (since a size is never
+ negative). This is what most callers want. For example, when laying
+ data out on the stack, it's better to keep all the constant-sized
+ data together so that it can be accessed as a constant offset from a
+ single base. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline int
+compare_sizes_for_sort (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b)
+{
+ for (unsigned int i = N; i-- > 0; )
+ if (a.coeffs[i] != b.coeffs[i])
+ return a.coeffs[i] < b.coeffs[i] ? -1 : 1;
+ return 0;
+}
+
+/* Return true if we can calculate VALUE & (ALIGN - 1) at compile time. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+can_align_p (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ for (unsigned int i = 1; i < N; i++)
+ if ((value.coeffs[i] & (align - 1)) != 0)
+ return false;
+ return true;
+}
+
+/* Return true if we can align VALUE up to the smallest multiple of
+ ALIGN that is >= VALUE. Store the aligned value in *ALIGNED if so. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+can_align_up (const poly_int_pod<N, Ca> &value, Cb align,
+ poly_int_pod<N, Ca> *aligned)
+{
+ if (!can_align_p (value, align))
+ return false;
+ *aligned = value + (-value.coeffs[0] & (align - 1));
+ return true;
+}
+
+/* Return true if we can align VALUE down to the largest multiple of
+ ALIGN that is <= VALUE. Store the aligned value in *ALIGNED if so. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+can_align_down (const poly_int_pod<N, Ca> &value, Cb align,
+ poly_int_pod<N, Ca> *aligned)
+{
+ if (!can_align_p (value, align))
+ return false;
+ *aligned = value - (value.coeffs[0] & (align - 1));
+ return true;
+}
+
+/* Return true if we can align A and B up to the smallest multiples of
+ ALIGN that are >= A and B respectively, and if doing so gives the
+ same value. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cc>
+inline bool
+known_equal_after_align_up (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cc align)
+{
+ poly_int<N, Ca> aligned_a;
+ poly_int<N, Cb> aligned_b;
+ return (can_align_up (a, align, &aligned_a)
+ && can_align_up (b, align, &aligned_b)
+ && known_eq (aligned_a, aligned_b));
+}
+
+/* Return true if we can align A and B down to the largest multiples of
+ ALIGN that are <= A and B respectively, and if doing so gives the
+ same value. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cc>
+inline bool
+known_equal_after_align_down (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cc align)
+{
+ poly_int<N, Ca> aligned_a;
+ poly_int<N, Cb> aligned_b;
+ return (can_align_down (a, align, &aligned_a)
+ && can_align_down (b, align, &aligned_b)
+ && known_eq (aligned_a, aligned_b));
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time and return
+ the smallest multiple of ALIGN that is >= VALUE.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_up (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+ return value + (-value.coeffs[0] & (align - 1));
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time and return
+ the largest multiple of ALIGN that is <= VALUE.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_down (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+ return value - (value.coeffs[0] & (align - 1));
+}
+
+/* Return a value <= VALUE that is a multiple of ALIGN. It will be the
+ greatest such value for some indeterminate values but not necessarily
+ for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+aligned_lower_bound (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ poly_int<N, Ca> r;
+ for (unsigned int i = 0; i < N; i++)
+ /* This form copes correctly with more type combinations than
+ value.coeffs[i] & -align would. */
+ POLY_SET_COEFF (Ca, r, i, (value.coeffs[i]
+ - (value.coeffs[i] & (align - 1))));
+ return r;
+}
+
+/* Return a value >= VALUE that is a multiple of ALIGN. It will be the
+ least such value for some indeterminate values but not necessarily
+ for all. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+aligned_upper_bound (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ poly_int<N, Ca> r;
+ for (unsigned int i = 0; i < N; i++)
+ POLY_SET_COEFF (Ca, r, i, (value.coeffs[i]
+ + (-value.coeffs[i] & (align - 1))));
+ return r;
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time. Align VALUE
+ down to the largest multiple of ALIGN that is <= VALUE, then divide by
+ ALIGN.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_down_and_div (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+
+ poly_int<N, Ca> r;
+ POLY_SET_COEFF (Ca, r, 0, ((value.coeffs[0]
+ - (value.coeffs[0] & (align - 1)))
+ / align));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (Ca, r, i, value.coeffs[i] / align);
+ return r;
+}
+
+/* Assert that we can align VALUE to ALIGN at compile time. Align VALUE
+ up to the smallest multiple of ALIGN that is >= VALUE, then divide by
+ ALIGN.
+
+ NOTE: When using this function, please add a comment above the call
+ explaining why we know the non-constant coefficients must already
+ be a multiple of ALIGN. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline poly_int<N, Ca>
+force_align_up_and_div (const poly_int_pod<N, Ca> &value, Cb align)
+{
+ gcc_checking_assert (can_align_p (value, align));
+
+ poly_int<N, Ca> r;
+ POLY_SET_COEFF (Ca, r, 0, ((value.coeffs[0]
+ + (-value.coeffs[0] & (align - 1)))
+ / align));
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ POLY_SET_COEFF (Ca, r, i, value.coeffs[i] / align);
+ return r;
+}
+
+/* Return true if we know at compile time the difference between VALUE
+ and the equal or preceding multiple of ALIGN. Store the value in
+ *MISALIGN if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline bool
+known_misalignment (const poly_int_pod<N, Ca> &value, Cb align, Cm *misalign)
+{
+ gcc_checking_assert (align != 0);
+ if (!can_align_p (value, align))
+ return false;
+ *misalign = value.coeffs[0] & (align - 1);
+ return true;
+}
+
+/* Return X & (Y - 1), asserting that this value is known. Please add
+ an a comment above callers to this function to explain why the condition
+ is known to hold. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_BINARY_COEFF (Ca, Ca)
+force_get_misalignment (const poly_int_pod<N, Ca> &a, Cb align)
+{
+ gcc_checking_assert (can_align_p (a, align));
+ return a.coeffs[0] & (align - 1);
+}
+
+/* Return the maximum alignment that A is known to have. Return 0
+ if A is known to be zero. */
+
+template<unsigned int N, typename Ca>
+inline POLY_BINARY_COEFF (Ca, Ca)
+known_alignment (const poly_int_pod<N, Ca> &a)
+{
+ typedef POLY_BINARY_COEFF (Ca, Ca) C;
+ C r = a.coeffs[0];
+ for (unsigned int i = 1; i < N; ++i)
+ r |= a.coeffs[i];
+ return r & -r;
+}
+
+/* Return true if we can compute A | B at compile time, storing the
+ result in RES if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cr>
+inline typename if_nonpoly<Cb, bool>::type
+can_ior_p (const poly_int_pod<N, Ca> &a, Cb b, Cr *result)
+{
+ /* Coefficients 1 and above must be a multiple of something greater
+ than B. */
+ typedef POLY_INT_TYPE (Ca) int_type;
+ if (N >= 2)
+ for (unsigned int i = 1; i < N; i++)
+ if ((-(a.coeffs[i] & -a.coeffs[i]) & b) != int_type (0))
+ return false;
+ *result = a;
+ result->coeffs[0] |= b;
+ return true;
+}
+
+/* Return true if A is a constant multiple of B, storing the
+ multiple in *MULTIPLE if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Cb, bool>::type
+constant_multiple_p (const poly_int_pod<N, Ca> &a, Cb b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a.coeffs[0]) % NCb (b) != 0 || !a.is_constant ())
+ return false;
+ *multiple = NCa (a.coeffs[0]) / NCb (b);
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Ca, bool>::type
+constant_multiple_p (Ca a, const poly_int_pod<N, Cb> &b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) int_type;
+
+ /* Do the modulus before the constant check, to catch divide by
+ zero errors. */
+ if (NCa (a) % NCb (b.coeffs[0]) != 0
+ || (a != int_type (0) && !b.is_constant ()))
+ return false;
+ *multiple = NCa (a) / NCb (b.coeffs[0]);
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline bool
+constant_multiple_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) ICa;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+
+ if (NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0)
+ return false;
+
+ C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+ for (unsigned int i = 1; i < N; ++i)
+ if (b.coeffs[i] == ICb (0)
+ ? a.coeffs[i] != ICa (0)
+ : (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0
+ || NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != r))
+ return false;
+
+ *multiple = r;
+ return true;
+}
+
+/* Return true if A is a multiple of B. */
+
+template<typename Ca, typename Cb>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+multiple_p (Ca a, Cb b)
+{
+ return a % b != 0;
+}
+
+/* Return true if A is a (polynomial) multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Cb, bool>::type
+multiple_p (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ for (unsigned int i = 0; i < N; ++i)
+ if (a.coeffs[i] % b != 0)
+ return false;
+ return true;
+}
+
+/* Return true if A is a (constant) multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline typename if_nonpoly<Ca, bool>::type
+multiple_p (Ca a, const poly_int_pod<N, Cb> &b)
+{
+ typedef POLY_INT_TYPE (Ca) int_type;
+
+ /* Do the modulus before the constant check, to catch divide by
+ potential zeros. */
+ return a % b.coeffs[0] == 0 && (a == int_type (0) || b.is_constant ());
+}
+
+/* Return true if A is a (polynomial) multiple of B. This handles cases
+ where either B is constant or the multiple is constant. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline bool
+multiple_p (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (b.is_constant ())
+ return multiple_p (a, b.coeffs[0]);
+ POLY_BINARY_COEFF (Ca, Ca) tmp;
+ return constant_multiple_p (a, b, &tmp);
+}
+
+/* Return true if A is a (constant) multiple of B, storing the
+ multiple in *MULTIPLE if so. */
+
+template<typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly2<Ca, Cb, bool>::type
+multiple_p (Ca a, Cb b, Cm *multiple)
+{
+ if (a % b != 0)
+ return false;
+ *multiple = a / b;
+ return true;
+}
+
+/* Return true if A is a (polynomial) multiple of B, storing the
+ multiple in *MULTIPLE if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Cb, bool>::type
+multiple_p (const poly_int_pod<N, Ca> &a, Cb b, poly_int_pod<N, Cm> *multiple)
+{
+ if (!multiple_p (a, b))
+ return false;
+ for (unsigned int i = 0; i < N; ++i)
+ multiple->coeffs[i] = a.coeffs[i] / b;
+ return true;
+}
+
+/* Return true if B is a constant and A is a (constant) multiple of B,
+ storing the multiple in *MULTIPLE if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline typename if_nonpoly<Ca, bool>::type
+multiple_p (Ca a, const poly_int_pod<N, Cb> &b, Cm *multiple)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+
+ /* Do the modulus before the constant check, to catch divide by
+ potential zeros. */
+ if (a % b.coeffs[0] != 0 || (NCa (a) != 0 && !b.is_constant ()))
+ return false;
+ *multiple = a / b.coeffs[0];
+ return true;
+}
+
+/* Return true if A is a (polynomial) multiple of B, storing the
+ multiple in *MULTIPLE if so. This handles cases where either
+ B is constant or the multiple is constant. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cm>
+inline bool
+multiple_p (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
+ poly_int_pod<N, Cm> *multiple)
+{
+ if (b.is_constant ())
+ return multiple_p (a, b.coeffs[0], multiple);
+ return constant_multiple_p (a, b, multiple);
+}
+
+/* Return A / B, given that A is known to be a multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_CONST_RESULT (N, Ca, Cb)
+exact_div (const poly_int_pod<N, Ca> &a, Cb b)
+{
+ typedef POLY_CONST_COEFF (Ca, Cb) C;
+ poly_int<N, C> r;
+ for (unsigned int i = 0; i < N; i++)
+ {
+ gcc_checking_assert (a.coeffs[i] % b == 0);
+ POLY_SET_COEFF (C, r, i, a.coeffs[i] / b);
+ }
+ return r;
+}
+
+/* Return A / B, given that A is known to be a multiple of B. */
+
+template<unsigned int N, typename Ca, typename Cb>
+inline POLY_POLY_RESULT (N, Ca, Cb)
+exact_div (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
+{
+ if (b.is_constant ())
+ return exact_div (a, b.coeffs[0]);
+
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+ typedef POLY_INT_TYPE (Cb) int_type;
+
+ gcc_checking_assert (a.coeffs[0] % b.coeffs[0] == 0);
+ C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+ for (unsigned int i = 1; i < N; ++i)
+ gcc_checking_assert (b.coeffs[i] == int_type (0)
+ ? a.coeffs[i] == int_type (0)
+ : (a.coeffs[i] % b.coeffs[i] == 0
+ && NCa (a.coeffs[i]) / NCb (b.coeffs[i]) == r));
+
+ return r;
+}
+
+/* Return true if there is some constant Q and polynomial r such that:
+
+ (1) a = b * Q + r
+ (2) |b * Q| <= |a|
+ (3) |r| < |b|
+
+ Store the value Q in *QUOTIENT if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly2<Cb, Cq, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b, Cq *quotient)
+{
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+
+ /* Do the division before the constant check, to catch divide by
+ zero errors. */
+ Cq q = NCa (a.coeffs[0]) / NCb (b);
+ if (!a.is_constant ())
+ return false;
+ *quotient = q;
+ return true;
+}
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly<Cq, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cq *quotient)
+{
+ /* We can calculate Q from the case in which the indeterminates
+ are zero. */
+ typedef POLY_CAST (Ca, Cb) NCa;
+ typedef POLY_CAST (Cb, Ca) NCb;
+ typedef POLY_INT_TYPE (Ca) ICa;
+ typedef POLY_INT_TYPE (Cb) ICb;
+ typedef POLY_BINARY_COEFF (Ca, Cb) C;
+ C q = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
+
+ /* Check the other coefficients and record whether the division is exact.
+ The only difficult case is when it isn't. If we require a and b to
+ ordered wrt zero, there can be no two coefficients of the same value
+ that have opposite signs. This means that:
+
+ |a| = |a0| + |a1 * x1| + |a2 * x2| + ...
+ |b| = |b0| + |b1 * x1| + |b2 * x2| + ...
+
+ The Q we've just calculated guarantees:
+
+ |b0 * Q| <= |a0|
+ |a0 - b0 * Q| < |b0|
+
+ and so:
+
+ (2) |b * Q| <= |a|
+
+ is satisfied if:
+
+ |bi * xi * Q| <= |ai * xi|
+
+ for each i in [1, N]. This is trivially true when xi is zero.
+ When it isn't we need:
+
+ (2') |bi * Q| <= |ai|
+
+ r is calculated as:
+
+ r = r0 + r1 * x1 + r2 * x2 + ...
+ where ri = ai - bi * Q
+
+ Restricting to ordered a and b also guarantees that no two ris
+ have opposite signs, so we have:
+
+ |r| = |r0| + |r1 * x1| + |r2 * x2| + ...
+
+ We know from the calculation of Q that |r0| < |b0|, so:
+
+ (3) |r| < |b|
+
+ is satisfied if:
+
+ (3') |ai - bi * Q| <= |bi|
+
+ for each i in [1, N]. */
+ bool rem_p = NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0;
+ for (unsigned int i = 1; i < N; ++i)
+ {
+ if (b.coeffs[i] == ICb (0))
+ {
+ /* For bi == 0 we simply need: (3') |ai| == 0. */
+ if (a.coeffs[i] != ICa (0))
+ return false;
+ }
+ else
+ {
+ if (q == 0)
+ {
+ /* For Q == 0 we simply need: (3') |ai| <= |bi|. */
+ if (a.coeffs[i] != ICa (0))
+ {
+ /* Use negative absolute to avoid overflow, i.e.
+ -|ai| >= -|bi|. */
+ C neg_abs_a = (a.coeffs[i] < 0 ? a.coeffs[i] : -a.coeffs[i]);
+ C neg_abs_b = (b.coeffs[i] < 0 ? b.coeffs[i] : -b.coeffs[i]);
+ if (neg_abs_a < neg_abs_b)
+ return false;
+ rem_p = true;
+ }
+ }
+ else
+ {
+ /* Otherwise just check for the case in which ai / bi == Q. */
+ if (NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != q)
+ return false;
+ if (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0)
+ rem_p = true;
+ }
+ }
+ }
+
+ /* If the division isn't exact, require both values to be ordered wrt 0,
+ so that we can guarantee conditions (2) and (3) for all indeterminate
+ values. */
+ if (rem_p && (!ordered_p (a, ICa (0)) || !ordered_p (b, ICb (0))))
+ return false;
+
+ *quotient = q;
+ return true;
+}
+
+/* Likewise, but also store r in *REMAINDER. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq, typename Cr>
+inline typename if_nonpoly<Cq, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cq *quotient, Cr *remainder)
+{
+ if (!can_div_trunc_p (a, b, quotient))
+ return false;
+ *remainder = a - *quotient * b;
+ return true;
+}
+
+/* Return true if there is some polynomial q and constant R such that:
+
+ (1) a = B * q + R
+ (2) |B * q| <= |a|
+ (3) |R| < |B|
+
+ Store the value q in *QUOTIENT if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly<Cb, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b,
+ poly_int_pod<N, Cq> *quotient)
+{
+ /* The remainder must be constant. */
+ for (unsigned int i = 1; i < N; ++i)
+ if (a.coeffs[i] % b != 0)
+ return false;
+ for (unsigned int i = 0; i < N; ++i)
+ quotient->coeffs[i] = a.coeffs[i] / b;
+ return true;
+}
+
+/* Likewise, but also store R in *REMAINDER. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq, typename Cr>
+inline typename if_nonpoly<Cb, bool>::type
+can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b,
+ poly_int_pod<N, Cq> *quotient, Cr *remainder)
+{
+ if (!can_div_trunc_p (a, b, quotient))
+ return false;
+ *remainder = a.coeffs[0] % b;
+ return true;
+}
+
+/* Return true if there is some constant Q and polynomial r such that:
+
+ (1) a = b * Q + r
+ (2) |a| <= |b * Q|
+ (3) |r| < |b|
+
+ Store the value Q in *QUOTIENT if so. */
+
+template<unsigned int N, typename Ca, typename Cb, typename Cq>
+inline typename if_nonpoly<Cq, bool>::type
+can_div_away_from_zero_p (const poly_int_pod<N, Ca> &a,
+ const poly_int_pod<N, Cb> &b,
+ Cq *quotient)
+{
+ if (!can_div_trunc_p (a, b, quotient))
+ return false;
+ if (maybe_ne (*quotient * b, a))
+ *quotient += (*quotient < 0 ? -1 : 1);
+ return true;
+}
+
+/* Use print_dec to print VALUE to FILE, where SGN is the sign
+ of the values. */
+
+template<unsigned int N, typename C>
+void
+print_dec (const poly_int_pod<N, C> &value, FILE *file, signop sgn)
+{
+ if (value.is_constant ())
+ print_dec (value.coeffs[0], file, sgn);
+ else
+ {
+ fprintf (file, "[");
+ for (unsigned int i = 0; i < N; ++i)
+ {
+ print_dec (value.coeffs[i], file, sgn);
+ fputc (i == N - 1 ? ']' : ',', file);
+ }
+ }
+}
+
+/* Likewise without the signop argument, for coefficients that have an
+ inherent signedness. */
+
+template<unsigned int N, typename C>
+void
+print_dec (const poly_int_pod<N, C> &value, FILE *file)
+{
+ STATIC_ASSERT (poly_coeff_traits<C>::signedness >= 0);
+ print_dec (value, file,
+ poly_coeff_traits<C>::signedness ? SIGNED : UNSIGNED);
+}
+
+/* Helper for correctly comparing Pos - Start with Size in cases where
+ known_ge (Pos, Start), Pos and Start are potentially signed, and Size is
+ potentially unsigned. Applying the cast function to the result of
+ Pos - Start gives the value that should be compared with the size.
+
+ Try to avoid doing any unnecessary arithmetic or copying. */
+template<typename Pos, typename Start, typename Size,
+ typename Diff = POLY_BINARY_COEFF (Start, Pos),
+ typename Res = POLY_BINARY_COEFF (Size, Diff)>
+struct poly_span_traits
+{
+ /* Assume no cast is needed. We'll get a warning about signed vs.
+ unsigned comparisons if the assumption is wrong. */
+ template<typename T>
+ static const T &cast (const T &x) { return x; }
+};
+
+/* The only case a change in type is needed is this one, in which the
+ subtraction would give a HOST_WIDE_INT-based result if done on poly_ints
+ and adding a zero size would give an unsigned HOST_WIDE_INT-based
+ result. Since we know known_ge (Pos, Start), it is safe to treat
+ Pos - Start as an unsigned HOST_WIDE_INT. */
+template<typename T1, typename T2, typename T3>
+struct poly_span_traits<T1, T2, T3, HOST_WIDE_INT, unsigned HOST_WIDE_INT>
+{
+ template<typename T>
+ static typename if_nonpoly<T, unsigned HOST_WIDE_INT>::type
+ cast (const T &x) { return x; }
+
+ template<unsigned int N, typename T>
+ static poly_int<N, unsigned HOST_WIDE_INT>
+ cast (const poly_int_pod<N, T> &x) { return x; }
+};
+
+/* Return true if SIZE represents a known size, assuming that all-ones
+ indicates an unknown size. */
+
+template<typename T>
+inline bool
+known_size_p (const T &a)
+{
+ return maybe_ne (a, POLY_INT_TYPE (T) (-1));
+}
+
+/* Return true if range [POS, POS + SIZE) might include VAL.
+ SIZE can be the special value -1, in which case the range is
+ open-ended. */
+
+template<typename T1, typename T2, typename T3>
+inline bool
+maybe_in_range_p (const T1 &val, const T2 &pos, const T3 &size)
+{
+ typedef poly_span_traits<T1, T2, T3> span;
+ if (known_lt (val, pos))
+ return false;
+ if (!known_size_p (size))
+ return true;
+ if ((poly_int_traits<T1>::num_coeffs > 1
+ || poly_int_traits<T2>::num_coeffs > 1)
+ && maybe_lt (val, pos))
+ /* In this case we don't know whether VAL >= POS is true at compile
+ time, so we can't prove that VAL >= POS + SIZE. */
+ return true;
+ return maybe_lt (span::cast (val - pos), size);
+}
+
+/* Return true if range [POS, POS + SIZE) is known to include VAL.
+ SIZE can be the special value -1, in which case the range is
+ open-ended. */
+
+template<typename T1, typename T2, typename T3>
+inline bool
+known_in_range_p (const T1 &val, const T2 &pos, const T3 &size)
+{
+ typedef poly_span_traits<T1, T2, T3> span;
+ return (known_size_p (size)
+ && known_ge (val, pos)
+ && known_lt (span::cast (val - pos), size));
+}
+
+/* Return true if the two ranges [POS1, POS1 + SIZE1) and [POS2, POS2 + SIZE2)
+ might overlap. SIZE1 and/or SIZE2 can be the special value -1, in which
+ case the range is open-ended. */
+
+template<typename T1, typename T2, typename T3, typename T4>
+inline bool
+ranges_maybe_overlap_p (const T1 &pos1, const T2 &size1,
+ const T3 &pos2, const T4 &size2)
+{
+ if (maybe_in_range_p (pos2, pos1, size1))
+ return maybe_ne (size2, POLY_INT_TYPE (T4) (0));
+ if (maybe_in_range_p (pos1, pos2, size2))
+ return maybe_ne (size1, POLY_INT_TYPE (T2) (0));
+ return false;
+}
+
+/* Return true if the two ranges [POS1, POS1 + SIZE1) and [POS2, POS2 + SIZE2)
+ are known to overlap. SIZE1 and/or SIZE2 can be the special value -1,
+ in which case the range is open-ended. */
+
+template<typename T1, typename T2, typename T3, typename T4>
+inline bool
+ranges_known_overlap_p (const T1 &pos1, const T2 &size1,
+ const T3 &pos2, const T4 &size2)
+{
+ typedef poly_span_traits<T1, T3, T2> span1;
+ typedef poly_span_traits<T1, T3, T4> span2;
+ /* known_gt (POS1 + SIZE1, POS2) [infinite precision]
+ --> known_gt (SIZE1, POS2 - POS1) [infinite precision]
+ --> known_gt (SIZE1, POS2 - lower_bound (POS1, POS2)) [infinite precision]
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ always nonnegative
+ --> known_gt (SIZE1, span1::cast (POS2 - lower_bound (POS1, POS2))).
+
+ Using the saturating subtraction enforces that SIZE1 must be
+ nonzero, since known_gt (0, x) is false for all nonnegative x.
+ If POS2.coeff[I] < POS1.coeff[I] for some I > 0, increasing
+ indeterminate number I makes the unsaturated condition easier to
+ satisfy, so using a saturated coefficient of zero tests the case in
+ which the indeterminate is zero (the minimum value). */
+ return (known_size_p (size1)
+ && known_size_p (size2)
+ && known_lt (span1::cast (pos2 - lower_bound (pos1, pos2)), size1)
+ && known_lt (span2::cast (pos1 - lower_bound (pos1, pos2)), size2));
+}
+
+/* Return true if range [POS1, POS1 + SIZE1) is known to be a subrange of
+ [POS2, POS2 + SIZE2). SIZE1 and/or SIZE2 can be the special value -1,
+ in which case the range is open-ended. */
+
+template<typename T1, typename T2, typename T3, typename T4>
+inline bool
+known_subrange_p (const T1 &pos1, const T2 &size1,
+ const T3 &pos2, const T4 &size2)
+{
+ typedef typename poly_int_traits<T2>::coeff_type C2;
+ typedef POLY_BINARY_COEFF (T2, T4) size_diff_type;
+ typedef poly_span_traits<T1, T3, size_diff_type> span;
+ return (known_gt (size1, POLY_INT_TYPE (T2) (0))
+ && (poly_coeff_traits<C2>::signedness > 0
+ || known_size_p (size1))
+ && known_size_p (size2)
+ && known_ge (pos1, pos2)
+ && known_le (size1, size2)
+ && known_le (span::cast (pos1 - pos2), size2 - size1));
+}
+
+/* Return true if the endpoint of the range [POS, POS + SIZE) can be
+ stored in a T, or if SIZE is the special value -1, which makes the
+ range open-ended. */
+
+template<typename T>
+inline typename if_nonpoly<T, bool>::type
+endpoint_representable_p (const T &pos, const T &size)
+{
+ return (!known_size_p (size)
+ || pos <= poly_coeff_traits<T>::max_value - size);
+}
+
+template<unsigned int N, typename C>
+inline bool
+endpoint_representable_p (const poly_int_pod<N, C> &pos,
+ const poly_int_pod<N, C> &size)
+{
+ if (known_size_p (size))
+ for (unsigned int i = 0; i < N; ++i)
+ if (pos.coeffs[i] > poly_coeff_traits<C>::max_value - size.coeffs[i])
+ return false;
+ return true;
+}
+
+template<unsigned int N, typename C>
+void
+gt_ggc_mx (poly_int_pod<N, C> *)
+{
+}
+
+template<unsigned int N, typename C>
+void
+gt_pch_nx (poly_int_pod<N, C> *)
+{
+}
+
+template<unsigned int N, typename C>
+void
+gt_pch_nx (poly_int_pod<N, C> *, void (*) (void *, void *), void *)
+{
+}
+
+#undef POLY_SET_COEFF
+#undef POLY_INT_TYPE
+#undef POLY_BINARY_COEFF
+#undef CONST_CONST_RESULT
+#undef POLY_CONST_RESULT
+#undef CONST_POLY_RESULT
+#undef POLY_POLY_RESULT
+#undef POLY_CONST_COEFF
+#undef CONST_POLY_COEFF
+#undef POLY_POLY_COEFF
+
+#endif
--- /dev/null
+/* This file contains templated tests that are then instantiated in
+ multiple plugin tests, in order to reduce the size of each test. */
+
+#define ASSERT_FALSE(X) gcc_assert (!(X))
+#define ASSERT_TRUE(X) gcc_assert (X)
+#define ASSERT_EQ(X, Y) gcc_assert ((X) == (Y))
+#define ASSERT_KNOWN_EQ(X, Y) gcc_assert (known_eq (X, Y))
+#define ASSERT_MAYBE_NE(X, Y) gcc_assert (maybe_ne (X, Y))
+
+/* make (X) converts an X of type int into T, using an arbitrary
+ precision for wide_int. It passes other types of X through as-is. */
+template<typename T>
+struct coeff_helper
+{
+ static inline const T &make (const T &x) { return x; }
+};
+
+template<>
+struct coeff_helper<wide_int>
+{
+ template<typename T>
+ static inline const T &make (const T &x) { return x; }
+ static inline wide_int make (int i) { return wi::shwi (i, 77); }
+};
+
+/* make (C1, C2, C3) constructs a T using coefficients from C1, C2 and C3,
+ picking only enough to fill the T. */
+template<typename T>
+struct poly_helper
+{
+ typedef typename poly_int_traits<T>::coeff_type C;
+ template<typename T1, typename T2, typename T3>
+ static T make (const T1 &a, const T2 &b, const T3 &c);
+};
+
+template<typename T>
+template<typename T1, typename T2, typename T3>
+inline T
+poly_helper<T>::make (const T1 &a, const T2 &b, const T3 &c)
+{
+ T res;
+ res = coeff_helper<C>::make (a);
+ if (poly_int_traits<T>::num_coeffs >= 2)
+ res.coeffs[1] = coeff_helper<C>::make (b);
+ if (poly_int_traits<T>::num_coeffs >= 3)
+ res.coeffs[2] = coeff_helper<C>::make (c);
+ return res;
+}
+
+/* Test the helper, */
+
+static void
+test_helper ()
+{
+ typedef poly_helper< poly_int<1, int> > p1;
+ typedef poly_helper< poly_int<2, int> > p2;
+ typedef poly_helper< poly_int<3, int> > p3;
+
+ ASSERT_MAYBE_NE (p1::make (1, 2, 3), 0);
+ ASSERT_KNOWN_EQ (p1::make (1, 2, 3) - p1::make (1, 0, 0), 0);
+ ASSERT_KNOWN_EQ (p1::make (1, 2, 3) - p1::make (1, 2, 0), 0);
+ ASSERT_KNOWN_EQ (p1::make (1, 2, 3) - p1::make (1, 2, 3), 0);
+
+ ASSERT_MAYBE_NE (p2::make (1, 2, 3), 0);
+ ASSERT_MAYBE_NE (p2::make (1, 2, 3) - p2::make (1, 0, 0), 0);
+ ASSERT_KNOWN_EQ (p2::make (1, 2, 3) - p2::make (1, 2, 0), 0);
+ ASSERT_KNOWN_EQ (p2::make (1, 2, 3) - p2::make (1, 2, 3), 0);
+
+ ASSERT_MAYBE_NE (p3::make (1, 2, 3), 0);
+ ASSERT_MAYBE_NE (p3::make (1, 2, 3) - p3::make (1, 0, 0), 0);
+ ASSERT_MAYBE_NE (p3::make (1, 2, 3) - p3::make (1, 2, 0), 0);
+ ASSERT_KNOWN_EQ (p3::make (1, 2, 3) - p3::make (1, 2, 3), 0);
+}
+
+/* Test poly_coeff_traits. */
+
+static void
+test_poly_coeff_traits ()
+{
+ ASSERT_EQ (poly_coeff_traits<unsigned short>::signedness, 0);
+ ASSERT_EQ (poly_coeff_traits<unsigned short>::max_value, 0xffff);
+
+ ASSERT_EQ (poly_coeff_traits<int>::signedness, 1);
+ ASSERT_EQ (poly_coeff_traits<int>::max_value, INT_MAX);
+
+ ASSERT_EQ (poly_coeff_traits<unsigned int>::signedness, 0);
+ ASSERT_EQ (poly_coeff_traits<unsigned int>::max_value, UINT_MAX);
+
+ ASSERT_EQ (poly_coeff_traits<HOST_WIDE_INT>::signedness, 1);
+ ASSERT_EQ (poly_coeff_traits<HOST_WIDE_INT>::max_value, HOST_WIDE_INT_MAX);
+
+ ASSERT_EQ (poly_coeff_traits<unsigned HOST_WIDE_INT>::signedness, 0);
+ ASSERT_EQ (poly_coeff_traits<unsigned HOST_WIDE_INT>::max_value,
+ HOST_WIDE_INT_M1U);
+
+ ASSERT_EQ (poly_coeff_traits<wide_int>::signedness, -1);
+ ASSERT_EQ (poly_coeff_traits<offset_int>::signedness, 1);
+ ASSERT_EQ (poly_coeff_traits<widest_int>::signedness, 1);
+}
+
+/* Test poly_int_traits. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_poly_int_traits ()
+{
+ /* Check the properties of poly_int_traits<C>. */
+ ASSERT_FALSE (poly_int_traits<C>::is_poly);
+ ASSERT_EQ (poly_int_traits<C>::num_coeffs, 1);
+ ASSERT_EQ ((C *) 0 - (typename poly_int_traits<C>::coeff_type *) 0, 0);
+
+ /* Check the properties of poly_int_traits<T>. */
+ ASSERT_TRUE (poly_int_traits<T>::is_poly);
+ ASSERT_EQ (poly_int_traits<T>::num_coeffs, N);
+ ASSERT_EQ ((C *) 0 - (typename poly_int_traits<T>::coeff_type *) 0, 0);
+}
+
+/* Test the handling of constants. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_constants ()
+{
+ typedef coeff_helper<C> ch;
+ T zero, one, two;
+ poly_int<N, unsigned char> two_uc = 2;
+
+ /* Test operator = on C. */
+ zero = ch::make (0);
+ one = ch::make (1);
+ two = ch::make (2);
+
+ /* Basic tests of known_eq and maybe_ne. */
+ ASSERT_KNOWN_EQ (zero, ch::make (0));
+ ASSERT_MAYBE_NE (one, ch::make (0));
+ ASSERT_MAYBE_NE (two, ch::make (0));
+ ASSERT_KNOWN_EQ (ch::make (0), zero);
+ ASSERT_MAYBE_NE (ch::make (0), one);
+ ASSERT_MAYBE_NE (ch::make (0), two);
+ ASSERT_KNOWN_EQ (zero, zero);
+ ASSERT_MAYBE_NE (one, zero);
+ ASSERT_MAYBE_NE (two, zero);
+
+ ASSERT_MAYBE_NE (zero, ch::make (1));
+ ASSERT_KNOWN_EQ (one, ch::make (1));
+ ASSERT_MAYBE_NE (two, ch::make (1));
+ ASSERT_MAYBE_NE (ch::make (1), zero);
+ ASSERT_KNOWN_EQ (ch::make (1), one);
+ ASSERT_MAYBE_NE (ch::make (1), two);
+ ASSERT_MAYBE_NE (zero, one);
+ ASSERT_KNOWN_EQ (one, one);
+ ASSERT_MAYBE_NE (two, one);
+
+ ASSERT_MAYBE_NE (zero, ch::make (2));
+ ASSERT_MAYBE_NE (one, ch::make (2));
+ ASSERT_KNOWN_EQ (two, ch::make (2));
+ ASSERT_MAYBE_NE (ch::make (2), zero);
+ ASSERT_MAYBE_NE (ch::make (2), one);
+ ASSERT_KNOWN_EQ (ch::make (2), two);
+ ASSERT_MAYBE_NE (zero, two);
+ ASSERT_MAYBE_NE (one, two);
+ ASSERT_KNOWN_EQ (two, two);
+
+ ASSERT_MAYBE_NE (zero, two_uc);
+ ASSERT_MAYBE_NE (one, two_uc);
+ ASSERT_KNOWN_EQ (two, two_uc);
+ ASSERT_MAYBE_NE (two_uc, zero);
+ ASSERT_MAYBE_NE (two_uc, one);
+ ASSERT_KNOWN_EQ (two_uc, two);
+}
+
+/* Test operator +=. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_plus_equals ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test += on int. */
+ T add_cm = ph::make (17, 11, 9);
+ add_cm += 14;
+ ASSERT_KNOWN_EQ (add_cm, ph::make (31, 11, 9));
+
+ /* Test += on T. */
+ T add_pm = ph::make (100, 44, 11);
+ add_pm += ph::make (1, 2, 3);
+ ASSERT_KNOWN_EQ (add_pm, ph::make (101, 46, 14));
+}
+
+/* Test operator -=. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_minus_equals ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test -= on int. */
+ T sub_cm = ph::make (82, 13, 61);
+ sub_cm -= 76;
+ ASSERT_KNOWN_EQ (sub_cm, ph::make (6, 13, 61));
+
+ /* Test -= on T. */
+ T sub_pm = ph::make (82, 13, 61);
+ sub_pm -= ph::make (19, 12, 14);
+ ASSERT_KNOWN_EQ (sub_pm, ph::make (63, 1, 47));
+}
+
+/* Test operator *=. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_times_equals ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test *= on int. */
+ T mul_cm = ph::make (11, 22, 33);
+ mul_cm *= 3;
+ ASSERT_KNOWN_EQ (mul_cm, ph::make (33, 66, 99));
+}
+
+/* Test operator <<=. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_shl_equals ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test <<= on int. */
+ T shl_cm = ph::make (10, 11, 13);
+ shl_cm <<= 2;
+ ASSERT_KNOWN_EQ (shl_cm, ph::make (40, 44, 52));
+}
+
+/* Test is_constant. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_is_constant ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test is_constant without arguments. */
+ ASSERT_TRUE (ph::make (1, 0, 0).is_constant ());
+ ASSERT_EQ (ph::make (2, 0, 1).is_constant (), N <= 2);
+ ASSERT_EQ (ph::make (3, 1, 0).is_constant (), N == 1);
+
+ /* Test is_constant with an argument. */
+ C const_value;
+ ASSERT_TRUE (ph::make (1, 0, 0).is_constant (&const_value));
+ ASSERT_EQ (const_value, 1);
+ ASSERT_EQ (ph::make (2, 0, 1).is_constant (&const_value), N <= 2);
+ ASSERT_EQ (const_value, N <= 2 ? 2 : 1);
+ ASSERT_EQ (ph::make (3, 1, 0).is_constant (&const_value), N == 1);
+ ASSERT_EQ (const_value, 4 - N);
+}
+
+/* Test to_constant. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_to_constant ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_TRUE (ph::make (1, 0, 0).to_constant () == 1);
+ ASSERT_TRUE (ph::make (111, 0, 0).to_constant () == 111);
+}
+
+/* Test addition, both via operators and wi::. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_addition ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test +. */
+ ASSERT_KNOWN_EQ (ph::make (55, 43, 30) + 1,
+ ph::make (56, 43, 30));
+ ASSERT_KNOWN_EQ (100 + ph::make (5, 15, 26),
+ ph::make (105, 15, 26));
+ ASSERT_KNOWN_EQ (ph::make (7, 100, 41) + ph::make (96, 9, 21),
+ ph::make (103, 109, 62));
+
+ /* Test wi::add. */
+ ASSERT_KNOWN_EQ (wi::add (ph::make (55, 43, 30), 1),
+ ph::make (56, 43, 30));
+ ASSERT_KNOWN_EQ (wi::add (100, ph::make (5, 15, 26)),
+ ph::make (105, 15, 26));
+ ASSERT_KNOWN_EQ (wi::add (ph::make (7, 100, 41), ph::make (96, 9, 21)),
+ ph::make (103, 109, 62));
+}
+
+/* Test subtraction, both via operators and wi::. */
+
+template<unsigned int N, typename C, typename RC, typename T>
+static void
+test_subtraction ()
+{
+ typedef poly_helper<T> ph;
+ typedef poly_helper< poly_int<N, RC> > rph;
+ typedef poly_helper< poly_int<N, int> > iph;
+
+ /* Test -. Cs with a rank lower than HOST_WIDE_INT promote to
+ HOST_WIDE_INT; use rph to capture this. */
+ ASSERT_KNOWN_EQ (ph::make (64, 49, 36) - 42,
+ rph::make (22, 49, 36));
+ ASSERT_KNOWN_EQ (11 - ph::make (9, 3, 4),
+ rph::make (2, -3, -4));
+ ASSERT_KNOWN_EQ (ph::make (100, 200, 300) - ph::make (99, 197, 305),
+ rph::make (1, 3, -5));
+
+ /* Test wi::sub. Primitive Cs promote to widest_int; use iph to capture
+ this. */
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (64, 49, 36), 42),
+ iph::make (22, 49, 36));
+ ASSERT_KNOWN_EQ (wi::sub (11, ph::make (9, 3, 4)),
+ iph::make (2, -3, -4));
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (100, 200, 300), ph::make (99, 197, 305)),
+ iph::make (1, 3, -5));
+}
+
+/* Test negation, both via operators and wi::. */
+
+template<unsigned int N, typename C, typename RC, typename T>
+static void
+test_negation ()
+{
+ typedef poly_helper<T> ph;
+ typedef poly_helper< poly_int<N, RC> > rph;
+ typedef poly_helper< poly_int<N, int> > iph;
+
+ /* Test unary -. */
+ ASSERT_KNOWN_EQ (-ph::make (10, 20, 30),
+ rph::make (-10, -20, -30));
+
+ /* Test wi::neg. */
+ ASSERT_KNOWN_EQ (wi::neg (ph::make (10, 20, 30)),
+ iph::make (-10, -20, -30));
+}
+
+/* Test multiplication, both via operators and wi::. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_multiplication ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test *. */
+ ASSERT_KNOWN_EQ (ph::make (5, 20, 25) * 10,
+ ph::make (50, 200, 250));
+ ASSERT_KNOWN_EQ (111 * ph::make (7, 6, 5),
+ ph::make (777, 666, 555));
+
+ /* Test wi::mul. */
+ ASSERT_KNOWN_EQ (wi::mul (ph::make (5, 20, 25), 10),
+ ph::make (50, 200, 250));
+ ASSERT_KNOWN_EQ (wi::mul (111, ph::make (7, 6, 5)),
+ ph::make (777, 666, 555));
+}
+
+/* Test shift left, both via operators and wi::. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_shift_left ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test <<. */
+ ASSERT_KNOWN_EQ (ph::make (1, 20, 300) << 4,
+ ph::make (16, 320, 4800));
+
+ /* Test wi::lshift. */
+ ASSERT_KNOWN_EQ (wi::lshift (ph::make (9, 15, 50), 3),
+ ph::make (72, 120, 400));
+}
+
+/* Test maybe_ne. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_maybe_ne ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_ne (T, C). */
+ ASSERT_EQ (maybe_ne (ph::make (1, 0, 2), ch::make (1)), N == 3);
+ ASSERT_EQ (maybe_ne (ph::make (-11, -2, 0), ch::make (-11)), N >= 2);
+ ASSERT_TRUE (maybe_ne (ph::make (199, 0, 0), ch::make (200)));
+
+ /* Test maybe_ne (C, T). */
+ ASSERT_EQ (maybe_ne (ch::make (-22), ph::make (-22, 0, -1)), N == 3);
+ ASSERT_EQ (maybe_ne (ch::make (5), ph::make (5, 4, 0)), N >= 2);
+ ASSERT_TRUE (maybe_ne (ch::make (-3), ph::make (-4, 0, 0)));
+
+ /* Test maybe_ne (T, T). */
+ ASSERT_EQ (maybe_ne (ph::make (1, 3, 5),
+ ph::make (1, 3, 6)), N == 3);
+ ASSERT_EQ (maybe_ne (ph::make (1, 3, 5),
+ ph::make (1, 4, 5)), N >= 2);
+ ASSERT_TRUE (maybe_ne (ph::make (1, 3, 5),
+ ph::make (0, 3, 5)));
+}
+
+/* Test known_eq. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_eq ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_eq (T, C). */
+ ASSERT_EQ (known_eq (ph::make (1, 0, 2), ch::make (1)), N <= 2);
+ ASSERT_EQ (known_eq (ph::make (-11, -2, 0), ch::make (-11)), N == 1);
+ ASSERT_FALSE (known_eq (ph::make (199, 0, 0), ch::make (200)));
+
+ /* Test known_eq (C, T). */
+ ASSERT_EQ (known_eq (ch::make (-22), ph::make (-22, 0, -1)), N <= 2);
+ ASSERT_EQ (known_eq (ch::make (5), ph::make (5, 4, 0)), N == 1);
+ ASSERT_FALSE (known_eq (ch::make (-3), ph::make (-4, 0, 0)));
+
+ /* Test known_eq (T, T). */
+ ASSERT_EQ (known_eq (ph::make (1, 3, 5),
+ ph::make (1, 3, 6)), N <= 2);
+ ASSERT_EQ (known_eq (ph::make (1, 3, 5),
+ ph::make (1, 4, 5)), N == 1);
+ ASSERT_FALSE (known_eq (ph::make (1, 3, 5),
+ ph::make (0, 3, 5)));
+}
+
+/* Test can_align_p. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_can_align_p ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_TRUE (can_align_p (ph::make (41, 32, 16), 16));
+ ASSERT_EQ (can_align_p (ph::make (15, 64, 8), 16), N <= 2);
+ ASSERT_EQ (can_align_p (ph::make (17, 8, 80), 16), N == 1);
+ ASSERT_TRUE (can_align_p (ph::make (-39, -64, -32), 32));
+ ASSERT_EQ (can_align_p (ph::make (-32, -96, -31), 32), N <= 2);
+ ASSERT_EQ (can_align_p (ph::make (-31, -31, -128), 32), N == 1);
+ ASSERT_TRUE (can_align_p (ph::make (17, 0, 0), 16));
+ ASSERT_TRUE (can_align_p (ph::make (16, 0, 0), 16));
+ ASSERT_TRUE (can_align_p (ph::make (15, 0, 0), 16));
+ ASSERT_TRUE (can_align_p (ph::make (-17, 0, 0), 16));
+ ASSERT_TRUE (can_align_p (ph::make (-16, 0, 0), 16));
+ ASSERT_TRUE (can_align_p (ph::make (-15, 0, 0), 16));
+}
+
+/* Test can_align_up. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_can_align_up ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ T aligned;
+ ASSERT_TRUE (can_align_up (ph::make (41, 32, 16), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ph::make (48, 32, 16));
+ ASSERT_EQ (can_align_up (ph::make (15, 64, 8), 16, &aligned), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (aligned, ph::make (16, 64, 0));
+ ASSERT_EQ (can_align_up (ph::make (17, 8, 80), 16, &aligned), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (aligned, ch::make (32));
+ ASSERT_TRUE (can_align_up (ph::make (-39, -64, -32), 32, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ph::make (-32, -64, -32));
+ ASSERT_EQ (can_align_up (ph::make (-32, -96, -31), 32, &aligned), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (aligned, ph::make (-32, -96, 0));
+ ASSERT_EQ (can_align_up (ph::make (-31, -31, -128), 32, &aligned), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (aligned, ch::make (0));
+ ASSERT_TRUE (can_align_up (ph::make (17, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (32));
+ ASSERT_TRUE (can_align_up (ph::make (16, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (16));
+ ASSERT_TRUE (can_align_up (ph::make (15, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (16));
+ ASSERT_TRUE (can_align_up (ph::make (-17, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (-16));
+ ASSERT_TRUE (can_align_up (ph::make (-16, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (-16));
+ ASSERT_TRUE (can_align_up (ph::make (-15, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (0));
+}
+
+/* Test can_align_down. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_can_align_down ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ T aligned;
+ ASSERT_TRUE (can_align_down (ph::make (41, 32, 16), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ph::make (32, 32, 16));
+ ASSERT_EQ (can_align_down (ph::make (15, 64, 8), 16, &aligned), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (aligned, ph::make (0, 64, 0));
+ ASSERT_EQ (can_align_down (ph::make (17, 8, 80), 16, &aligned), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (aligned, ch::make (16));
+ ASSERT_TRUE (can_align_down (ph::make (-39, -64, -32), 32, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ph::make (-64, -64, -32));
+ ASSERT_EQ (can_align_down (ph::make (-32, -96, -31), 32, &aligned), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (aligned, ph::make (-32, -96, 0));
+ ASSERT_EQ (can_align_down (ph::make (-31, -31, -128), 32, &aligned), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (aligned, ch::make (-32));
+ ASSERT_TRUE (can_align_down (ph::make (17, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (16));
+ ASSERT_TRUE (can_align_down (ph::make (16, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (16));
+ ASSERT_TRUE (can_align_down (ph::make (15, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (0));
+ ASSERT_TRUE (can_align_down (ph::make (-17, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (-32));
+ ASSERT_TRUE (can_align_down (ph::make (-16, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (-16));
+ ASSERT_TRUE (can_align_down (ph::make (-15, 0, 0), 16, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ch::make (-16));
+}
+
+/* Test known_equal_after_align_up. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_equal_after_align_up ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (known_equal_after_align_up (ph::make (15, 15, 32),
+ ph::make (16, 15, 32), 16), N == 1);
+ ASSERT_EQ (known_equal_after_align_up (ph::make (16, 16, 15),
+ ph::make (15, 16, 15), 16), N <= 2);
+ ASSERT_EQ (known_equal_after_align_up (ph::make (15, 16, 32),
+ ph::make (7, 16, 48), 16), N <= 2);
+ ASSERT_EQ (known_equal_after_align_up (ph::make (7, 32, 16),
+ ph::make (15, 48, 16), 16), N == 1);
+ ASSERT_TRUE (known_equal_after_align_up (ph::make (16, 16, 32),
+ ph::make (15, 16, 32), 16));
+ ASSERT_TRUE (known_equal_after_align_up (ph::make (32, 0, 0),
+ ph::make (31, 0, 0), 16));
+ ASSERT_TRUE (known_equal_after_align_up (ph::make (32, 0, 0),
+ ph::make (32, 0, 0), 32));
+ ASSERT_FALSE (known_equal_after_align_up (ph::make (32, 0, 0),
+ ph::make (33, 0, 0), 16));
+ ASSERT_FALSE (known_equal_after_align_up (ph::make (-31, 0, 0),
+ ph::make (-32, 0, 0), 16));
+ ASSERT_TRUE (known_equal_after_align_up (ph::make (-32, 0, 0),
+ ph::make (-32, 0, 0), 32));
+ ASSERT_TRUE (known_equal_after_align_up (ph::make (-33, 0, 0),
+ ph::make (-32, 0, 0), 16));
+}
+
+/* Test known_equal_after_align_down. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_equal_after_align_down ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (known_equal_after_align_down (ph::make (17, 15, 32),
+ ph::make (16, 15, 32), 16), N == 1);
+ ASSERT_EQ (known_equal_after_align_down (ph::make (16, 16, 15),
+ ph::make (17, 16, 15), 16), N <= 2);
+ ASSERT_EQ (known_equal_after_align_down (ph::make (15, 16, 32),
+ ph::make (7, 16, 48), 16), N <= 2);
+ ASSERT_EQ (known_equal_after_align_down (ph::make (15, 32, 16),
+ ph::make (7, 48, 16), 16), N == 1);
+ ASSERT_TRUE (known_equal_after_align_down (ph::make (16, 16, 32),
+ ph::make (17, 16, 32), 16));
+ ASSERT_FALSE (known_equal_after_align_down (ph::make (32, 0, 0),
+ ph::make (31, 0, 0), 16));
+ ASSERT_TRUE (known_equal_after_align_down (ph::make (32, 0, 0),
+ ph::make (32, 0, 0), 32));
+ ASSERT_TRUE (known_equal_after_align_down (ph::make (32, 0, 0),
+ ph::make (33, 0, 0), 16));
+ ASSERT_TRUE (known_equal_after_align_down (ph::make (-31, 0, 0),
+ ph::make (-32, 0, 0), 16));
+ ASSERT_TRUE (known_equal_after_align_down (ph::make (-32, 0, 0),
+ ph::make (-32, 0, 0), 32));
+ ASSERT_FALSE (known_equal_after_align_down (ph::make (-33, 0, 0),
+ ph::make (-32, 0, 0), 16));
+}
+
+/* Test force_align_up. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_force_align_up ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test force_align_up. */
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (41, 32, 16), 16),
+ ph::make (48, 32, 16));
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (-39, -64, -32), 32),
+ ph::make (-32, -64, -32));
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (17, 0, 0), 16),
+ ch::make (32));
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (16, 0, 0), 16),
+ ch::make (16));
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (15, 0, 0), 16),
+ ch::make (16));
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (-17, 0, 0), 16),
+ ch::make (-16));
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (-16, 0, 0), 16),
+ ch::make (-16));
+ ASSERT_KNOWN_EQ (force_align_up (ph::make (-15, 0, 0), 16),
+ ch::make (0));
+}
+
+/* Test force_align_down. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_force_align_down ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (41, 32, 16), 16),
+ ph::make (32, 32, 16));
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (-39, -64, -32), 32),
+ ph::make (-64, -64, -32));
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (17, 0, 0), 16),
+ ch::make (16));
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (16, 0, 0), 16),
+ ch::make (16));
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (15, 0, 0), 16),
+ ch::make (0));
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (-17, 0, 0), 16),
+ ch::make (-32));
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (-16, 0, 0), 16),
+ ch::make (-16));
+ ASSERT_KNOWN_EQ (force_align_down (ph::make (-15, 0, 0), 16),
+ ch::make (-16));
+}
+
+/* Test aligned_lower_bound. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_aligned_lower_bound ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_KNOWN_EQ (aligned_lower_bound (ph::make (17, 63, 33), 16),
+ ph::make (16, 48, 32));
+ ASSERT_KNOWN_EQ (aligned_lower_bound (ph::make (11, -33, 64), 32),
+ ph::make (0, -64, 64));
+ ASSERT_KNOWN_EQ (aligned_lower_bound (ph::make (-9, 16, -31), 8),
+ ph::make (-16, 16, -32));
+ ASSERT_KNOWN_EQ (aligned_lower_bound (ph::make (-8, -12, 16), 4),
+ ph::make (-8, -12, 16));
+}
+
+/* Test aligned_upper_bound. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_aligned_upper_bound ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_KNOWN_EQ (aligned_upper_bound (ph::make (17, 63, 33), 16),
+ ph::make (32, 64, 48));
+ ASSERT_KNOWN_EQ (aligned_upper_bound (ph::make (11, -33, 64), 32),
+ ph::make (32, -32, 64));
+ ASSERT_KNOWN_EQ (aligned_upper_bound (ph::make (-9, 16, -31), 8),
+ ph::make (-8, 16, -24));
+ ASSERT_KNOWN_EQ (aligned_upper_bound (ph::make (-8, -12, 16), 4),
+ ph::make (-8, -12, 16));
+}
+
+/* Test known_misalignment. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_misalignment ()
+{
+ typedef poly_helper<T> ph;
+
+ C misalignment;
+ ASSERT_TRUE (known_misalignment (ph::make (45, 8, 24), 8, &misalignment));
+ ASSERT_EQ (misalignment, 5);
+ ASSERT_EQ (known_misalignment (ph::make (17, 16, 23), 8, &misalignment),
+ N <= 2);
+ ASSERT_EQ (misalignment, N <= 2 ? 1 : 5);
+ ASSERT_EQ (known_misalignment (ph::make (31, 15, 0), 16, &misalignment),
+ N == 1);
+ ASSERT_EQ (misalignment, N == 1 ? 15 : N == 2 ? 1 : 5);
+ ASSERT_TRUE (known_misalignment (ph::make (-45, -8, -24), 8, &misalignment));
+ ASSERT_EQ (misalignment, 3);
+ ASSERT_TRUE (known_misalignment (ph::make (-11, 0, 0), 32, &misalignment));
+ ASSERT_EQ (misalignment, 21);
+}
+
+/* Test force_get_misalignment. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_force_get_misalignment ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (force_get_misalignment (ph::make (45, 8, 24), 8), 5);
+ ASSERT_EQ (force_get_misalignment (ph::make (17, 16, 24), 8), 1);
+ ASSERT_EQ (force_get_misalignment (ph::make (31, -16, 0), 16), 15);
+ ASSERT_EQ (force_get_misalignment (ph::make (-45, -8, -24), 8), 3);
+ ASSERT_EQ (force_get_misalignment (ph::make (-11, 0, 0), 32), 21);
+}
+
+/* Test known_alignment. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_alignment ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (known_alignment (ph::make (16, 24, 30)),
+ N == 1 ? 16 : N == 2 ? 8 : 2);
+ ASSERT_EQ (known_alignment (ph::make (30, 0, 31)),
+ N <= 2 ? 2 : 1);
+ ASSERT_EQ (known_alignment (ph::make (20, 16, 24)), 4);
+ ASSERT_EQ (known_alignment (ph::make (24, 0, 0)), 8);
+ ASSERT_EQ (known_alignment (ph::make (0, 0, 0)), 0);
+ ASSERT_EQ (known_alignment (ph::make (0, 12, 0)),
+ N == 1 ? 0 : 4);
+ ASSERT_EQ (known_alignment (ph::make (0, 12, 6)),
+ N == 1 ? 0 : N == 2 ? 4 : 2);
+ ASSERT_EQ (known_alignment (ph::make (-40, -80, -12)),
+ N <= 2 ? 8 : 4);
+}
+
+/* Test can_ior_p. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_can_ior_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ T ior;
+ ASSERT_TRUE (can_ior_p (ph::make (0x87, 0x60, 0xa0), 0x13, &ior));
+ ASSERT_KNOWN_EQ (ior, ph::make (0x97, 0x60, 0xa0));
+ ASSERT_EQ (can_ior_p (ph::make (9, 96, 48), 28, &ior), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (ior, ph::make (29, 96, 0));
+ ASSERT_EQ (can_ior_p (ph::make (0x81, 0x20, 0), 0x44, &ior), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (ior, ch::make (0xc5));
+}
+
+/* Test maybe_eq for poly_int<2, C>. */
+
+template<typename C>
+static void
+test_maybe_eq_2 ()
+{
+ typedef poly_int<2, C> T;
+
+ /* Test maybe_eq (T, C). */
+ ASSERT_TRUE (maybe_eq (T (1, 4), 41));
+ ASSERT_FALSE (maybe_eq (T (1, 4), 42));
+ ASSERT_FALSE (maybe_eq (T (1, 4), 40));
+ ASSERT_TRUE (maybe_eq (T (1, 4), 1));
+ ASSERT_FALSE (maybe_eq (T (1, 4), 0));
+ ASSERT_FALSE (maybe_eq (T (1, 4), 2));
+
+ /* Test maybe_eq (C, T). */
+ ASSERT_TRUE (maybe_eq (20, T (5, 3)));
+ ASSERT_FALSE (maybe_eq (21, T (5, 3)));
+ ASSERT_FALSE (maybe_eq (19, T (5, 3)));
+ ASSERT_TRUE (maybe_eq (5, T (5, 3)));
+ ASSERT_FALSE (maybe_eq (2, T (5, 3)));
+ ASSERT_FALSE (maybe_eq (6, T (5, 3)));
+
+ /* Test maybe_eq (T, T). */
+ ASSERT_TRUE (maybe_eq (T (2, 5), T (22, 3)));
+ ASSERT_FALSE (maybe_eq (T (3, 5), T (22, 3)));
+ ASSERT_FALSE (maybe_eq (T (2, 5), T (23, 3)));
+ ASSERT_FALSE (maybe_eq (T (2, 5), T (3, 5)));
+ ASSERT_TRUE (maybe_eq (T (10, 3), T (19, 0)));
+ ASSERT_FALSE (maybe_eq (T (10, 3), T (20, 0)));
+ ASSERT_TRUE (maybe_eq (T (10, 0), T (4, 2)));
+ ASSERT_FALSE (maybe_eq (T (11, 0), T (4, 2)));
+}
+
+/* Test known_ne for poly_int<2, C>. */
+
+template<typename C>
+static void
+test_known_ne_2 ()
+{
+ typedef poly_int<2, C> T;
+
+ /* Test known_ne (T, C). */
+ ASSERT_FALSE (known_ne (T (1, 4), 41));
+ ASSERT_TRUE (known_ne (T (1, 4), 42));
+ ASSERT_TRUE (known_ne (T (1, 4), 40));
+ ASSERT_FALSE (known_ne (T (1, 4), 1));
+ ASSERT_TRUE (known_ne (T (1, 4), 0));
+ ASSERT_TRUE (known_ne (T (1, 4), 2));
+
+ /* Test known_ne (C, T). */
+ ASSERT_FALSE (known_ne (20, T (5, 3)));
+ ASSERT_TRUE (known_ne (21, T (5, 3)));
+ ASSERT_TRUE (known_ne (19, T (5, 3)));
+ ASSERT_FALSE (known_ne (5, T (5, 3)));
+ ASSERT_TRUE (known_ne (2, T (5, 3)));
+ ASSERT_TRUE (known_ne (6, T (5, 3)));
+
+ /* Test known_ne (T, T). */
+ ASSERT_FALSE (known_ne (T (2, 5), T (22, 3)));
+ ASSERT_TRUE (known_ne (T (3, 5), T (22, 3)));
+ ASSERT_TRUE (known_ne (T (2, 5), T (23, 3)));
+ ASSERT_TRUE (known_ne (T (2, 5), T (3, 5)));
+ ASSERT_FALSE (known_ne (T (10, 3), T (19, 0)));
+ ASSERT_TRUE (known_ne (T (10, 3), T (20, 0)));
+ ASSERT_FALSE (known_ne (T (10, 0), T (4, 2)));
+ ASSERT_TRUE (known_ne (T (11, 0), T (4, 2)));
+}
+
+/* Test maybe_le for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_maybe_le ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_le (T, C). */
+ ASSERT_FALSE (maybe_le (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_FALSE (maybe_le (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_TRUE (maybe_le (ph::make (60, 1, 2), ch::make (60)));
+ ASSERT_TRUE (maybe_le (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_TRUE (maybe_le (ph::make (30, 9, 4), ch::make (31)));
+ ASSERT_TRUE (maybe_le (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test maybe_le (C, T). */
+ ASSERT_TRUE (maybe_le (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_TRUE (maybe_le (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_TRUE (maybe_le (ch::make (60), ph::make (60, 1, 2)));
+ ASSERT_TRUE (maybe_le (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_EQ (maybe_le (ch::make (31), ph::make (30, 9, 4)), N >= 2);
+ ASSERT_EQ (maybe_le (ch::make (31), ph::make (30, 0, 4)), N == 3);
+ ASSERT_FALSE (maybe_le (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test maybe_le (T, T). */
+ ASSERT_EQ (maybe_le (ph::make (3, 14, 99), ph::make (2, 15, 100)), N >= 2);
+ ASSERT_EQ (maybe_le (ph::make (3, 14, 99), ph::make (2, 13, 100)), N == 3);
+ ASSERT_EQ (maybe_le (ph::make (3, 14, 99), ph::make (2, 15, 98)), N >= 2);
+ ASSERT_FALSE (maybe_le (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (maybe_le (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (maybe_le (ph::make (2, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (maybe_le (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (maybe_le (ph::make (2, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (maybe_le (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (maybe_le (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (maybe_le (ph::make (1, 14, 99), ph::make (2, 13, 98)));
+}
+
+/* Test maybe_lt for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_maybe_lt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_lt (T, C). */
+ ASSERT_FALSE (maybe_lt (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_FALSE (maybe_lt (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_FALSE (maybe_lt (ph::make (60, 1, 2), ch::make (60)));
+ ASSERT_FALSE (maybe_lt (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_TRUE (maybe_lt (ph::make (30, 9, 4), ch::make (31)));
+ ASSERT_TRUE (maybe_lt (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test maybe_lt (C, T). */
+ ASSERT_TRUE (maybe_lt (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_TRUE (maybe_lt (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_EQ (maybe_lt (ch::make (60), ph::make (60, 1, 2)), N >= 2);
+ ASSERT_EQ (maybe_lt (ch::make (60), ph::make (60, 0, 2)), N == 3);
+ ASSERT_FALSE (maybe_lt (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_EQ (maybe_lt (ch::make (31), ph::make (30, 9, 4)), N >= 2);
+ ASSERT_EQ (maybe_lt (ch::make (31), ph::make (30, 0, 4)), N == 3);
+ ASSERT_FALSE (maybe_lt (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test maybe_lt (T, T). */
+ ASSERT_EQ (maybe_lt (ph::make (3, 14, 99), ph::make (2, 15, 100)), N >= 2);
+ ASSERT_EQ (maybe_lt (ph::make (3, 14, 99), ph::make (2, 13, 100)), N == 3);
+ ASSERT_EQ (maybe_lt (ph::make (3, 14, 99), ph::make (2, 15, 98)), N >= 2);
+ ASSERT_FALSE (maybe_lt (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (maybe_lt (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_EQ (maybe_lt (ph::make (2, 14, 99), ph::make (2, 15, 100)), N >= 2);
+ ASSERT_EQ (maybe_lt (ph::make (2, 14, 99), ph::make (2, 13, 100)), N == 3);
+ ASSERT_EQ (maybe_lt (ph::make (2, 14, 99), ph::make (2, 15, 98)), N >= 2);
+ ASSERT_FALSE (maybe_lt (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (maybe_lt (ph::make (2, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (maybe_lt (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (maybe_lt (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (maybe_lt (ph::make (1, 14, 99), ph::make (2, 13, 98)));
+}
+
+/* Test maybe_ge for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_maybe_ge ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_ge (T, C). */
+ ASSERT_TRUE (maybe_ge (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_TRUE (maybe_ge (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_TRUE (maybe_ge (ph::make (60, 1, 2), ch::make (60)));
+ ASSERT_TRUE (maybe_ge (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_EQ (maybe_ge (ph::make (30, 9, 4), ch::make (31)), N >= 2);
+ ASSERT_EQ (maybe_ge (ph::make (30, 0, 4), ch::make (31)), N == 3);
+ ASSERT_FALSE (maybe_ge (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test maybe_ge (C, T). */
+ ASSERT_FALSE (maybe_ge (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_FALSE (maybe_ge (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_TRUE (maybe_ge (ch::make (60), ph::make (60, 1, 2)));
+ ASSERT_TRUE (maybe_ge (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_TRUE (maybe_ge (ch::make (31), ph::make (30, 9, 4)));
+ ASSERT_TRUE (maybe_ge (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test maybe_ge (T, T). */
+ ASSERT_TRUE (maybe_ge (ph::make (3, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (maybe_ge (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (maybe_ge (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (maybe_ge (ph::make (2, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (maybe_ge (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (maybe_ge (ph::make (2, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_FALSE (maybe_ge (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (maybe_ge (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (maybe_ge (ph::make (1, 14, 99), ph::make (2, 15, 98)), N == 3);
+ ASSERT_EQ (maybe_ge (ph::make (1, 14, 99), ph::make (2, 13, 100)), N >= 2);
+ ASSERT_EQ (maybe_ge (ph::make (1, 14, 99), ph::make (2, 13, 98)), N >= 2);
+}
+
+/* Test maybe_gt for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_maybe_gt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_gt (T, C). */
+ ASSERT_TRUE (maybe_gt (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_TRUE (maybe_gt (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_EQ (maybe_gt (ph::make (60, 1, 2), ch::make (60)), N >= 2);
+ ASSERT_EQ (maybe_gt (ph::make (60, 0, 2), ch::make (60)), N == 3);
+ ASSERT_FALSE (maybe_gt (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_EQ (maybe_gt (ph::make (30, 9, 4), ch::make (31)), N >= 2);
+ ASSERT_EQ (maybe_gt (ph::make (30, 0, 4), ch::make (31)), N == 3);
+ ASSERT_FALSE (maybe_gt (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test maybe_gt (C, T). */
+ ASSERT_FALSE (maybe_gt (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_FALSE (maybe_gt (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_FALSE (maybe_gt (ch::make (60), ph::make (60, 1, 2)));
+ ASSERT_FALSE (maybe_gt (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_TRUE (maybe_gt (ch::make (31), ph::make (30, 9, 4)));
+ ASSERT_TRUE (maybe_gt (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test maybe_gt (T, T). */
+ ASSERT_TRUE (maybe_gt (ph::make (3, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (maybe_gt (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (maybe_gt (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_FALSE (maybe_gt (ph::make (2, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (maybe_gt (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (maybe_gt (ph::make (2, 14, 99), ph::make (2, 15, 98)), N == 3);
+ ASSERT_EQ (maybe_gt (ph::make (2, 14, 99), ph::make (2, 13, 100)), N >= 2);
+ ASSERT_EQ (maybe_gt (ph::make (2, 14, 99), ph::make (2, 13, 98)), N >= 2);
+ ASSERT_FALSE (maybe_gt (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (maybe_gt (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (maybe_gt (ph::make (1, 14, 99), ph::make (2, 15, 98)), N == 3);
+ ASSERT_EQ (maybe_gt (ph::make (1, 14, 99), ph::make (2, 13, 100)), N >= 2);
+ ASSERT_EQ (maybe_gt (ph::make (1, 14, 99), ph::make (2, 13, 98)), N >= 2);
+}
+
+/* Test known_gt for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_gt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_gt (T, C). */
+ ASSERT_TRUE (known_gt (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_TRUE (known_gt (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_FALSE (known_gt (ph::make (60, 1, 2), ch::make (60)));
+ ASSERT_FALSE (known_gt (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_FALSE (known_gt (ph::make (30, 9, 4), ch::make (31)));
+ ASSERT_FALSE (known_gt (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test known_gt (C, T). */
+ ASSERT_FALSE (known_gt (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_FALSE (known_gt (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_FALSE (known_gt (ch::make (60), ph::make (60, 1, 2)));
+ ASSERT_FALSE (known_gt (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_EQ (known_gt (ch::make (31), ph::make (30, 9, 4)), N == 1);
+ ASSERT_EQ (known_gt (ch::make (31), ph::make (30, 0, 4)), N <= 2);
+ ASSERT_TRUE (known_gt (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test known_gt (T, T). */
+ ASSERT_EQ (known_gt (ph::make (3, 14, 99), ph::make (2, 15, 100)), N == 1);
+ ASSERT_EQ (known_gt (ph::make (3, 14, 99), ph::make (2, 13, 100)), N <= 2);
+ ASSERT_EQ (known_gt (ph::make (3, 14, 99), ph::make (2, 15, 98)), N == 1);
+ ASSERT_TRUE (known_gt (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (known_gt (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_FALSE (known_gt (ph::make (2, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (known_gt (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (known_gt (ph::make (2, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_FALSE (known_gt (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (known_gt (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (known_gt (ph::make (1, 14, 99), ph::make (2, 13, 98)));
+}
+
+/* Test known_ge for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_ge ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_ge (T, C). */
+ ASSERT_TRUE (known_ge (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_TRUE (known_ge (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_TRUE (known_ge (ph::make (60, 1, 2), ch::make (60)));
+ ASSERT_TRUE (known_ge (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_FALSE (known_ge (ph::make (30, 9, 4), ch::make (31)));
+ ASSERT_FALSE (known_ge (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test known_ge (C, T). */
+ ASSERT_FALSE (known_ge (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_FALSE (known_ge (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_EQ (known_ge (ch::make (60), ph::make (60, 1, 2)), N == 1);
+ ASSERT_EQ (known_ge (ch::make (60), ph::make (60, 0, 2)), N <= 2);
+ ASSERT_TRUE (known_ge (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_EQ (known_ge (ch::make (31), ph::make (30, 9, 4)), N == 1);
+ ASSERT_EQ (known_ge (ch::make (31), ph::make (30, 0, 4)), N <= 2);
+ ASSERT_TRUE (known_ge (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test known_ge (T, T). */
+ ASSERT_EQ (known_ge (ph::make (3, 14, 99), ph::make (2, 15, 100)), N == 1);
+ ASSERT_EQ (known_ge (ph::make (3, 14, 99), ph::make (2, 13, 100)), N <= 2);
+ ASSERT_EQ (known_ge (ph::make (3, 14, 99), ph::make (2, 15, 98)), N == 1);
+ ASSERT_TRUE (known_ge (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (known_ge (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_EQ (known_ge (ph::make (2, 14, 99), ph::make (2, 15, 100)), N == 1);
+ ASSERT_EQ (known_ge (ph::make (2, 14, 99), ph::make (2, 13, 100)), N <= 2);
+ ASSERT_EQ (known_ge (ph::make (2, 14, 99), ph::make (2, 15, 98)), N == 1);
+ ASSERT_TRUE (known_ge (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (known_ge (ph::make (2, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_FALSE (known_ge (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (known_ge (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (known_ge (ph::make (1, 14, 99), ph::make (2, 13, 98)));
+}
+
+/* Test known_lt for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_lt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_lt (T, C). */
+ ASSERT_FALSE (known_lt (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_FALSE (known_lt (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_FALSE (known_lt (ph::make (60, 1, 2), ch::make (60)));
+ ASSERT_FALSE (known_lt (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_EQ (known_lt (ph::make (30, 9, 4), ch::make (31)), N == 1);
+ ASSERT_EQ (known_lt (ph::make (30, 0, 4), ch::make (31)), N <= 2);
+ ASSERT_TRUE (known_lt (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test known_lt (C, T). */
+ ASSERT_TRUE (known_lt (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_TRUE (known_lt (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_FALSE (known_lt (ch::make (60), ph::make (60, 1, 2)));
+ ASSERT_FALSE (known_lt (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_FALSE (known_lt (ch::make (31), ph::make (30, 9, 4)));
+ ASSERT_FALSE (known_lt (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test known_lt (T, T). */
+ ASSERT_FALSE (known_lt (ph::make (3, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (known_lt (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (known_lt (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_FALSE (known_lt (ph::make (2, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (known_lt (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (known_lt (ph::make (2, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (known_lt (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (known_lt (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (known_lt (ph::make (1, 14, 99), ph::make (2, 15, 98)), N <= 2);
+ ASSERT_EQ (known_lt (ph::make (1, 14, 99), ph::make (2, 13, 100)), N == 1);
+ ASSERT_EQ (known_lt (ph::make (1, 14, 99), ph::make (2, 13, 98)), N == 1);
+}
+
+/* Test known_le for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_le ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_le (T, C). */
+ ASSERT_FALSE (known_le (ph::make (7, 5, 4), ch::make (6)));
+ ASSERT_FALSE (known_le (ph::make (7, 0, 0), ch::make (6)));
+ ASSERT_EQ (known_le (ph::make (60, 1, 2), ch::make (60)), N == 1);
+ ASSERT_EQ (known_le (ph::make (60, 0, 2), ch::make (60)), N <= 2);
+ ASSERT_TRUE (known_le (ph::make (60, 0, 0), ch::make (60)));
+ ASSERT_EQ (known_le (ph::make (30, 9, 4), ch::make (31)), N == 1);
+ ASSERT_EQ (known_le (ph::make (30, 0, 4), ch::make (31)), N <= 2);
+ ASSERT_TRUE (known_le (ph::make (30, 0, 0), ch::make (31)));
+
+ /* Test known_le (C, T). */
+ ASSERT_TRUE (known_le (ch::make (6), ph::make (7, 5, 4)));
+ ASSERT_TRUE (known_le (ch::make (6), ph::make (7, 0, 0)));
+ ASSERT_TRUE (known_le (ch::make (60), ph::make (60, 1, 2)));
+ ASSERT_TRUE (known_le (ch::make (60), ph::make (60, 0, 0)));
+ ASSERT_FALSE (known_le (ch::make (31), ph::make (30, 9, 4)));
+ ASSERT_FALSE (known_le (ch::make (31), ph::make (30, 0, 0)));
+
+ /* Test known_le (T, T). */
+ ASSERT_FALSE (known_le (ph::make (3, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_FALSE (known_le (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_FALSE (known_le (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (known_le (ph::make (2, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (known_le (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (known_le (ph::make (2, 14, 99), ph::make (2, 15, 98)), N <= 2);
+ ASSERT_EQ (known_le (ph::make (2, 14, 99), ph::make (2, 13, 100)), N == 1);
+ ASSERT_EQ (known_le (ph::make (2, 14, 99), ph::make (2, 13, 98)), N == 1);
+ ASSERT_TRUE (known_le (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (known_le (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (known_le (ph::make (1, 14, 99), ph::make (2, 15, 98)), N <= 2);
+ ASSERT_EQ (known_le (ph::make (1, 14, 99), ph::make (2, 13, 100)), N == 1);
+ ASSERT_EQ (known_le (ph::make (1, 14, 99), ph::make (2, 13, 98)), N == 1);
+}
+
+/* Test ordered_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_ordered_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_p (T, C). */
+ ASSERT_EQ (ordered_p (ph::make (4, 1, 2), ch::make (5)), N == 1);
+ ASSERT_EQ (ordered_p (ph::make (4, 0, 2), ch::make (5)), N <= 2);
+ ASSERT_TRUE (ordered_p (ph::make (4, 0, 0), ch::make (5)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 1, 2), ch::make (4)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 0, 0), ch::make (4)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 1, 2), ch::make (3)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 0, 0), ch::make (3)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 4, 4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 4, 0), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 0, 4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (-4, -4, -4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (-4, -4, 0), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (-4, 0, -4), ch::make (0)));
+
+ /* Test ordered_p (C, T). */
+ ASSERT_EQ (ordered_p (ch::make (5), ph::make (4, 1, 2)), N == 1);
+ ASSERT_EQ (ordered_p (ch::make (5), ph::make (4, 0, 2)), N <= 2);
+ ASSERT_TRUE (ordered_p (ch::make (5), ph::make (4, 0, 0)));
+ ASSERT_TRUE (ordered_p (ch::make (4), ph::make (4, 1, 2)));
+ ASSERT_TRUE (ordered_p (ch::make (4), ph::make (4, 0, 0)));
+ ASSERT_TRUE (ordered_p (ch::make (3), ph::make (4, 1, 2)));
+ ASSERT_TRUE (ordered_p (ch::make (3), ph::make (4, 0, 0)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (4, 4, 4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (4, 4, 0)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (4, 0, 4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (-4, -4, -4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (-4, -4, 0)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (-4, 0, -4)));
+
+ /* Test ordered_p (T, T). */
+ ASSERT_EQ (ordered_p (ph::make (3, 14, 99), ph::make (2, 15, 100)), N == 1);
+ ASSERT_EQ (ordered_p (ph::make (3, 14, 99), ph::make (2, 13, 100)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (3, 14, 99), ph::make (2, 15, 98)), N == 1);
+ ASSERT_TRUE (ordered_p (ph::make (3, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_TRUE (ordered_p (ph::make (3, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (ordered_p (ph::make (2, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (ordered_p (ph::make (2, 14, 99), ph::make (2, 14, 100)));
+ ASSERT_TRUE (ordered_p (ph::make (2, 14, 99), ph::make (2, 15, 99)));
+ ASSERT_EQ (ordered_p (ph::make (2, 14, 99), ph::make (2, 13, 100)), N <= 2);
+ ASSERT_TRUE (ordered_p (ph::make (2, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (ordered_p (ph::make (2, 14, 99), ph::make (2, 15, 98)), N <= 2);
+ ASSERT_TRUE (ordered_p (ph::make (2, 14, 99), ph::make (2, 13, 99)));
+ ASSERT_TRUE (ordered_p (ph::make (2, 14, 99), ph::make (2, 14, 98)));
+ ASSERT_TRUE (ordered_p (ph::make (2, 14, 99), ph::make (2, 13, 98)));
+ ASSERT_TRUE (ordered_p (ph::make (1, 14, 99), ph::make (2, 15, 100)));
+ ASSERT_TRUE (ordered_p (ph::make (1, 14, 99), ph::make (2, 14, 99)));
+ ASSERT_EQ (ordered_p (ph::make (1, 14, 99), ph::make (2, 15, 98)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (1, 14, 99), ph::make (2, 13, 100)), N == 1);
+ ASSERT_EQ (ordered_p (ph::make (1, 14, 99), ph::make (2, 13, 98)), N == 1);
+}
+
+/* Test ordered_min for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_ordered_min ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_min (T, C). */
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (4, 0, 0), ch::make (5)),
+ ch::make (4));
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (12, 0, 0), ch::make (11)),
+ ch::make (11));
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (12, 6, 4), ch::make (11)),
+ ch::make (11));
+
+ /* Test ordered_min (C, T). */
+ ASSERT_KNOWN_EQ (ordered_min (ch::make (5), ph::make (4, 0, 0)),
+ ch::make (4));
+ ASSERT_KNOWN_EQ (ordered_min (ch::make (11), ph::make (12, 0, 0)),
+ ch::make (11));
+ ASSERT_KNOWN_EQ (ordered_min (ch::make (11), ph::make (12, 6, 4)),
+ ch::make (11));
+
+ /* Test ordered_min (T, T). */
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (4, 6, 14), ph::make (5, 6, 19)),
+ ph::make (4, 6, 14));
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (4, 9, 17), ph::make (3, 9, 0)),
+ ph::make (3, 9, 0));
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (-4, -5, 12), ph::make (-3, -5, 12)),
+ ph::make (-4, -5, 12));
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (4, -9, 6), ph::make (4, -8, 6)),
+ ph::make (4, -9, 6));
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (5, -1, -14), ph::make (5, -1, -16)),
+ ph::make (5, -1, -16));
+}
+
+/* Test ordered_max for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_ordered_max ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_max (T, C). */
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (4, 0, 0), ch::make (5)),
+ ch::make (5));
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (12, 0, 0), ch::make (11)),
+ ch::make (12));
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (12, 6, 4), ch::make (11)),
+ ph::make (12, 6, 4));
+
+ /* Test ordered_max (C, T). */
+ ASSERT_KNOWN_EQ (ordered_max (ch::make (5), ph::make (4, 0, 0)),
+ ch::make (5));
+ ASSERT_KNOWN_EQ (ordered_max (ch::make (11), ph::make (12, 0, 0)),
+ ch::make (12));
+ ASSERT_KNOWN_EQ (ordered_max (ch::make (11), ph::make (12, 6, 4)),
+ ph::make (12, 6, 4));
+
+ /* Test ordered_max (T, T). */
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (4, 6, 14), ph::make (5, 6, 19)),
+ ph::make (5, 6, 19));
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (4, 9, 17), ph::make (3, 9, 0)),
+ ph::make (4, 9, 17));
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (-4, -5, 12), ph::make (-3, -5, 12)),
+ ph::make (-3, -5, 12));
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (4, -9, 6), ph::make (4, -8, 6)),
+ ph::make (4, -8, 6));
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (5, -1, -14), ph::make (5, -1, -16)),
+ ph::make (5, -1, -14));
+}
+
+/* Test constant_lower_bound for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_constant_lower_bound ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (constant_lower_bound (ph::make (4, 1, 2)), 4);
+ ASSERT_EQ (constant_lower_bound (ph::make (5, 0, 1)), 5);
+ ASSERT_EQ (constant_lower_bound (ph::make (6, 1, 0)), 6);
+ ASSERT_EQ (constant_lower_bound (ph::make (7, 0, 0)), 7);
+}
+
+/* Test lower_bound for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_lower_bound ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test lower_bound (T, C). */
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (7, 2, 15), ch::make (4)),
+ ch::make (4));
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (100, 5, 50), ch::make (200)),
+ ch::make (100));
+
+ /* Test lower_bound (C, T). */
+ ASSERT_KNOWN_EQ (lower_bound (ch::make (4), ph::make (7, 2, 15)),
+ ch::make (4));
+ ASSERT_KNOWN_EQ (lower_bound (ch::make (200), ph::make (100, 5, 50)),
+ ch::make (100));
+
+ /* Test lower_bound (T, T). */
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (7, 2, 15), ph::make (5, 19, 14)),
+ ph::make (5, 2, 14));
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (100, 5, 50), ph::make (200, 0, 80)),
+ ph::make (100, 0, 50));
+}
+
+/* Test upper_bound for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_upper_bound ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test upper_bound (T, C). */
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (7, 2, 15), ch::make (4)),
+ ph::make (7, 2, 15));
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (100, 5, 50), ch::make (200)),
+ ph::make (200, 5, 50));
+
+ /* Test upper_bound (C, T). */
+ ASSERT_KNOWN_EQ (upper_bound (ch::make (4), ph::make (7, 2, 15)),
+ ph::make (7, 2, 15));
+ ASSERT_KNOWN_EQ (upper_bound (ch::make (200), ph::make (100, 5, 50)),
+ ph::make (200, 5, 50));
+
+ /* Test upper_bound (T, T). */
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (7, 2, 15), ph::make (5, 19, 14)),
+ ph::make (7, 19, 15));
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (100, 5, 50), ph::make (200, 0, 80)),
+ ph::make (200, 5, 80));
+}
+
+/* Test compare_sizes_for_sort for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_compare_sizes_for_sort ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (compare_sizes_for_sort (ph::make (5, 10, 8),
+ ph::make (7, 9, 11)),
+ N == 2 ? 1 : -1);
+ ASSERT_EQ (compare_sizes_for_sort (ph::make (5, 9, 8),
+ ph::make (7, 9, 11)),
+ -1);
+ ASSERT_EQ (compare_sizes_for_sort (ph::make (19, 9, 13),
+ ph::make (7, 9, 13)),
+ 1);
+ ASSERT_EQ (compare_sizes_for_sort (ph::make (5, 9, 7),
+ ph::make (5, 10, 5)),
+ N == 1 ? 0 : N == 2 ? -1 : 1);
+ ASSERT_EQ (compare_sizes_for_sort (ph::make (10, 9, 10),
+ ph::make (10, 9, 6)),
+ N <= 2 ? 0 : 1);
+ ASSERT_EQ (compare_sizes_for_sort (ph::make (10, 9, 6),
+ ph::make (10, 9, 6)),
+ 0);
+}
+
+/* Test force_align_up_and_div for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_force_align_up_and_div ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (41, 32, 16), 16),
+ ph::make (3, 2, 1));
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (-39, -64, -32), 32),
+ ph::make (C (-32) / 32, C (-64) / 32, C (-32) / 32));
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (17, 0, 0), 16),
+ ch::make (2));
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (16, 0, 0), 16),
+ ch::make (1));
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (15, 0, 0), 16),
+ ch::make (1));
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (-17, 0, 0), 16),
+ ch::make (C (-16) / 16));
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (-16, 0, 0), 16),
+ ch::make (C (-16) / 16));
+ /* For unsigned short C this gives 0x10000 / 16. */
+ ASSERT_KNOWN_EQ (force_align_up_and_div (ph::make (-15, 0, 0), 16),
+ ch::make ((C (-1) + 1) / 16));
+}
+
+/* Test force_align_down_and_div for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_force_align_down_and_div ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (41, 32, 16), 16),
+ ph::make (2, 2, 1));
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (-39, -64, -32), 32),
+ ph::make (C (-64) / 32, C (-64) / 32, C (-32) / 32));
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (17, 0, 0), 16),
+ ch::make (1));
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (16, 0, 0), 16),
+ ch::make (1));
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (15, 0, 0), 16),
+ ch::make (0));
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (-17, 0, 0), 16),
+ ch::make (C (-32) / 16));
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (-16, 0, 0), 16),
+ ch::make (C (-16) / 16));
+ ASSERT_KNOWN_EQ (force_align_down_and_div (ph::make (-15, 0, 0), 16),
+ ch::make (C (-16) / 16));
+}
+
+/* Test constant_multiple_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_constant_multiple_p ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test constant_multiple_p (T, C). */
+ C const_multiple;
+ ASSERT_TRUE (constant_multiple_p (ph::make (15, 0, 0), 5,
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 3);
+ ASSERT_FALSE (constant_multiple_p (ph::make (16, 0, 0), 5,
+ &const_multiple));
+ ASSERT_FALSE (constant_multiple_p (ph::make (14, 5, 5), 5,
+ &const_multiple));
+ ASSERT_EQ (constant_multiple_p (ph::make (44, 0, 55), 11,
+ &const_multiple), N <= 2);
+ ASSERT_EQ (const_multiple, N <= 2 ? 4 : 3);
+ ASSERT_EQ (constant_multiple_p (ph::make (30, 30, 0), 6,
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? 5 : N == 2 ? 4 : 3);
+ ASSERT_TRUE (constant_multiple_p (ph::make (0, 0, 0), 5,
+ &const_multiple));
+
+ /* Test constant_multiple_p (C, T). */
+ ASSERT_TRUE (constant_multiple_p (15, ph::make (5, 0, 0),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 3);
+ ASSERT_FALSE (constant_multiple_p (16, ph::make (5, 0, 0),
+ &const_multiple));
+ ASSERT_FALSE (constant_multiple_p (14, ph::make (5, 5, 5),
+ &const_multiple));
+ ASSERT_EQ (constant_multiple_p (44, ph::make (11, 0, 4),
+ &const_multiple), N <= 2);
+ ASSERT_EQ (const_multiple, N <= 2 ? 4 : 3);
+ ASSERT_EQ (constant_multiple_p (30, ph::make (6, 6, 6),
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? 5 : N == 2 ? 4 : 3);
+ ASSERT_TRUE (constant_multiple_p (0, ph::make (5, 4, 11),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 0);
+
+ /* Test constant_multiple_p (T, T). */
+ ASSERT_TRUE (constant_multiple_p (ph::make (5, 15, 25),
+ ph::make (1, 3, 5),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 5);
+ ASSERT_EQ (constant_multiple_p (ph::make (18, 30, 7),
+ ph::make (6, 10, 2),
+ &const_multiple), N <= 2);
+ ASSERT_EQ (const_multiple, N <= 2 ? 3 : 5);
+ ASSERT_EQ (constant_multiple_p (ph::make (54, 19, 0),
+ ph::make (9, 3, 0),
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? 6 : N == 2 ? 3: 5);
+ ASSERT_TRUE (constant_multiple_p (ph::make (120, 0, 90),
+ ph::make (12, 0, 9),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 10);
+ ASSERT_EQ (constant_multiple_p (ph::make (110, 1, 22),
+ ph::make (10, 0, 2),
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? 11 : 10);
+ ASSERT_EQ (constant_multiple_p (ph::make (120, -1, 22),
+ ph::make (10, 0, 2),
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? 12 : 10);
+ ASSERT_EQ (constant_multiple_p (ph::make (130, 0, 26),
+ ph::make (10, 1, 2),
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? 13 : 10);
+ ASSERT_EQ (constant_multiple_p (ph::make (140, 0, 28),
+ ph::make (10, -1, 2),
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? 14 : 10);
+ ASSERT_FALSE (constant_multiple_p (ph::make (89, 0, 0),
+ ph::make (11, 0, 0),
+ &const_multiple));
+ ASSERT_TRUE (constant_multiple_p (ph::make (88, 0, 0),
+ ph::make (11, 0, 0),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 8);
+ ASSERT_FALSE (constant_multiple_p (ph::make (87, 0, 0),
+ ph::make (11, 0, 0),
+ &const_multiple));
+ ASSERT_TRUE (constant_multiple_p (ph::make (35, 63, 0),
+ ph::make (5, 9, 0),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 7);
+ ASSERT_TRUE (constant_multiple_p (ph::make (0, 0, 0),
+ ph::make (11, -24, 25),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 0);
+}
+
+/* Test multiple_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_multiple_p ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test multiple_p (T, C). */
+ ASSERT_TRUE (multiple_p (ph::make (15, 0, 0), 5));
+ ASSERT_FALSE (multiple_p (ph::make (16, 0, 0), 5));
+ ASSERT_FALSE (multiple_p (ph::make (14, 5, 5), 5));
+ ASSERT_TRUE (multiple_p (ph::make (44, 0, 55), 11));
+ ASSERT_TRUE (multiple_p (ph::make (30, 30, 0), 6));
+ ASSERT_TRUE (multiple_p (ph::make (30, 35, 45), 5));
+ ASSERT_EQ (multiple_p (ph::make (30, 35, 44), 5), N <= 2);
+ ASSERT_EQ (multiple_p (ph::make (30, 34, 45), 5), N == 1);
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0), 5));
+
+ /* Test multiple_p (C, T). */
+ ASSERT_TRUE (multiple_p (15, ph::make (5, 0, 0)));
+ ASSERT_FALSE (multiple_p (16, ph::make (5, 0, 0)));
+ ASSERT_FALSE (multiple_p (14, ph::make (5, 5, 5)));
+ ASSERT_EQ (multiple_p (44, ph::make (11, 0, 4)), N <= 2);
+ ASSERT_EQ (multiple_p (30, ph::make (6, 6, 6)), N == 1);
+ ASSERT_TRUE (multiple_p (0, ph::make (5, 4, 11)));
+
+ /* Test multiple_p (T, T). */
+ ASSERT_TRUE (multiple_p (ph::make (15, 0, 0),
+ ph::make (5, 0, 0)));
+ ASSERT_FALSE (multiple_p (ph::make (16, 0, 0),
+ ph::make (5, 0, 0)));
+ ASSERT_FALSE (multiple_p (ph::make (14, 5, 5),
+ ph::make (5, 0, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (44, 0, 55),
+ ph::make (11, 0, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (30, 30, 0),
+ ph::make (6, 0, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (30, 35, 45),
+ ph::make (5, 0, 0)));
+ ASSERT_EQ (multiple_p (ph::make (30, 35, 44),
+ ph::make (5, 0, 0)), N <= 2);
+ ASSERT_EQ (multiple_p (ph::make (30, 34, 45),
+ ph::make (5, 0, 0)), N == 1);
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0),
+ ph::make (5, 0, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (15, 0, 0),
+ ph::make (5, 0, 0)));
+ ASSERT_FALSE (multiple_p (ph::make (16, 0, 0),
+ ph::make (5, 0, 0)));
+ ASSERT_FALSE (multiple_p (ph::make (14, 0, 0),
+ ph::make (5, 5, 5)));
+ ASSERT_EQ (multiple_p (ph::make (44, 0, 0),
+ ph::make (11, 0, 4)), N <= 2);
+ ASSERT_EQ (multiple_p (ph::make (30, 0, 0),
+ ph::make (6, 6, 6)), N == 1);
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0),
+ ph::make (5, 4, 11)));
+ ASSERT_TRUE (multiple_p (ph::make (5, 15, 25),
+ ph::make (1, 3, 5)));
+ ASSERT_EQ (multiple_p (ph::make (18, 30, 7),
+ ph::make (6, 10, 2)), N <= 2);
+ ASSERT_EQ (multiple_p (ph::make (54, 19, 0),
+ ph::make (9, 3, 0)), N == 1);
+ ASSERT_TRUE (multiple_p (ph::make (120, 0, 90),
+ ph::make (12, 0, 9)));
+ ASSERT_EQ (multiple_p (ph::make (110, 1, 22),
+ ph::make (10, 0, 2)), N == 1);
+ ASSERT_EQ (multiple_p (ph::make (120, -1, 22),
+ ph::make (10, 0, 2)), N == 1);
+ ASSERT_EQ (multiple_p (ph::make (130, 0, 26),
+ ph::make (10, 1, 2)), N == 1);
+ ASSERT_EQ (multiple_p (ph::make (140, 0, 28),
+ ph::make (10, -1, 2)), N == 1);
+ ASSERT_FALSE (multiple_p (ph::make (89, 0, 0),
+ ph::make (11, 0, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (88, 0, 0),
+ ph::make (11, 0, 0)));
+ ASSERT_FALSE (multiple_p (ph::make (87, 0, 0),
+ ph::make (11, 0, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (35, 63, 0),
+ ph::make (5, 9, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0),
+ ph::make (11, -24, 25)));
+}
+
+/* Test the 3-operand form of multiple_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_multiple_p_with_result ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test multiple_p (T, C) -> T. */
+ T multiple;
+ ASSERT_TRUE (multiple_p (ph::make (15, 0, 0), 5, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (3));
+ ASSERT_FALSE (multiple_p (ph::make (16, 0, 0), 5, &multiple));
+ ASSERT_FALSE (multiple_p (ph::make (14, 5, 5), 5, &multiple));
+ ASSERT_TRUE (multiple_p (ph::make (44, 0, 55), 11, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (4, 0, 5));
+ ASSERT_TRUE (multiple_p (ph::make (30, 30, 0), 6, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (5, 5, 0));
+ ASSERT_TRUE (multiple_p (ph::make (30, 35, 45), 5, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (6, 7, 9));
+ ASSERT_EQ (multiple_p (ph::make (30, 35, 44), 5, &multiple), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (multiple, ph::make (6, 7, 0));
+ ASSERT_EQ (multiple_p (ph::make (30, 34, 45), 5, &multiple), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (multiple, ch::make (6));
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0), 5, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (0));
+
+ /* Test multiple_p (C, T) -> T. */
+ ASSERT_TRUE (multiple_p (15, ph::make (5, 0, 0), &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (3));
+ ASSERT_FALSE (multiple_p (16, ph::make (5, 0, 0), &multiple));
+ ASSERT_FALSE (multiple_p (14, ph::make (5, 5, 5), &multiple));
+ ASSERT_EQ (multiple_p (44, ph::make (11, 0, 4), &multiple), N <= 2);
+ ASSERT_KNOWN_EQ (multiple, ch::make (N <= 2 ? 4 : 3));
+ ASSERT_EQ (multiple_p (30, ph::make (6, 6, 6), &multiple), N == 1);
+ ASSERT_KNOWN_EQ (multiple, ch::make (N == 1 ? 5 : N == 2 ? 4 : 3));
+ ASSERT_TRUE (multiple_p (0, ph::make (5, 4, 11), &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (0));
+
+ /* Test multiple_p (T, T) -> T. */
+ ASSERT_TRUE (multiple_p (ph::make (15, 0, 0),
+ ph::make (5, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (3));
+ ASSERT_FALSE (multiple_p (ph::make (16, 0, 0),
+ ph::make (5, 0, 0),
+ &multiple));
+ ASSERT_FALSE (multiple_p (ph::make (14, 5, 5),
+ ph::make (5, 0, 0),
+ &multiple));
+ ASSERT_TRUE (multiple_p (ph::make (44, 0, 55),
+ ph::make (11, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (4, 0, 5));
+ ASSERT_TRUE (multiple_p (ph::make (30, 30, 0),
+ ph::make (6, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (5, 5, 0));
+ ASSERT_TRUE (multiple_p (ph::make (30, 35, 45),
+ ph::make (5, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (6, 7, 9));
+ ASSERT_EQ (multiple_p (ph::make (30, 35, 44),
+ ph::make (5, 0, 0),
+ &multiple), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (multiple, ph::make (6, 7, 0));
+ ASSERT_EQ (multiple_p (ph::make (30, 34, 45),
+ ph::make (5, 0, 0),
+ &multiple), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (multiple, ch::make (6));
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0),
+ ph::make (5, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (0));
+ ASSERT_TRUE (multiple_p (ph::make (15, 0, 0),
+ ph::make (5, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (3));
+ ASSERT_FALSE (multiple_p (ph::make (16, 0, 0),
+ ph::make (5, 0, 0),
+ &multiple));
+ ASSERT_FALSE (multiple_p (ph::make (14, 0, 0),
+ ph::make (5, 5, 5),
+ &multiple));
+ ASSERT_EQ (multiple_p (ph::make (44, 0, 0),
+ ph::make (11, 0, 4),
+ &multiple), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (multiple, ch::make (4));
+ ASSERT_EQ (multiple_p (ph::make (30, 0, 0),
+ ph::make (6, 6, 6),
+ &multiple), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (multiple, ch::make (5));
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0),
+ ph::make (5, 4, 11),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (0));
+ ASSERT_TRUE (multiple_p (ph::make (5, 15, 25),
+ ph::make (1, 3, 5),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (5));
+ ASSERT_EQ (multiple_p (ph::make (18, 30, 7),
+ ph::make (6, 10, 2),
+ &multiple), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (multiple, ch::make (3));
+ ASSERT_EQ (multiple_p (ph::make (54, 19, 0),
+ ph::make (9, 3, 0),
+ &multiple), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (multiple, ch::make (6));
+ ASSERT_TRUE (multiple_p (ph::make (120, 0, 90),
+ ph::make (12, 0, 9),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (10));
+ ASSERT_EQ (multiple_p (ph::make (110, 1, 22),
+ ph::make (10, 0, 2),
+ &multiple), N == 1);
+ ASSERT_KNOWN_EQ (multiple, ch::make (N == 1 ? 11 : 10));
+ ASSERT_EQ (multiple_p (ph::make (120, -1, 22),
+ ph::make (10, 0, 2),
+ &multiple), N == 1);
+ ASSERT_KNOWN_EQ (multiple, ch::make (N == 1 ? 12 : 10));
+ ASSERT_EQ (multiple_p (ph::make (130, 0, 26),
+ ph::make (10, 1, 2),
+ &multiple), N == 1);
+ ASSERT_KNOWN_EQ (multiple, ch::make (N == 1 ? 13 : 10));
+ ASSERT_EQ (multiple_p (ph::make (140, 0, 28),
+ ph::make (10, -1, 2),
+ &multiple), N == 1);
+ ASSERT_KNOWN_EQ (multiple, ch::make (N == 1 ? 14 : 10));
+ ASSERT_FALSE (multiple_p (ph::make (89, 0, 0),
+ ph::make (11, 0, 0),
+ &multiple));
+ ASSERT_TRUE (multiple_p (ph::make (88, 0, 0),
+ ph::make (11, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (8));
+ ASSERT_FALSE (multiple_p (ph::make (87, 0, 0),
+ ph::make (11, 0, 0),
+ &multiple));
+ ASSERT_TRUE (multiple_p (ph::make (35, 63, 0),
+ ph::make (5, 9, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (7));
+ ASSERT_TRUE (multiple_p (ph::make (0, 0, 0),
+ ph::make (11, -24, 25),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (0));
+}
+
+/* Test exact_div for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_exact_div ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test exact_div (T, C). */
+ ASSERT_KNOWN_EQ (exact_div (ph::make (15, 0, 0), 5),
+ ch::make (3));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (44, 0, 55), 11),
+ ph::make (4, 0, 5));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (30, 30, 0), 6),
+ ph::make (5, 5, 0));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (30, 35, 45), 5),
+ ph::make (6, 7, 9));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (0, 0, 0), 5),
+ ch::make (0));
+
+ /* Test exact_div (T, T). */
+ ASSERT_KNOWN_EQ (exact_div (ph::make (15, 0, 0),
+ ph::make (5, 0, 0)),
+ ch::make (3));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (44, 0, 55),
+ ph::make (11, 0, 0)),
+ ph::make (4, 0, 5));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (30, 30, 0),
+ ph::make (6, 0, 0)),
+ ph::make (5, 5, 0));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (30, 35, 45),
+ ph::make (5, 0, 0)),
+ ph::make (6, 7, 9));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (0, 0, 0),
+ ph::make (5, 0, 0)),
+ ch::make (0));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (15, 0, 0),
+ ph::make (5, 0, 0)),
+ ch::make (3));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (0, 0, 0),
+ ph::make (5, 4, 11)),
+ ch::make (0));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (5, 15, 25),
+ ph::make (1, 3, 5)),
+ ch::make (5));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (120, 0, 90),
+ ph::make (12, 0, 9)),
+ ch::make (10));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (88, 0, 0),
+ ph::make (11, 0, 0)),
+ ch::make (8));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (35, 63, 0),
+ ph::make (5, 9, 0)),
+ ch::make (7));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (0, 0, 0),
+ ph::make (11, -24, 25)),
+ ch::make (0));
+}
+
+/* Test the form of can_div_trunc_p that returns a constant quotient,
+ for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_can_div_trunc_p_const ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test can_div_trunc_p (T, C) -> C. */
+ C const_quot;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (22, 0, 0), 5, &const_quot));
+ ASSERT_KNOWN_EQ (const_quot, C (4));
+ ASSERT_EQ (can_div_trunc_p (ph::make (44, 0, 1), 5, &const_quot), N <= 2);
+ ASSERT_KNOWN_EQ (const_quot, C (N <= 2 ? 8 : 4));
+ ASSERT_EQ (can_div_trunc_p (ph::make (88, 1, 0), 5, &const_quot), N == 1);
+ ASSERT_KNOWN_EQ (const_quot, C (N == 1 ? 17 : N == 2 ? 8 : 4));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (20, 0, 0), 5, &const_quot));
+ ASSERT_KNOWN_EQ (const_quot, C (4));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (19, 0, 0), 5, &const_quot));
+ ASSERT_KNOWN_EQ (const_quot, C (3));
+
+ /* Test can_div_trunc_p (T, T) -> C. */
+ ASSERT_TRUE (can_div_trunc_p (ph::make (8, 44, 28),
+ ph::make (2, 11, 7),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (4));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (9, 23, 30),
+ ph::make (4, 8, 12),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (2));
+ ASSERT_EQ (can_div_trunc_p (ph::make (15, 25, 40),
+ ph::make (4, 8, 10),
+ &const_quot), N <= 2);
+ ASSERT_EQ (const_quot, C (N <= 2 ? 3 : 2));
+ ASSERT_EQ (can_div_trunc_p (ph::make (43, 79, 80),
+ ph::make (4, 8, 10),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 10 : N == 2 ? 3 : 2));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (3, 4, 5),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (3, 4, 6),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (3, 5, 5),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_EQ (can_div_trunc_p (ph::make (3, 4, 7),
+ ph::make (4, 5, 6),
+ &const_quot), N <= 2);
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_EQ (can_div_trunc_p (ph::make (3, 6, 0),
+ ph::make (4, 5, 6),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (56, 0, 11),
+ ph::make (11, 0, 2),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (5));
+ ASSERT_EQ (can_div_trunc_p (ph::make (66, 1, 12),
+ ph::make (11, 0, 2),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 6 : 5));
+ ASSERT_EQ (can_div_trunc_p (ph::make (77, -1, 14),
+ ph::make (11, 0, 2),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 7 : 5));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (89, 0, 0),
+ ph::make (11, 0, 0),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (8));
+ ASSERT_EQ (can_div_trunc_p (ph::make (101, 0, 1),
+ ph::make (11, 0, 0),
+ &const_quot), N <= 2);
+ ASSERT_EQ (const_quot, C (N <= 2 ? 9 : 8));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (0, 0, 0),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (0));
+
+ /* Test can_div_trunc_p (T, T) -> C, T. */
+ T rem;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (8, 44, 28),
+ ph::make (2, 11, 7),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (4));
+ ASSERT_KNOWN_EQ (rem, ch::make (0));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (9, 23, 30),
+ ph::make (4, 8, 12),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (2));
+ ASSERT_KNOWN_EQ (rem, ph::make (1, 7, 6));
+ ASSERT_EQ (can_div_trunc_p (ph::make (15, 25, 40),
+ ph::make (4, 8, 10),
+ &const_quot, &rem), N <= 2);
+ ASSERT_EQ (const_quot, C (N <= 2 ? 3 : 2));
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (rem, ph::make (3, 1, 0));
+ ASSERT_EQ (can_div_trunc_p (ph::make (43, 79, 80),
+ ph::make (4, 8, 10),
+ &const_quot, &rem), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 10 : N == 2 ? 3 : 2));
+ if (N == 1)
+ ASSERT_KNOWN_EQ (rem, ch::make (3));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (3, 4, 5),
+ ph::make (4, 5, 6),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_KNOWN_EQ (rem, ph::make (3, 4, 5));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (3, 4, 6),
+ ph::make (4, 5, 6),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_KNOWN_EQ (rem, ph::make (3, 4, 6));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (3, 5, 5),
+ ph::make (4, 5, 6),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_KNOWN_EQ (rem, ph::make (3, 5, 5));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (56, 0, 11),
+ ph::make (11, 0, 2),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (5));
+ ASSERT_KNOWN_EQ (rem, ph::make (1, 0, 1));
+ ASSERT_EQ (can_div_trunc_p (ph::make (66, 1, 12),
+ ph::make (11, 0, 2),
+ &const_quot, &rem), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 6 : 5));
+ if (N == 1)
+ ASSERT_KNOWN_EQ (rem, ch::make (0));
+ ASSERT_EQ (can_div_trunc_p (ph::make (77, -1, 14),
+ ph::make (11, 0, 2),
+ &const_quot, &rem), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 7 : 5));
+ if (N == 1)
+ ASSERT_KNOWN_EQ (rem, ch::make (0));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (89, 0, 0),
+ ph::make (11, 0, 0),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (8));
+ ASSERT_KNOWN_EQ (rem, ch::make (1));
+ ASSERT_EQ (can_div_trunc_p (ph::make (101, 0, 1),
+ ph::make (11, 0, 0),
+ &const_quot, &rem), N <= 2);
+ ASSERT_EQ (const_quot, C (N <= 2 ? 9 : 8));
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (rem, ch::make (2));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (0, 0, 0),
+ ph::make (4, 5, 6),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, C (0));
+ ASSERT_KNOWN_EQ (rem, ch::make (0));
+}
+
+/* Test the form of can_div_trunc_p that returns a polynomail quotient,
+ for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_can_div_trunc_p_poly ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test can_div_trunc_p (T, C) -> T. */
+ T quot;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (22, 0, 0), 5, "));
+ ASSERT_KNOWN_EQ (quot, ch::make (4));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (45, 40, 24), 4, "));
+ ASSERT_KNOWN_EQ (quot, ph::make (11, 10, 6));
+ ASSERT_EQ (can_div_trunc_p (ph::make (13, 18, 19), 6, "), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (quot, ph::make (2, 3, 0));
+ ASSERT_EQ (can_div_trunc_p (ph::make (55, 11, 10), 10, "), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (quot, ch::make (5));
+
+ /* Test can_div_trunc_p (T, C) -> T, C. */
+ C const_rem;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (22, 0, 0), 5,
+ ", &const_rem));
+ ASSERT_KNOWN_EQ (quot, ch::make (4));
+ ASSERT_EQ (const_rem, C (2));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (45, 40, 24), 4,
+ ", &const_rem));
+ ASSERT_KNOWN_EQ (quot, ph::make (11, 10, 6));
+ ASSERT_EQ (const_rem, C (1));
+ ASSERT_EQ (can_div_trunc_p (ph::make (13, 18, 19), 6,
+ ", &const_rem), N <= 2);
+ if (N <= 2)
+ {
+ ASSERT_KNOWN_EQ (quot, ph::make (2, 3, 0));
+ ASSERT_EQ (const_rem, C (1));
+ }
+ ASSERT_EQ (can_div_trunc_p (ph::make (55, 11, 10), 10,
+ ", &const_rem), N == 1);
+ if (N == 1)
+ {
+ ASSERT_KNOWN_EQ (quot, ch::make (5));
+ ASSERT_EQ (const_rem, C (5));
+ }
+}
+
+/* Test can_div_away_from_zero_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_can_div_away_from_zero_p ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test can_div_away_from_zero_p (T, T) -> C. */
+ C const_quot;
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (8, 44, 28),
+ ph::make (2, 11, 7),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (4));
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (9, 23, 30),
+ ph::make (4, 8, 12),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (3));
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (15, 25, 40),
+ ph::make (4, 8, 10),
+ &const_quot), N <= 2);
+ ASSERT_EQ (const_quot, C (N <= 2 ? 4 : 3));
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (43, 79, 80),
+ ph::make (4, 8, 10),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 11 : N == 2 ? 4 : 3));
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (3, 4, 5),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (1));
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (3, 4, 6),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (1));
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (3, 5, 5),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (1));
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (56, 0, 11),
+ ph::make (11, 0, 2),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (6));
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (66, 1, 12),
+ ph::make (11, 0, 2),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, C (6));
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (77, -1, 14),
+ ph::make (11, 0, 2),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, C (N == 1 ? 7 : 6));
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (89, 0, 0),
+ ph::make (11, 0, 0),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (9));
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (101, 0, 1),
+ ph::make (11, 0, 0),
+ &const_quot), N <= 2);
+ ASSERT_EQ (const_quot, C (N <= 2 ? 10 : 9));
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (0, 0, 0),
+ ph::make (4, 5, 6),
+ &const_quot));
+ ASSERT_EQ (const_quot, C (0));
+}
+
+/* Test known_size_p. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_size_p ()
+{
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (known_size_p (ph::make (-1, 0, -1)), N == 3);
+ ASSERT_EQ (known_size_p (ph::make (-1, -1, 0)), N >= 2);
+ ASSERT_EQ (known_size_p (ph::make (-1, -1, -1)), N >= 2);
+ ASSERT_FALSE (known_size_p (ph::make (-1, 0, 0)));
+ ASSERT_TRUE (known_size_p (ph::make (0, 0, 0)));
+ ASSERT_TRUE (known_size_p (ph::make (1, 0, 0)));
+}
+
+/* Test maybe_in_range_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_maybe_in_range_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_FALSE (maybe_in_range_p (ch::make (4),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_FALSE (maybe_in_range_p (ph::make (4, 0, 0),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_FALSE (maybe_in_range_p (ph::make (4, 1, 2),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_TRUE (maybe_in_range_p (ph::make (5, 1, 2),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_EQ (maybe_in_range_p (ph::make (4, 0, 3),
+ ph::make (5, 1, 2),
+ ch::make (-1)), N == 3);
+ ASSERT_EQ (maybe_in_range_p (ph::make (4, 2, 0),
+ ph::make (5, 1, 2),
+ ch::make (-1)), N >= 2);
+ ASSERT_TRUE (maybe_in_range_p (ph::make (500, 100, 200),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_EQ (maybe_in_range_p (ph::make (6, 1, 0),
+ ph::make (5, 1, 1),
+ ch::make (1)), N == 3);
+ ASSERT_EQ (maybe_in_range_p (ph::make (6, 0, 1),
+ ph::make (5, 1, 1),
+ ch::make (1)), N >= 2);
+ ASSERT_FALSE (maybe_in_range_p (ph::make (14, 1, 2),
+ ph::make (5, 1, 2),
+ ch::make (9)));
+ ASSERT_FALSE (maybe_in_range_p (ph::make (14, 1, 2),
+ ch::make (5),
+ ph::make (9, 1, 2)));
+ ASSERT_FALSE (maybe_in_range_p (ph::make (15, 15, 17),
+ ph::make (8, 10, 11),
+ ph::make (7, 5, 6)));
+ ASSERT_EQ (maybe_in_range_p (ph::make (15, 15, 16),
+ ph::make (8, 10, 11),
+ ph::make (7, 5, 6)), N == 3);
+ ASSERT_EQ (maybe_in_range_p (ph::make (15, 14, 17),
+ ph::make (8, 10, 11),
+ ph::make (7, 5, 6)), N >= 2);
+ ASSERT_TRUE (maybe_in_range_p (ph::make (6, 100, 1000),
+ ph::make (5, 10, 11),
+ ph::make (2, 1, 2)));
+ ASSERT_FALSE (maybe_in_range_p (ph::make (6, 8, 2),
+ ph::make (6, 8, 2),
+ ch::make (0)));
+ ASSERT_EQ (maybe_in_range_p (ph::make (6, 8, 1),
+ ph::make (6, 7, 2),
+ ph::make (0, 1, 2)), N == 3);
+}
+
+/* Test known_in_range_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_in_range_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_FALSE (known_in_range_p (ch::make (4),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_FALSE (known_in_range_p (ph::make (5, 1, 2),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_FALSE (known_in_range_p (ph::make (6, 2, 3),
+ ph::make (5, 1, 2),
+ ch::make (-1)));
+ ASSERT_FALSE (known_in_range_p (ph::make (6, 1, 0),
+ ph::make (5, 1, 1),
+ ch::make (1)));
+ ASSERT_FALSE (known_in_range_p (ph::make (6, 0, 1),
+ ph::make (5, 1, 1),
+ ch::make (1)));
+ ASSERT_EQ (known_in_range_p (ph::make (6, 1, 0),
+ ph::make (5, 1, 1),
+ ch::make (2)), N <= 2);
+ ASSERT_EQ (known_in_range_p (ph::make (6, 0, 1),
+ ph::make (5, 1, 1),
+ ch::make (2)), N == 1);
+ ASSERT_TRUE (known_in_range_p (ph::make (6, 4, 5),
+ ph::make (5, 1, 2),
+ ph::make (2, 3, 3)));
+ ASSERT_EQ (known_in_range_p (ph::make (6, 4, 6),
+ ph::make (5, 1, 2),
+ ph::make (2, 3, 3)), N <= 2);
+ ASSERT_EQ (known_in_range_p (ph::make (6, 5, 5),
+ ph::make (5, 1, 2),
+ ph::make (2, 3, 3)), N == 1);
+ ASSERT_FALSE (known_in_range_p (ph::make (6, 8, 2),
+ ph::make (6, 8, 2),
+ ch::make (0)));
+ ASSERT_FALSE (known_in_range_p (ph::make (6, 8, 1),
+ ph::make (6, 7, 2),
+ ph::make (0, 1, 2)));
+}
+
+/* Test ranges_maybe_overlap_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_ranges_maybe_overlap_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_TRUE (ranges_maybe_overlap_p (ph::make (4, 1, 2),
+ ch::make (-1),
+ ph::make (500, 3, 5),
+ ch::make (1)));
+ ASSERT_FALSE (ranges_maybe_overlap_p (ph::make (100, 1, 5),
+ ch::make (-1),
+ ph::make (50, 1, 5),
+ ch::make (50)));
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (100, 1, 5),
+ ch::make (-1),
+ ph::make (50, 0, 6),
+ ch::make (50)), N == 3);
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (100, 1, 5),
+ ch::make (-1),
+ ph::make (50, 2, 0),
+ ch::make (50)), N >= 2);
+ ASSERT_TRUE (ranges_maybe_overlap_p (ph::make (500, 3, 5),
+ ch::make (1),
+ ph::make (4, 1, 2),
+ ch::make (-1)));
+ ASSERT_FALSE (ranges_maybe_overlap_p (ph::make (50, 1, 5),
+ ch::make (50),
+ ph::make (100, 1, 5),
+ ch::make (-1)));
+ ASSERT_FALSE (ranges_maybe_overlap_p (ph::make (10, 2, 3),
+ ch::make (0),
+ ch::make (0),
+ ph::make (20, 30, 40)));
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (10, 2, 3),
+ ph::make (0, 1, 1),
+ ph::make (0, 1, 1),
+ ph::make (20, 30, 40)), N >= 2);
+ ASSERT_FALSE (ranges_maybe_overlap_p (ch::make (0),
+ ph::make (20, 30, 40),
+ ph::make (10, 2, 3),
+ ch::make (0)));
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (0, 1, 1),
+ ph::make (20, 30, 40),
+ ph::make (10, 2, 3),
+ ph::make (0, 1, 0)), N >= 2);
+ ASSERT_TRUE (ranges_maybe_overlap_p (ph::make (8, 10, 15),
+ ph::make (2, 6, 20),
+ ch::make (7),
+ ch::make (2)));
+ ASSERT_FALSE (ranges_maybe_overlap_p (ph::make (8, 10, 15),
+ ph::make (2, 6, 20),
+ ch::make (6),
+ ph::make (2, 10, 15)));
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (8, 10, 15),
+ ph::make (2, 6, 20),
+ ch::make (6),
+ ph::make (0, 0, 16)), N == 3);
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (8, 10, 15),
+ ph::make (2, 6, 20),
+ ch::make (6),
+ ph::make (0, 11, 0)), N >= 2);
+ ASSERT_FALSE (ranges_maybe_overlap_p (ph::make (80, 4, 5),
+ ph::make (10, 6, 7),
+ ph::make (100, 10, 12),
+ ph::make (20, 1, 2)));
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (80, 4, 5),
+ ph::make (10, 6, 7),
+ ph::make (100, 10, 11),
+ ph::make (0, 0, 2)), N == 3);
+ ASSERT_EQ (ranges_maybe_overlap_p (ph::make (80, 5, 5),
+ ph::make (0, 6, 0),
+ ph::make (100, 10, 12),
+ ph::make (20, 1, 2)), N >= 2);
+}
+
+/* Test ranges_known_overlap_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_ranges_known_overlap_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_FALSE (ranges_known_overlap_p (ph::make (5, 1, 2),
+ ch::make (-1),
+ ch::make (4),
+ ch::make (2)));
+ ASSERT_FALSE (ranges_known_overlap_p (ch::make (9),
+ ph::make (2, 3, 4),
+ ch::make (10),
+ ch::make (-1)));
+ ASSERT_FALSE (ranges_known_overlap_p (ph::make (10, 2, 3),
+ ch::make (0),
+ ch::make (0),
+ ph::make (20, 30, 40)));
+ ASSERT_FALSE (ranges_known_overlap_p (ph::make (10, 2, 3),
+ ph::make (0, 1, 1),
+ ph::make (0, 1, 1),
+ ph::make (20, 30, 40)));
+ ASSERT_FALSE (ranges_known_overlap_p (ch::make (0),
+ ph::make (20, 30, 40),
+ ph::make (10, 2, 3),
+ ch::make (0)));
+ ASSERT_FALSE (ranges_known_overlap_p (ph::make (0, 1, 1),
+ ph::make (20, 30, 40),
+ ph::make (10, 2, 3),
+ ph::make (0, 1, 0)));
+ ASSERT_EQ (ranges_known_overlap_p (ph::make (5, 1, 2),
+ ch::make (1),
+ ch::make (4),
+ ch::make (2)), N == 1);
+ ASSERT_TRUE (ranges_known_overlap_p (ph::make (5, 1, 2),
+ ch::make (1),
+ ph::make (4, 1, 2),
+ ch::make (2)));
+ ASSERT_TRUE (ranges_known_overlap_p (ch::make (9),
+ ph::make (2, 3, 4),
+ ch::make (10),
+ ch::make (1)));
+ ASSERT_FALSE (ranges_known_overlap_p (ph::make (10, 11, 12),
+ ph::make (20, 30, 40),
+ ch::make (30),
+ ch::make (1)));
+ ASSERT_TRUE (ranges_known_overlap_p (ph::make (10, 11, 12),
+ ph::make (20, 30, 40),
+ ph::make (29, 41, 52),
+ ch::make (1)));
+ ASSERT_EQ (ranges_known_overlap_p (ph::make (10, 11, 12),
+ ph::make (20, 30, 40),
+ ph::make (29, 41, 53),
+ ch::make (1)), N <= 2);
+ ASSERT_EQ (ranges_known_overlap_p (ph::make (10, 11, 12),
+ ph::make (20, 30, 40),
+ ph::make (29, 42, 52),
+ ch::make (1)), N == 1);
+ ASSERT_TRUE (ranges_known_overlap_p (ph::make (29, 41, 52),
+ ch::make (1),
+ ph::make (10, 11, 12),
+ ph::make (20, 30, 40)));
+ ASSERT_EQ (ranges_known_overlap_p (ph::make (29, 41, 53),
+ ch::make (1),
+ ph::make (10, 11, 12),
+ ph::make (20, 30, 40)), N <= 2);
+ ASSERT_EQ (ranges_known_overlap_p (ph::make (29, 42, 52),
+ ch::make (1),
+ ph::make (10, 11, 12),
+ ph::make (20, 30, 40)), N == 1);
+ ASSERT_TRUE (ranges_known_overlap_p (ph::make (10, 0, 20),
+ ph::make (4, 4, 4),
+ ph::make (7, 3, 20),
+ ph::make (4, 4, 4)));
+}
+
+/* Test known_subrange_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_known_subrange_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_FALSE (known_subrange_p (ph::make (5, 1, 2),
+ ch::make (-1),
+ ch::make (4),
+ ph::make (2, 2, 2)));
+ ASSERT_FALSE (known_subrange_p (ph::make (5, 2, 3),
+ ch::make (2),
+ ph::make (4, 1, 2),
+ ch::make (-1)));
+ ASSERT_FALSE (known_subrange_p (ph::make (6, 2, 3),
+ ph::make (0, 1, 1),
+ ch::make (4),
+ ph::make (3, 4, 11)));
+ ASSERT_TRUE (known_subrange_p (ph::make (6, 2, 3),
+ ph::make (1, 1, 1),
+ ch::make (4),
+ ph::make (3, 4, 11)));
+ ASSERT_FALSE (known_subrange_p (ph::make (6, 2, 3),
+ ph::make (1, 1, 1),
+ ch::make (4),
+ ph::make (2, 4, 11)));
+ ASSERT_TRUE (known_subrange_p (ph::make (10, 20, 30),
+ ph::make (5, 6, 7),
+ ph::make (9, 19, 29),
+ ph::make (6, 7, 8)));
+ ASSERT_EQ (known_subrange_p (ph::make (10, 20, 31),
+ ph::make (5, 6, 7),
+ ph::make (9, 19, 29),
+ ph::make (6, 7, 8)), N <= 2);
+ ASSERT_EQ (known_subrange_p (ph::make (10, 20, 30),
+ ph::make (5, 7, 7),
+ ph::make (9, 19, 29),
+ ph::make (6, 7, 8)), N == 1);
+ ASSERT_EQ (known_subrange_p (ph::make (10, 20, 30),
+ ph::make (5, 6, 7),
+ ph::make (9, 18, 29),
+ ph::make (6, 7, 8)), N == 1);
+ ASSERT_EQ (known_subrange_p (ph::make (10, 20, 30),
+ ph::make (5, 6, 7),
+ ph::make (9, 19, 29),
+ ph::make (6, 6, 8)), N == 1);
+}
+
+/* Test coeffs_in_range_p for both signed and unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_coeffs_in_range_p (void)
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_TRUE (coeffs_in_range_p (ph::make (10, 20, 30), 10, 30));
+ ASSERT_EQ (coeffs_in_range_p (ph::make (1, 10, 19), 0, 11), N <= 2);
+ ASSERT_EQ (coeffs_in_range_p (ph::make (100, 1, 102), 10, 100), N == 1);
+ ASSERT_FALSE (coeffs_in_range_p (ph::make (10, 11, 12), 7, 9));
+ ASSERT_FALSE (coeffs_in_range_p (ph::make (10, 11, 12), 13, 15));
+}
+
+/* Test maybe_eq for poly_int<2, C>, given that C is signed. */
+
+template<typename C>
+static void
+test_signed_maybe_eq_2 ()
+{
+ typedef poly_int<2, C> T;
+
+ /* Test maybe_eq (T, C). */
+ ASSERT_TRUE (maybe_eq (T (4, -4), 0));
+ ASSERT_FALSE (maybe_eq (T (4, -4), 1));
+ ASSERT_TRUE (maybe_eq (T (4, -4), 4));
+ ASSERT_FALSE (maybe_eq (T (4, -4), 8));
+ ASSERT_TRUE (maybe_eq (T (4, -4), -4));
+ ASSERT_FALSE (maybe_eq (T (4, -4), -3));
+
+ /* Test maybe_eq (C, T). */
+ ASSERT_FALSE (maybe_eq (0, T (4, -3)));
+ ASSERT_TRUE (maybe_eq (1, T (4, -3)));
+ ASSERT_TRUE (maybe_eq (4, T (4, -3)));
+ ASSERT_FALSE (maybe_eq (7, T (4, -3)));
+ ASSERT_FALSE (maybe_eq (T (4, -3), -3));
+ ASSERT_TRUE (maybe_eq (T (4, -3), -2));
+
+ /* Test maybe_eq (T, T). */
+ ASSERT_TRUE (maybe_eq (T (0, 3), T (6, 1)));
+ ASSERT_FALSE (maybe_eq (T (0, -3), T (6, 1)));
+ ASSERT_FALSE (maybe_eq (T (0, 3), T (7, 1)));
+ ASSERT_TRUE (maybe_eq (T (-3, 4), T (7, -1)));
+ ASSERT_FALSE (maybe_eq (T (-3, 4), T (6, -1)));
+}
+
+/* Test known_ne for poly_int<2, C>, given that C is signed. */
+
+template<typename C>
+static void
+test_signed_known_ne_2 ()
+{
+ typedef poly_int<2, C> T;
+
+ /* Test known_ne (T, C). */
+ ASSERT_FALSE (known_ne (T (4, -4), 0));
+ ASSERT_TRUE (known_ne (T (4, -4), 1));
+ ASSERT_FALSE (known_ne (T (4, -4), 4));
+ ASSERT_TRUE (known_ne (T (4, -4), 8));
+ ASSERT_FALSE (known_ne (T (4, -4), -4));
+ ASSERT_TRUE (known_ne (T (4, -4), -3));
+
+ /* Test known_ne (C, T). */
+ ASSERT_TRUE (known_ne (0, T (4, -3)));
+ ASSERT_FALSE (known_ne (1, T (4, -3)));
+ ASSERT_FALSE (known_ne (4, T (4, -3)));
+ ASSERT_TRUE (known_ne (7, T (4, -3)));
+ ASSERT_TRUE (known_ne (T (4, -3), -3));
+ ASSERT_FALSE (known_ne (T (4, -3), -2));
+
+ /* Test known_ne (T, T). */
+ ASSERT_FALSE (known_ne (T (0, 3), T (6, 1)));
+ ASSERT_TRUE (known_ne (T (0, -3), T (6, 1)));
+ ASSERT_TRUE (known_ne (T (0, 3), T (7, 1)));
+ ASSERT_FALSE (known_ne (T (-3, 4), T (7, -1)));
+ ASSERT_TRUE (known_ne (T (-3, 4), T (6, -1)));
+}
+
+/* Test negation for signed C, both via operators and wi::. */
+
+template<unsigned int N, typename C, typename RC, typename T>
+static void
+test_signed_negation ()
+{
+ typedef poly_helper<T> ph;
+ typedef poly_helper< poly_int<N, RC> > rph;
+ typedef poly_helper< poly_int<N, int> > iph;
+
+ /* Test unary -. */
+ ASSERT_KNOWN_EQ (-ph::make (-11, 22, -33),
+ rph::make (11, -22, 33));
+
+ /* Test wi::neg. */
+ ASSERT_KNOWN_EQ (wi::neg (ph::make (-11, 22, -33)),
+ iph::make (11, -22, 33));
+}
+
+/* Test maybe_le for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_maybe_le ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_le (T, C). */
+ ASSERT_EQ (maybe_le (ph::make (3, 5, -1), ch::make (2)), N == 3);
+ ASSERT_EQ (maybe_le (ph::make (40, -10, 60), ch::make (15)), N >= 2);
+ ASSERT_TRUE (maybe_le (ph::make (-14, 0, 0), ch::make (13)));
+
+ /* Test maybe_le (C, T). */
+ ASSERT_EQ (maybe_le (ch::make (4), ph::make (3, 5, -1)), N >= 2);
+ ASSERT_EQ (maybe_le (ch::make (41), ph::make (40, -10, 60)), N == 3);
+ ASSERT_TRUE (maybe_le (ch::make (-15), ph::make (11, 0, 0)));
+
+ /* Test maybe_le (T, T). */
+ ASSERT_EQ (maybe_le (ph::make (-2, 4, -2),
+ ph::make (-3, -5, -1)), N == 3);
+ ASSERT_EQ (maybe_le (ph::make (-2, -6, 0),
+ ph::make (-3, 0, 100)), N >= 2);
+ ASSERT_FALSE (maybe_le (ph::make (-2, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test maybe_lt for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_maybe_lt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_lt (T, C). */
+ ASSERT_EQ (maybe_lt (ph::make (3, 5, -1), ch::make (2)), N == 3);
+ ASSERT_EQ (maybe_lt (ph::make (40, -10, 60), ch::make (15)), N >= 2);
+ ASSERT_TRUE (maybe_lt (ph::make (-18, 0, 0), ch::make (18)));
+ ASSERT_EQ (maybe_lt (ph::make (-2, -2, -2), ch::make (-2)), N >= 2);
+
+ /* Test maybe_lt (C, T). */
+ ASSERT_EQ (maybe_lt (ch::make (4), ph::make (3, 5, -1)), N >= 2);
+ ASSERT_EQ (maybe_lt (ch::make (41), ph::make (40, -10, 60)), N == 3);
+ ASSERT_TRUE (maybe_lt (ch::make (-45), ph::make (40, 0, 0)));
+ ASSERT_FALSE (maybe_lt (ch::make (-2), ph::make (-2, -2, -2)));
+
+ /* Test maybe_lt (T, T). */
+ ASSERT_EQ (maybe_lt (ph::make (-3, 4, -2),
+ ph::make (-3, -5, -1)), N == 3);
+ ASSERT_EQ (maybe_lt (ph::make (-3, -6, 0),
+ ph::make (-3, 0, 100)), N >= 2);
+ ASSERT_FALSE (maybe_lt (ph::make (-3, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test maybe_ge for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_maybe_ge ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_ge (T, C). */
+ ASSERT_EQ (maybe_ge (ph::make (3, 5, -1), ch::make (4)), N >= 2);
+ ASSERT_EQ (maybe_ge (ph::make (40, -10, 60), ch::make (41)), N == 3);
+ ASSERT_TRUE (maybe_ge (ph::make (11, 0, 0), ch::make (-15)));
+
+ /* Test maybe_ge (C, T). */
+ ASSERT_EQ (maybe_ge (ch::make (2), ph::make (3, 5, -1)), N == 3);
+ ASSERT_EQ (maybe_ge (ch::make (15), ph::make (40, -10, 60)), N >= 2);
+ ASSERT_TRUE (maybe_ge (ch::make (13), ph::make (-14, 0, 0)));
+
+ /* Test maybe_ge (T, T). */
+ ASSERT_EQ (maybe_ge (ph::make (-3, -5, -1),
+ ph::make (-2, 4, -2)), N == 3);
+ ASSERT_EQ (maybe_ge (ph::make (-3, 0, 100),
+ ph::make (-2, -6, 0)), N >= 2);
+ ASSERT_FALSE (maybe_ge (ph::make (-3, 4, 0),
+ ph::make (-2, 5, 1)));
+}
+
+/* Test maybe_gt for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_maybe_gt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_gt (T, C). */
+ ASSERT_EQ (maybe_gt (ph::make (3, 5, -1), ch::make (4)), N >= 2);
+ ASSERT_EQ (maybe_gt (ph::make (40, -10, 60), ch::make (41)), N == 3);
+ ASSERT_TRUE (maybe_gt (ph::make (40, 0, 0), ch::make (-45)));
+ ASSERT_FALSE (maybe_gt (ph::make (-2, -2, -2), ch::make (-2)));
+
+ /* Test maybe_gt (C, T). */
+ ASSERT_EQ (maybe_gt (ch::make (2), ph::make (3, 5, -1)), N == 3);
+ ASSERT_EQ (maybe_gt (ch::make (15), ph::make (40, -10, 60)), N >= 2);
+ ASSERT_TRUE (maybe_gt (ch::make (18), ph::make (-18, 0, 0)));
+ ASSERT_EQ (maybe_gt (ch::make (-2), ph::make (-2, -2, -2)), N >= 2);
+
+ /* Test maybe_gt (T, T). */
+ ASSERT_EQ (maybe_gt (ph::make (-3, -5, -1),
+ ph::make (-3, 4, -2)), N == 3);
+ ASSERT_EQ (maybe_gt (ph::make (-3, 0, 100),
+ ph::make (-3, -6, 0)), N >= 2);
+ ASSERT_FALSE (maybe_gt (ph::make (-3, 4, 0),
+ ph::make (-3, 5, 1)));
+}
+
+/* Test known_gt for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_known_gt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_gt (T, C). */
+ ASSERT_EQ (known_gt (ph::make (3, 5, -1), ch::make (2)), N <= 2);
+ ASSERT_EQ (known_gt (ph::make (40, -10, 60), ch::make (15)), N == 1);
+ ASSERT_FALSE (known_gt (ph::make (-14, 0, 0), ch::make (13)));
+
+ /* Test known_gt (C, T). */
+ ASSERT_EQ (known_gt (ch::make (4), ph::make (3, 5, -1)), N == 1);
+ ASSERT_EQ (known_gt (ch::make (41), ph::make (40, -10, 60)), N <= 2);
+ ASSERT_FALSE (known_gt (ch::make (-15), ph::make (11, 0, 0)));
+
+ /* Test known_gt (T, T). */
+ ASSERT_EQ (known_gt (ph::make (-2, 4, -2),
+ ph::make (-3, -5, -1)), N <= 2);
+ ASSERT_EQ (known_gt (ph::make (-2, -6, 0),
+ ph::make (-3, 0, 100)), N == 1);
+ ASSERT_TRUE (known_gt (ph::make (-2, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test known_ge for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_known_ge ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_ge (T, C). */
+ ASSERT_EQ (known_ge (ph::make (3, 5, -1), ch::make (2)), N <= 2);
+ ASSERT_EQ (known_ge (ph::make (40, -10, 60), ch::make (15)), N == 1);
+ ASSERT_FALSE (known_ge (ph::make (-18, 0, 0), ch::make (18)));
+ ASSERT_EQ (known_ge (ph::make (-2, -2, -2), ch::make (-2)), N == 1);
+
+ /* Test known_ge (C, T). */
+ ASSERT_EQ (known_ge (ch::make (4), ph::make (3, 5, -1)), N == 1);
+ ASSERT_EQ (known_ge (ch::make (41), ph::make (40, -10, 60)), N <= 2);
+ ASSERT_FALSE (known_ge (ch::make (-45), ph::make (40, 0, 0)));
+ ASSERT_TRUE (known_ge (ch::make (-2), ph::make (-2, -2, -2)));
+
+ /* Test known_ge (T, T). */
+ ASSERT_EQ (known_ge (ph::make (-3, 4, -2),
+ ph::make (-3, -5, -1)), N <= 2);
+ ASSERT_EQ (known_ge (ph::make (-3, -6, 0),
+ ph::make (-3, 0, 100)), N == 1);
+ ASSERT_TRUE (known_ge (ph::make (-3, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test known_lt for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_known_lt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_lt (T, C). */
+ ASSERT_EQ (known_lt (ph::make (3, 5, -1), ch::make (4)), N == 1);
+ ASSERT_EQ (known_lt (ph::make (40, -10, 60), ch::make (41)), N <= 2);
+ ASSERT_FALSE (known_lt (ph::make (11, 0, 0), ch::make (-15)));
+
+ /* Test known_lt (C, T). */
+ ASSERT_EQ (known_lt (ch::make (2), ph::make (3, 5, -1)), N <= 2);
+ ASSERT_EQ (known_lt (ch::make (15), ph::make (40, -10, 60)), N == 1);
+ ASSERT_FALSE (known_lt (ch::make (13), ph::make (-14, 0, 0)));
+
+ /* Test known_lt (T, T). */
+ ASSERT_EQ (known_lt (ph::make (-3, -5, -1),
+ ph::make (-2, 4, -2)), N <= 2);
+ ASSERT_EQ (known_lt (ph::make (-3, 0, 100),
+ ph::make (-2, -6, 0)), N == 1);
+ ASSERT_TRUE (known_lt (ph::make (-3, 4, 0),
+ ph::make (-2, 5, 1)));
+}
+
+/* Test known_le for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_known_le ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_le (T, C). */
+ ASSERT_EQ (known_le (ph::make (3, 5, -1), ch::make (4)), N == 1);
+ ASSERT_EQ (known_le (ph::make (40, -10, 60), ch::make (41)), N <= 2);
+ ASSERT_FALSE (known_le (ph::make (40, 0, 0), ch::make (-45)));
+ ASSERT_TRUE (known_le (ph::make (-2, -2, -2), ch::make (-2)));
+
+ /* Test known_le (C, T). */
+ ASSERT_EQ (known_le (ch::make (2), ph::make (3, 5, -1)), N <= 2);
+ ASSERT_EQ (known_le (ch::make (15), ph::make (40, -10, 60)), N == 1);
+ ASSERT_FALSE (known_le (ch::make (18), ph::make (-18, 0, 0)));
+ ASSERT_EQ (known_le (ch::make (-2), ph::make (-2, -2, -2)), N == 1);
+
+ /* Test known_le (T, T). */
+ ASSERT_EQ (known_le (ph::make (-3, -5, -1),
+ ph::make (-3, 4, -2)), N <= 2);
+ ASSERT_EQ (known_le (ph::make (-3, 0, 100),
+ ph::make (-3, -6, 0)), N == 1);
+ ASSERT_TRUE (known_le (ph::make (-3, 4, 0),
+ ph::make (-3, 5, 1)));
+}
+
+/* Test ordered_p for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_ordered_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_p (T, C). */
+ ASSERT_EQ (ordered_p (ph::make (3, 5, -1), ch::make (4)), N == 1);
+ ASSERT_EQ (ordered_p (ph::make (3, 5, -1), ch::make (3)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (3, 5, -1), ch::make (2)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (40, -10, 60), ch::make (41)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (40, -10, 60), ch::make (40)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (40, -10, 60), ch::make (39)), N == 1);
+ ASSERT_EQ (ordered_p (ph::make (4, -4, -4), ch::make (0)), N == 1);
+ ASSERT_EQ (ordered_p (ph::make (4, 0, -4), ch::make (0)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (4, 4, -4), ch::make (0)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (-4, 4, 4), ch::make (0)), N == 1);
+ ASSERT_EQ (ordered_p (ph::make (-4, 0, 4), ch::make (0)), N <= 2);
+ ASSERT_EQ (ordered_p (ph::make (-4, -4, 4), ch::make (0)), N <= 2);
+
+ /* Test ordered_p (C, T). */
+ ASSERT_EQ (ordered_p (ch::make (4), ph::make (3, 5, -1)), N == 1);
+ ASSERT_EQ (ordered_p (ch::make (3), ph::make (3, 5, -1)), N <= 2);
+ ASSERT_EQ (ordered_p (ch::make (2), ph::make (3, 5, -1)), N <= 2);
+ ASSERT_EQ (ordered_p (ch::make (41), ph::make (40, -10, 60)), N <= 2);
+ ASSERT_EQ (ordered_p (ch::make (40), ph::make (40, -10, 60)), N <= 2);
+ ASSERT_EQ (ordered_p (ch::make (39), ph::make (40, -10, 60)), N == 1);
+ ASSERT_EQ (ordered_p (ch::make (0), ph::make (4, -4, -4)), N == 1);
+ ASSERT_EQ (ordered_p (ch::make (0), ph::make (4, 0, -4)), N <= 2);
+ ASSERT_EQ (ordered_p (ch::make (0), ph::make (4, 4, -4)), N <= 2);
+ ASSERT_EQ (ordered_p (ch::make (0), ph::make (-4, 4, 4)), N == 1);
+ ASSERT_EQ (ordered_p (ch::make (0), ph::make (-4, 0, 4)), N <= 2);
+ ASSERT_EQ (ordered_p (ch::make (0), ph::make (-4, -4, 4)), N <= 2);
+}
+
+/* Test ordered_min for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_ordered_min ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_min (T, C). */
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (4, -12, -14), ch::make (5)),
+ ph::make (4, -12, -14));
+
+ /* Test ordered_min (C, T). */
+ ASSERT_KNOWN_EQ (ordered_min (ch::make (9), ph::make (9, -90, -77)),
+ ph::make (9, -90, -77));
+
+ /* Test ordered_min (T, T). */
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (4, 9, 17), ph::make (4, -1, 17)),
+ ph::make (4, -1, 17));
+}
+
+/* Test ordered_max for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_ordered_max ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_max (T, C). */
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (4, -12, -14), ch::make (5)),
+ ch::make (5));
+
+ /* Test ordered_max (C, T). */
+ ASSERT_KNOWN_EQ (ordered_max (ch::make (9), ph::make (9, -90, -77)),
+ ch::make (9));
+
+ /* Test ordered_max (T, T). */
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (4, 9, 17), ph::make (4, -1, 17)),
+ ph::make (4, 9, 17));
+}
+
+/* Test lower_bound for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_lower_bound ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test lower_bound (T, C). */
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (4, -1, 3), ch::make (5)),
+ ph::make (4, -1, 0));
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (6, 5, -14), ch::make (-11)),
+ ph::make (-11, 0, -14));
+
+ /* Test lower_bound (C, T). */
+ ASSERT_KNOWN_EQ (lower_bound (ch::make (5), ph::make (4, -1, 3)),
+ ph::make (4, -1, 0));
+ ASSERT_KNOWN_EQ (lower_bound (ch::make (-11), ph::make (6, 5, -14)),
+ ph::make (-11, 0, -14));
+
+ /* Test lower_bound (T, T). */
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (4, -1, 3), ph::make (5, 7, -2)),
+ ph::make (4, -1, -2));
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (6, 5, -14), ph::make (-11, 4, 3)),
+ ph::make (-11, 4, -14));
+}
+
+/* Test upper_bound for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_upper_bound ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test upper_bound (T, C). */
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (4, -1, 3), ch::make (5)),
+ ph::make (5, 0, 3));
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (6, 5, -14), ch::make (-11)),
+ ph::make (6, 5, 0));
+
+ /* Test upper_bound (C, T). */
+ ASSERT_KNOWN_EQ (upper_bound (ch::make (5), ph::make (4, -1, 3)),
+ ph::make (5, 0, 3));
+ ASSERT_KNOWN_EQ (upper_bound (ch::make (-11), ph::make (6, 5, -14)),
+ ph::make (6, 5, 0));
+
+ /* Test upper_bound (T, T). */
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (4, -1, 3), ph::make (5, 7, -2)),
+ ph::make (5, 7, 3));
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (6, 5, -14), ph::make (-11, 4, 3)),
+ ph::make (6, 5, 3));
+}
+
+/* Test constant_multiple_p for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_constant_multiple_p ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test constant_multiple_p (T, C). */
+ C const_multiple;
+ ASSERT_TRUE (constant_multiple_p (ph::make (-45, 0, 0), 9,
+ &const_multiple));
+ ASSERT_EQ (const_multiple, -5);
+ ASSERT_TRUE (constant_multiple_p (ph::make (63, 0, 0), -7,
+ &const_multiple));
+ ASSERT_EQ (const_multiple, -9);
+ ASSERT_FALSE (constant_multiple_p (ph::make (-121, 0, 0), -12,
+ &const_multiple));
+ ASSERT_TRUE (constant_multiple_p (ph::make (-120, 0, 0), -12,
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 10);
+ ASSERT_FALSE (constant_multiple_p (ph::make (-119, 0, 0), -12,
+ &const_multiple));
+ ASSERT_EQ (constant_multiple_p (ph::make (-120, -23, 12), 12,
+ &const_multiple), N == 1);
+ if (N == 1)
+ ASSERT_EQ (const_multiple, -10);
+
+ /* Test constant_multiple_p (C, T). */
+ ASSERT_TRUE (constant_multiple_p (-45, ph::make (9, 0, 0),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, -5);
+ ASSERT_TRUE (constant_multiple_p (63, ph::make (-7, 0, 0),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, -9);
+ ASSERT_FALSE (constant_multiple_p (-121, ph::make (-12, 0, 0),
+ &const_multiple));
+ ASSERT_TRUE (constant_multiple_p (-120, ph::make (-12, 0, 0),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 10);
+ ASSERT_FALSE (constant_multiple_p (-119, ph::make (-12, 0, 0),
+ &const_multiple));
+ ASSERT_EQ (constant_multiple_p (-120, ph::make (12, 10, 6),
+ &const_multiple), N == 1);
+ if (N == 1)
+ ASSERT_EQ (const_multiple, -10);
+
+ ASSERT_TRUE (constant_multiple_p (ph::make (-40, 80, -200),
+ ph::make (2, -4, 10),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, -20);
+ ASSERT_EQ (constant_multiple_p (ph::make (-20, 40, 100),
+ ph::make (2, -4, 10),
+ &const_multiple), N <= 2);
+ ASSERT_EQ (const_multiple, N <= 2 ? -10 : -20);
+ ASSERT_EQ (constant_multiple_p (ph::make (-10, -20, -50),
+ ph::make (2, -4, 10),
+ &const_multiple), N == 1);
+ ASSERT_EQ (const_multiple, N == 1 ? -5 : N == 2 ? -10 : -20);
+ ASSERT_FALSE (constant_multiple_p (ph::make (-31, 0, 0),
+ ph::make (-6, 0, 0),
+ &const_multiple));
+ ASSERT_TRUE (constant_multiple_p (ph::make (-30, 0, 0),
+ ph::make (-6, 0, 0),
+ &const_multiple));
+ ASSERT_EQ (const_multiple, 5);
+ ASSERT_FALSE (constant_multiple_p (ph::make (-29, 0, 0),
+ ph::make (-6, 0, 0),
+ &const_multiple));
+}
+
+/* Test multiple_p for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_multiple_p ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test multiple_p (T, C). */
+ ASSERT_TRUE (multiple_p (ph::make (-45, 36, 0), 9));
+ ASSERT_TRUE (multiple_p (ph::make (63, 0, -14), -7));
+ ASSERT_FALSE (multiple_p (ph::make (-121, 0, 0), -12));
+ ASSERT_TRUE (multiple_p (ph::make (-120, 0, 0), -12));
+ ASSERT_FALSE (multiple_p (ph::make (-119, 0, 0), -12));
+ ASSERT_TRUE (multiple_p (ph::make (-120, -24, 12), 12));
+ ASSERT_EQ (multiple_p (ph::make (-120, -24, 11), 12), N <= 2);
+ ASSERT_EQ (multiple_p (ph::make (-120, -23, 12), 12), N == 1);
+
+ /* Test multiple_p (C, T). */
+ ASSERT_TRUE (multiple_p (-45, ph::make (9, 0, 0)));
+ ASSERT_TRUE (multiple_p (63, ph::make (-7, 0, 0)));
+ ASSERT_FALSE (multiple_p (-121, ph::make (-12, 0, 0)));
+ ASSERT_TRUE (multiple_p (-120, ph::make (-12, 0, 0)));
+ ASSERT_FALSE (multiple_p (-119, ph::make (-12, 0, 0)));
+ ASSERT_EQ (multiple_p (-120, ph::make (12, 10, 6)), N == 1);
+
+ /* Test multiple_p (T, T). */
+ ASSERT_TRUE (multiple_p (ph::make (-40, 80, -200),
+ ph::make (2, -4, 10)));
+ ASSERT_EQ (multiple_p (ph::make (-20, 40, 100),
+ ph::make (2, -4, 10)), N <= 2);
+ ASSERT_EQ (multiple_p (ph::make (-10, -20, -50),
+ ph::make (2, -4, 10)), N == 1);
+ ASSERT_FALSE (multiple_p (ph::make (-31, 0, 0),
+ ph::make (-6, 0, 0)));
+ ASSERT_TRUE (multiple_p (ph::make (-30, 0, 0),
+ ph::make (-6, 0, 0)));
+ ASSERT_FALSE (multiple_p (ph::make (-29, 0, 0),
+ ph::make (-6, 0, 0)));
+}
+
+/* Test the 3-operand form of multiple_p for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_multiple_p_with_result ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test multiple_p (T, C) -> T. */
+ T multiple;
+ ASSERT_TRUE (multiple_p (ph::make (-45, 36, 0), 9, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (-5, 4, 0));
+ ASSERT_TRUE (multiple_p (ph::make (63, 0, -14), -7, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (-9, 0, 2));
+ ASSERT_FALSE (multiple_p (ph::make (-121, 0, 0), -12, &multiple));
+ ASSERT_TRUE (multiple_p (ph::make (-120, 0, 0), -12, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (10));
+ ASSERT_FALSE (multiple_p (ph::make (-119, 0, 0), -12, &multiple));
+ ASSERT_TRUE (multiple_p (ph::make (-120, -24, 12), 12, &multiple));
+ ASSERT_KNOWN_EQ (multiple, ph::make (-10, -2, 1));
+ ASSERT_EQ (multiple_p (ph::make (-120, -24, 11), 12, &multiple), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (multiple, ph::make (-10, -2, 0));
+ ASSERT_EQ (multiple_p (ph::make (-120, -23, 12), 12, &multiple), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (multiple, ch::make (-10));
+
+ /* Test multiple_p (C, T) -> T. */
+ ASSERT_TRUE (multiple_p (-45, ph::make (9, 0, 0), &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (-5));
+ ASSERT_TRUE (multiple_p (63, ph::make (-7, 0, 0), &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (-9));
+ ASSERT_FALSE (multiple_p (-121, ph::make (-12, 0, 0), &multiple));
+ ASSERT_TRUE (multiple_p (-120, ph::make (-12, 0, 0), &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (10));
+ ASSERT_FALSE (multiple_p (-119, ph::make (-12, 0, 0), &multiple));
+ ASSERT_EQ (multiple_p (-120, ph::make (12, 10, 6), &multiple), N == 1);
+ ASSERT_KNOWN_EQ (multiple, ch::make (N == 1 ? -10 : 10));
+
+ /* Test multiple_p (T, T) -> T. */
+ ASSERT_TRUE (multiple_p (ph::make (-40, 80, -200),
+ ph::make (2, -4, 10),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (-20));
+ ASSERT_EQ (multiple_p (ph::make (-20, 40, 100),
+ ph::make (2, -4, 10),
+ &multiple), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (multiple, ch::make (-10));
+ ASSERT_EQ (multiple_p (ph::make (-10, -20, -50),
+ ph::make (2, -4, 10),
+ &multiple), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (multiple, ch::make (-5));
+ ASSERT_FALSE (multiple_p (ph::make (-31, 0, 0),
+ ph::make (-6, 0, 0),
+ &multiple));
+ ASSERT_TRUE (multiple_p (ph::make (-30, 0, 0),
+ ph::make (-6, 0, 0),
+ &multiple));
+ ASSERT_KNOWN_EQ (multiple, ch::make (5));
+ ASSERT_FALSE (multiple_p (ph::make (-29, 0, 0),
+ ph::make (-6, 0, 0),
+ &multiple));
+}
+
+/* Test exact_div for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_exact_div ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test exact_div (T, C). */
+ ASSERT_KNOWN_EQ (exact_div (ph::make (-45, 36, 0), 9),
+ ph::make (-5, 4, 0));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (63, 0, -14), -7),
+ ph::make (-9, 0, 2));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (-120, 0, 0), -12),
+ ch::make (10));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (-120, -24, 12), 12),
+ ph::make (-10, -2, 1));
+
+ /* Test exact_div (T, T). */
+ ASSERT_KNOWN_EQ (exact_div (ph::make (-40, 80, -200),
+ ph::make (2, -4, 10)),
+ ch::make (-20));
+ ASSERT_KNOWN_EQ (exact_div (ph::make (-30, 0, 0),
+ ph::make (-6, 0, 0)),
+ ch::make (5));
+}
+
+/* Test the form of can_div_trunc_p that returns a constant, for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_can_div_trunc_p_const ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test can_div_trunc_p (T, C) -> C. */
+ C const_quot;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-31, 0, 0), 10, &const_quot));
+ ASSERT_KNOWN_EQ (const_quot, -3);
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-29, 0, 0), 10, &const_quot));
+ ASSERT_KNOWN_EQ (const_quot, -2);
+
+ /* Test can_div_trunc_p (T, T) -> C. */
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-10, 25, -15),
+ ph::make (2, -5, 3),
+ &const_quot));
+ ASSERT_EQ (const_quot, -5);
+ /* (-5 + 2x) / (-3 + 2x) != 1 when x == 1. */
+ ASSERT_EQ (can_div_trunc_p (ph::make (-5, 2, 0),
+ ph::make (-3, 2, 0),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, N == 1 ? 1 : -5);
+ /* Similarly for the third coefficient. */
+ ASSERT_EQ (can_div_trunc_p (ph::make (-5, -5, 2),
+ ph::make (-3, -3, 2),
+ &const_quot), N <= 2);
+ ASSERT_EQ (const_quot, N <= 2 ? 1 : -5);
+ /* (-15 + 3x) / (-12 + 2x) != 1 when x == 7. */
+ ASSERT_EQ (can_div_trunc_p (ph::make (-15, 3, 0),
+ ph::make (-12, 2, 0),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, N <= 2 ? 1 : -5);
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-21, -18, -14),
+ ph::make (5, 4, 3),
+ &const_quot));
+ ASSERT_EQ (const_quot, -4);
+ ASSERT_TRUE (can_div_trunc_p (ph::make (18, 9, 13),
+ ph::make (-8, -4, -5),
+ &const_quot));
+ ASSERT_EQ (const_quot, -2);
+
+ /* Test can_div_trunc_p (T, T) -> C, T. */
+ T rem;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-10, 25, -15),
+ ph::make (2, -5, 3),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, -5);
+ ASSERT_KNOWN_EQ (rem, ch::make (0));
+ /* (-5 + 2x) / (-3 + 2x) != 1 when x == 1. */
+ ASSERT_EQ (can_div_trunc_p (ph::make (-5, 2, 0),
+ ph::make (-3, 2, 0),
+ &const_quot, &rem), N == 1);
+ ASSERT_KNOWN_EQ (const_quot, N == 1 ? 1 : -5);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (rem, ch::make (-2));
+ /* Similarly for the third coefficient. */
+ ASSERT_EQ (can_div_trunc_p (ph::make (-5, -5, 2),
+ ph::make (-3, -3, 2),
+ &const_quot, &rem), N <= 2);
+ ASSERT_KNOWN_EQ (const_quot, N <= 2 ? 1 : -5);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (rem, ph::make (-2, -2, 0));
+ /* (-15 + 3x) / (-12 + 2x) != 1 when x == 7. */
+ ASSERT_EQ (can_div_trunc_p (ph::make (-15, 3, 0),
+ ph::make (-12, 2, 0),
+ &const_quot, &rem), N == 1);
+ ASSERT_KNOWN_EQ (const_quot, N <= 2 ? 1 : -5);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (rem, ch::make (-3));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-21, -18, -14),
+ ph::make (5, 4, 3),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, -4);
+ ASSERT_KNOWN_EQ (rem, ph::make (-1, -2, -2));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (18, 9, 13),
+ ph::make (-8, -4, -5),
+ &const_quot, &rem));
+ ASSERT_EQ (const_quot, -2);
+ ASSERT_KNOWN_EQ (rem, ph::make (2, 1, 3));
+}
+
+/* Test the form of can_div_trunc_p that returns a poly_int, for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_can_div_trunc_p_poly ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test can_div_trunc_p (T, C) -> T. */
+ T quot;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-99, 0, 0), 10, "));
+ ASSERT_KNOWN_EQ (quot, ch::make (-9));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (7, -63, 81), 9, "));
+ ASSERT_KNOWN_EQ (quot, ph::make (0, -7, 9));
+ ASSERT_TRUE (can_div_trunc_p (ph::make (15, 44, -55), -11, "));
+ ASSERT_KNOWN_EQ (quot, ph::make (-1, -4, 5));
+ ASSERT_EQ (can_div_trunc_p (ph::make (-63, -24, -17), -8, "), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (quot, ph::make (7, 3, 0));
+ ASSERT_EQ (can_div_trunc_p (ph::make (40, 48, 70), -7, "), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (quot, ch::make (-5));
+
+ /* Test can_div_trunc_p (T, C) -> T, C. */
+ C const_rem;
+ ASSERT_TRUE (can_div_trunc_p (ph::make (-99, 0, 0), 10,
+ ", &const_rem));
+ ASSERT_KNOWN_EQ (quot, ch::make (-9));
+ ASSERT_EQ (const_rem, -9);
+ ASSERT_TRUE (can_div_trunc_p (ph::make (7, -63, 81), 9,
+ ", &const_rem));
+ ASSERT_KNOWN_EQ (quot, ph::make (0, -7, 9));
+ ASSERT_EQ (const_rem, 7);
+ ASSERT_TRUE (can_div_trunc_p (ph::make (15, 44, -55), -11,
+ ", &const_rem));
+ ASSERT_KNOWN_EQ (quot, ph::make (-1, -4, 5));
+ ASSERT_EQ (const_rem, 4);
+ ASSERT_EQ (can_div_trunc_p (ph::make (-63, -24, -17), -8,
+ ", &const_rem), N <= 2);
+ if (N <= 2)
+ {
+ ASSERT_KNOWN_EQ (quot, ph::make (7, 3, 0));
+ ASSERT_EQ (const_rem, -7);
+ }
+ ASSERT_EQ (can_div_trunc_p (ph::make (40, 48, 70), -7,
+ ", &const_rem), N == 1);
+ if (N == 1)
+ {
+ ASSERT_KNOWN_EQ (quot, ch::make (-5));
+ ASSERT_EQ (const_rem, 5);
+ }
+}
+
+/* Test can_div_away_from_zero_p for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_can_div_away_from_zero_p ()
+{
+ typedef poly_helper<T> ph;
+
+ /* Test can_div_away_from_zero_p (T, T) -> C. */
+ C const_quot;
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (-10, 25, -15),
+ ph::make (2, -5, 3),
+ &const_quot));
+ ASSERT_EQ (const_quot, -5);
+ /* (-5 + 2x) / (-3 + 2x) != 1 when x == 1. */
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (-5, 2, 0),
+ ph::make (-3, 2, 0),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, N == 1 ? 2 : -5);
+ /* Similarly for the third coefficient. */
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (-5, -5, 2),
+ ph::make (-3, -3, 2),
+ &const_quot), N <= 2);
+ ASSERT_EQ (const_quot, N <= 2 ? 2 : -5);
+ /* (-15 + 3x) / (-12 + 2x) != 1 when x == 7. */
+ ASSERT_EQ (can_div_away_from_zero_p (ph::make (-15, 3, 0),
+ ph::make (-12, 2, 0),
+ &const_quot), N == 1);
+ ASSERT_EQ (const_quot, N <= 2 ? 2 : -5);
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (-21, -18, -14),
+ ph::make (5, 4, 3),
+ &const_quot));
+ ASSERT_EQ (const_quot, -5);
+ ASSERT_TRUE (can_div_away_from_zero_p (ph::make (18, 9, 13),
+ ph::make (-8, -4, -5),
+ &const_quot));
+ ASSERT_EQ (const_quot, -3);
+}
+
+/* Test maybe_in_range_p for signed C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_signed_maybe_in_range_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_EQ (maybe_in_range_p (ch::make (4),
+ ph::make (5, 1, -2),
+ ph::make (-1, -1, -1)), N == 3);
+ ASSERT_EQ (maybe_in_range_p (ch::make (4),
+ ph::make (5, -1, 2),
+ ph::make (-1, -1, -1)), N >= 2);
+}
+
+/* Test maybe_le for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_maybe_le ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_le (T, C). */
+ ASSERT_FALSE (maybe_le (ph::make (3, 5, -1), ch::make (2)));
+ ASSERT_FALSE (maybe_le (ph::make (40, -10, 60), ch::make (15)));
+ ASSERT_FALSE (maybe_le (ph::make (-14, 0, 0), ch::make (13)));
+
+ /* Test maybe_le (C, T). */
+ ASSERT_EQ (maybe_le (ch::make (4), ph::make (3, 5, -1)), N >= 2);
+ ASSERT_EQ (maybe_le (ch::make (41), ph::make (40, -10, 60)), N >= 2);
+ ASSERT_FALSE (maybe_le (ch::make (-15), ph::make (11, 0, 0)));
+
+ /* Test maybe_le (T, T). */
+ ASSERT_EQ (maybe_le (ph::make (-2, 4, -2),
+ ph::make (-3, -5, -1)), N >= 2);
+ ASSERT_EQ (maybe_le (ph::make (-2, -6, 0),
+ ph::make (-3, 0, 100)), N == 3);
+ ASSERT_FALSE (maybe_le (ph::make (-2, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test maybe_lt for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_maybe_lt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_lt (T, C). */
+ ASSERT_FALSE (maybe_lt (ph::make (3, 5, -1), ch::make (2)));
+ ASSERT_FALSE (maybe_lt (ph::make (40, -10, 60), ch::make (15)));
+ ASSERT_FALSE (maybe_lt (ph::make (-18, 0, 0), ch::make (18)));
+ ASSERT_FALSE (maybe_lt (ph::make (-2, -2, -2), ch::make (-2)));
+
+ /* Test maybe_lt (C, T). */
+ ASSERT_EQ (maybe_lt (ch::make (4), ph::make (3, 5, -1)), N >= 2);
+ ASSERT_EQ (maybe_lt (ch::make (41), ph::make (40, -10, 60)), N >= 2);
+ ASSERT_FALSE (maybe_lt (ch::make (-45), ph::make (40, 0, 0)));
+ ASSERT_EQ (maybe_lt (ch::make (-2), ph::make (-2, -2, -2)), N >= 2);
+
+ /* Test maybe_lt (T, T). */
+ ASSERT_EQ (maybe_lt (ph::make (-3, 4, -2),
+ ph::make (-3, -5, -1)), N >= 2);
+ ASSERT_EQ (maybe_lt (ph::make (-3, -6, 0),
+ ph::make (-3, 0, 100)), N == 3);
+ ASSERT_FALSE (maybe_lt (ph::make (-3, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test maybe_ge for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_maybe_ge ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_ge (T, C). */
+ ASSERT_EQ (maybe_ge (ph::make (3, 5, -1), ch::make (4)), N >= 2);
+ ASSERT_EQ (maybe_ge (ph::make (40, -10, 60), ch::make (41)), N >= 2);
+ ASSERT_FALSE (maybe_ge (ph::make (11, 0, 0), ch::make (-15)));
+
+ /* Test maybe_ge (C, T). */
+ ASSERT_FALSE (maybe_ge (ch::make (2), ph::make (3, 5, -1)));
+ ASSERT_FALSE (maybe_ge (ch::make (15), ph::make (40, -10, 60)));
+ ASSERT_FALSE (maybe_ge (ch::make (13), ph::make (-14, 0, 0)));
+
+ /* Test maybe_ge (T, T). */
+ ASSERT_EQ (maybe_ge (ph::make (-3, -5, -1),
+ ph::make (-2, 4, -2)), N >= 2);
+ ASSERT_EQ (maybe_ge (ph::make (-3, 0, 100),
+ ph::make (-2, -6, 0)), N == 3);
+ ASSERT_FALSE (maybe_ge (ph::make (-3, 4, 0),
+ ph::make (-2, 5, 1)));
+}
+
+/* Test maybe_gt for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_maybe_gt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test maybe_gt (T, C). */
+ ASSERT_EQ (maybe_gt (ph::make (3, 5, -1), ch::make (4)), N >= 2);
+ ASSERT_EQ (maybe_gt (ph::make (40, -10, 60), ch::make (41)), N >= 2);
+ ASSERT_FALSE (maybe_gt (ph::make (40, 0, 0), ch::make (-45)));
+ ASSERT_EQ (maybe_gt (ph::make (-2, -2, -2), ch::make (-2)), N >= 2);
+
+ /* Test maybe_gt (C, T). */
+ ASSERT_FALSE (maybe_gt (ch::make (2), ph::make (3, 5, -1)));
+ ASSERT_FALSE (maybe_gt (ch::make (15), ph::make (40, -10, 60)));
+ ASSERT_FALSE (maybe_gt (ch::make (18), ph::make (-18, 0, 0)));
+ ASSERT_FALSE (maybe_gt (ch::make (-2), ph::make (-2, -2, -2)));
+
+ /* Test maybe_gt (T, T). */
+ ASSERT_EQ (maybe_gt (ph::make (-3, -5, -1),
+ ph::make (-3, 4, -2)), N >= 2);
+ ASSERT_EQ (maybe_gt (ph::make (-3, 0, 100),
+ ph::make (-3, -6, 0)), N == 3);
+ ASSERT_FALSE (maybe_gt (ph::make (-3, 4, 0),
+ ph::make (-3, 5, 1)));
+}
+
+/* Test known_gt for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_known_gt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_gt (T, C). */
+ ASSERT_TRUE (known_gt (ph::make (3, 5, -1), ch::make (2)));
+ ASSERT_TRUE (known_gt (ph::make (40, -10, 60), ch::make (15)));
+ ASSERT_TRUE (known_gt (ph::make (-14, 0, 0), ch::make (13)));
+
+ /* Test known_gt (C, T). */
+ ASSERT_EQ (known_gt (ch::make (4), ph::make (3, 5, -1)), N == 1);
+ ASSERT_EQ (known_gt (ch::make (41), ph::make (40, -10, 60)), N == 1);
+ ASSERT_TRUE (known_gt (ch::make (-15), ph::make (11, 0, 0)));
+
+ /* Test known_gt (T, T). */
+ ASSERT_EQ (known_gt (ph::make (-2, 4, -2),
+ ph::make (-3, -5, -1)), N == 1);
+ ASSERT_EQ (known_gt (ph::make (-2, -6, 0),
+ ph::make (-3, 0, 100)), N <= 2);
+ ASSERT_TRUE (known_gt (ph::make (-2, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test known_ge for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_known_ge ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_ge (T, C). */
+ ASSERT_TRUE (known_ge (ph::make (3, 5, -1), ch::make (2)));
+ ASSERT_TRUE (known_ge (ph::make (40, -10, 60), ch::make (15)));
+ ASSERT_TRUE (known_ge (ph::make (-18, 0, 0), ch::make (18)));
+ ASSERT_TRUE (known_ge (ph::make (-2, -2, -2), ch::make (-2)));
+
+ /* Test known_ge (C, T). */
+ ASSERT_EQ (known_ge (ch::make (4), ph::make (3, 5, -1)), N == 1);
+ ASSERT_EQ (known_ge (ch::make (41), ph::make (40, -10, 60)), N == 1);
+ ASSERT_TRUE (known_ge (ch::make (-45), ph::make (40, 0, 0)));
+ ASSERT_EQ (known_ge (ch::make (-2), ph::make (-2, -2, -2)), N == 1);
+
+ /* Test known_ge (T, T). */
+ ASSERT_EQ (known_ge (ph::make (-3, 4, -2),
+ ph::make (-3, -5, -1)), N == 1);
+ ASSERT_EQ (known_ge (ph::make (-3, -6, 0),
+ ph::make (-3, 0, 100)), N <= 2);
+ ASSERT_TRUE (known_ge (ph::make (-3, 5, 1),
+ ph::make (-3, 4, 0)));
+}
+
+/* Test known_lt for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_known_lt ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_lt (T, C). */
+ ASSERT_EQ (known_lt (ph::make (3, 5, -1), ch::make (4)), N == 1);
+ ASSERT_EQ (known_lt (ph::make (40, -10, 60), ch::make (41)), N == 1);
+ ASSERT_TRUE (known_lt (ph::make (11, 0, 0), ch::make (-15)));
+
+ /* Test known_lt (C, T). */
+ ASSERT_TRUE (known_lt (ch::make (2), ph::make (3, 5, -1)));
+ ASSERT_TRUE (known_lt (ch::make (15), ph::make (40, -10, 60)));
+ ASSERT_TRUE (known_lt (ch::make (13), ph::make (-14, 0, 0)));
+
+ /* Test known_lt (T, T). */
+ ASSERT_EQ (known_lt (ph::make (-3, -5, -1),
+ ph::make (-2, 4, -2)), N == 1);
+ ASSERT_EQ (known_lt (ph::make (-3, 0, 100),
+ ph::make (-2, -6, 0)), N <= 2);
+ ASSERT_TRUE (known_lt (ph::make (-3, 4, 0),
+ ph::make (-2, 5, 1)));
+}
+
+/* Test known_le for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_known_le ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test known_le (T, C). */
+ ASSERT_EQ (known_le (ph::make (3, 5, -1), ch::make (4)), N == 1);
+ ASSERT_EQ (known_le (ph::make (40, -10, 60), ch::make (41)), N == 1);
+ ASSERT_TRUE (known_le (ph::make (40, 0, 0), ch::make (-45)));
+ ASSERT_EQ (known_le (ph::make (-2, -2, -2), ch::make (-2)), N == 1);
+
+ /* Test known_le (C, T). */
+ ASSERT_TRUE (known_le (ch::make (2), ph::make (3, 5, -1)));
+ ASSERT_TRUE (known_le (ch::make (15), ph::make (40, -10, 60)));
+ ASSERT_TRUE (known_le (ch::make (18), ph::make (-18, 0, 0)));
+ ASSERT_TRUE (known_le (ch::make (-2), ph::make (-2, -2, -2)));
+
+ /* Test known_le (T, T). */
+ ASSERT_EQ (known_le (ph::make (-3, -5, -1),
+ ph::make (-3, 4, -2)), N == 1);
+ ASSERT_EQ (known_le (ph::make (-3, 0, 100),
+ ph::make (-3, -6, 0)), N <= 2);
+ ASSERT_TRUE (known_le (ph::make (-3, 4, 0),
+ ph::make (-3, 5, 1)));
+}
+
+/* Test ordered_p for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_ordered_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_p (T, C). */
+ ASSERT_EQ (ordered_p (ph::make (3, 5, -1), ch::make (4)), N == 1);
+ ASSERT_TRUE (ordered_p (ph::make (3, 5, -1), ch::make (3)));
+ ASSERT_TRUE (ordered_p (ph::make (3, 5, -1), ch::make (2)));
+ ASSERT_EQ (ordered_p (ph::make (40, -10, 60), ch::make (41)), N == 1);
+ ASSERT_TRUE (ordered_p (ph::make (40, -10, 60), ch::make (40)));
+ ASSERT_TRUE (ordered_p (ph::make (40, -10, 60), ch::make (39)));
+ ASSERT_TRUE (ordered_p (ph::make (4, -4, -4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 0, -4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (4, 4, -4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (-4, 4, 4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (-4, 0, 4), ch::make (0)));
+ ASSERT_TRUE (ordered_p (ph::make (-4, -4, 4), ch::make (0)));
+
+ /* Test ordered_p (C, T). */
+ ASSERT_EQ (ordered_p (ch::make (4), ph::make (3, 5, -1)), N == 1);
+ ASSERT_TRUE (ordered_p (ch::make (3), ph::make (3, 5, -1)));
+ ASSERT_TRUE (ordered_p (ch::make (2), ph::make (3, 5, -1)));
+ ASSERT_EQ (ordered_p (ch::make (41), ph::make (40, -10, 60)), N == 1);
+ ASSERT_TRUE (ordered_p (ch::make (40), ph::make (40, -10, 60)));
+ ASSERT_TRUE (ordered_p (ch::make (39), ph::make (40, -10, 60)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (4, -4, -4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (4, 0, -4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (4, 4, -4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (-4, 4, 4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (-4, 0, 4)));
+ ASSERT_TRUE (ordered_p (ch::make (0), ph::make (-4, -4, 4)));
+}
+
+/* Test ordered_min for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_ordered_min ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_min (T, C). */
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (5, -12, -14), ch::make (5)),
+ ch::make (5));
+
+ /* Test ordered_min (C, T). */
+ ASSERT_KNOWN_EQ (ordered_min (ch::make (9), ph::make (9, -90, -77)),
+ ch::make (9));
+
+ /* Test ordered_min (T, T). */
+ ASSERT_KNOWN_EQ (ordered_min (ph::make (4, 9, 17), ph::make (4, -1, 17)),
+ ph::make (4, 9, 17));
+}
+
+/* Test ordered_max for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_ordered_max ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test ordered_max (T, C). */
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (5, -12, -14), ch::make (5)),
+ ph::make (5, -12, -14));
+
+ /* Test ordered_max (C, T). */
+ ASSERT_KNOWN_EQ (ordered_max (ch::make (9), ph::make (9, -90, -77)),
+ ph::make (9, -90, -77));
+
+ /* Test ordered_max (T, T). */
+ ASSERT_KNOWN_EQ (ordered_max (ph::make (4, 9, 17), ph::make (4, -1, 17)),
+ ph::make (4, -1, 17));
+}
+
+/* Test lower_bound for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_lower_bound ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test lower_bound (T, C). */
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (4, -1, 3), ch::make (5)),
+ ch::make (4));
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (6, 5, -14), ch::make (-11)),
+ ch::make (6));
+
+ /* Test lower_bound (C, T). */
+ ASSERT_KNOWN_EQ (lower_bound (ch::make (5), ph::make (4, -1, 3)),
+ ch::make (4));
+ ASSERT_KNOWN_EQ (lower_bound (ch::make (-11), ph::make (6, 5, -14)),
+ ch::make (6));
+
+ /* Test lower_bound (T, T). */
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (4, -1, 3), ph::make (5, 7, -2)),
+ ph::make (4, 7, 3));
+ ASSERT_KNOWN_EQ (lower_bound (ph::make (6, 5, -14), ph::make (-11, 4, 3)),
+ ph::make (6, 4, 3));
+}
+
+/* Test upper_bound for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_upper_bound ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test upper_bound (T, C). */
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (4, -1, 3), ch::make (5)),
+ ph::make (5, -1, 3));
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (6, 5, -14), ch::make (-11)),
+ ph::make (-11, 5, -14));
+
+ /* Test upper_bound (C, T). */
+ ASSERT_KNOWN_EQ (upper_bound (ch::make (5), ph::make (4, -1, 3)),
+ ph::make (5, -1, 3));
+ ASSERT_KNOWN_EQ (upper_bound (ch::make (-11), ph::make (6, 5, -14)),
+ ph::make (-11, 5, -14));
+
+ /* Test upper_bound (T, T). */
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (4, -1, 3), ph::make (5, 7, -2)),
+ ph::make (5, -1, -2));
+ ASSERT_KNOWN_EQ (upper_bound (ph::make (6, 5, -14), ph::make (-11, 4, 3)),
+ ph::make (-11, 5, -14));
+}
+
+/* Test maybe_in_range_p for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_maybe_in_range_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Unknown size for N == 1. */
+ ASSERT_TRUE (maybe_in_range_p (ch::make (-1),
+ ch::make (0),
+ ph::make (-1, -1, -1)));
+ /* Unknown size for all N. */
+ ASSERT_TRUE (maybe_in_range_p (ph::make (-1, -1, -1),
+ ch::make (0),
+ ch::make (-1)));
+ /* Unknown size for N == 1. */
+ ASSERT_EQ (maybe_in_range_p (ph::make (-1, -1, -1),
+ ch::make (0),
+ ph::make (-1, -1, -1)), N == 1);
+ ASSERT_EQ (maybe_in_range_p (ch::make (-2),
+ ch::make (0),
+ ph::make (-2, -2, -2)), N >= 2);
+ ASSERT_FALSE (maybe_in_range_p (ph::make (-2, -2, -2),
+ ch::make (0),
+ ch::make (-2)));
+ ASSERT_FALSE (maybe_in_range_p (ph::make (-2, -2, -2),
+ ch::make (0),
+ ph::make (-2, -2, -2)));
+ ASSERT_TRUE (maybe_in_range_p (ph::make (-2, -2, -2),
+ ch::make (1),
+ ph::make (-2, -2, -2)));
+ ASSERT_TRUE (maybe_in_range_p (ph::make (-2, -2, -2),
+ ch::make (1),
+ ch::make (-2)));
+}
+
+/* Test known_in_range_p for unsigned C. */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_unsigned_known_in_range_p ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ ASSERT_FALSE (known_in_range_p (ch::make (4),
+ ph::make (5, 1, 2),
+ ch::make (-2)));
+ ASSERT_TRUE (known_in_range_p (ph::make (6, 1, 2),
+ ph::make (5, 1, 2),
+ ch::make (-2)));
+ ASSERT_TRUE (known_in_range_p (ph::make (6, 1, 2),
+ ph::make (5, 1, 2),
+ ph::make (-2, -2, -2)));
+}
+
+/* Test things that work for poly_int-based types T, given that the
+ coefficient type C is a primitive integer type. N is the number of
+ coefficients in C */
+
+template<unsigned int N, typename C, typename T>
+static void
+test_hwi ()
+{
+ typedef coeff_helper<C> ch;
+ typedef poly_helper<T> ph;
+
+ /* Test coeff_gcd. */
+ ASSERT_EQ (coeff_gcd (ph::make (30, 45, 10)),
+ N == 1 ? 30 : N == 2 ? 15 : 5);
+ ASSERT_EQ (coeff_gcd (ph::make (0, 18, 21)),
+ N == 1 ? 0 : N == 2 ? 18 : 3);
+ ASSERT_EQ (coeff_gcd (ph::make (0, 0, 101)),
+ N <= 2 ? 0 : 101);
+ ASSERT_EQ (coeff_gcd (ph::make (21, 0, 28)),
+ N <= 2 ? 21 : 7);
+ ASSERT_EQ (coeff_gcd (ph::make (100, 175, 0)),
+ N == 1 ? 100 : 25);
+
+ /* Test common_multiple (T, C). */
+ ASSERT_KNOWN_EQ (common_multiple (ph::make (8, 24, 16), 6),
+ ph::make (24, 72, 48));
+ ASSERT_KNOWN_EQ (common_multiple (ph::make (30, 0, 0), 45),
+ ch::make (90));
+ if (N >= 2)
+ ASSERT_KNOWN_EQ (common_multiple (ph::make (18, 15, 0), 12),
+ ph::make (72, 60, 0));
+ if (N == 3)
+ ASSERT_KNOWN_EQ (common_multiple (ph::make (18, 15, 4), 12),
+ ph::make (216, 180, 48));
+
+ /* Test common_multiple (C, T). */
+ ASSERT_KNOWN_EQ (common_multiple (6, ph::make (8, 24, 16)),
+ ph::make (24, 72, 48));
+ ASSERT_KNOWN_EQ (common_multiple (45, ph::make (30, 0, 0)),
+ ch::make (90));
+ if (N >= 2)
+ ASSERT_KNOWN_EQ (common_multiple (12, ph::make (18, 15, 0)),
+ ph::make (72, 60, 0));
+ if (N == 3)
+ ASSERT_KNOWN_EQ (common_multiple (12, ph::make (18, 15, 4)),
+ ph::make (216, 180, 48));
+
+ /* Test force_common_multiple. */
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (30, 0, 0),
+ ph::make (25, 0, 0)),
+ ph::make (150, 0, 0));
+ if (N >= 2)
+ {
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (16, 24, 0),
+ ph::make (24, 36, 0)),
+ ph::make (48, 72, 0));
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (16, 24, 0),
+ ph::make (12, 0, 0)),
+ ph::make (48, 72, 0));
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (15, 0, 0),
+ ph::make (21, 9, 0)),
+ ph::make (105, 45, 0));
+ }
+ if (N == 3)
+ {
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (33, 99, 66),
+ ph::make (22, 66, 44)),
+ ph::make (66, 198, 132));
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (30, 0, 45),
+ ph::make (12, 0, 18)),
+ ph::make (60, 0, 90));
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (40, 0, 50),
+ ph::make (8, 0, 0)),
+ ph::make (160, 0, 200));
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (6, 0, 0),
+ ph::make (10, 0, 15)),
+ ph::make (60, 0, 90));
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (20, 40, 30),
+ ph::make (15, 0, 0)),
+ ph::make (60, 120, 90));
+ ASSERT_KNOWN_EQ (force_common_multiple (ph::make (9, 0, 0),
+ ph::make (90, 81, 27)),
+ ph::make (90, 81, 27));
+ }
+}
+
+/* Test poly_int<N, C>::to_shwi, using in-range source coefficient value
+ SRCV (equal to DESTV) and adding DELTA to get an out-of-range value. */
+
+template<unsigned int N, typename C>
+static void
+test_to_shwi (const C &srcv, int delta, HOST_WIDE_INT destv)
+{
+ typedef poly_helper< poly_int<N, HOST_WIDE_INT> > ps64h;
+ typedef poly_int<N, C> T;
+ typedef poly_helper<T> ph;
+ poly_int<N, HOST_WIDE_INT> shwi;
+
+ /* Test in-range T::to_shwi. */
+ ASSERT_TRUE (ph::make (srcv,
+ srcv - delta,
+ srcv - delta * 2).to_shwi (&shwi));
+ ASSERT_KNOWN_EQ (shwi, ps64h::make (destv,
+ destv - delta,
+ destv - delta * 2));
+
+ /* Test partially in-range T::to_shwi. */
+ ASSERT_EQ (ph::make (srcv,
+ srcv + delta,
+ srcv + delta * 2).to_shwi (&shwi), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (shwi, destv);
+ ASSERT_EQ (ph::make (srcv - delta,
+ srcv,
+ srcv + delta).to_shwi (&shwi), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (shwi, ps64h::make (destv - delta,
+ destv,
+ destv /* ignored */));
+
+ /* Test fully out-of-range T::to_shwi. */
+ ASSERT_FALSE (ph::make (srcv + delta, srcv, srcv).to_shwi (&shwi));
+}
+
+/* Test poly_int<N, C>::to_uhwi, using in-range source coefficient value
+ SRCV (equal to DESTV) and adding DELTA to get an out-of-range value. */
+
+template<unsigned int N, typename C>
+static void
+test_to_uhwi (const C &srcv, int delta, unsigned HOST_WIDE_INT destv)
+{
+ typedef poly_helper< poly_int<N, unsigned HOST_WIDE_INT> > pu64h;
+ typedef poly_int<N, C> T;
+ typedef poly_helper<T> ph;
+ poly_int<N, unsigned HOST_WIDE_INT> uhwi;
+
+ /* Test in-range T::to_uhwi. */
+ ASSERT_TRUE (ph::make (srcv,
+ srcv - delta,
+ srcv - delta * 2).to_uhwi (&uhwi));
+ ASSERT_KNOWN_EQ (uhwi, pu64h::make (destv,
+ destv - delta,
+ destv - delta * 2));
+
+ /* Test partially in-range T::to_uhwi. */
+ ASSERT_EQ (ph::make (srcv,
+ srcv + delta,
+ srcv + delta * 2).to_uhwi (&uhwi), N == 1);
+ if (N == 1)
+ ASSERT_KNOWN_EQ (uhwi, destv);
+ ASSERT_EQ (ph::make (srcv - delta,
+ srcv,
+ srcv + delta).to_uhwi (&uhwi), N <= 2);
+ if (N <= 2)
+ ASSERT_KNOWN_EQ (uhwi, pu64h::make (destv - delta,
+ destv,
+ destv /* ignored */));
+
+ /* Test fully out-of-range T::to_uhwi. */
+ ASSERT_FALSE (ph::make (srcv + delta, srcv, srcv).to_uhwi (&uhwi));
+}
+
+/* Test poly_int<N, C>::force_shwi and poly_int<N, C>::force_uhwi, given
+ that MASK66 has the low 66 bits set and the rest clear. */
+
+template<unsigned int N, typename C>
+static void
+test_force_hwi (const C &mask66)
+{
+ typedef poly_helper< poly_int<N, HOST_WIDE_INT> > ps64h;
+ typedef poly_helper< poly_int<N, unsigned HOST_WIDE_INT> > pu64h;
+ typedef poly_int<N, C> T;
+ typedef poly_helper<T> ph;
+ poly_int<N, HOST_WIDE_INT> shwi;
+ poly_int<N, unsigned HOST_WIDE_INT> uhwi;
+
+ C mask65 = wi::arshift (mask66, 1);
+ C mask64 = wi::arshift (mask66, 2);
+ C mask63 = wi::arshift (mask66, 3);
+ C mask62 = wi::arshift (mask66, 4);
+ C mask61 = wi::arshift (mask66, 5);
+
+ /* Test force_shwi. */
+ ASSERT_KNOWN_EQ (ph::make (mask66, mask65, mask64).force_shwi (),
+ ps64h::make (HOST_WIDE_INT_M1,
+ HOST_WIDE_INT_M1,
+ HOST_WIDE_INT_M1));
+ ASSERT_KNOWN_EQ (ph::make (mask65, mask64, mask63).force_shwi (),
+ ps64h::make (HOST_WIDE_INT_M1,
+ HOST_WIDE_INT_M1,
+ HOST_WIDE_INT_MAX));
+ ASSERT_KNOWN_EQ (ph::make (mask64, mask63, mask62).force_shwi (),
+ ps64h::make (HOST_WIDE_INT_M1,
+ HOST_WIDE_INT_MAX,
+ HOST_WIDE_INT_MAX / 2));
+ ASSERT_KNOWN_EQ (ph::make (mask63, mask62, mask61).force_shwi (),
+ ps64h::make (HOST_WIDE_INT_MAX,
+ HOST_WIDE_INT_MAX / 2,
+ HOST_WIDE_INT_MAX / 4));
+
+ /* Test force_uhwi. */
+ ASSERT_KNOWN_EQ (ph::make (mask66, mask65, mask64).force_uhwi (),
+ pu64h::make (HOST_WIDE_INT_M1U,
+ HOST_WIDE_INT_M1U,
+ HOST_WIDE_INT_M1U));
+ ASSERT_KNOWN_EQ (ph::make (mask65, mask64, mask63).force_uhwi (),
+ pu64h::make (HOST_WIDE_INT_M1U,
+ HOST_WIDE_INT_M1U,
+ HOST_WIDE_INT_M1U >> 1));
+ ASSERT_KNOWN_EQ (ph::make (mask64, mask63, mask62).force_uhwi (),
+ pu64h::make (HOST_WIDE_INT_M1U,
+ HOST_WIDE_INT_M1U >> 1,
+ HOST_WIDE_INT_M1U >> 2));
+ ASSERT_KNOWN_EQ (ph::make (mask63, mask62, mask61).force_uhwi (),
+ pu64h::make (HOST_WIDE_INT_M1U >> 1,
+ HOST_WIDE_INT_M1U >> 2,
+ HOST_WIDE_INT_M1U >> 3));
+}
+
+/* Test poly_int<N, wide_int>::from. */
+
+template<unsigned int N>
+static void
+test_wide_int_from ()
+{
+ typedef poly_helper< poly_int<N, unsigned char> > pu8h;
+ typedef poly_int<N, wide_int> T;
+ typedef poly_helper<T> ph;
+
+ /* Test narrowing cases of T::from. */
+ T p_8_3_1 = ph::make (wi::uhwi (8, 3),
+ wi::uhwi (3, 3),
+ wi::uhwi (1, 3));
+ ASSERT_KNOWN_EQ (T::from (pu8h::make (0xf8,0x23,0x81), 3, SIGNED),
+ p_8_3_1);
+ ASSERT_KNOWN_EQ (T::from (pu8h::make (0xf8,0x23,0x81), 3, UNSIGNED),
+ p_8_3_1);
+
+ /* Test equal-sized cases of T::from. */
+ T p_f8_23_81 = ph::make (wi::uhwi (0xf8, 8),
+ wi::uhwi (0x23, 8),
+ wi::uhwi (0x81, 8));
+ ASSERT_KNOWN_EQ (T::from (pu8h::make (0xf8,0x23,0x81), 8, SIGNED),
+ p_f8_23_81);
+ ASSERT_KNOWN_EQ (T::from (pu8h::make (0xf8,0x23,0x81), 8, UNSIGNED),
+ p_f8_23_81);
+
+ /* Test widening cases of T::from. */
+ T p_fff8_0023_ff81 = ph::make (wi::uhwi (0xfff8, 16),
+ wi::uhwi (0x0023, 16),
+ wi::uhwi (0xff81, 16));
+ ASSERT_KNOWN_EQ (T::from (pu8h::make (0xf8,0x23,0x81), 16, SIGNED),
+ p_fff8_0023_ff81);
+ T p_00f8_0023_0081 = ph::make (wi::uhwi (0xf8, 16),
+ wi::uhwi (0x23, 16),
+ wi::uhwi (0x81, 16));
+ ASSERT_KNOWN_EQ (T::from (pu8h::make (0xf8,0x23,0x81), 16, UNSIGNED),
+ p_00f8_0023_0081);
+}
+
+/* Test wi::sext for poly_int<N, wide_int>. */
+
+template<unsigned int N>
+static void
+test_wide_int_sext ()
+{
+ typedef poly_int<N, wide_int> T;
+ typedef poly_helper<T> ph;
+
+ ASSERT_KNOWN_EQ (wi::sext (ph::make (wi::shwi (16, 12),
+ wi::shwi (63, 12),
+ wi::shwi (14, 12)), 5),
+ ph::make (wi::shwi (-16, 12),
+ wi::shwi (-1, 12),
+ wi::shwi (14, 12)));
+ ASSERT_KNOWN_EQ (wi::sext (ph::make (wi::shwi (1024, 12),
+ wi::shwi (1023, 12),
+ wi::shwi (1200, 12)), 11),
+ ph::make (wi::shwi (-1024, 12),
+ wi::shwi (1023, 12),
+ wi::shwi (-848, 12)));
+}
+
+/* Test wi::zext for poly_int<N, wide_int>. */
+
+template<unsigned int N>
+static void
+test_wide_int_zext ()
+{
+ typedef poly_int<N, wide_int> T;
+ typedef poly_helper<T> ph;
+
+ ASSERT_KNOWN_EQ (wi::zext (ph::make (wi::uhwi (16, 12),
+ wi::uhwi (63, 12),
+ wi::uhwi (14, 12)), 5),
+ ph::make (wi::uhwi (16, 12),
+ wi::uhwi (31, 12),
+ wi::uhwi (14, 12)));
+ ASSERT_KNOWN_EQ (wi::zext (ph::make (wi::uhwi (1024, 12),
+ wi::uhwi (1023, 12),
+ wi::uhwi (3248, 12)), 11),
+ ph::make (wi::uhwi (1024, 12),
+ wi::uhwi (1023, 12),
+ wi::uhwi (1200, 12)));
+}
+
+/* Test wi::add for poly_int<N, wide_int>. */
+
+template<unsigned int N>
+static void
+test_wide_int_add ()
+{
+ typedef poly_int<N, wide_int> T;
+ typedef poly_helper<T> ph;
+
+ bool overflow;
+ ASSERT_KNOWN_EQ (wi::add (ph::make (wi::uhwi (15, 4),
+ wi::uhwi (4, 4),
+ wi::uhwi (2, 4)),
+ ph::make (wi::uhwi (1, 4),
+ wi::uhwi (0, 4),
+ wi::uhwi (0, 4)),
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (0, 4),
+ wi::uhwi (4, 4),
+ wi::uhwi (2, 4)));
+ ASSERT_TRUE (overflow);
+ ASSERT_KNOWN_EQ (wi::add (ph::make (wi::uhwi (30, 5),
+ wi::uhwi (6, 5),
+ wi::uhwi (11, 5)),
+ ph::make (wi::uhwi (1, 5),
+ wi::uhwi (26, 5),
+ wi::uhwi (19, 5)),
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (31, 5),
+ wi::uhwi (0, 5),
+ wi::uhwi (30, 5)));
+ ASSERT_EQ (overflow, N >= 2);
+ ASSERT_KNOWN_EQ (wi::add (ph::make (wi::uhwi (1, 6),
+ wi::uhwi (63, 6),
+ wi::uhwi (50, 6)),
+ ph::make (wi::uhwi (61, 6),
+ wi::uhwi (0, 6),
+ wi::uhwi (50, 6)),
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (62, 6),
+ wi::uhwi (63, 6),
+ wi::uhwi (36, 6)));
+ ASSERT_EQ (overflow, N == 3);
+
+ ASSERT_KNOWN_EQ (wi::add (ph::make (wi::shwi (7, 4),
+ wi::shwi (7, 4),
+ wi::shwi (-8, 4)),
+ ph::make (wi::shwi (1, 4),
+ wi::shwi (0, 4),
+ wi::shwi (0, 4)),
+ SIGNED, &overflow),
+ ph::make (wi::shwi (-8, 4),
+ wi::shwi (7, 4),
+ wi::shwi (-8, 4)));
+ ASSERT_TRUE (overflow);
+ ASSERT_KNOWN_EQ (wi::add (ph::make (wi::shwi (-1, 5),
+ wi::shwi (6, 5),
+ wi::shwi (11, 5)),
+ ph::make (wi::shwi (15, 5),
+ wi::shwi (11, 5),
+ wi::shwi (-15, 5)),
+ SIGNED, &overflow),
+ ph::make (wi::shwi (14, 5),
+ wi::shwi (-15, 5),
+ wi::shwi (-4, 5)));
+ ASSERT_EQ (overflow, N >= 2);
+ ASSERT_KNOWN_EQ (wi::add (ph::make (wi::shwi (4, 6),
+ wi::shwi (0, 6),
+ wi::shwi (-1, 6)),
+ ph::make (wi::shwi (-32, 6),
+ wi::shwi (-32, 6),
+ wi::shwi (-32, 6)),
+ SIGNED, &overflow),
+ ph::make (wi::shwi (-28, 6),
+ wi::shwi (-32, 6),
+ wi::shwi (31, 6)));
+ ASSERT_EQ (overflow, N == 3);
+}
+
+/* Test wi::sub for poly_int<N, wide_int>. */
+
+template<unsigned int N>
+static void
+test_wide_int_sub ()
+{
+ typedef poly_int<N, wide_int> T;
+ typedef poly_helper<T> ph;
+
+ bool overflow;
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (wi::uhwi (0, 4),
+ wi::uhwi (4, 4),
+ wi::uhwi (2, 4)),
+ ph::make (wi::uhwi (1, 4),
+ wi::uhwi (0, 4),
+ wi::uhwi (0, 4)),
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (15, 4),
+ wi::uhwi (4, 4),
+ wi::uhwi (2, 4)));
+ ASSERT_TRUE (overflow);
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (wi::uhwi (30, 5),
+ wi::uhwi (29, 5),
+ wi::uhwi (11, 5)),
+ ph::make (wi::uhwi (1, 5),
+ wi::uhwi (31, 5),
+ wi::uhwi (9, 5)),
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (29, 5),
+ wi::uhwi (30, 5),
+ wi::uhwi (2, 5)));
+ ASSERT_EQ (overflow, N >= 2);
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (wi::uhwi (0, 6),
+ wi::uhwi (63, 6),
+ wi::uhwi (0, 6)),
+ ph::make (wi::uhwi (0, 6),
+ wi::uhwi (0, 6),
+ wi::uhwi (52, 6)),
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (0, 6),
+ wi::uhwi (63, 6),
+ wi::uhwi (12, 6)));
+ ASSERT_EQ (overflow, N == 3);
+
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (wi::shwi (-8, 4),
+ wi::shwi (5, 4),
+ wi::shwi (-7, 4)),
+ ph::make (wi::shwi (1, 4),
+ wi::shwi (0, 4),
+ wi::shwi (0, 4)),
+ SIGNED, &overflow),
+ ph::make (wi::shwi (7, 4),
+ wi::shwi (5, 4),
+ wi::shwi (-7, 4)));
+ ASSERT_TRUE (overflow);
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (wi::shwi (-1, 5),
+ wi::shwi (-7, 5),
+ wi::shwi (0, 5)),
+ ph::make (wi::shwi (15, 5),
+ wi::shwi (11, 5),
+ wi::shwi (-15, 5)),
+ SIGNED, &overflow),
+ ph::make (wi::shwi (-16, 5),
+ wi::shwi (14, 5),
+ wi::shwi (15, 5)));
+ ASSERT_EQ (overflow, N >= 2);
+ ASSERT_KNOWN_EQ (wi::sub (ph::make (wi::shwi (-32, 6),
+ wi::shwi (-1, 6),
+ wi::shwi (0, 6)),
+ ph::make (wi::shwi (-32, 6),
+ wi::shwi (-32, 6),
+ wi::shwi (-32, 6)),
+ SIGNED, &overflow),
+ ph::make (wi::shwi (0, 6),
+ wi::shwi (31, 6),
+ wi::shwi (-32, 6)));
+ ASSERT_EQ (overflow, N == 3);
+}
+
+/* Test wi::mul for poly_int<N, wide_int>. */
+
+template<unsigned int N>
+static void
+test_wide_int_mul ()
+{
+ typedef poly_int<N, wide_int> T;
+ typedef poly_helper<T> ph;
+
+ bool overflow;
+ ASSERT_KNOWN_EQ (wi::mul (ph::make (wi::uhwi (4, 4),
+ wi::uhwi (3, 4),
+ wi::uhwi (2, 4)), 4,
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (0, 4),
+ wi::uhwi (12, 4),
+ wi::uhwi (8, 4)));
+ ASSERT_TRUE (overflow);
+ ASSERT_KNOWN_EQ (wi::mul (ph::make (wi::uhwi (15, 5),
+ wi::uhwi (31, 5),
+ wi::uhwi (7, 5)), 2,
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (30, 5),
+ wi::uhwi (30, 5),
+ wi::uhwi (14, 5)));
+ ASSERT_EQ (overflow, N >= 2);
+ ASSERT_KNOWN_EQ (wi::mul (ph::make (wi::uhwi (1, 6),
+ wi::uhwi (0, 6),
+ wi::uhwi (2, 6)), 63,
+ UNSIGNED, &overflow),
+ ph::make (wi::uhwi (63, 6),
+ wi::uhwi (0, 6),
+ wi::uhwi (62, 6)));
+ ASSERT_EQ (overflow, N == 3);
+
+ ASSERT_KNOWN_EQ (wi::mul (ph::make (wi::shwi (-1, 4),
+ wi::shwi (1, 4),
+ wi::shwi (0, 4)), -8,
+ SIGNED, &overflow),
+ ph::make (wi::shwi (-8, 4),
+ wi::shwi (-8, 4),
+ wi::shwi (0, 4)));
+ ASSERT_TRUE (overflow);
+ ASSERT_KNOWN_EQ (wi::mul (ph::make (wi::shwi (2, 5),
+ wi::shwi (-3, 5),
+ wi::shwi (1, 5)), 6,
+ SIGNED, &overflow),
+ ph::make (wi::shwi (12, 5),
+ wi::shwi (14, 5),
+ wi::shwi (6, 5)));
+ ASSERT_EQ (overflow, N >= 2);
+ ASSERT_KNOWN_EQ (wi::mul (ph::make (wi::shwi (5, 6),
+ wi::shwi (-6, 6),
+ wi::shwi (7, 6)), -5,
+ SIGNED, &overflow),
+ ph::make (wi::shwi (-25, 6),
+ wi::shwi (30, 6),
+ wi::shwi (29, 6)));
+ ASSERT_EQ (overflow, N == 3);
+}
+
+/* Test wi::neg for poly_int<N, wide_int>. */
+
+template<unsigned int N>
+static void
+test_wide_int_neg ()
+{
+ typedef poly_int<N, wide_int> T;
+ typedef poly_helper<T> ph;
+
+ bool overflow;
+ ASSERT_KNOWN_EQ (wi::neg (ph::make (wi::shwi (-8, 4),
+ wi::shwi (7, 4),
+ wi::shwi (-7, 4)), &overflow),
+ ph::make (wi::shwi (-8, 4),
+ wi::shwi (-7, 4),
+ wi::shwi (7, 4)));
+ ASSERT_TRUE (overflow);
+ ASSERT_KNOWN_EQ (wi::neg (ph::make (wi::shwi (-15, 5),
+ wi::shwi (-16, 5),
+ wi::shwi (15, 5)), &overflow),
+ ph::make (wi::shwi (15, 5),
+ wi::shwi (-16, 5),
+ wi::shwi (-15, 5)));
+ ASSERT_EQ (overflow, N >= 2);
+ ASSERT_KNOWN_EQ (wi::neg (ph::make (wi::shwi (-28, 6),
+ wi::shwi (30, 6),
+ wi::shwi (-32, 6)), &overflow),
+ ph::make (wi::shwi (28, 6),
+ wi::shwi (-30, 6),
+ wi::shwi (-32, 6)));
+ ASSERT_EQ (overflow, N == 3);
+}
+
+/* Test poly_int<N, C> for things that only make sense when C is an
+ offset_int or widest_int. */
+
+template<unsigned int N, typename C>
+static void
+test_fixed_int (void)
+{
+ typedef poly_helper< poly_int<N, int> > pih;
+ typedef poly_int<N, C> T;
+ typedef poly_helper<T> ph;
+
+ /* Test signed case. */
+ ASSERT_KNOWN_EQ (T::from (pih::make (-100, 200, -300), SIGNED),
+ ph::make (-100, 200, -300));
+ ASSERT_MAYBE_NE (T::from (pih::make (-100, 200, -300), SIGNED),
+ ph::make (-100U, 200U, -300U));
+
+ /* Test unsigned case. */
+ ASSERT_MAYBE_NE (T::from (pih::make (-100, 200, -300), UNSIGNED),
+ ph::make (-100, 200, -300));
+ ASSERT_KNOWN_EQ (T::from (pih::make (-100, 200, -300), UNSIGNED),
+ ph::make (-100U, 200U, -300U));
+
+ C one = 1;
+ test_to_shwi<N> (-(one << 63), -1, HOST_WIDE_INT_MIN);
+ test_to_shwi<N> ((one << 63) - 1, 1, HOST_WIDE_INT_MAX);
+ test_to_uhwi<N> (C (0), -1, 0U);
+ test_to_uhwi<N> ((one << 64) - 1, 1, HOST_WIDE_INT_M1U);
+
+ /* Test force_shwi and force_uhwi. */
+ test_force_hwi<N> ((one << 66) - 1);
+}
+
+/* Test type promotions. */
+
+template<unsigned int N>
+static void
+test_type_promotions ()
+{
+ typedef poly_helper< poly_int<N, unsigned short> > pu16h;
+ typedef poly_helper< poly_int<N, HOST_WIDE_INT> > ps64h;
+ HOST_WIDE_INT mask32 = ~0U;
+
+ /* Test that + on unsigned short promotes to HOST_WIDE_INT. */
+ ASSERT_KNOWN_EQ (pu16h::make (0xffff, 0xfffe, 0xfffd) + 16,
+ ps64h::make (0x1000f, 0xfffe, 0xfffd));
+ ASSERT_KNOWN_EQ (32 + pu16h::make (0xffff, 0xfffe, 0xfffd),
+ ps64h::make (0x1001f, 0xfffe, 0xfffd));
+ ASSERT_KNOWN_EQ (pu16h::make (0xffff, 0xfffe, 0xfffd)
+ + pu16h::make (4, 10, 17),
+ ps64h::make (0x10003, 0x10008, 0x1000e));
+
+ /* Test that - on unsigned short promotes to HOST_WIDE_INT. */
+ ASSERT_KNOWN_EQ (pu16h::make (1, 2, 3) - ~0U,
+ ps64h::make (-mask32 + 1, 2, 3));
+ ASSERT_KNOWN_EQ (INT_MIN - pu16h::make (4, 5, 6),
+ ps64h::make ((HOST_WIDE_INT) INT_MIN - 4, -5, -6));
+ ASSERT_KNOWN_EQ (pu16h::make (1, 2, 3) - pu16h::make (100, 200, 300),
+ ps64h::make (-99, -198, -297));
+
+ /* Same for unary -. */
+ ASSERT_KNOWN_EQ (-pu16h::make (0x8000, 0x9000, 0xa000),
+ ps64h::make (-0x8000, -0x9000, -0xa000));
+ ASSERT_MAYBE_NE (-pu16h::make (0x8000, 0x9000, 0xa000),
+ ps64h::make (0x8000, 0x9000, 0xa000));
+
+ /* Test that * on unsigned short promotes to HOST_WIDE_INT. */
+ ASSERT_KNOWN_EQ (pu16h::make (10, 14, 17) * ~0U,
+ ps64h::make (10 * mask32, 14 * mask32, 17 * mask32));
+ ASSERT_KNOWN_EQ (-400000 * pu16h::make (10, 14, 17),
+ ps64h::make (-4000000, -5600000, -6800000));
+
+ /* Test that << on unsigned short promotes to HOST_WIDE_INT. */
+ ASSERT_KNOWN_EQ (pu16h::make (4, 5, 6) << 50,
+ ps64h::make ((HOST_WIDE_INT) 4 << 50,
+ (HOST_WIDE_INT) 5 << 50,
+ (HOST_WIDE_INT) 6 << 50));
+
+ /* Test that can_align_up doesn't truncate to the type of the alignment. */
+ poly_int<N, HOST_WIDE_INT> aligned;
+ HOST_WIDE_INT a = (HOST_WIDE_INT_1 << 50);
+ HOST_WIDE_INT b = (HOST_WIDE_INT_1 << 51);
+ HOST_WIDE_INT c = (HOST_WIDE_INT_1 << 52);
+ ASSERT_TRUE (can_align_up (ps64h::make (a - 31, b, c), 16U, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ps64h::make (a - 16, b, c));
+
+ /* Likewise for can_align_down. */
+ ASSERT_TRUE (can_align_down (ps64h::make (a - 31, b, c), 16U, &aligned));
+ ASSERT_KNOWN_EQ (aligned, ps64h::make (a - 32, b, c));
+
+ /* Same for the force_* routines. */
+ ASSERT_KNOWN_EQ (force_align_up (ps64h::make (a - 31, b, c), 16U),
+ ps64h::make (a - 16, b, c));
+ ASSERT_KNOWN_EQ (force_align_down (ps64h::make (a - 31, b, c), 16U),
+ ps64h::make (a - 32, b, c));
+
+ /* Same for the aligned_*_bound routines. */
+ ASSERT_KNOWN_EQ (aligned_upper_bound (ps64h::make (a - 31, b - 33, c - 55),
+ 16U),
+ ps64h::make (a - 16, b - 32, c - 48));
+ ASSERT_KNOWN_EQ (aligned_lower_bound (ps64h::make (a - 31, b - 33, c - 55),
+ 16U),
+ ps64h::make (a - 32, b - 48, c - 64));
+}
+
+/* Test endpoint_representable_p. */
+
+static void
+test_endpoint_representable (void)
+{
+ /* True because the size is unknown. */
+ ASSERT_TRUE (endpoint_representable_p ((unsigned char) 0x80,
+ (unsigned char) 0xff));
+ ASSERT_FALSE (endpoint_representable_p ((unsigned char) 0x80,
+ (unsigned char) 0xfe));
+ ASSERT_FALSE (endpoint_representable_p ((unsigned char) 0x80,
+ (unsigned char) 0x80));
+ ASSERT_TRUE (endpoint_representable_p ((unsigned char) 0x80,
+ (unsigned char) 0x7f));
+ ASSERT_FALSE (endpoint_representable_p ((unsigned char) 0x11,
+ (unsigned char) 0xef));
+ ASSERT_TRUE (endpoint_representable_p ((unsigned char) 0x11,
+ (unsigned char) 0xee));
+
+ /* True because the size is unknown. */
+ ASSERT_TRUE (endpoint_representable_p (INT_MAX, -1));
+ ASSERT_FALSE (endpoint_representable_p (INT_MAX - 100, INT_MAX));
+ ASSERT_FALSE (endpoint_representable_p (INT_MAX - 100, 101));
+ ASSERT_TRUE (endpoint_representable_p (INT_MAX - 100, 100));
+ ASSERT_TRUE (endpoint_representable_p (0, INT_MAX));
+ ASSERT_TRUE (endpoint_representable_p (INT_MIN, INT_MAX));
+
+ /* True because the size is unknown. */
+ ASSERT_TRUE (endpoint_representable_p (UINT_MAX, -1U));
+ ASSERT_FALSE (endpoint_representable_p (UINT_MAX - 400, UINT_MAX - 1));
+ ASSERT_FALSE (endpoint_representable_p (UINT_MAX - 400, 401U));
+ ASSERT_TRUE (endpoint_representable_p (UINT_MAX - 400, 400U));
+}
+
+/* Test wi::shwi with N coefficients. */
+
+template<unsigned int N>
+static void
+test_shwi ()
+{
+ typedef poly_int<N, wi::hwi_with_prec> T;
+ typedef poly_helper<T> ph;
+
+ poly_int<N, wide_int> mult;
+ mult = ph::make (wi::shwi (80, 16),
+ wi::shwi (-10, 16),
+ wi::shwi (70, 16)) * 3;
+ ASSERT_KNOWN_EQ (mult, ph::make (wi::shwi (240, 16),
+ wi::shwi (-30, 16),
+ wi::shwi (210, 16)));
+}
+
+/* Test wi::uhwi with N coefficients. */
+
+template<unsigned int N>
+static void
+test_uhwi ()
+{
+ typedef poly_int<N, wi::hwi_with_prec> T;
+ typedef poly_helper<T> ph;
+
+ poly_int<N, wide_int> mult;
+ mult = ph::make (wi::uhwi (80, 16),
+ wi::uhwi (-10, 16),
+ wi::uhwi (70, 16)) * 3;
+ ASSERT_KNOWN_EQ (mult, ph::make (wi::uhwi (240, 16),
+ wi::uhwi (-30, 16),
+ wi::uhwi (210, 16)));
+}
+
+/* Test known_size_p for non-polynomial T. */
+
+template<typename T>
+static void
+test_nonpoly_known_size_p ()
+{
+ ASSERT_TRUE (known_size_p (T (0)));
+ ASSERT_TRUE (known_size_p (T (1)));
+ ASSERT_TRUE (known_size_p (T (2)));
+ ASSERT_FALSE (known_size_p (T (-1)));
+}
+
+/* Test poly-int.h operations on non-polynomial type T. */
+
+template<typename T>
+static void
+test_nonpoly_type ()
+{
+ test_nonpoly_known_size_p<T> ();
+}
+
+/* Test poly-int.h operations on non-polynomial values. */
+
+static void
+test_nonpoly ()
+{
+ test_nonpoly_type<unsigned char> ();
+ test_nonpoly_type<unsigned short> ();
+ test_nonpoly_type<int> ();
+ test_nonpoly_type<unsigned int> ();
+ test_nonpoly_type<HOST_WIDE_INT> ();
+ test_nonpoly_type<unsigned HOST_WIDE_INT> ();
+ test_nonpoly_type<offset_int> ();
+ test_nonpoly_type<widest_int> ();
+}
+
+/* Test things that work for all poly_int-based types T, given that T
+ has N coefficients of type C. RC is the type to which C promotes
+ after an operator. */
+
+template<unsigned int N, typename C, typename RC, typename T>
+static void
+test_general ()
+{
+ test_poly_int_traits<N, C, T> ();
+ test_constants<N, C, T> ();
+ test_plus_equals<N, C, T> ();
+ test_minus_equals<N, C, T> ();
+ test_times_equals<N, C, T> ();
+ test_shl_equals<N, C, T> ();
+ test_is_constant<N, C, T> ();
+ test_to_constant<N, C, T> ();
+ test_addition<N, C, T> ();
+ test_subtraction<N, C, RC, T> ();
+ test_negation<N, C, RC, T> ();
+ test_multiplication<N, C, T> ();
+ test_shift_left<N, C, T> ();
+ test_maybe_ne<N, C, T> ();
+ test_known_eq<N, C, T> ();
+ test_can_align_p<N, C, T> ();
+ test_can_align_up<N, C, T> ();
+ test_can_align_down<N, C, T> ();
+ test_known_equal_after_align_up<N, C, T> ();
+ test_known_equal_after_align_down<N, C, T> ();
+ test_force_align_up<N, C, T> ();
+ test_force_align_down<N, C, T> ();
+ test_aligned_lower_bound<N, C, T> ();
+ test_aligned_upper_bound<N, C, T> ();
+ test_known_misalignment<N, C, T> ();
+ test_force_get_misalignment<N, C, T> ();
+ test_known_alignment<N, C, T> ();
+ test_can_ior_p<N, C, T> ();
+ test_known_size_p<N, C, T> ();
+}
+
+/* Test things that work for poly_int<2, C>, given that C is signed. */
+
+template<typename C>
+static void
+test_ordered_2 ()
+{
+ test_maybe_eq_2<C> ();
+ test_known_ne_2<C> ();
+}
+
+/* Test things that work for poly_int-based types T, given that the
+ coefficient type C supports all the normal C operators. N is the
+ number of coefficients in C and RC is the type to which C promotes
+ after an operator. */
+
+template<unsigned int N, typename C, typename RC, typename T>
+static void
+test_ordered ()
+{
+ test_general<N, C, RC, T> ();
+ test_maybe_le<N, C, T> ();
+ test_maybe_lt<N, C, T> ();
+ test_maybe_ge<N, C, T> ();
+ test_maybe_gt<N, C, T> ();
+ test_known_gt<N, C, T> ();
+ test_known_ge<N, C, T> ();
+ test_known_lt<N, C, T> ();
+ test_known_le<N, C, T> ();
+ test_ordered_p<N, C, T> ();
+ test_ordered_min<N, C, T> ();
+ test_ordered_max<N, C, T> ();
+ test_constant_lower_bound<N, C, T> ();
+ test_lower_bound<N, C, T> ();
+ test_upper_bound<N, C, T> ();
+ test_compare_sizes_for_sort<N, C, T> ();
+ test_force_align_up_and_div<N, C, T> ();
+ test_force_align_down_and_div<N, C, T> ();
+ test_constant_multiple_p<N, C, T> ();
+ test_multiple_p<N, C, T> ();
+ test_multiple_p_with_result<N, C, T> ();
+ test_exact_div<N, C, T> ();
+ test_can_div_trunc_p_const<N, C, T> ();
+ test_can_div_trunc_p_poly<N, C, T> ();
+ test_can_div_away_from_zero_p<N, C, T> ();
+ test_maybe_in_range_p<N, C, T> ();
+ test_known_in_range_p<N, C, T> ();
+ test_ranges_maybe_overlap_p<N, C, T> ();
+ test_ranges_known_overlap_p<N, C, T> ();
+ test_known_subrange_p<N, C, T> ();
+ test_coeffs_in_range_p<N, C, T> ();
+}
+
+/* Test things that work for poly_int<2, C>, given that C is signed. */
+
+template<typename C>
+static void
+test_signed_2 ()
+{
+ test_ordered_2<C> ();
+ test_signed_maybe_eq_2<C> ();
+ test_signed_known_ne_2<C> ();
+}
+
+/* Test things that work for poly_int-based types T, given that the
+ coefficient type C is signed. N is the number of coefficients in C
+ and RC is the type to which C promotes after an operator. */
+
+template<unsigned int N, typename C, typename RC, typename T>
+static void
+test_signed ()
+{
+ test_ordered<N, C, RC, T> ();
+ test_signed_negation<N, C, RC, T> ();
+ test_signed_maybe_le<N, C, T> ();
+ test_signed_maybe_lt<N, C, T> ();
+ test_signed_maybe_ge<N, C, T> ();
+ test_signed_maybe_gt<N, C, T> ();
+ test_signed_known_gt<N, C, T> ();
+ test_signed_known_ge<N, C, T> ();
+ test_signed_known_lt<N, C, T> ();
+ test_signed_known_le<N, C, T> ();
+ test_signed_ordered_p<N, C, T> ();
+ test_signed_ordered_min<N, C, T> ();
+ test_signed_ordered_max<N, C, T> ();
+ test_signed_lower_bound<N, C, T> ();
+ test_signed_upper_bound<N, C, T> ();
+ test_signed_constant_multiple_p<N, C, T> ();
+ test_signed_multiple_p<N, C, T> ();
+ test_signed_multiple_p_with_result<N ,C, T> ();
+ test_signed_exact_div<N, C, T> ();
+ test_signed_can_div_trunc_p_const<N, C, T> ();
+ test_signed_can_div_trunc_p_poly<N, C, T> ();
+ test_signed_can_div_away_from_zero_p<N, C, T> ();
+ test_signed_maybe_in_range_p<N, C, T> ();
+}
+
+/* Test things that work for poly_int-based types T, given that the
+ coefficient type C is unsigned. N is the number of coefficients in C
+ and RC is the type to which C promotes after an operator. */
+
+template<unsigned int N, typename C, typename RC, typename T>
+static void
+test_unsigned ()
+{
+ test_ordered<N, C, RC, T> ();
+ test_unsigned_maybe_le<N, C, T> ();
+ test_unsigned_maybe_lt<N, C, T> ();
+ test_unsigned_maybe_ge<N, C, T> ();
+ test_unsigned_maybe_gt<N, C, T> ();
+ test_unsigned_known_gt<N, C, T> ();
+ test_unsigned_known_ge<N, C, T> ();
+ test_unsigned_known_lt<N, C, T> ();
+ test_unsigned_known_le<N, C, T> ();
+ test_unsigned_ordered_p<N, C, T> ();
+ test_unsigned_ordered_min<N, C, T> ();
+ test_unsigned_ordered_max<N, C, T> ();
+ test_unsigned_lower_bound<N, C, T> ();
+ test_unsigned_upper_bound<N, C, T> ();
+ test_unsigned_maybe_in_range_p<N, C, T> ();
+ test_unsigned_known_in_range_p<N, C, T> ();
+}
+
+/* Test things that are specific to coefficients of type wide_int,
+ using a poly_int with N coefficients. */
+
+template<unsigned int N>
+static void
+test_wide_int ()
+{
+ test_wide_int_from<N> ();
+
+ test_to_shwi<N> (wi::mask (63, true, 77), -1, HOST_WIDE_INT_MIN);
+ test_to_shwi<N> (wi::mask (63, false, 77), 1, HOST_WIDE_INT_MAX);
+ test_to_uhwi<N> (wide_int (wi::zero (94)), -1, 0U);
+ test_to_uhwi<N> (wi::mask (64, false, 94), 1, HOST_WIDE_INT_M1U);
+
+ test_force_hwi<N> (wi::mask (66, false, 81));
+
+ test_wide_int_sext<N> ();
+ test_wide_int_zext<N> ();
+ test_wide_int_add<N> ();
+ test_wide_int_sub<N> ();
+ test_wide_int_mul<N> ();
+ test_wide_int_neg<N> ();
+}
+
+/* Run the tests that are common to all coefficient counts N. */
+
+template<unsigned int N>
+static void
+test_num_coeffs_core ()
+{
+ test_unsigned<N, unsigned short, HOST_WIDE_INT,
+ poly_int<N, unsigned short> > ();
+ test_signed<N, HOST_WIDE_INT, HOST_WIDE_INT,
+ poly_int<N, HOST_WIDE_INT> > ();
+ test_unsigned<N, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+ poly_int<N, unsigned HOST_WIDE_INT> >();
+
+ test_general<N, wide_int, wide_int, poly_int<N, wide_int> > ();
+
+ test_hwi<N, unsigned short, poly_int<N, unsigned short> > ();
+ test_hwi<N, HOST_WIDE_INT, poly_int<N, HOST_WIDE_INT> > ();
+ test_hwi<N, unsigned HOST_WIDE_INT, poly_int<N, unsigned HOST_WIDE_INT> > ();
+
+ test_wide_int<N> ();
+ test_fixed_int<N, offset_int> ();
+ test_fixed_int<N, widest_int> ();
+
+ test_type_promotions<N> ();
+ test_shwi<N> ();
+ test_uhwi<N> ();
+}
+
+/* Run extra tests for the most important coefficient counts N. */
+
+template<unsigned int N>
+static void
+test_num_coeffs_extra ()
+{
+ /* Test the most common POD types. */
+ test_unsigned<N, unsigned short, HOST_WIDE_INT,
+ poly_int_pod<N, unsigned short> > ();
+ test_signed<N, HOST_WIDE_INT, HOST_WIDE_INT,
+ poly_int_pod<N, HOST_WIDE_INT> > ();
+ test_unsigned<N, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+ poly_int_pod<N, unsigned HOST_WIDE_INT> > ();
+
+ /* Test some coefficient types that weren't covered in the core tests. */
+ test_signed<N, int, HOST_WIDE_INT,
+ poly_int<N, int> > ();
+ test_signed<N, offset_int, offset_int,
+ poly_int<N, offset_int> > ();
+ test_signed<N, widest_int, widest_int,
+ poly_int<N, widest_int> > ();
+}