int_u.hh

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

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