123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- /* Operations with long integers.
- Copyright (C) 2006-2015 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/>. */
- #ifndef DOUBLE_INT_H
- #define DOUBLE_INT_H
- #include "wide-int.h"
- /* A large integer is currently represented as a pair of HOST_WIDE_INTs.
- It therefore represents a number with precision of
- 2 * HOST_BITS_PER_WIDE_INT bits (it is however possible that the
- internal representation will change, if numbers with greater precision
- are needed, so the users should not rely on it). The representation does
- not contain any information about signedness of the represented value, so
- it can be used to represent both signed and unsigned numbers. For
- operations where the results depend on signedness (division, comparisons),
- it must be specified separately. For each such operation, there are three
- versions of the function -- double_int_op, that takes an extra UNS argument
- giving the signedness of the values, and double_int_sop and double_int_uop
- that stand for its specializations for signed and unsigned values.
- You may also represent with numbers in smaller precision using double_int.
- You however need to use double_int_ext (that fills in the bits of the
- number over the prescribed precision with zeros or with the sign bit) before
- operations that do not perform arithmetics modulo 2^precision (comparisons,
- division), and possibly before storing the results, if you want to keep
- them in some canonical form). In general, the signedness of double_int_ext
- should match the signedness of the operation.
- ??? The components of double_int differ in signedness mostly for
- historical reasons (they replace an older structure used to represent
- numbers with precision higher than HOST_WIDE_INT). It might be less
- confusing to have them both signed or both unsigned. */
- struct double_int
- {
- /* Normally, we would define constructors to create instances.
- Two things prevent us from doing so.
- First, defining a constructor makes the class non-POD in C++03,
- and we certainly want double_int to be a POD.
- Second, the GCC conding conventions prefer explicit conversion,
- and explicit conversion operators are not available until C++11. */
- static double_int from_uhwi (unsigned HOST_WIDE_INT cst);
- static double_int from_shwi (HOST_WIDE_INT cst);
- static double_int from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low);
- /* Construct from a fuffer of length LEN. BUFFER will be read according
- to byte endianess and word endianess. */
- static double_int from_buffer (const unsigned char *buffer, int len);
- /* No copy assignment operator or destructor to keep the type a POD. */
- /* There are some special value-creation static member functions. */
- static double_int mask (unsigned prec);
- static double_int max_value (unsigned int prec, bool uns);
- static double_int min_value (unsigned int prec, bool uns);
- /* The following functions are mutating operations. */
- double_int &operator ++ (); // prefix
- double_int &operator -- (); // prefix
- double_int &operator *= (double_int);
- double_int &operator += (double_int);
- double_int &operator -= (double_int);
- double_int &operator &= (double_int);
- double_int &operator ^= (double_int);
- double_int &operator |= (double_int);
- /* The following functions are non-mutating operations. */
- /* Conversion functions. */
- HOST_WIDE_INT to_shwi () const;
- unsigned HOST_WIDE_INT to_uhwi () const;
- /* Conversion query functions. */
- bool fits_uhwi () const;
- bool fits_shwi () const;
- bool fits_hwi (bool uns) const;
- /* Attribute query functions. */
- int trailing_zeros () const;
- int popcount () const;
- /* Arithmetic query operations. */
- bool multiple_of (double_int, bool, double_int *) const;
- /* Arithmetic operation functions. */
- /* The following operations perform arithmetics modulo 2^precision, so you
- do not need to call .ext between them, even if you are representing
- numbers with precision less than HOST_BITS_PER_DOUBLE_INT bits. */
- double_int set_bit (unsigned) const;
- double_int mul_with_sign (double_int, bool unsigned_p, bool *overflow) const;
- double_int wide_mul_with_sign (double_int, bool unsigned_p,
- double_int *higher, bool *overflow) const;
- double_int add_with_sign (double_int, bool unsigned_p, bool *overflow) const;
- double_int sub_with_overflow (double_int, bool *overflow) const;
- double_int neg_with_overflow (bool *overflow) const;
- double_int operator * (double_int) const;
- double_int operator + (double_int) const;
- double_int operator - (double_int) const;
- double_int operator - () const;
- double_int operator ~ () const;
- double_int operator & (double_int) const;
- double_int operator | (double_int) const;
- double_int operator ^ (double_int) const;
- double_int and_not (double_int) const;
- double_int lshift (HOST_WIDE_INT count) const;
- double_int lshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const;
- double_int rshift (HOST_WIDE_INT count) const;
- double_int rshift (HOST_WIDE_INT count, unsigned int prec, bool arith) const;
- double_int alshift (HOST_WIDE_INT count, unsigned int prec) const;
- double_int arshift (HOST_WIDE_INT count, unsigned int prec) const;
- double_int llshift (HOST_WIDE_INT count, unsigned int prec) const;
- double_int lrshift (HOST_WIDE_INT count, unsigned int prec) const;
- double_int lrotate (HOST_WIDE_INT count, unsigned int prec) const;
- double_int rrotate (HOST_WIDE_INT count, unsigned int prec) const;
- /* You must ensure that double_int::ext is called on the operands
- of the following operations, if the precision of the numbers
- is less than HOST_BITS_PER_DOUBLE_INT bits. */
- double_int div (double_int, bool, unsigned) const;
- double_int sdiv (double_int, unsigned) const;
- double_int udiv (double_int, unsigned) const;
- double_int mod (double_int, bool, unsigned) const;
- double_int smod (double_int, unsigned) const;
- double_int umod (double_int, unsigned) const;
- double_int divmod_with_overflow (double_int, bool, unsigned,
- double_int *, bool *) const;
- double_int divmod (double_int, bool, unsigned, double_int *) const;
- double_int sdivmod (double_int, unsigned, double_int *) const;
- double_int udivmod (double_int, unsigned, double_int *) const;
- /* Precision control functions. */
- double_int ext (unsigned prec, bool uns) const;
- double_int zext (unsigned prec) const;
- double_int sext (unsigned prec) const;
- /* Comparative functions. */
- bool is_zero () const;
- bool is_one () const;
- bool is_minus_one () const;
- bool is_negative () const;
- int cmp (double_int b, bool uns) const;
- int ucmp (double_int b) const;
- int scmp (double_int b) const;
- bool ult (double_int b) const;
- bool ule (double_int b) const;
- bool ugt (double_int b) const;
- bool slt (double_int b) const;
- bool sle (double_int b) const;
- bool sgt (double_int b) const;
- double_int max (double_int b, bool uns);
- double_int smax (double_int b);
- double_int umax (double_int b);
- double_int min (double_int b, bool uns);
- double_int smin (double_int b);
- double_int umin (double_int b);
- bool operator == (double_int cst2) const;
- bool operator != (double_int cst2) const;
- /* Please migrate away from using these member variables publicly. */
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- };
- #define HOST_BITS_PER_DOUBLE_INT (2 * HOST_BITS_PER_WIDE_INT)
- /* Constructors and conversions. */
- /* Constructs double_int from integer CST. The bits over the precision of
- HOST_WIDE_INT are filled with the sign bit. */
- inline double_int
- double_int::from_shwi (HOST_WIDE_INT cst)
- {
- double_int r;
- r.low = (unsigned HOST_WIDE_INT) cst;
- r.high = cst < 0 ? -1 : 0;
- return r;
- }
- /* Some useful constants. */
- /* FIXME(crowl): Maybe remove after converting callers?
- The problem is that a named constant would not be as optimizable,
- while the functional syntax is more verbose. */
- #define double_int_minus_one (double_int::from_shwi (-1))
- #define double_int_zero (double_int::from_shwi (0))
- #define double_int_one (double_int::from_shwi (1))
- #define double_int_two (double_int::from_shwi (2))
- #define double_int_ten (double_int::from_shwi (10))
- /* Constructs double_int from unsigned integer CST. The bits over the
- precision of HOST_WIDE_INT are filled with zeros. */
- inline double_int
- double_int::from_uhwi (unsigned HOST_WIDE_INT cst)
- {
- double_int r;
- r.low = cst;
- r.high = 0;
- return r;
- }
- inline double_int
- double_int::from_pair (HOST_WIDE_INT high, unsigned HOST_WIDE_INT low)
- {
- double_int r;
- r.low = low;
- r.high = high;
- return r;
- }
- inline double_int &
- double_int::operator ++ ()
- {
- *this += double_int_one;
- return *this;
- }
- inline double_int &
- double_int::operator -- ()
- {
- *this -= double_int_one;
- return *this;
- }
- inline double_int &
- double_int::operator &= (double_int b)
- {
- *this = *this & b;
- return *this;
- }
- inline double_int &
- double_int::operator ^= (double_int b)
- {
- *this = *this ^ b;
- return *this;
- }
- inline double_int &
- double_int::operator |= (double_int b)
- {
- *this = *this | b;
- return *this;
- }
- /* Returns value of CST as a signed number. CST must satisfy
- double_int::fits_signed. */
- inline HOST_WIDE_INT
- double_int::to_shwi () const
- {
- return (HOST_WIDE_INT) low;
- }
- /* Returns value of CST as an unsigned number. CST must satisfy
- double_int::fits_unsigned. */
- inline unsigned HOST_WIDE_INT
- double_int::to_uhwi () const
- {
- return low;
- }
- /* Returns true if CST fits in unsigned HOST_WIDE_INT. */
- inline bool
- double_int::fits_uhwi () const
- {
- return high == 0;
- }
- /* Logical operations. */
- /* Returns ~A. */
- inline double_int
- double_int::operator ~ () const
- {
- double_int result;
- result.low = ~low;
- result.high = ~high;
- return result;
- }
- /* Returns A | B. */
- inline double_int
- double_int::operator | (double_int b) const
- {
- double_int result;
- result.low = low | b.low;
- result.high = high | b.high;
- return result;
- }
- /* Returns A & B. */
- inline double_int
- double_int::operator & (double_int b) const
- {
- double_int result;
- result.low = low & b.low;
- result.high = high & b.high;
- return result;
- }
- /* Returns A & ~B. */
- inline double_int
- double_int::and_not (double_int b) const
- {
- double_int result;
- result.low = low & ~b.low;
- result.high = high & ~b.high;
- return result;
- }
- /* Returns A ^ B. */
- inline double_int
- double_int::operator ^ (double_int b) const
- {
- double_int result;
- result.low = low ^ b.low;
- result.high = high ^ b.high;
- return result;
- }
- void dump_double_int (FILE *, double_int, bool);
- #define ALL_ONES (~((unsigned HOST_WIDE_INT) 0))
- /* The operands of the following comparison functions must be processed
- with double_int_ext, if their precision is less than
- HOST_BITS_PER_DOUBLE_INT bits. */
- /* Returns true if CST is zero. */
- inline bool
- double_int::is_zero () const
- {
- return low == 0 && high == 0;
- }
- /* Returns true if CST is one. */
- inline bool
- double_int::is_one () const
- {
- return low == 1 && high == 0;
- }
- /* Returns true if CST is minus one. */
- inline bool
- double_int::is_minus_one () const
- {
- return low == ALL_ONES && high == -1;
- }
- /* Returns true if CST is negative. */
- inline bool
- double_int::is_negative () const
- {
- return high < 0;
- }
- /* Returns true if CST1 == CST2. */
- inline bool
- double_int::operator == (double_int cst2) const
- {
- return low == cst2.low && high == cst2.high;
- }
- /* Returns true if CST1 != CST2. */
- inline bool
- double_int::operator != (double_int cst2) const
- {
- return low != cst2.low || high != cst2.high;
- }
- /* Return number of set bits of CST. */
- inline int
- double_int::popcount () const
- {
- return popcount_hwi (high) + popcount_hwi (low);
- }
- #ifndef GENERATOR_FILE
- /* Conversion to and from GMP integer representations. */
- void mpz_set_double_int (mpz_t, double_int, bool);
- double_int mpz_get_double_int (const_tree, mpz_t, bool);
- #endif
- namespace wi
- {
- template <>
- struct int_traits <double_int>
- {
- static const enum precision_type precision_type = CONST_PRECISION;
- static const bool host_dependent_precision = true;
- static const unsigned int precision = HOST_BITS_PER_DOUBLE_INT;
- static unsigned int get_precision (const double_int &);
- static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
- const double_int &);
- };
- }
- inline unsigned int
- wi::int_traits <double_int>::get_precision (const double_int &)
- {
- return precision;
- }
- inline wi::storage_ref
- wi::int_traits <double_int>::decompose (HOST_WIDE_INT *scratch, unsigned int p,
- const double_int &x)
- {
- gcc_checking_assert (precision == p);
- scratch[0] = x.low;
- if ((x.high == 0 && scratch[0] >= 0) || (x.high == -1 && scratch[0] < 0))
- return wi::storage_ref (scratch, 1, precision);
- scratch[1] = x.high;
- return wi::storage_ref (scratch, 2, precision);
- }
- #endif /* DOUBLE_INT_H */
|