int_s.hh

00001 // Copyright (C) 2001, 2002, 2003  EPITA Research and Development Laboratory
00002 //
00003 // This file is part of the Olena Library.  This library is free
00004 // software; you can redistribute it and/or modify it under the terms
00005 // of the GNU General Public License version 2 as published by the
00006 // Free Software Foundation.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this library; see the file COPYING.  If not, write to
00015 // the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
00016 // MA 02111-1307, USA.
00017 //
00018 // As a special exception, you may use this file as part of a free
00019 // software library without restriction.  Specifically, if other files
00020 // instantiate templates or use macros or inline functions from this
00021 // file, or you compile this file and link it with other files to
00022 // produce an executable, this file does not by itself cause the
00023 // resulting executable to be covered by the GNU General Public
00024 // License.  This exception does not however invalidate any other
00025 // reasons why the executable file might be covered by the GNU General
00026 // Public License.
00027 
00028 #ifndef NTG_CORE_INT_S_HH
00029 # define NTG_CORE_INT_S_HH
00030 
00031 # include <ntg/basics.hh>
00032 # include <ntg/real/optraits_real.hh>
00033 # include <ntg/real/real_value.hh>
00034 # include <ntg/bin.hh>
00035 
00036 # include <mlc/bool.hh>
00037 # include <mlc/cmp.hh>
00038 # include <mlc/is_a.hh>
00039 
00040 # include <string>
00041 # include <sstream>
00042 
00043 /*-------.
00044 | macros |
00045 `-------*/
00046 
00047 // FIXME: add bits number comparison to avoid useless checks.
00048 
00049 # define INT_S_CTOR_FROM_UNSIGNED_BUILTIN(Builtin)                      \
00050 int_s (const Builtin rhs)                                               \
00051 {                                                                       \
00052   if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size < nbits) \
00053     this->val_ = rhs;                                                   \
00054   else                                                                  \
00055     this->val_ = optraits_type::check(rhs);                             \
00056 }                                                                       \
00057 self& operator=(const Builtin rhs)                                      \
00058 {                                                                       \
00059   if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size < nbits) \
00060     this->val_ = rhs;                                                   \
00061   else                                                                  \
00062     this->val_ = optraits_type::check(rhs);                             \
00063   return *this;                                                         \
00064 }
00065 
00066 # define INT_S_CTOR_FROM_SIGNED_BUILTIN(Builtin)                        \
00067 int_s (const Builtin rhs)                                               \
00068 {                                                                       \
00069   if ((unsigned)internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
00070     this->val_ = rhs;                                                   \
00071   else                                                                  \
00072     this->val_ = optraits_type::check(rhs);                             \
00073 }                                                                       \
00074 self& operator=(const Builtin rhs)                                      \
00075 {                                                                       \
00076   if ((unsigned)internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
00077     this->val_ = rhs;                                                   \
00078   else                                                                  \
00079     this->val_ = optraits_type::check(rhs);                             \
00080   return *this;                                                         \
00081 }
00082 
00083 
00084 namespace ntg {
00085 
00086   namespace internal {
00087 
00088     /*------------------.
00089     | typetraits<int_s> |
00090     `------------------*/
00091 
00092     template <unsigned nbits, class behavior>
00093     struct typetraits<int_s<nbits, behavior> >
00094       : public typetraits<sint_value<int_s<nbits, behavior> > >
00095     {
00096       typedef int_s<nbits, behavior>            self;
00097       typedef signed_integer                    abstract_type;
00098       typedef self                              ntg_type;
00099 
00100       ntg_build_value_type(sint_value<E>);
00101 
00102       typedef optraits<self>                            optraits_type;
00103       typedef behavior                                  abstract_behavior_type;
00104       typedef typename behavior::template get<self>     behavior_type;
00105 
00106       typedef self                              base_type;
00107       typedef typename C_for_int_s<nbits>::type storage_type;
00108       typedef self                              signed_type;
00109       typedef int_u<nbits-1, behavior>          unsigned_type;
00110       // FIXME: calculate it more precisely
00111       typedef int_s<32, behavior>               cumul_type;
00112       typedef int_s<32, behavior>               largest_type;
00113       typedef int_s<32, behavior>               signed_largest_type;
00114       typedef int_s<32, behavior>               signed_cumul_type;
00115       typedef int_u<32, behavior>               unsigned_largest_type;
00116       typedef int_u<32, behavior>               unsigned_cumul_type;
00117       typedef signed int                        integer_type;
00118       
00119       // Particular properties
00120       enum { size = nbits };
00121     };
00122 
00123   } // end of internal.
00124 
00125   /*-----------------------.
00126   | int_s<nbits, behavior> |
00127   `-----------------------*/
00128 
00129   template <unsigned nbits, class behavior>
00130   class int_s : public sint_value<int_s<nbits, behavior> >
00131   {
00132     typedef int_s<nbits, behavior> self;
00133     typedef ntgi_storage_type(self) storage_type;
00134     typedef ntgi_optraits_type(self) optraits_type;
00135 
00136   public:
00137 
00138     int_s () { this->val_ = 0; }
00139 
00140     // We define ctor for each builtin to avoid implicit builtin
00141     // promotion.
00142 
00143     INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned long);
00144     INT_S_CTOR_FROM_SIGNED_BUILTIN(signed long);
00145 
00146     INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned int);
00147     INT_S_CTOR_FROM_SIGNED_BUILTIN(signed int);
00148 
00149     INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned short);
00150     INT_S_CTOR_FROM_SIGNED_BUILTIN(signed short);
00151 
00152     INT_S_CTOR_FROM_UNSIGNED_BUILTIN(unsigned char);
00153     INT_S_CTOR_FROM_SIGNED_BUILTIN(signed char);
00154     INT_S_CTOR_FROM_SIGNED_BUILTIN(char);
00155 
00156     template <unsigned mbits, class B2>
00157     int_s (const int_s<mbits, B2>& rhs)
00158     {
00159       if (mbits <= nbits)
00160         this->val_ = rhs.val();
00161       else
00162         this->val_ = optraits_type::check(rhs.val());
00163     }
00164     template <unsigned mbits, class B2>
00165     self&
00166     operator=(const int_s<mbits, B2>& rhs)
00167     {
00168       if (mbits <= nbits)
00169         this->val_ = rhs.val();
00170       else
00171         this->val_ = optraits_type::check(rhs.val());
00172       return *this;
00173     }
00174 
00175     template <class T>
00176     int_s (const real_value<T>& rhs)
00177     {
00178       this->val_ = optraits_type::check(rhs.val());
00179     }
00180     template <class T>
00181     self&
00182     operator=(const real_value<T>& rhs)
00183     {
00184       this->val_ = optraits_type::check(rhs.val());
00185       return *this;
00186     }
00187 
00188     // FIXME: do we really want float to int conversions ?
00189 
00190     int_s (const float_s rhs)
00191     {
00192       this->val_ = optraits_type::check(roundf(rhs));
00193     }
00194     self& operator=(const float_s rhs)
00195     {
00196       this->val_ = optraits_type::check(roundf(rhs));
00197       return *this;
00198     }
00199 
00200     int_s (const float_d rhs)
00201     {
00202       this->val_ = optraits_type::check(round(rhs));
00203     }
00204     self& operator=(const float_d rhs)
00205     {
00206       this->val_ = optraits_type::check(round(rhs));
00207       return *this;
00208     }
00209 
00210     // bin is allowed since it has defined values 0 or 1.
00211     int_s (bin b)
00212     {
00213       this->val_ = b.val();
00214     }
00215     self& operator=(bin b)
00216     {
00217       this->val_ = b.val();
00218       return *this;
00219     }
00220 
00221     operator storage_type () const { return this->val_; }
00222 
00223   private:
00224     // We want to prevent this
00225     int_s(bool);
00226   };
00227 
00228   template<unsigned nbits, class behavior>
00229   inline std::ostream&
00230   operator<<(std::ostream& stream, const int_s<nbits, behavior>& rhs)
00231   {
00232     stream << signed(rhs.val());
00233     return stream;
00234   }
00235 
00236   namespace internal
00237   {
00238 
00239     /*----------------.
00240     | optraits<int_s> |
00241     `----------------*/
00242 
00243     template <unsigned nbits, class behavior>
00244     struct optraits<int_s<nbits, behavior> > :
00245       public optraits<sint_value<int_s<nbits, behavior> > >
00246     {
00247     public:
00248       typedef int_s<nbits, behavior> self;
00249       typedef optraits<sint_value<int_s<nbits, behavior> > > super;
00250 
00251     private:
00252       typedef typename typetraits<self>::base_type      base_type_;
00253       typedef typename typetraits<self>::storage_type   storage_type_;
00254       typedef typename behavior::template get<self>     behavior_type_;
00255 
00256     public:
00257       template <class P>
00258       static storage_type_
00259       check(const P& rhs)
00260       { return behavior_type_::check(rhs); }
00261 
00262       static storage_type_ max()
00263       { return C_for_int_s<nbits>::max(); }
00264 
00265       static storage_type_ min()
00266       { return C_for_int_s<nbits>::min(); }
00267 
00268       //
00269       //  Comparison operators
00270       //
00272 
00273       //  As int_x32 cannot grow, there is a problem with comparisons when a
00274       //  int_u32 is present, as we cannot convert it to a signed type safely.
00275       //
00276 
00277       //
00278       // cmp_eq
00279       //
00280 
00281       // int_sN == int_u32; int_u32 == int_sN
00282 
00283       template <unsigned mbits, class B1, class B2>
00284       static bool
00285       cmp_eq(const int_s<mbits, B1>& lhs, const int_u<32, B2>& rhs)
00286       {
00287         if (lhs.val() < 0)
00288           return false;
00289 
00290         return static_cast<int_u<32, B2> >(lhs).val() == rhs.val();
00291       }
00292       template <unsigned mbits, class B1, class B2>
00293       static bool cmp_eq(const int_u<32, B1>& lhs, const int_s<mbits, B2>& rhs)
00294       { return cmp_eq(rhs, lhs); }
00295 
00296       // <T1> == <T2>
00297 
00298       template <class T1, class T2>
00299       static bool
00300       cmp_eq(const T1& lhs, const T2& rhs)
00301       { return super::cmp_eq(lhs, rhs); }
00302 
00303       //
00304       // cmp_lt
00305       //
00306 
00307       // int_sN < int_u32; int_u32 < int_sN
00308 
00309       template <unsigned mbits, class B1, class B2>
00310       static bool
00311       cmp_lt(const int_s<mbits, B1>& lhs, const int_u<32, B2>& rhs)
00312       {
00313         if (lhs.val() < 0)
00314           return true;
00315 
00316         return static_cast<int_u<32, B2> >(lhs).val() < rhs.val();
00317       }
00318       template <unsigned mbits, class B1, class B2>
00319       static bool cmp_lt(const int_u<32, B1>& lhs, const int_s<mbits, B2>& rhs)
00320       {
00321         if (rhs.val() < 0)
00322           return false;
00323 
00324         return lhs.val() < static_cast<int_u<32, B1> >(rhs.val());
00325       }
00326 
00327       // <T1> < <T2>
00328 
00329       template <class T1, class T2>
00330       static bool
00331       cmp_lt(const T1& lhs, const T2& rhs)
00332       { return super::cmp_lt(lhs, rhs); }
00333 
00334       // debug
00335       static std::string name() {
00336         std::ostringstream out;
00337         out << "int_s<" << int(nbits) << ", " << behavior::name() << ">"
00338             << std::ends;
00339         return out.str();
00340       }
00341     };
00342 
00343 
00344     /*----------------.
00345     | operator traits |
00346     `----------------*/
00347 
00348     //
00349     // plus
00350     //
00351 
00352     // int_s + int_s
00353 
00354     template<unsigned nbits, class B1, unsigned mbits, class B2>
00355     struct operator_traits<operator_plus, int_s<nbits, B1>, int_s<mbits, B2> >
00356     {
00357       enum { commutative = true,
00358              need_check = ((unsigned) mlc::max<nbits, mbits>::ret >= 32) };
00359       typedef int_s<(unsigned)mlc::maxN<nbits + 1,mbits + 1, 32>::ret,
00360                     typename deduce_op_behavior<B1, B2>::ret> ret;
00361       typedef int_s<nbits, 
00362                     typename ret_behavior_if<need_check, ret>::ret> impl;
00363     };
00364 
00365 
00366     // int_s + int_u ; int_u + int_s
00367 
00368     template <unsigned nbits, class B1, unsigned mbits, class B2>
00369     struct operator_traits<operator_plus, int_s<nbits, B1>, int_u<mbits, B2> >
00370     {
00371       enum { commutative = true,
00372              need_check = ((mbits >= 31) || (nbits >= 32)) };
00373       typedef int_s<(unsigned)mlc::maxN<nbits + 1,mbits + 2, 32>::ret,
00374                     typename deduce_op_behavior<B1, B2>::ret> ret;
00375       typedef int_s<nbits, 
00376                     typename ret_behavior_if<need_check, ret>::ret> impl;
00377     };
00378 
00379 
00380     //
00381     // minus
00382     //
00383 
00384     // int_s - int_s
00385 
00386     template<unsigned nbits, class B1, unsigned mbits, class B2>
00387     struct operator_traits<operator_minus, int_s<nbits, B1>, int_s<mbits, B2> >
00388     {
00389       enum { commutative = true,
00390              need_check = ((mbits >= 31) || (nbits >= 31)) };
00391       typedef int_s<(unsigned)mlc::maxN<nbits + 1, mbits + 1, 32>::ret,
00392                     typename deduce_op_behavior<B1, B2>::ret> ret;
00393       typedef int_s<nbits, 
00394                     typename ret_behavior_if<need_check, ret>::ret> impl;
00395     };
00396 
00397     // int_s - int_u ; int_u - int_s
00398 
00399     template <unsigned nbits, class B1, unsigned mbits, class B2>
00400     struct operator_traits<operator_minus, int_s<nbits, B1>, int_u<mbits, B2> >
00401     {
00402       enum { commutative = true,
00403              need_check = ((mbits >= 31) || (nbits >= 32)) };
00404       typedef int_s<(unsigned)mlc::maxN<nbits + 1, mbits + 2, 32>::ret,
00405                     typename deduce_op_behavior<B1, B2>::ret> ret;
00406       typedef int_s<nbits, 
00407                     typename ret_behavior_if<need_check, ret>::ret> impl;
00408     };
00409 
00410 
00411     //
00412     // times
00413     //
00414 
00415     // int_s * int_s
00416 
00417     template<unsigned nbits, class B1, unsigned mbits, class B2>
00418     struct operator_traits<operator_times, int_s<nbits, B1>, int_s<mbits, B2> >
00419     {
00420       enum { commutative = true,
00421              need_check = (mbits + nbits > 32) };
00422       typedef int_s<(unsigned)mlc::saturateN<nbits + mbits, 32>::ret,
00423                     typename deduce_op_behavior<B1, B2>::ret> ret;
00424       typedef int_s<nbits, 
00425                     typename ret_behavior_if<need_check, ret>::ret> impl;
00426     };
00427 
00428 
00429     // int_s * int_u ; int_u * int_s
00430 
00431     template <unsigned nbits, class B1, unsigned mbits, class B2>
00432     struct operator_traits<operator_times, int_s<nbits, B1>, int_u<mbits, B2> >
00433     {
00434       enum { commutative = true,
00435              need_check = (nbits + mbits + 1 > 32)};
00436       typedef int_s<(unsigned)mlc::saturateN<nbits + mbits+1, 32>::ret,
00437                     typename deduce_op_behavior<B1, B2>::ret> ret;
00438       typedef int_s<nbits, 
00439                     typename ret_behavior_if<need_check, ret>::ret> impl;
00440     };
00441 
00442     //
00443     // div
00444     //
00445 
00446     // int_s / int_s
00447 
00448     template<unsigned nbits, class B1, unsigned mbits, class B2>
00449     struct operator_traits<operator_div, int_s<nbits, B1>, int_s<mbits, B2> >
00450     {
00451       enum { commutative = true };
00452       typedef int_s<nbits, typename deduce_op_behavior<B1, B2>::ret> ret;
00453       typedef int_s<nbits, force> impl;
00454     };
00455 
00456     // int_s / int_u ; int_u / int_s
00457 
00458     template <unsigned nbits, class B1, unsigned mbits, class B2>
00459     struct operator_traits<operator_div, int_s<nbits, B1>, int_u<mbits, B2> >
00460     {
00461       enum { commutative = false,
00462              need_check = (mbits >= 32) };
00463       typedef int_s<nbits, typename deduce_op_behavior<B1, B2>::ret> ret;
00464       typedef int_s<nbits, 
00465                     typename ret_behavior_if<need_check, ret>::ret> impl;
00466     };
00467 
00468     template <unsigned nbits, class B1, unsigned mbits, class B2>
00469     struct operator_traits<operator_div, int_u<mbits, B2>, int_s<nbits, B1> >
00470     {
00471       enum { commutative = false, 
00472              need_check = (mbits >= 32) };
00473       typedef int_s<mlc::saturateN<mbits + 1, 32>::ret,
00474                     typename deduce_op_behavior<B1, B2>::ret> ret;
00475       typedef int_s<nbits, 
00476                     typename ret_behavior_if<need_check, ret>::ret> impl;
00477     };
00478 
00479     //
00480     // mod
00481     //
00482 
00483     // int_s % int_s
00484 
00485     template<unsigned nbits, class B1, unsigned mbits, class B2>
00486     struct operator_traits<operator_mod, int_s<nbits, B1>, int_s<mbits, B2> >
00487     {
00488       enum { commutative = false };
00489       typedef int_s<mbits, typename deduce_op_behavior<B1, B2>::ret> ret;
00490       typedef int_s<nbits, force> impl;
00491     };
00492 
00493     // int_s % int_u ; int_u % int_s
00494 
00495     template <unsigned nbits, class B1, unsigned mbits, class B2>
00496     struct operator_traits<operator_mod, int_s<nbits, B1>, int_u<mbits, B2> >
00497     {
00498       enum { commutative = false, 
00499              need_check = (mbits >= 32) };
00500       typedef int_s<(unsigned)mlc::saturateN<mbits + 1, 32>::ret,
00501                     typename deduce_op_behavior<B1, B2>::ret> ret;
00502       typedef int_s<nbits, 
00503                     typename ret_behavior_if<need_check, ret>::ret> impl;
00504     };
00505 
00506   // FIXME: don't know what to do with this operator, so the
00507   // implementation is disabled. In classical C++, (a % b) with b < 0
00508   // returns a whatever b is.
00509 
00510 #if 0
00511     template <unsigned nbits, class B1, unsigned mbits, class B2>
00512     struct operator_traits<operator_mod, int_u<nbits, B1>, int_s<mbits, B2> >
00513     {
00514       enum { commutative = false };
00515       typedef int_u<mbits, typename deduce_op_behavior<B1, B2>::ret> ret;
00516       typedef int_s<nbits, B1> impl;
00517     };
00518 #endif
00519 
00520     //
00521     // Min
00522     //
00523 
00524     // min(int_s, int_s)
00525 
00526     template<unsigned nbits, class B1, unsigned mbits, class B2>
00527     struct operator_traits<operator_min, int_s<nbits, B1>, int_s<mbits, B2> >
00528     {
00529       enum { commutative = true };
00530       typedef int_s<(unsigned) mlc::min<nbits, mbits>::ret, 
00531                     typename deduce_op_behavior<B1, B2>::ret> ret;
00532       typedef int_s<nbits, force> impl;
00533     };
00534 
00535     //
00536     // Max
00537     //
00538 
00539     // max(int_s, int_s)
00540 
00541     template<unsigned nbits, class B1, unsigned mbits, class B2>
00542     struct operator_traits<operator_max, int_s<nbits, B1>, int_s<mbits, B2> >
00543     {
00544       enum { commutative = true };
00545       typedef int_s<(unsigned) mlc::max<nbits, mbits>::ret, 
00546                     typename deduce_op_behavior<B1, B2>::ret> ret;
00547       typedef int_s<nbits, force> impl;
00548     };
00549 
00550     //
00551     // Comparison operator
00552     //
00553 
00554     // int_s compared with int_s
00555 
00556     template<unsigned nbits, class B1, unsigned mbits, class B2>
00557     struct operator_traits<operator_cmp, int_s<nbits, B1>, int_s<mbits, B2> >
00558     {
00559       enum { commutative = true };
00560       typedef int_s<(unsigned)mlc::maxN<nbits,mbits,32>::ret, unsafe> ret;
00561       typedef int_s<nbits, force> impl;
00562     };
00563 
00564 
00565     // int_s CMP int_u ; int_u CMP int_s
00566 
00567     template <unsigned nbits, class B1, unsigned mbits, class B2>
00568     struct operator_traits<operator_cmp, int_s<nbits, B1>, int_u<mbits, B2> >
00569     {
00570       enum { commutative = true };
00571       typedef int_s<(unsigned)mlc::maxN<nbits,mbits+1, 32>::ret, unsafe> ret;
00572       typedef int_s<nbits, force> impl;
00573     };
00574 
00575   } // end of internal.
00576 
00577 } // end of ntg.
00578 
00579 #endif // !NTG_CORE_INT_S_HH

Generated on Thu Apr 15 20:13:12 2004 for Olena by doxygen 1.3.6-20040222