cast.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, 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_UTILS_CAST_HH
00029 # define NTG_UTILS_CAST_HH
00030 
00031 # include <ntg/config/system.hh>
00032 # include <ntg/core/macros.hh>
00033 # include <ntg/core/predecls.hh>
00034 # include <ntg/core/type_traits.hh>
00035 # include <ntg/real/real_value.hh>
00036 
00037 // FIXME: this file is completely broken, taking float_value as
00038 // parameter does not make sense.
00039 
00040 /*-------.
00041 | macros |
00042 `-------*/
00043 
00044 # define TO_NTG_CAST(Dest)                              \
00045   template<class T>                                     \
00046   inline ntg_##Dest##_type(T) to_##Dest##_ntg(T val)    \
00047   {                                                     \
00048     return static_cast<ntg_##Dest##_type(T)>(val);      \
00049   }
00050 
00051 namespace ntg {
00052 
00053   /*---------.
00054   | to_ntg() |
00055   `---------*/
00056 
00057   template<class T>
00058   inline ntg_type(T) to_ntg(T val)
00059   {
00060     return static_cast<ntg_type(T)>(val);
00061   }
00062 
00063   TO_NTG_CAST(signed)
00064 
00065   namespace cast {
00066 
00067     // FIXME: force does not seem to have any reason to live.
00068 
00069     /*------.
00070     | force |
00071     `------*/
00072 
00073     // a cast is performed instead of a constructor (unsafe one) call
00074     // because this last one may not be available with the good
00075     // signature.
00076     template<class Tdest, class Tsrc> inline
00077     const Tdest
00078     force(const Tsrc& val)
00079     {
00080       return ntg_unsafe_type(Tdest)(val);
00081     }
00082 
00083     /*------.
00084     | bound |
00085     `------*/
00086 
00087     // Like cast::force, but with saturation.
00088     template<class Tdest, class Tsrc> inline
00089     const Tdest
00090     bound(const Tsrc& val)
00091     {
00092       if (ntg_max_val(Tsrc) > ntg_max_val(Tdest))
00093         if (val > Tsrc(Tdest(ntg_max_val(Tdest))))
00094           return ntg_max_val(Tdest);
00095       if (ntg_min_val(Tsrc) < ntg_min_val(Tdest))
00096         if (val < Tsrc(Tdest(ntg_min_val(Tdest))))
00097           return ntg_min_val(Tdest);
00098       return val;
00099     }
00100 
00101     /*------.
00102     | round |
00103     `------*/
00104 
00105     namespace internal {
00106       template<class Tdest, class Tsrc>
00107       struct _round {
00108         // By default we don't define any function.
00109         // This cast does only work on float input.
00110       };
00111 
00112       template<class Tdest, class Tsrc>
00113       struct _round<Tdest, float_value<Tsrc> >
00114       {
00115         static const Tdest
00116         doit(const float_value<Tsrc>& val)
00117         {
00118           // FIXME: this code seems out of date.
00119 
00120 #if 1
00121           // KLUDGE: Cast the rounded value to Tdest::value_t before
00122           // returning it as Tdest. Otherwise g++-3.* complains there
00123           // is no Tdest constructor taking a float argument.
00124           return (ntg_storage_type(Tdest)) round(val.exact());
00125 #endif
00126           //      return round(val.exact());
00127         }
00128       };
00129 
00130       template<class Tdest>
00131       struct _round<Tdest, float_s >
00132       {
00133         static const Tdest
00134         doit(const float_s& val)
00135         {
00136           // FIXME: this code seems out of date.
00137 #if 1
00138           // KLUDGE: Cast the rounded value to Tdest::value_t before
00139           // returning it as Tdest. Otherwise g++-3.* complains there
00140           // is no Tdest constructor taking a float argument.
00141           return (ntg_storage_type(Tdest)) roundf(val);
00142 #endif
00143           //      return roundf(val);
00144         }
00145       };
00146 
00147       template<class Tdest>
00148       struct _round<Tdest, double>
00149       {
00150         static const Tdest
00151         doit(const float_d& val)
00152         {
00153           // FIXME: this code seems out of date.
00154 #if 0
00155           // KLUDGE: Cast the rounded value to Tdest::value_t before
00156           // returning it as Tdest. Otherwise g++-3.0 complains there
00157           // is no Tdest constructor taking a float argument.
00158           return (ntg_storage_type(Tdest)) round(val);
00159 #endif
00160           return round(val);
00161         }
00162       };
00163 
00164       template<class Tdest, class Tsrc>
00165       struct _round<float_value<Tdest>, float_value<Tsrc> >
00166       {
00167         static const Tdest
00168         doit(const float_value<Tsrc>& val)
00169         {
00170           return val.exact();
00171         }
00172       };
00173 
00174       template<class Tsrc>
00175       struct _round<float_s, float_value<Tsrc> >
00176       {
00177         static float_s
00178         doit(const float_value<Tsrc>& val)
00179         {
00180           return val.exact();
00181         }
00182       };
00183 
00184       template<class Tsrc>
00185       struct _round<float_d, float_value<Tsrc> >
00186       {
00187         static float_d
00188         doit(const float_value<Tsrc>& val)
00189         {
00190           return val.exact();
00191         }
00192       };
00193 
00194       template<>
00195       struct _round<float_s, float_d>
00196       {
00197         static float
00198         doit(const double& val)
00199         {
00200           return val;
00201         }
00202       };
00203 
00204       template<>
00205       struct _round<float_d, float_s>
00206       {
00207         static float_d
00208         doit(const float& val)
00209         {
00210           return val;
00211         }
00212       };
00213     } // end of internal.
00214 
00215     template<class Tdest, class Tsrc> inline
00216     const Tdest round(const Tsrc& val)
00217     {
00218       return internal::_round<Tdest, Tsrc>::doit(val);
00219     }
00220 
00221     /* Like cast::round, but with saturation.  */
00222     template<class Tdest, class Tsrc> inline
00223     const Tdest rbound(const Tsrc& val)
00224     {
00225       if (val > Tsrc(Tdest(ntg_max_val(Tdest))))
00226         return ntg_max_val(Tdest);
00227       if (val < Tsrc(Tdest(ntg_min_val(Tdest))))
00228         return ntg_min_val(Tdest);
00229       return cast::round<Tdest>(val);
00230     }
00231 
00232   } // end of cast.
00233 
00234 } // end of ntg.
00235 
00236 #endif // NTG_UTILS_CAST_HH

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