2749 lines
80 KiB
C
2749 lines
80 KiB
C
|
/* Polynomial integer classes.
|
||
|
Copyright (C) 2014-2023 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> struct 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 self-comparison against 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 *) (void *) &(RES).coeffs[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>
|
||
|
struct 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, wi::overflow_type *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++)
|
||
|
{
|
||
|
wi::overflow_type suboverflow;
|
||
|
POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i], b.coeffs[i], sgn,
|
||
|
&suboverflow));
|
||
|
wi::accumulate_overflow (*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, wi::overflow_type *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++)
|
||
|
{
|
||
|
wi::overflow_type suboverflow;
|
||
|
POLY_SET_COEFF (C, r, i, wi::sub (a.coeffs[i], b.coeffs[i], sgn,
|
||
|
&suboverflow));
|
||
|
wi::accumulate_overflow (*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, wi::overflow_type *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++)
|
||
|
{
|
||
|
wi::overflow_type suboverflow;
|
||
|
POLY_SET_COEFF (C, r, i, wi::neg (a.coeffs[i], &suboverflow));
|
||
|
wi::accumulate_overflow (*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, wi::overflow_type *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++)
|
||
|
{
|
||
|
wi::overflow_type suboverflow;
|
||
|
POLY_SET_COEFF (C, r, i, wi::mul (a.coeffs[i], b, sgn, &suboverflow));
|
||
|
wi::accumulate_overflow (*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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Poly version of sext_hwi, with the same interface. */
|
||
|
|
||
|
template<unsigned int N, typename C>
|
||
|
inline poly_int<N, HOST_WIDE_INT>
|
||
|
sext_hwi (const poly_int<N, C> &a, unsigned int precision)
|
||
|
{
|
||
|
poly_int_pod<N, HOST_WIDE_INT> r;
|
||
|
for (unsigned int i = 0; i < N; i++)
|
||
|
r.coeffs[i] = sext_hwi (a.coeffs[i], precision);
|
||
|
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 (b.coeffs[i] != 0)
|
||
|
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 (b.coeffs[i] > 0)
|
||
|
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 (b.coeffs[i] > 0)
|
||
|
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 the constant lower bound of A, given that it is no less than B. */
|
||
|
|
||
|
template<unsigned int N, typename Ca, typename Cb>
|
||
|
inline POLY_CONST_COEFF (Ca, Cb)
|
||
|
constant_lower_bound_with_limit (const poly_int_pod<N, Ca> &a, const Cb &b)
|
||
|
{
|
||
|
if (known_ge (a, b))
|
||
|
return a.coeffs[0];
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
/* Return the constant upper bound of A, given that it is no greater
|
||
|
than B. */
|
||
|
|
||
|
template<unsigned int N, typename Ca, typename Cb>
|
||
|
inline POLY_CONST_COEFF (Ca, Cb)
|
||
|
constant_upper_bound_with_limit (const poly_int_pod<N, Ca> &a, const Cb &b)
|
||
|
{
|
||
|
if (known_le (a, b))
|
||
|
return a.coeffs[0];
|
||
|
return b;
|
||
|
}
|
||
|
|
||
|
/* 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 constant multiple of B. */
|
||
|
|
||
|
template<unsigned int N, typename Ca, typename Cb>
|
||
|
inline typename if_nonpoly<Cb, bool>::type
|
||
|
constant_multiple_p (const poly_int_pod<N, Ca> &a, Cb b)
|
||
|
{
|
||
|
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;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
template<unsigned int N, typename Ca, typename Cb>
|
||
|
inline typename if_nonpoly<Ca, bool>::type
|
||
|
constant_multiple_p (Ca a, const poly_int_pod<N, Cb> &b)
|
||
|
{
|
||
|
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;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
template<unsigned int N, typename Ca, typename Cb>
|
||
|
inline bool
|
||
|
constant_multiple_p (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_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;
|
||
|
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 we can compute A / B at compile time, rounding towards zero.
|
||
|
Store the result in QUOTIENT if so.
|
||
|
|
||
|
This handles cases in which either B is constant or the result is
|
||
|
constant. */
|
||
|
|
||
|
template<unsigned int N, typename Ca, typename Cb, typename Cq>
|
||
|
inline bool
|
||
|
can_div_trunc_p (const poly_int_pod<N, Ca> &a,
|
||
|
const poly_int_pod<N, Cb> &b,
|
||
|
poly_int_pod<N, Cq> *quotient)
|
||
|
{
|
||
|
if (b.is_constant ())
|
||
|
return can_div_trunc_p (a, b.coeffs[0], quotient);
|
||
|
if (!can_div_trunc_p (a, b, "ient->coeffs[0]))
|
||
|
return false;
|
||
|
for (unsigned int i = 1; i < N; ++i)
|
||
|
quotient->coeffs[i] = 0;
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
/* Use print_hex to print VALUE to FILE. */
|
||
|
|
||
|
template<unsigned int N, typename C>
|
||
|
void
|
||
|
print_hex (const poly_int_pod<N, C> &value, FILE *file)
|
||
|
{
|
||
|
if (value.is_constant ())
|
||
|
print_hex (value.coeffs[0], file);
|
||
|
else
|
||
|
{
|
||
|
fprintf (file, "[");
|
||
|
for (unsigned int i = 0; i < N; ++i)
|
||
|
{
|
||
|
print_hex (value.coeffs[i], file);
|
||
|
fputc (i == N - 1 ? ']' : ',', file);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Helper for calculating the distance between two points P1 and P2,
|
||
|
in cases where known_le (P1, P2). T1 and T2 are the types of the
|
||
|
two positions, in either order. The coefficients of P2 - P1 have
|
||
|
type unsigned HOST_WIDE_INT if the coefficients of both T1 and T2
|
||
|
have C++ primitive type, otherwise P2 - P1 has its usual
|
||
|
wide-int-based type.
|
||
|
|
||
|
The actual subtraction should look something like this:
|
||
|
|
||
|
typedef poly_span_traits<T1, T2> span_traits;
|
||
|
span_traits::cast (P2) - span_traits::cast (P1)
|
||
|
|
||
|
Applying the cast before the subtraction avoids undefined overflow
|
||
|
for signed T1 and T2.
|
||
|
|
||
|
The implementation of the cast tries to avoid unnecessary arithmetic
|
||
|
or copying. */
|
||
|
template<typename T1, typename T2,
|
||
|
typename Res = POLY_BINARY_COEFF (POLY_BINARY_COEFF (T1, T2),
|
||
|
unsigned HOST_WIDE_INT)>
|
||
|
struct poly_span_traits
|
||
|
{
|
||
|
template<typename T>
|
||
|
static const T &cast (const T &x) { return x; }
|
||
|
};
|
||
|
|
||
|
template<typename T1, typename T2>
|
||
|
struct poly_span_traits<T1, T2, 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> start_span;
|
||
|
typedef poly_span_traits<T3, T3> size_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 (start_span::cast (val) - start_span::cast (pos),
|
||
|
size_span::cast (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> start_span;
|
||
|
typedef poly_span_traits<T3, T3> size_span;
|
||
|
return (known_size_p (size)
|
||
|
&& known_ge (val, pos)
|
||
|
&& known_lt (start_span::cast (val) - start_span::cast (pos),
|
||
|
size_span::cast (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> start_span;
|
||
|
typedef poly_span_traits<T2, T2> size1_span;
|
||
|
typedef poly_span_traits<T4, T4> size2_span;
|
||
|
/* 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 (start_span::cast (pos2)
|
||
|
- start_span::cast (lower_bound (pos1, pos2)),
|
||
|
size1_span::cast (size1))
|
||
|
&& known_lt (start_span::cast (pos1)
|
||
|
- start_span::cast (lower_bound (pos1, pos2)),
|
||
|
size2_span::cast (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_span_traits<T1, T3> start_span;
|
||
|
typedef poly_span_traits<T2, T4> size_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 (start_span::cast (pos1) - start_span::cast (pos2),
|
||
|
size_span::cast (size2) - size_span::cast (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> *, gt_pointer_operator, 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
|