int_s.hh

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

Generated on Tue Feb 20 20:19:57 2007 for Olena by  doxygen 1.5.1