123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655 |
- /* Polynomial integer classes.
- Copyright (C) 2014-2019 Free Software Foundation, Inc.
- This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it under
- the terms of the GNU General Public License as published by the Free
- Software Foundation; either version 3, or (at your option) any later
- version.
- GCC is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
- /* This file provides a representation of sizes and offsets whose exact
- values depend on certain runtime properties. The motivating example
- is the Arm SVE ISA, in which the number of vector elements is only
- known at runtime. See doc/poly-int.texi for more details.
- Tests for poly-int.h are located in testsuite/gcc.dg/plugin,
- since they are too expensive (in terms of binary size) to be
- included as selftests. */
- #ifndef HAVE_POLY_INT_H
- #define HAVE_POLY_INT_H
- template<unsigned int N, typename T> class poly_int_pod;
- template<unsigned int N, typename T> class poly_int;
- /* poly_coeff_traiits<T> describes the properties of a poly_int
- coefficient type T:
- - poly_coeff_traits<T1>::rank is less than poly_coeff_traits<T2>::rank
- if T1 can promote to T2. For C-like types the rank is:
- (2 * number of bytes) + (unsigned ? 1 : 0)
- wide_ints don't have a normal rank and so use a value of INT_MAX.
- Any fixed-width integer should be promoted to wide_int if possible
- and lead to an error otherwise.
- - poly_coeff_traits<T>::int_type is the type to which an integer
- literal should be cast before comparing it with T.
- - poly_coeff_traits<T>::precision is the number of bits that T can hold.
- - poly_coeff_traits<T>::signedness is:
- 0 if T is unsigned
- 1 if T is signed
- -1 if T has no inherent sign (as for wide_int).
- - poly_coeff_traits<T>::max_value, if defined, is the maximum value of T.
- - poly_coeff_traits<T>::result is a type that can hold results of
- operations on T. This is different from T itself in cases where T
- is the result of an accessor like wi::to_offset. */
- template<typename T, wi::precision_type = wi::int_traits<T>::precision_type>
- struct poly_coeff_traits;
- template<typename T>
- struct poly_coeff_traits<T, wi::FLEXIBLE_PRECISION>
- {
- typedef T result;
- typedef T int_type;
- static const int signedness = (T (0) >= T (-1));
- static const int precision = sizeof (T) * CHAR_BIT;
- static const T max_value = (signedness
- ? ((T (1) << (precision - 2))
- + ((T (1) << (precision - 2)) - 1))
- : T (-1));
- static const int rank = sizeof (T) * 2 + !signedness;
- };
- template<typename T>
- struct poly_coeff_traits<T, wi::VAR_PRECISION>
- {
- typedef T result;
- typedef int int_type;
- static const int signedness = -1;
- static const int precision = WIDE_INT_MAX_PRECISION;
- static const int rank = INT_MAX;
- };
- template<typename T>
- struct poly_coeff_traits<T, wi::CONST_PRECISION>
- {
- typedef WI_UNARY_RESULT (T) result;
- typedef int int_type;
- /* These types are always signed. */
- static const int signedness = 1;
- static const int precision = wi::int_traits<T>::precision;
- static const int rank = precision * 2 / CHAR_BIT;
- };
- /* Information about a pair of coefficient types. */
- template<typename T1, typename T2>
- struct poly_coeff_pair_traits
- {
- /* True if T1 can represent all the values of T2.
- Either:
- - T1 should be a type with the same signedness as T2 and no less
- precision. This allows things like int16_t -> int16_t and
- uint32_t -> uint64_t.
- - T1 should be signed, T2 should be unsigned, and T1 should be
- wider than T2. This allows things like uint16_t -> int32_t.
- This rules out cases in which T1 has less precision than T2 or where
- the conversion would reinterpret the top bit. E.g. int16_t -> uint32_t
- can be dangerous and should have an explicit cast if deliberate. */
- static const bool lossless_p = (poly_coeff_traits<T1>::signedness
- == poly_coeff_traits<T2>::signedness
- ? (poly_coeff_traits<T1>::precision
- >= poly_coeff_traits<T2>::precision)
- : (poly_coeff_traits<T1>::signedness == 1
- && poly_coeff_traits<T2>::signedness == 0
- && (poly_coeff_traits<T1>::precision
- > poly_coeff_traits<T2>::precision)));
- /* 0 if T1 op T2 should promote to HOST_WIDE_INT,
- 1 if T1 op T2 should promote to unsigned HOST_WIDE_INT,
- 2 if T1 op T2 should use wide-int rules. */
- #define RANK(X) poly_coeff_traits<X>::rank
- static const int result_kind
- = ((RANK (T1) <= RANK (HOST_WIDE_INT)
- && RANK (T2) <= RANK (HOST_WIDE_INT))
- ? 0
- : (RANK (T1) <= RANK (unsigned HOST_WIDE_INT)
- && RANK (T2) <= RANK (unsigned HOST_WIDE_INT))
- ? 1 : 2);
- #undef RANK
- };
- /* SFINAE class that makes T3 available as "type" if T2 can represent all the
- values in T1. */
- template<typename T1, typename T2, typename T3,
- bool lossless_p = poly_coeff_pair_traits<T1, T2>::lossless_p>
- struct if_lossless;
- template<typename T1, typename T2, typename T3>
- struct if_lossless<T1, T2, T3, true>
- {
- typedef T3 type;
- };
- /* poly_int_traits<T> describes an integer type T that might be polynomial
- or non-polynomial:
- - poly_int_traits<T>::is_poly is true if T is a poly_int-based type
- and false otherwise.
- - poly_int_traits<T>::num_coeffs gives the number of coefficients in T
- if T is a poly_int and 1 otherwise.
- - poly_int_traits<T>::coeff_type gives the coefficent type of T if T
- is a poly_int and T itself otherwise
- - poly_int_traits<T>::int_type is a shorthand for
- typename poly_coeff_traits<coeff_type>::int_type. */
- template<typename T>
- struct poly_int_traits
- {
- static const bool is_poly = false;
- static const unsigned int num_coeffs = 1;
- typedef T coeff_type;
- typedef typename poly_coeff_traits<T>::int_type int_type;
- };
- template<unsigned int N, typename C>
- struct poly_int_traits<poly_int_pod<N, C> >
- {
- static const bool is_poly = true;
- static const unsigned int num_coeffs = N;
- typedef C coeff_type;
- typedef typename poly_coeff_traits<C>::int_type int_type;
- };
- template<unsigned int N, typename C>
- struct poly_int_traits<poly_int<N, C> > : poly_int_traits<poly_int_pod<N, C> >
- {
- };
- /* SFINAE class that makes T2 available as "type" if T1 is a non-polynomial
- type. */
- template<typename T1, typename T2 = T1,
- bool is_poly = poly_int_traits<T1>::is_poly>
- struct if_nonpoly {};
- template<typename T1, typename T2>
- struct if_nonpoly<T1, T2, false>
- {
- typedef T2 type;
- };
- /* SFINAE class that makes T3 available as "type" if both T1 and T2 are
- non-polynomial types. */
- template<typename T1, typename T2, typename T3,
- bool is_poly1 = poly_int_traits<T1>::is_poly,
- bool is_poly2 = poly_int_traits<T2>::is_poly>
- struct if_nonpoly2 {};
- template<typename T1, typename T2, typename T3>
- struct if_nonpoly2<T1, T2, T3, false, false>
- {
- typedef T3 type;
- };
- /* SFINAE class that makes T2 available as "type" if T1 is a polynomial
- type. */
- template<typename T1, typename T2 = T1,
- bool is_poly = poly_int_traits<T1>::is_poly>
- struct if_poly {};
- template<typename T1, typename T2>
- struct if_poly<T1, T2, true>
- {
- typedef T2 type;
- };
- /* poly_result<T1, T2> describes the result of an operation on two
- types T1 and T2, where at least one of the types is polynomial:
- - poly_result<T1, T2>::type gives the result type for the operation.
- The intention is to provide normal C-like rules for integer ranks,
- except that everything smaller than HOST_WIDE_INT promotes to
- HOST_WIDE_INT.
- - poly_result<T1, T2>::cast is the type to which an operand of type
- T1 should be cast before doing the operation, to ensure that
- the operation is done at the right precision. Casting to
- poly_result<T1, T2>::type would also work, but casting to this
- type is more efficient. */
- template<typename T1, typename T2 = T1,
- int result_kind = poly_coeff_pair_traits<T1, T2>::result_kind>
- struct poly_result;
- /* Promote pair to HOST_WIDE_INT. */
- template<typename T1, typename T2>
- struct poly_result<T1, T2, 0>
- {
- typedef HOST_WIDE_INT type;
- /* T1 and T2 are primitive types, so cast values to T before operating
- on them. */
- typedef type cast;
- };
- /* Promote pair to unsigned HOST_WIDE_INT. */
- template<typename T1, typename T2>
- struct poly_result<T1, T2, 1>
- {
- typedef unsigned HOST_WIDE_INT type;
- /* T1 and T2 are primitive types, so cast values to T before operating
- on them. */
- typedef type cast;
- };
- /* Use normal wide-int rules. */
- template<typename T1, typename T2>
- struct poly_result<T1, T2, 2>
- {
- typedef WI_BINARY_RESULT (T1, T2) type;
- /* Don't cast values before operating on them; leave the wi:: routines
- to handle promotion as necessary. */
- typedef const T1 &cast;
- };
- /* The coefficient type for the result of a binary operation on two
- poly_ints, the first of which has coefficients of type C1 and the
- second of which has coefficients of type C2. */
- #define POLY_POLY_COEFF(C1, C2) typename poly_result<C1, C2>::type
- /* Enforce that T2 is non-polynomial and provide the cofficient type of
- the result of a binary operation in which the first operand is a
- poly_int with coefficients of type C1 and the second operand is
- a constant of type T2. */
- #define POLY_CONST_COEFF(C1, T2) \
- POLY_POLY_COEFF (C1, typename if_nonpoly<T2>::type)
- /* Likewise in reverse. */
- #define CONST_POLY_COEFF(T1, C2) \
- POLY_POLY_COEFF (typename if_nonpoly<T1>::type, C2)
- /* The result type for a binary operation on poly_int<N, C1> and
- poly_int<N, C2>. */
- #define POLY_POLY_RESULT(N, C1, C2) poly_int<N, POLY_POLY_COEFF (C1, C2)>
- /* Enforce that T2 is non-polynomial and provide the result type
- for a binary operation on poly_int<N, C1> and T2. */
- #define POLY_CONST_RESULT(N, C1, T2) poly_int<N, POLY_CONST_COEFF (C1, T2)>
- /* Enforce that T1 is non-polynomial and provide the result type
- for a binary operation on T1 and poly_int<N, C2>. */
- #define CONST_POLY_RESULT(N, T1, C2) poly_int<N, CONST_POLY_COEFF (T1, C2)>
- /* Enforce that T1 and T2 are non-polynomial and provide the result type
- for a binary operation on T1 and T2. */
- #define CONST_CONST_RESULT(N, T1, T2) \
- POLY_POLY_COEFF (typename if_nonpoly<T1>::type, \
- typename if_nonpoly<T2>::type)
- /* The type to which a coefficient of type C1 should be cast before
- using it in a binary operation with a coefficient of type C2. */
- #define POLY_CAST(C1, C2) typename poly_result<C1, C2>::cast
- /* Provide the coefficient type for the result of T1 op T2, where T1
- and T2 can be polynomial or non-polynomial. */
- #define POLY_BINARY_COEFF(T1, T2) \
- typename poly_result<typename poly_int_traits<T1>::coeff_type, \
- typename poly_int_traits<T2>::coeff_type>::type
- /* The type to which an integer constant should be cast before
- comparing it with T. */
- #define POLY_INT_TYPE(T) typename poly_int_traits<T>::int_type
- /* RES is a poly_int result that has coefficients of type C and that
- is being built up a coefficient at a time. Set coefficient number I
- to VALUE in the most efficient way possible.
- For primitive C it is better to assign directly, since it avoids
- any further calls and so is more efficient when the compiler is
- built at -O0. But for wide-int based C it is better to construct
- the value in-place. This means that calls out to a wide-int.cc
- routine can take the address of RES rather than the address of
- a temporary.
- The dummy comparison against a null C * is just a way of checking
- that C gives the right type. */
- #define POLY_SET_COEFF(C, RES, I, VALUE) \
- ((void) (&(RES).coeffs[0] == (C *) 0), \
- wi::int_traits<C>::precision_type == wi::FLEXIBLE_PRECISION \
- ? (void) ((RES).coeffs[I] = VALUE) \
- : (void) ((RES).coeffs[I].~C (), new (&(RES).coeffs[I]) C (VALUE)))
- /* A base POD class for polynomial integers. The polynomial has N
- coefficients of type C. */
- template<unsigned int N, typename C>
- class poly_int_pod
- {
- public:
- template<typename Ca>
- poly_int_pod &operator = (const poly_int_pod<N, Ca> &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int_pod>::type &operator = (const Ca &);
- template<typename Ca>
- poly_int_pod &operator += (const poly_int_pod<N, Ca> &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int_pod>::type &operator += (const Ca &);
- template<typename Ca>
- poly_int_pod &operator -= (const poly_int_pod<N, Ca> &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int_pod>::type &operator -= (const Ca &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int_pod>::type &operator *= (const Ca &);
- poly_int_pod &operator <<= (unsigned int);
- bool is_constant () const;
- template<typename T>
- typename if_lossless<T, C, bool>::type is_constant (T *) const;
- C to_constant () const;
- template<typename Ca>
- static poly_int<N, C> from (const poly_int_pod<N, Ca> &, unsigned int,
- signop);
- template<typename Ca>
- static poly_int<N, C> from (const poly_int_pod<N, Ca> &, signop);
- bool to_shwi (poly_int_pod<N, HOST_WIDE_INT> *) const;
- bool to_uhwi (poly_int_pod<N, unsigned HOST_WIDE_INT> *) const;
- poly_int<N, HOST_WIDE_INT> force_shwi () const;
- poly_int<N, unsigned HOST_WIDE_INT> force_uhwi () const;
- #if POLY_INT_CONVERSION
- operator C () const;
- #endif
- C coeffs[N];
- };
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int_pod<N, C>&
- poly_int_pod<N, C>::operator = (const poly_int_pod<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
- poly_int_pod<N, C>::operator = (const Ca &a)
- {
- POLY_SET_COEFF (C, *this, 0, a);
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int_pod<N, C>&
- poly_int_pod<N, C>::operator += (const poly_int_pod<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] += a.coeffs[i];
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
- poly_int_pod<N, C>::operator += (const Ca &a)
- {
- this->coeffs[0] += a;
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int_pod<N, C>&
- poly_int_pod<N, C>::operator -= (const poly_int_pod<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] -= a.coeffs[i];
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
- poly_int_pod<N, C>::operator -= (const Ca &a)
- {
- this->coeffs[0] -= a;
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int_pod<N, C> >::type &
- poly_int_pod<N, C>::operator *= (const Ca &a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] *= a;
- return *this;
- }
- template<unsigned int N, typename C>
- inline poly_int_pod<N, C>&
- poly_int_pod<N, C>::operator <<= (unsigned int a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] <<= a;
- return *this;
- }
- /* Return true if the polynomial value is a compile-time constant. */
- template<unsigned int N, typename C>
- inline bool
- poly_int_pod<N, C>::is_constant () const
- {
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- if (this->coeffs[i] != 0)
- return false;
- return true;
- }
- /* Return true if the polynomial value is a compile-time constant,
- storing its value in CONST_VALUE if so. */
- template<unsigned int N, typename C>
- template<typename T>
- inline typename if_lossless<T, C, bool>::type
- poly_int_pod<N, C>::is_constant (T *const_value) const
- {
- if (is_constant ())
- {
- *const_value = this->coeffs[0];
- return true;
- }
- return false;
- }
- /* Return the value of a polynomial that is already known to be a
- compile-time constant.
- NOTE: When using this function, please add a comment above the call
- explaining why we know the value is constant in that context. */
- template<unsigned int N, typename C>
- inline C
- poly_int_pod<N, C>::to_constant () const
- {
- gcc_checking_assert (is_constant ());
- return this->coeffs[0];
- }
- /* Convert X to a wide_int-based polynomial in which each coefficient
- has BITSIZE bits. If X's coefficients are smaller than BITSIZE,
- extend them according to SGN. */
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int<N, C>
- poly_int_pod<N, C>::from (const poly_int_pod<N, Ca> &a,
- unsigned int bitsize, signop sgn)
- {
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, C::from (a.coeffs[i], bitsize, sgn));
- return r;
- }
- /* Convert X to a fixed_wide_int-based polynomial, extending according
- to SGN. */
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int<N, C>
- poly_int_pod<N, C>::from (const poly_int_pod<N, Ca> &a, signop sgn)
- {
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, C::from (a.coeffs[i], sgn));
- return r;
- }
- /* Return true if the coefficients of this generic_wide_int-based
- polynomial can be represented as signed HOST_WIDE_INTs without loss
- of precision. Store the HOST_WIDE_INT representation in *R if so. */
- template<unsigned int N, typename C>
- inline bool
- poly_int_pod<N, C>::to_shwi (poly_int_pod<N, HOST_WIDE_INT> *r) const
- {
- for (unsigned int i = 0; i < N; i++)
- if (!wi::fits_shwi_p (this->coeffs[i]))
- return false;
- for (unsigned int i = 0; i < N; i++)
- r->coeffs[i] = this->coeffs[i].to_shwi ();
- return true;
- }
- /* Return true if the coefficients of this generic_wide_int-based
- polynomial can be represented as unsigned HOST_WIDE_INTs without
- loss of precision. Store the unsigned HOST_WIDE_INT representation
- in *R if so. */
- template<unsigned int N, typename C>
- inline bool
- poly_int_pod<N, C>::to_uhwi (poly_int_pod<N, unsigned HOST_WIDE_INT> *r) const
- {
- for (unsigned int i = 0; i < N; i++)
- if (!wi::fits_uhwi_p (this->coeffs[i]))
- return false;
- for (unsigned int i = 0; i < N; i++)
- r->coeffs[i] = this->coeffs[i].to_uhwi ();
- return true;
- }
- /* Force a generic_wide_int-based constant to HOST_WIDE_INT precision,
- truncating if necessary. */
- template<unsigned int N, typename C>
- inline poly_int<N, HOST_WIDE_INT>
- poly_int_pod<N, C>::force_shwi () const
- {
- poly_int_pod<N, HOST_WIDE_INT> r;
- for (unsigned int i = 0; i < N; i++)
- r.coeffs[i] = this->coeffs[i].to_shwi ();
- return r;
- }
- /* Force a generic_wide_int-based constant to unsigned HOST_WIDE_INT precision,
- truncating if necessary. */
- template<unsigned int N, typename C>
- inline poly_int<N, unsigned HOST_WIDE_INT>
- poly_int_pod<N, C>::force_uhwi () const
- {
- poly_int_pod<N, unsigned HOST_WIDE_INT> r;
- for (unsigned int i = 0; i < N; i++)
- r.coeffs[i] = this->coeffs[i].to_uhwi ();
- return r;
- }
- #if POLY_INT_CONVERSION
- /* Provide a conversion operator to constants. */
- template<unsigned int N, typename C>
- inline
- poly_int_pod<N, C>::operator C () const
- {
- gcc_checking_assert (this->is_constant ());
- return this->coeffs[0];
- }
- #endif
- /* The main class for polynomial integers. The class provides
- constructors that are necessarily missing from the POD base. */
- template<unsigned int N, typename C>
- class poly_int : public poly_int_pod<N, C>
- {
- public:
- poly_int () {}
- template<typename Ca>
- poly_int (const poly_int<N, Ca> &);
- template<typename Ca>
- poly_int (const poly_int_pod<N, Ca> &);
- template<typename C0>
- poly_int (const C0 &);
- template<typename C0, typename C1>
- poly_int (const C0 &, const C1 &);
- template<typename Ca>
- poly_int &operator = (const poly_int_pod<N, Ca> &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int>::type &operator = (const Ca &);
- template<typename Ca>
- poly_int &operator += (const poly_int_pod<N, Ca> &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int>::type &operator += (const Ca &);
- template<typename Ca>
- poly_int &operator -= (const poly_int_pod<N, Ca> &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int>::type &operator -= (const Ca &);
- template<typename Ca>
- typename if_nonpoly<Ca, poly_int>::type &operator *= (const Ca &);
- poly_int &operator <<= (unsigned int);
- };
- template<unsigned int N, typename C>
- template<typename Ca>
- inline
- poly_int<N, C>::poly_int (const poly_int<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline
- poly_int<N, C>::poly_int (const poly_int_pod<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, *this, i, a.coeffs[i]);
- }
- template<unsigned int N, typename C>
- template<typename C0>
- inline
- poly_int<N, C>::poly_int (const C0 &c0)
- {
- POLY_SET_COEFF (C, *this, 0, c0);
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
- }
- template<unsigned int N, typename C>
- template<typename C0, typename C1>
- inline
- poly_int<N, C>::poly_int (const C0 &c0, const C1 &c1)
- {
- STATIC_ASSERT (N >= 2);
- POLY_SET_COEFF (C, *this, 0, c0);
- POLY_SET_COEFF (C, *this, 1, c1);
- for (unsigned int i = 2; i < N; i++)
- POLY_SET_COEFF (C, *this, i, wi::ints_for<C>::zero (this->coeffs[0]));
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int<N, C>&
- poly_int<N, C>::operator = (const poly_int_pod<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] = a.coeffs[i];
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
- poly_int<N, C>::operator = (const Ca &a)
- {
- this->coeffs[0] = a;
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- this->coeffs[i] = wi::ints_for<C>::zero (this->coeffs[0]);
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int<N, C>&
- poly_int<N, C>::operator += (const poly_int_pod<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] += a.coeffs[i];
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
- poly_int<N, C>::operator += (const Ca &a)
- {
- this->coeffs[0] += a;
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline poly_int<N, C>&
- poly_int<N, C>::operator -= (const poly_int_pod<N, Ca> &a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] -= a.coeffs[i];
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
- poly_int<N, C>::operator -= (const Ca &a)
- {
- this->coeffs[0] -= a;
- return *this;
- }
- template<unsigned int N, typename C>
- template<typename Ca>
- inline typename if_nonpoly<Ca, poly_int<N, C> >::type &
- poly_int<N, C>::operator *= (const Ca &a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] *= a;
- return *this;
- }
- template<unsigned int N, typename C>
- inline poly_int<N, C>&
- poly_int<N, C>::operator <<= (unsigned int a)
- {
- for (unsigned int i = 0; i < N; i++)
- this->coeffs[i] <<= a;
- return *this;
- }
- /* Return true if every coefficient of A is in the inclusive range [B, C]. */
- template<typename Ca, typename Cb, typename Cc>
- inline typename if_nonpoly<Ca, bool>::type
- coeffs_in_range_p (const Ca &a, const Cb &b, const Cc &c)
- {
- return a >= b && a <= c;
- }
- template<unsigned int N, typename Ca, typename Cb, typename Cc>
- inline typename if_nonpoly<Ca, bool>::type
- coeffs_in_range_p (const poly_int_pod<N, Ca> &a, const Cb &b, const Cc &c)
- {
- for (unsigned int i = 0; i < N; i++)
- if (a.coeffs[i] < b || a.coeffs[i] > c)
- return false;
- return true;
- }
- namespace wi {
- /* Poly version of wi::shwi, with the same interface. */
- template<unsigned int N>
- inline poly_int<N, hwi_with_prec>
- shwi (const poly_int_pod<N, HOST_WIDE_INT> &a, unsigned int precision)
- {
- poly_int<N, hwi_with_prec> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (hwi_with_prec, r, i, wi::shwi (a.coeffs[i], precision));
- return r;
- }
- /* Poly version of wi::uhwi, with the same interface. */
- template<unsigned int N>
- inline poly_int<N, hwi_with_prec>
- uhwi (const poly_int_pod<N, unsigned HOST_WIDE_INT> &a, unsigned int precision)
- {
- poly_int<N, hwi_with_prec> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (hwi_with_prec, r, i, wi::uhwi (a.coeffs[i], precision));
- return r;
- }
- /* Poly version of wi::sext, with the same interface. */
- template<unsigned int N, typename Ca>
- inline POLY_POLY_RESULT (N, Ca, Ca)
- sext (const poly_int_pod<N, Ca> &a, unsigned int precision)
- {
- typedef POLY_POLY_COEFF (Ca, Ca) C;
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, wi::sext (a.coeffs[i], precision));
- return r;
- }
- /* Poly version of wi::zext, with the same interface. */
- template<unsigned int N, typename Ca>
- inline POLY_POLY_RESULT (N, Ca, Ca)
- zext (const poly_int_pod<N, Ca> &a, unsigned int precision)
- {
- typedef POLY_POLY_COEFF (Ca, Ca) C;
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, wi::zext (a.coeffs[i], precision));
- return r;
- }
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_POLY_RESULT (N, Ca, Cb)
- operator + (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_POLY_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]) + b.coeffs[i]);
- return r;
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_CONST_RESULT (N, Ca, Cb)
- operator + (const poly_int_pod<N, Ca> &a, const Cb &b)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CONST_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- POLY_SET_COEFF (C, r, 0, NCa (a.coeffs[0]) + b);
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, r, i, NCa (a.coeffs[i]));
- return r;
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline CONST_POLY_RESULT (N, Ca, Cb)
- operator + (const Ca &a, const poly_int_pod<N, Cb> &b)
- {
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef CONST_POLY_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- POLY_SET_COEFF (C, r, 0, a + NCb (b.coeffs[0]));
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, r, i, NCb (b.coeffs[i]));
- return r;
- }
- namespace wi {
- /* Poly versions of wi::add, with the same interface. */
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
- add (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
- {
- typedef WI_BINARY_RESULT (Ca, Cb) C;
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i], b.coeffs[i]));
- return r;
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
- add (const poly_int_pod<N, Ca> &a, const Cb &b)
- {
- typedef WI_BINARY_RESULT (Ca, Cb) C;
- poly_int<N, C> r;
- POLY_SET_COEFF (C, r, 0, wi::add (a.coeffs[0], b));
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, r, i, wi::add (a.coeffs[i],
- wi::ints_for<Cb>::zero (b)));
- return r;
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
- add (const Ca &a, const poly_int_pod<N, Cb> &b)
- {
- typedef WI_BINARY_RESULT (Ca, Cb) C;
- poly_int<N, C> r;
- POLY_SET_COEFF (C, r, 0, wi::add (a, b.coeffs[0]));
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, r, i, wi::add (wi::ints_for<Ca>::zero (a),
- b.coeffs[i]));
- return r;
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, WI_BINARY_RESULT (Ca, Cb)>
- add (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
- signop sgn, 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;
- }
- }
- /* 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 a value that is known to be no greater than A and B. This
- will be the greatest lower bound for some indeterminate values but
- not necessarily for all. */
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_CONST_RESULT (N, Ca, Cb)
- lower_bound (const poly_int_pod<N, Ca> &a, const Cb &b)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_INT_TYPE (Cb) ICb;
- typedef POLY_CONST_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- POLY_SET_COEFF (C, r, 0, MIN (NCa (a.coeffs[0]), NCb (b)));
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, r, i, MIN (NCa (a.coeffs[i]), ICb (0)));
- return r;
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline CONST_POLY_RESULT (N, Ca, Cb)
- lower_bound (const Ca &a, const poly_int_pod<N, Cb> &b)
- {
- return lower_bound (b, a);
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_POLY_RESULT (N, Ca, Cb)
- lower_bound (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_POLY_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, MIN (NCa (a.coeffs[i]), NCb (b.coeffs[i])));
- return r;
- }
- template<typename Ca, typename Cb>
- inline CONST_CONST_RESULT (N, Ca, Cb)
- lower_bound (const Ca &a, const Cb &b)
- {
- return a < b ? a : b;
- }
- /* Return a value that is known to be no less than A and B. This will
- be the least upper bound for some indeterminate values but not
- necessarily for all. */
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_CONST_RESULT (N, Ca, Cb)
- upper_bound (const poly_int_pod<N, Ca> &a, const Cb &b)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_INT_TYPE (Cb) ICb;
- typedef POLY_CONST_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- POLY_SET_COEFF (C, r, 0, MAX (NCa (a.coeffs[0]), NCb (b)));
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (C, r, i, MAX (NCa (a.coeffs[i]), ICb (0)));
- return r;
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline CONST_POLY_RESULT (N, Ca, Cb)
- upper_bound (const Ca &a, const poly_int_pod<N, Cb> &b)
- {
- return upper_bound (b, a);
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_POLY_RESULT (N, Ca, Cb)
- upper_bound (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_POLY_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (C, r, i, MAX (NCa (a.coeffs[i]), NCb (b.coeffs[i])));
- return r;
- }
- /* Return the greatest common divisor of all nonzero coefficients, or zero
- if all coefficients are zero. */
- template<unsigned int N, typename Ca>
- inline POLY_BINARY_COEFF (Ca, Ca)
- coeff_gcd (const poly_int_pod<N, Ca> &a)
- {
- /* Find the first nonzero coefficient, stopping at 0 whatever happens. */
- unsigned int i;
- for (i = N - 1; i > 0; --i)
- if (a.coeffs[i] != 0)
- break;
- typedef POLY_BINARY_COEFF (Ca, Ca) C;
- C r = a.coeffs[i];
- for (unsigned int j = 0; j < i; ++j)
- if (a.coeffs[j] != 0)
- r = gcd (r, C (a.coeffs[j]));
- return r;
- }
- /* Return a value that is a multiple of both A and B. This will be the
- least common multiple for some indeterminate values but necessarily
- for all. */
- template<unsigned int N, typename Ca, typename Cb>
- POLY_CONST_RESULT (N, Ca, Cb)
- common_multiple (const poly_int_pod<N, Ca> &a, Cb b)
- {
- POLY_BINARY_COEFF (Ca, Ca) xgcd = coeff_gcd (a);
- return a * (least_common_multiple (xgcd, b) / xgcd);
- }
- template<unsigned int N, typename Ca, typename Cb>
- inline CONST_POLY_RESULT (N, Ca, Cb)
- common_multiple (const Ca &a, const poly_int_pod<N, Cb> &b)
- {
- return common_multiple (b, a);
- }
- /* Return a value that is a multiple of both A and B, asserting that
- such a value exists. The result will be the least common multiple
- for some indeterminate values but necessarily for all.
- NOTE: When using this function, please add a comment above the call
- explaining why we know the values have a common multiple (which might
- for example be because we know A / B is rational). */
- template<unsigned int N, typename Ca, typename Cb>
- POLY_POLY_RESULT (N, Ca, Cb)
- force_common_multiple (const poly_int_pod<N, Ca> &a,
- const poly_int_pod<N, Cb> &b)
- {
- if (b.is_constant ())
- return common_multiple (a, b.coeffs[0]);
- if (a.is_constant ())
- return common_multiple (a.coeffs[0], b);
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_BINARY_COEFF (Ca, Cb) C;
- typedef POLY_INT_TYPE (Ca) ICa;
- for (unsigned int i = 1; i < N; ++i)
- if (a.coeffs[i] != ICa (0))
- {
- C lcm = least_common_multiple (NCa (a.coeffs[i]), NCb (b.coeffs[i]));
- C amul = lcm / a.coeffs[i];
- C bmul = lcm / b.coeffs[i];
- for (unsigned int j = 0; j < N; ++j)
- gcc_checking_assert (a.coeffs[j] * amul == b.coeffs[j] * bmul);
- return a * amul;
- }
- gcc_unreachable ();
- }
- /* Compare A and B for sorting purposes, returning -1 if A should come
- before B, 0 if A and B are identical, and 1 if A should come after B.
- This is a lexicographical compare of the coefficients in reverse order.
- A consequence of this is that all constant sizes come before all
- non-constant ones, regardless of magnitude (since a size is never
- negative). This is what most callers want. For example, when laying
- data out on the stack, it's better to keep all the constant-sized
- data together so that it can be accessed as a constant offset from a
- single base. */
- template<unsigned int N, typename Ca, typename Cb>
- inline int
- compare_sizes_for_sort (const poly_int_pod<N, Ca> &a,
- const poly_int_pod<N, Cb> &b)
- {
- for (unsigned int i = N; i-- > 0; )
- if (a.coeffs[i] != b.coeffs[i])
- return a.coeffs[i] < b.coeffs[i] ? -1 : 1;
- return 0;
- }
- /* Return true if we can calculate VALUE & (ALIGN - 1) at compile time. */
- template<unsigned int N, typename Ca, typename Cb>
- inline bool
- can_align_p (const poly_int_pod<N, Ca> &value, Cb align)
- {
- for (unsigned int i = 1; i < N; i++)
- if ((value.coeffs[i] & (align - 1)) != 0)
- return false;
- return true;
- }
- /* Return true if we can align VALUE up to the smallest multiple of
- ALIGN that is >= VALUE. Store the aligned value in *ALIGNED if so. */
- template<unsigned int N, typename Ca, typename Cb>
- inline bool
- can_align_up (const poly_int_pod<N, Ca> &value, Cb align,
- poly_int_pod<N, Ca> *aligned)
- {
- if (!can_align_p (value, align))
- return false;
- *aligned = value + (-value.coeffs[0] & (align - 1));
- return true;
- }
- /* Return true if we can align VALUE down to the largest multiple of
- ALIGN that is <= VALUE. Store the aligned value in *ALIGNED if so. */
- template<unsigned int N, typename Ca, typename Cb>
- inline bool
- can_align_down (const poly_int_pod<N, Ca> &value, Cb align,
- poly_int_pod<N, Ca> *aligned)
- {
- if (!can_align_p (value, align))
- return false;
- *aligned = value - (value.coeffs[0] & (align - 1));
- return true;
- }
- /* Return true if we can align A and B up to the smallest multiples of
- ALIGN that are >= A and B respectively, and if doing so gives the
- same value. */
- template<unsigned int N, typename Ca, typename Cb, typename Cc>
- inline bool
- known_equal_after_align_up (const poly_int_pod<N, Ca> &a,
- const poly_int_pod<N, Cb> &b,
- Cc align)
- {
- poly_int<N, Ca> aligned_a;
- poly_int<N, Cb> aligned_b;
- return (can_align_up (a, align, &aligned_a)
- && can_align_up (b, align, &aligned_b)
- && known_eq (aligned_a, aligned_b));
- }
- /* Return true if we can align A and B down to the largest multiples of
- ALIGN that are <= A and B respectively, and if doing so gives the
- same value. */
- template<unsigned int N, typename Ca, typename Cb, typename Cc>
- inline bool
- known_equal_after_align_down (const poly_int_pod<N, Ca> &a,
- const poly_int_pod<N, Cb> &b,
- Cc align)
- {
- poly_int<N, Ca> aligned_a;
- poly_int<N, Cb> aligned_b;
- return (can_align_down (a, align, &aligned_a)
- && can_align_down (b, align, &aligned_b)
- && known_eq (aligned_a, aligned_b));
- }
- /* Assert that we can align VALUE to ALIGN at compile time and return
- the smallest multiple of ALIGN that is >= VALUE.
- NOTE: When using this function, please add a comment above the call
- explaining why we know the non-constant coefficients must already
- be a multiple of ALIGN. */
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, Ca>
- force_align_up (const poly_int_pod<N, Ca> &value, Cb align)
- {
- gcc_checking_assert (can_align_p (value, align));
- return value + (-value.coeffs[0] & (align - 1));
- }
- /* Assert that we can align VALUE to ALIGN at compile time and return
- the largest multiple of ALIGN that is <= VALUE.
- NOTE: When using this function, please add a comment above the call
- explaining why we know the non-constant coefficients must already
- be a multiple of ALIGN. */
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, Ca>
- force_align_down (const poly_int_pod<N, Ca> &value, Cb align)
- {
- gcc_checking_assert (can_align_p (value, align));
- return value - (value.coeffs[0] & (align - 1));
- }
- /* Return a value <= VALUE that is a multiple of ALIGN. It will be the
- greatest such value for some indeterminate values but not necessarily
- for all. */
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, Ca>
- aligned_lower_bound (const poly_int_pod<N, Ca> &value, Cb align)
- {
- poly_int<N, Ca> r;
- for (unsigned int i = 0; i < N; i++)
- /* This form copes correctly with more type combinations than
- value.coeffs[i] & -align would. */
- POLY_SET_COEFF (Ca, r, i, (value.coeffs[i]
- - (value.coeffs[i] & (align - 1))));
- return r;
- }
- /* Return a value >= VALUE that is a multiple of ALIGN. It will be the
- least such value for some indeterminate values but not necessarily
- for all. */
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, Ca>
- aligned_upper_bound (const poly_int_pod<N, Ca> &value, Cb align)
- {
- poly_int<N, Ca> r;
- for (unsigned int i = 0; i < N; i++)
- POLY_SET_COEFF (Ca, r, i, (value.coeffs[i]
- + (-value.coeffs[i] & (align - 1))));
- return r;
- }
- /* Assert that we can align VALUE to ALIGN at compile time. Align VALUE
- down to the largest multiple of ALIGN that is <= VALUE, then divide by
- ALIGN.
- NOTE: When using this function, please add a comment above the call
- explaining why we know the non-constant coefficients must already
- be a multiple of ALIGN. */
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, Ca>
- force_align_down_and_div (const poly_int_pod<N, Ca> &value, Cb align)
- {
- gcc_checking_assert (can_align_p (value, align));
- poly_int<N, Ca> r;
- POLY_SET_COEFF (Ca, r, 0, ((value.coeffs[0]
- - (value.coeffs[0] & (align - 1)))
- / align));
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (Ca, r, i, value.coeffs[i] / align);
- return r;
- }
- /* Assert that we can align VALUE to ALIGN at compile time. Align VALUE
- up to the smallest multiple of ALIGN that is >= VALUE, then divide by
- ALIGN.
- NOTE: When using this function, please add a comment above the call
- explaining why we know the non-constant coefficients must already
- be a multiple of ALIGN. */
- template<unsigned int N, typename Ca, typename Cb>
- inline poly_int<N, Ca>
- force_align_up_and_div (const poly_int_pod<N, Ca> &value, Cb align)
- {
- gcc_checking_assert (can_align_p (value, align));
- poly_int<N, Ca> r;
- POLY_SET_COEFF (Ca, r, 0, ((value.coeffs[0]
- + (-value.coeffs[0] & (align - 1)))
- / align));
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- POLY_SET_COEFF (Ca, r, i, value.coeffs[i] / align);
- return r;
- }
- /* Return true if we know at compile time the difference between VALUE
- and the equal or preceding multiple of ALIGN. Store the value in
- *MISALIGN if so. */
- template<unsigned int N, typename Ca, typename Cb, typename Cm>
- inline bool
- known_misalignment (const poly_int_pod<N, Ca> &value, Cb align, Cm *misalign)
- {
- gcc_checking_assert (align != 0);
- if (!can_align_p (value, align))
- return false;
- *misalign = value.coeffs[0] & (align - 1);
- return true;
- }
- /* Return X & (Y - 1), asserting that this value is known. Please add
- an a comment above callers to this function to explain why the condition
- is known to hold. */
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_BINARY_COEFF (Ca, Ca)
- force_get_misalignment (const poly_int_pod<N, Ca> &a, Cb align)
- {
- gcc_checking_assert (can_align_p (a, align));
- return a.coeffs[0] & (align - 1);
- }
- /* Return the maximum alignment that A is known to have. Return 0
- if A is known to be zero. */
- template<unsigned int N, typename Ca>
- inline POLY_BINARY_COEFF (Ca, Ca)
- known_alignment (const poly_int_pod<N, Ca> &a)
- {
- typedef POLY_BINARY_COEFF (Ca, Ca) C;
- C r = a.coeffs[0];
- for (unsigned int i = 1; i < N; ++i)
- r |= a.coeffs[i];
- return r & -r;
- }
- /* Return true if we can compute A | B at compile time, storing the
- result in RES if so. */
- template<unsigned int N, typename Ca, typename Cb, typename Cr>
- inline typename if_nonpoly<Cb, bool>::type
- can_ior_p (const poly_int_pod<N, Ca> &a, Cb b, Cr *result)
- {
- /* Coefficients 1 and above must be a multiple of something greater
- than B. */
- typedef POLY_INT_TYPE (Ca) int_type;
- if (N >= 2)
- for (unsigned int i = 1; i < N; i++)
- if ((-(a.coeffs[i] & -a.coeffs[i]) & b) != int_type (0))
- return false;
- *result = a;
- result->coeffs[0] |= b;
- return true;
- }
- /* Return true if A is a constant multiple of B, storing the
- multiple in *MULTIPLE if so. */
- template<unsigned int N, typename Ca, typename Cb, typename Cm>
- inline typename if_nonpoly<Cb, bool>::type
- constant_multiple_p (const poly_int_pod<N, Ca> &a, Cb b, Cm *multiple)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- /* Do the modulus before the constant check, to catch divide by
- zero errors. */
- if (NCa (a.coeffs[0]) % NCb (b) != 0 || !a.is_constant ())
- return false;
- *multiple = NCa (a.coeffs[0]) / NCb (b);
- return true;
- }
- template<unsigned int N, typename Ca, typename Cb, typename Cm>
- inline typename if_nonpoly<Ca, bool>::type
- constant_multiple_p (Ca a, const poly_int_pod<N, Cb> &b, Cm *multiple)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_INT_TYPE (Ca) int_type;
- /* Do the modulus before the constant check, to catch divide by
- zero errors. */
- if (NCa (a) % NCb (b.coeffs[0]) != 0
- || (a != int_type (0) && !b.is_constant ()))
- return false;
- *multiple = NCa (a) / NCb (b.coeffs[0]);
- return true;
- }
- template<unsigned int N, typename Ca, typename Cb, typename Cm>
- inline bool
- constant_multiple_p (const poly_int_pod<N, Ca> &a,
- const poly_int_pod<N, Cb> &b, Cm *multiple)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_INT_TYPE (Ca) ICa;
- typedef POLY_INT_TYPE (Cb) ICb;
- typedef POLY_BINARY_COEFF (Ca, Cb) C;
- if (NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0)
- return false;
- C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
- for (unsigned int i = 1; i < N; ++i)
- if (b.coeffs[i] == ICb (0)
- ? a.coeffs[i] != ICa (0)
- : (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0
- || NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != r))
- return false;
- *multiple = r;
- return true;
- }
- /* Return true if A is a multiple of B. */
- template<typename Ca, typename Cb>
- inline typename if_nonpoly2<Ca, Cb, bool>::type
- multiple_p (Ca a, Cb b)
- {
- return a % b == 0;
- }
- /* Return true if A is a (polynomial) multiple of B. */
- template<unsigned int N, typename Ca, typename Cb>
- inline typename if_nonpoly<Cb, bool>::type
- multiple_p (const poly_int_pod<N, Ca> &a, Cb b)
- {
- for (unsigned int i = 0; i < N; ++i)
- if (a.coeffs[i] % b != 0)
- return false;
- return true;
- }
- /* Return true if A is a (constant) multiple of B. */
- template<unsigned int N, typename Ca, typename Cb>
- inline typename if_nonpoly<Ca, bool>::type
- multiple_p (Ca a, const poly_int_pod<N, Cb> &b)
- {
- typedef POLY_INT_TYPE (Ca) int_type;
- /* Do the modulus before the constant check, to catch divide by
- potential zeros. */
- return a % b.coeffs[0] == 0 && (a == int_type (0) || b.is_constant ());
- }
- /* Return true if A is a (polynomial) multiple of B. This handles cases
- where either B is constant or the multiple is constant. */
- template<unsigned int N, typename Ca, typename Cb>
- inline bool
- multiple_p (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
- {
- if (b.is_constant ())
- return multiple_p (a, b.coeffs[0]);
- POLY_BINARY_COEFF (Ca, Ca) tmp;
- return constant_multiple_p (a, b, &tmp);
- }
- /* Return true if A is a (constant) multiple of B, storing the
- multiple in *MULTIPLE if so. */
- template<typename Ca, typename Cb, typename Cm>
- inline typename if_nonpoly2<Ca, Cb, bool>::type
- multiple_p (Ca a, Cb b, Cm *multiple)
- {
- if (a % b != 0)
- return false;
- *multiple = a / b;
- return true;
- }
- /* Return true if A is a (polynomial) multiple of B, storing the
- multiple in *MULTIPLE if so. */
- template<unsigned int N, typename Ca, typename Cb, typename Cm>
- inline typename if_nonpoly<Cb, bool>::type
- multiple_p (const poly_int_pod<N, Ca> &a, Cb b, poly_int_pod<N, Cm> *multiple)
- {
- if (!multiple_p (a, b))
- return false;
- for (unsigned int i = 0; i < N; ++i)
- multiple->coeffs[i] = a.coeffs[i] / b;
- return true;
- }
- /* Return true if B is a constant and A is a (constant) multiple of B,
- storing the multiple in *MULTIPLE if so. */
- template<unsigned int N, typename Ca, typename Cb, typename Cm>
- inline typename if_nonpoly<Ca, bool>::type
- multiple_p (Ca a, const poly_int_pod<N, Cb> &b, Cm *multiple)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- /* Do the modulus before the constant check, to catch divide by
- potential zeros. */
- if (a % b.coeffs[0] != 0 || (NCa (a) != 0 && !b.is_constant ()))
- return false;
- *multiple = a / b.coeffs[0];
- return true;
- }
- /* Return true if A is a (polynomial) multiple of B, storing the
- multiple in *MULTIPLE if so. This handles cases where either
- B is constant or the multiple is constant. */
- template<unsigned int N, typename Ca, typename Cb, typename Cm>
- inline bool
- multiple_p (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b,
- poly_int_pod<N, Cm> *multiple)
- {
- if (b.is_constant ())
- return multiple_p (a, b.coeffs[0], multiple);
- return constant_multiple_p (a, b, multiple);
- }
- /* Return A / B, given that A is known to be a multiple of B. */
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_CONST_RESULT (N, Ca, Cb)
- exact_div (const poly_int_pod<N, Ca> &a, Cb b)
- {
- typedef POLY_CONST_COEFF (Ca, Cb) C;
- poly_int<N, C> r;
- for (unsigned int i = 0; i < N; i++)
- {
- gcc_checking_assert (a.coeffs[i] % b == 0);
- POLY_SET_COEFF (C, r, i, a.coeffs[i] / b);
- }
- return r;
- }
- /* Return A / B, given that A is known to be a multiple of B. */
- template<unsigned int N, typename Ca, typename Cb>
- inline POLY_POLY_RESULT (N, Ca, Cb)
- exact_div (const poly_int_pod<N, Ca> &a, const poly_int_pod<N, Cb> &b)
- {
- if (b.is_constant ())
- return exact_div (a, b.coeffs[0]);
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_BINARY_COEFF (Ca, Cb) C;
- typedef POLY_INT_TYPE (Cb) int_type;
- gcc_checking_assert (a.coeffs[0] % b.coeffs[0] == 0);
- C r = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
- for (unsigned int i = 1; i < N; ++i)
- gcc_checking_assert (b.coeffs[i] == int_type (0)
- ? a.coeffs[i] == int_type (0)
- : (a.coeffs[i] % b.coeffs[i] == 0
- && NCa (a.coeffs[i]) / NCb (b.coeffs[i]) == r));
- return r;
- }
- /* Return true if there is some constant Q and polynomial r such that:
- (1) a = b * Q + r
- (2) |b * Q| <= |a|
- (3) |r| < |b|
- Store the value Q in *QUOTIENT if so. */
- template<unsigned int N, typename Ca, typename Cb, typename Cq>
- inline typename if_nonpoly2<Cb, Cq, bool>::type
- can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b, Cq *quotient)
- {
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- /* Do the division before the constant check, to catch divide by
- zero errors. */
- Cq q = NCa (a.coeffs[0]) / NCb (b);
- if (!a.is_constant ())
- return false;
- *quotient = q;
- return true;
- }
- template<unsigned int N, typename Ca, typename Cb, typename Cq>
- inline typename if_nonpoly<Cq, bool>::type
- can_div_trunc_p (const poly_int_pod<N, Ca> &a,
- const poly_int_pod<N, Cb> &b,
- Cq *quotient)
- {
- /* We can calculate Q from the case in which the indeterminates
- are zero. */
- typedef POLY_CAST (Ca, Cb) NCa;
- typedef POLY_CAST (Cb, Ca) NCb;
- typedef POLY_INT_TYPE (Ca) ICa;
- typedef POLY_INT_TYPE (Cb) ICb;
- typedef POLY_BINARY_COEFF (Ca, Cb) C;
- C q = NCa (a.coeffs[0]) / NCb (b.coeffs[0]);
- /* Check the other coefficients and record whether the division is exact.
- The only difficult case is when it isn't. If we require a and b to
- ordered wrt zero, there can be no two coefficients of the same value
- that have opposite signs. This means that:
- |a| = |a0| + |a1 * x1| + |a2 * x2| + ...
- |b| = |b0| + |b1 * x1| + |b2 * x2| + ...
- The Q we've just calculated guarantees:
- |b0 * Q| <= |a0|
- |a0 - b0 * Q| < |b0|
- and so:
- (2) |b * Q| <= |a|
- is satisfied if:
- |bi * xi * Q| <= |ai * xi|
- for each i in [1, N]. This is trivially true when xi is zero.
- When it isn't we need:
- (2') |bi * Q| <= |ai|
- r is calculated as:
- r = r0 + r1 * x1 + r2 * x2 + ...
- where ri = ai - bi * Q
- Restricting to ordered a and b also guarantees that no two ris
- have opposite signs, so we have:
- |r| = |r0| + |r1 * x1| + |r2 * x2| + ...
- We know from the calculation of Q that |r0| < |b0|, so:
- (3) |r| < |b|
- is satisfied if:
- (3') |ai - bi * Q| <= |bi|
- for each i in [1, N]. */
- bool rem_p = NCa (a.coeffs[0]) % NCb (b.coeffs[0]) != 0;
- for (unsigned int i = 1; i < N; ++i)
- {
- if (b.coeffs[i] == ICb (0))
- {
- /* For bi == 0 we simply need: (3') |ai| == 0. */
- if (a.coeffs[i] != ICa (0))
- return false;
- }
- else
- {
- if (q == 0)
- {
- /* For Q == 0 we simply need: (3') |ai| <= |bi|. */
- if (a.coeffs[i] != ICa (0))
- {
- /* Use negative absolute to avoid overflow, i.e.
- -|ai| >= -|bi|. */
- C neg_abs_a = (a.coeffs[i] < 0 ? a.coeffs[i] : -a.coeffs[i]);
- C neg_abs_b = (b.coeffs[i] < 0 ? b.coeffs[i] : -b.coeffs[i]);
- if (neg_abs_a < neg_abs_b)
- return false;
- rem_p = true;
- }
- }
- else
- {
- /* Otherwise just check for the case in which ai / bi == Q. */
- if (NCa (a.coeffs[i]) / NCb (b.coeffs[i]) != q)
- return false;
- if (NCa (a.coeffs[i]) % NCb (b.coeffs[i]) != 0)
- rem_p = true;
- }
- }
- }
- /* If the division isn't exact, require both values to be ordered wrt 0,
- so that we can guarantee conditions (2) and (3) for all indeterminate
- values. */
- if (rem_p && (!ordered_p (a, ICa (0)) || !ordered_p (b, ICb (0))))
- return false;
- *quotient = q;
- return true;
- }
- /* Likewise, but also store r in *REMAINDER. */
- template<unsigned int N, typename Ca, typename Cb, typename Cq, typename Cr>
- inline typename if_nonpoly<Cq, bool>::type
- can_div_trunc_p (const poly_int_pod<N, Ca> &a,
- const poly_int_pod<N, Cb> &b,
- Cq *quotient, Cr *remainder)
- {
- if (!can_div_trunc_p (a, b, quotient))
- return false;
- *remainder = a - *quotient * b;
- return true;
- }
- /* Return true if there is some polynomial q and constant R such that:
- (1) a = B * q + R
- (2) |B * q| <= |a|
- (3) |R| < |B|
- Store the value q in *QUOTIENT if so. */
- template<unsigned int N, typename Ca, typename Cb, typename Cq>
- inline typename if_nonpoly<Cb, bool>::type
- can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b,
- poly_int_pod<N, Cq> *quotient)
- {
- /* The remainder must be constant. */
- for (unsigned int i = 1; i < N; ++i)
- if (a.coeffs[i] % b != 0)
- return false;
- for (unsigned int i = 0; i < N; ++i)
- quotient->coeffs[i] = a.coeffs[i] / b;
- return true;
- }
- /* Likewise, but also store R in *REMAINDER. */
- template<unsigned int N, typename Ca, typename Cb, typename Cq, typename Cr>
- inline typename if_nonpoly<Cb, bool>::type
- can_div_trunc_p (const poly_int_pod<N, Ca> &a, Cb b,
- poly_int_pod<N, Cq> *quotient, Cr *remainder)
- {
- if (!can_div_trunc_p (a, b, quotient))
- return false;
- *remainder = a.coeffs[0] % b;
- return true;
- }
- /* Return true if 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> *, void (*) (void *, void *), void *)
- {
- }
- #undef POLY_SET_COEFF
- #undef POLY_INT_TYPE
- #undef POLY_BINARY_COEFF
- #undef CONST_CONST_RESULT
- #undef POLY_CONST_RESULT
- #undef CONST_POLY_RESULT
- #undef POLY_POLY_RESULT
- #undef POLY_CONST_COEFF
- #undef CONST_POLY_COEFF
- #undef POLY_POLY_COEFF
- #endif
|