int_u.hh

00001 // Copyright (C) 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_REAL_INT_U_HH
00029 # define NTG_REAL_INT_U_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 # define INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(Builtin)                   \
00048 int_u (const Builtin rhs)                                                \
00049 {                                                                        \
00050   if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
00051     this->val_ = rhs;                                                    \
00052   else                                                                   \
00053     this->val_ = optraits_type::check(rhs);                              \
00054 }                                                                        \
00055 self& operator=(const Builtin rhs)                                       \
00056 {                                                                        \
00057   if ((unsigned) internal::typetraits<ntg_type(Builtin)>::size <= nbits) \
00058     this->val_ = rhs;                                                    \
00059   else                                                                   \
00060     this->val_ = optraits_type::check(rhs);                              \
00061   return *this;                                                          \
00062 }
00063 
00064 # define INT_U_CTOR_FROM_BUILTIN_INT(Builtin)   \
00065 int_u (const Builtin rhs)                       \
00066 {                                               \
00067     this->val_ = optraits_type::check(rhs);     \
00068 }                                               \
00069 self& operator=(const Builtin rhs)              \
00070 {                                               \
00071   this->val_ = optraits_type::check(rhs);       \
00072   return *this;                                 \
00073 }
00074 
00075 
00076 namespace ntg {
00077 
00078   namespace internal {
00079 
00080     /*------------------.
00081     | typetraits<int_u> |
00082     `------------------*/
00083 
00084     template <unsigned nbits, typename behavior>
00085     struct typetraits<int_u<nbits, behavior> >
00086       : public typetraits<uint_value<int_u<nbits, behavior> > >
00087     {
00088       typedef int_u<nbits, behavior>            self;
00089       typedef unsigned_integer                  abstract_type;
00090       typedef self                              ntg_type;
00091 
00092       ntg_build_value_type(uint_value<E>);
00093 
00094       typedef optraits<self>                            optraits_type;
00095       typedef behavior                                  abstract_behavior_type;
00096       typedef typename behavior::template get<self>     behavior_type;
00097 
00098       typedef self                                      base_type;
00099       typedef typename C_for_int_u<nbits>::type         storage_type;
00100       typedef int_s<mlc::saturateN<nbits+1, 32>::ret,
00101                     behavior>                           signed_type;
00102       typedef self                                      unsigned_type;
00103       // FIXME: calculate it more precisely
00104       typedef int_u<32, behavior>                       cumul_type;
00105       typedef int_u<32, behavior>                       largest_type;
00106       typedef int_s<32, behavior>                       signed_largest_type;
00107       typedef int_s<32, behavior>                       signed_cumul_type;
00108       typedef int_u<32, behavior>                       unsigned_largest_type;
00109       typedef int_u<32, behavior>                       unsigned_cumul_type;
00110       typedef unsigned int                              integer_type;
00111       typedef int_u<nbits, unsafe>                      unsafe_type;
00112 
00113       // Particular properties
00114       enum { size = nbits };
00115     };
00116 
00117   } // end of internal.
00118 
00119   /*-----------------------.
00120   | int_u<nbits, behavior> |
00121   `-----------------------*/
00122 
00123   template <unsigned nbits, class behavior>
00124   class int_u : public uint_value<int_u<nbits, behavior> >
00125   {
00126     typedef int_u<nbits, behavior> self;
00127     typedef ntgi_storage_type(self) storage_type;
00128     // dev note : should be directly optraits<self_t>, but with g++ this
00129     // breaks inheritance in optraits herarchy ...
00130     typedef ntgi_optraits_type(self) optraits_type;
00131 
00132   public:
00133     int_u () { this->val_ = 0; }
00134 
00135     // We define ctor for each builtin to avoid implicit builtin
00136     // promotion.
00137 
00138     // FIXME: dynamic checks are not necessary for all builtin types!
00139 
00140     INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned long);
00141     INT_U_CTOR_FROM_BUILTIN_INT(signed long);
00142 
00143     INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned int);
00144     INT_U_CTOR_FROM_BUILTIN_INT(signed int);
00145 
00146     INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned short);
00147     INT_U_CTOR_FROM_BUILTIN_INT(signed short);
00148 
00149     INT_U_CTOR_FROM_UNSIGNED_BUILTIN_INT(unsigned char);
00150     INT_U_CTOR_FROM_BUILTIN_INT(signed char);
00151     INT_U_CTOR_FROM_BUILTIN_INT(char);
00152 
00153     int_u (const float_s rhs)
00154     {
00155       this->val_ = optraits_type::check(roundf(rhs));
00156     }
00157     self&
00158     operator=(const float rhs)
00159     {
00160       this->val_ = optraits_type::check(roundf(rhs));
00161       return *this;
00162     }
00163 
00164     int_u (const float_d rhs)
00165     {
00166       this->val_ = optraits_type::check(round(rhs));
00167     }
00168     self&
00169     operator=(const double rhs)
00170     {
00171       this->val_ = optraits_type::check(round(rhs));
00172       return *this;
00173     }
00174 
00175     template <unsigned mbits, class B2>
00176     int_u (const int_u<mbits, B2>& rhs)
00177     {
00178       if (mbits <= nbits)
00179         this->val_ = rhs.val();
00180       else
00181         this->val_ = optraits_type::check(rhs.val());
00182     }
00183     template <unsigned mbits, class B2>
00184     self&
00185     operator=(const int_u<mbits, B2>& rhs)
00186     {
00187       if (mbits <= nbits)
00188         this->val_ = rhs.val();
00189       else
00190           this->val_ = optraits_type::check(rhs.val());
00191       return *this;
00192     }
00193 
00194     template <class T>
00195     int_u (const real_value<T>& rhs)
00196     {
00197       this->val_ = optraits_type::check(rhs.val());
00198     }
00199     template <class T>
00200     self&
00201     operator=(const real_value<T>& rhs)
00202     {
00203       this->val_ = optraits_type::check(rhs.val());
00204       return *this;
00205     }
00206 
00207     // bin is allowed since it has defined values 0 or 1.
00208     int_u (bin b)
00209     {
00210       this->val_ = b.val();
00211     }
00212     self&
00213     operator=(bin b)
00214     {
00215       this->val_ = b.val();
00216       return *this;
00217     }
00218 
00219     operator storage_type () const { return this->val_; }
00220 
00221   private:
00222     // We want to prevent this
00223     int_u(bool);
00224   };
00225 
00226   template<unsigned nbits, class behavior>
00227   inline std::ostream&
00228   operator<<(std::ostream& stream, const int_u<nbits, behavior>& rhs)
00229   {
00230     stream << unsigned(rhs.val());
00231     return stream;
00232   }
00233 
00234   namespace internal
00235   {
00236 
00237     /*----------------.
00238     | optraits<int_u> |
00239     `----------------*/
00240 
00241     template <unsigned nbits, class behavior>
00242     struct optraits<int_u<nbits, behavior> > :
00243       public optraits<uint_value<int_u<nbits, behavior> > >
00244     {
00245     private:
00246       typedef int_u<nbits, behavior>                    self;
00247       typedef typename typetraits<self>::storage_type   storage_type_;
00248       typedef typename behavior::template get<self>     behavior_type_;
00249 
00250     public:
00251       template <class P>
00252       static storage_type_ check(const P& rhs)
00253       { return behavior_type_::check(rhs); }
00254 
00255       static storage_type_ max()
00256       { return C_for_int_u<nbits>::max(); }
00257 
00258       static std::string
00259       name()
00260       {
00261         std::ostringstream out;
00262         out << "int_u<" << int(nbits) << ", " << behavior::name() << ">"
00263             << std::ends;
00264         return out.str();
00265       }
00266     };
00267 
00268     /*----------------.
00269     | operator traits |
00270     `----------------*/
00271 
00272     //
00273     // plus
00274     //
00275 
00276     // int_u + int_u
00277 
00278     template<unsigned nbits, class B1, unsigned mbits, class B2>
00279     struct operator_traits<operator_plus, int_u<nbits, B1>, int_u<mbits, B2> >
00280     {
00281       enum { commutative = true,
00282              need_check = ((unsigned) mlc::max<nbits, mbits>::ret >= 32) };
00283       typedef int_u<(unsigned) mlc::maxN<nbits + 1, mbits + 1, 32>::ret,
00284                     typename deduce_op_behavior<B1, B2>::ret> ret;
00285       typedef int_u<nbits,
00286                     typename ret_behavior_if<need_check, ret>::ret> impl;
00287     };
00288 
00289     //
00290     // minus
00291     //
00292 
00293     // int_u - int_u
00294 
00295     template<unsigned nbits, class B1, unsigned mbits, class B2>
00296     struct operator_traits<operator_minus, int_u<nbits, B1>, int_u<mbits, B2> >
00297     {
00298       enum { commutative = true,
00299              need_check = ((unsigned) mlc::max<nbits, mbits>::ret >= 32) };
00300       typedef int_s<(unsigned) mlc::maxN<nbits+1, mbits+1, 32>::ret,
00301                     typename deduce_op_behavior<B1, B2>::ret> ret;
00302       typedef int_u<nbits,
00303                     typename ret_behavior_if<need_check, ret>::ret> impl;
00304     };
00305 
00306     // int_u32 - int_u : we do not convert result to int_s because we
00307     // want to access (UINT_MAX - 1).
00308 
00309     template<class B1, unsigned mbits, class B2>
00310     struct operator_traits<operator_minus, int_u<32, B1>, int_u<mbits, B2> >
00311     {
00312       enum { commutative = true };
00313       typedef int_u<32, typename deduce_op_behavior<B1, B2>::ret> ret;
00314       typedef int_u<32, force> impl;
00315     };
00316 
00317     //
00318     // times
00319     //
00320 
00321     // int_u * int_u
00322 
00323     template<unsigned nbits, class B1, unsigned mbits, class B2>
00324     struct operator_traits<operator_times, int_u<nbits, B1>, int_u<mbits, B2> >
00325     {
00326       enum { commutative = true, need_check = (nbits + mbits > 32) };
00327       typedef int_u<(unsigned) mlc::saturateN<nbits + mbits, 32>::ret,
00328         typename deduce_op_behavior<B1, B2>::ret> ret;
00329       typedef int_u<nbits,
00330                     typename ret_behavior_if<need_check, ret>::ret> impl;
00331     };
00332 
00333     //
00334     // div
00335     //
00336 
00337     // int_u / int_u
00338 
00339     template<unsigned nbits, class B1, unsigned mbits, class B2>
00340     struct operator_traits<operator_div, int_u<nbits, B1>, int_u<mbits, B2> >
00341     {
00342       enum { commutative = true };
00343       typedef int_u<nbits, typename deduce_op_behavior<B1, B2>::ret> ret;
00344       typedef int_u<nbits, force> impl;
00345     };
00346 
00347     //
00348     // modulo
00349     //
00350 
00351     // int_u % int_u
00352 
00353     template<unsigned nbits, class B1, unsigned mbits, class B2>
00354     struct operator_traits<operator_mod, int_u<nbits, B1>, int_u<mbits, B2> >
00355     {
00356       enum { commutative = false };
00357       typedef int_u<mbits, typename deduce_op_behavior<B1, B2>::ret> ret;
00358       typedef int_u<nbits, force> impl;
00359     };
00360 
00361     //
00362     // Min
00363     //
00364 
00365     // min(int_u, int_u)
00366 
00367     template<unsigned nbits, class B1, unsigned mbits, class B2>
00368     struct operator_traits<operator_min, int_u<nbits, B1>, int_u<mbits, B2> >
00369     {
00370       enum { commutative = true };
00371       typedef int_u<(unsigned) mlc::min<nbits, mbits>::ret,
00372                     typename deduce_op_behavior<B1, B2>::ret> ret;
00373       typedef int_u<nbits, force> impl;
00374     };
00375 
00376 
00377     //
00378     // Max
00379     //
00380 
00381     // max(int_u, int_u)
00382 
00383     template<unsigned nbits, class B1, unsigned mbits, class B2>
00384     struct operator_traits<operator_max, int_u<nbits, B1>, int_u<mbits, B2> >
00385     {
00386       enum { commutative = true };
00387       typedef int_u<(unsigned) mlc::max<nbits, mbits>::ret,
00388                     typename deduce_op_behavior<B1, B2>::ret> ret;
00389       typedef int_u<nbits, force> impl;
00390     };
00391 
00392 
00393     //
00394     // Comparison
00395     //
00396 
00397     // int_u CMP int_u
00398 
00399     template<unsigned nbits, class B1, unsigned mbits, class B2>
00400     struct operator_traits<operator_cmp, int_u<nbits, B1>, int_u<mbits, B2> >
00401     {
00402       enum { commutative = true };
00403       // FIXME: why unsafe? I think there is a reason.
00404       typedef int_u<(unsigned) mlc::maxN<nbits, mbits, 32>::ret, unsafe> ret;
00405       typedef int_u<nbits, force> impl;
00406     };
00407 
00408   } // end of internal.
00409 
00410 } // end of ntg.
00411 
00412 #endif // !NTG_REAL_INT_U_HH

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