upgrade_val.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2010 NICTA and the authors listed below
00002 // http://nicta.com.au
00003 // 
00004 // Authors:
00005 // - Conrad Sanderson (conradsand at ieee dot org)
00006 // 
00007 // This file is part of the Armadillo C++ library.
00008 // It is provided without any warranty of fitness
00009 // for any purpose. You can redistribute this file
00010 // and/or modify it under the terms of the GNU
00011 // Lesser General Public License (LGPL) as published
00012 // by the Free Software Foundation, either version 3
00013 // of the License or (at your option) any later version.
00014 // (see http://www.opensource.org/licenses for more info)
00015 
00016 
00017 //! \addtogroup upgrade_val
00018 //! @{
00019 
00020 
00021 
00022 //! upgrade_val is used to ensure an operation such as multiplication is possible between two types.
00023 //! values are upgraded only where necessary.
00024 
00025 template<typename T1, typename T2>
00026 struct upgrade_val
00027   {
00028   typedef typename promote_type<T1,T2>::result T1_result;
00029   typedef typename promote_type<T1,T2>::result T2_result;
00030   
00031   arma_inline
00032   static
00033   typename promote_type<T1,T2>::result
00034   apply(const T1 x)
00035     {
00036     typedef typename promote_type<T1,T2>::result out_type;
00037     return out_type(x);
00038     }
00039   
00040   arma_inline
00041   static
00042   typename promote_type<T1,T2>::result
00043   apply(const T2 x)
00044     {
00045     typedef typename promote_type<T1,T2>::result out_type;
00046     return out_type(x);
00047     }
00048   
00049   };
00050 
00051 
00052 // template<>
00053 template<typename T>
00054 struct upgrade_val<T,T>
00055   {
00056   typedef T T1_result;
00057   typedef T T2_result;
00058   
00059   arma_inline static const T& apply(const T& x) { return x; }
00060   };
00061 
00062 
00063 //! upgrade a type to allow multiplication with a complex type
00064 //! e.g. the int in "int * complex<double>" is upgraded to a double
00065 // template<>
00066 template<typename T, typename T2>
00067 struct upgrade_val< std::complex<T>, T2 >
00068   {
00069   typedef std::complex<T> T1_result;
00070   typedef T               T2_result;
00071   
00072   arma_inline static const std::complex<T>& apply(const std::complex<T>& x) { return x;    }
00073   arma_inline static       T                apply(const T2 x)               { return T(x); }
00074   };
00075 
00076 
00077 // template<>
00078 template<typename T1, typename T>
00079 struct upgrade_val< T1, std::complex<T> >
00080   {
00081   typedef T               T1_result;
00082   typedef std::complex<T> T2_result;
00083   
00084   arma_inline static       T                apply(const T1 x)               { return T(x); }
00085   arma_inline static const std::complex<T>& apply(const std::complex<T>& x) { return x;    }
00086   };
00087 
00088 
00089 //! ensure we don't lose precision when multiplying a complex number with a higher precision real number
00090 template<>
00091 struct upgrade_val< std::complex<float>, double >
00092   {
00093   typedef std::complex<double> T1_result;
00094   typedef double               T2_result;
00095   
00096   arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
00097   arma_inline static       double               apply(const double x)               { return x; }
00098   };
00099 
00100 
00101 template<>
00102 struct upgrade_val< double, std::complex<float> >
00103   {
00104   typedef double              T1_result;
00105   typedef std::complex<float> T2_result;
00106   
00107   arma_inline static       double               apply(const double x)               { return x; }
00108   arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
00109   };
00110 
00111 
00112 //! ensure we don't lose precision when multiplying complex numbers with different underlying types
00113 template<>
00114 struct upgrade_val< std::complex<float>, std::complex<double> >
00115   {
00116   typedef std::complex<double> T1_result;
00117   typedef std::complex<double> T2_result;
00118   
00119   arma_inline static const std::complex<double>  apply(const std::complex<float>&  x) { return std::complex<double>(x); }
00120   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00121   };
00122 
00123 
00124 template<>
00125 struct upgrade_val< std::complex<double>, std::complex<float> >
00126   {
00127   typedef std::complex<double> T1_result;
00128   typedef std::complex<double> T2_result;
00129   
00130   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00131   arma_inline static const std::complex<double>  apply(const std::complex<float>&  x) { return std::complex<double>(x); }
00132   };
00133 
00134 
00135 //! work around limitations in the complex class (at least as present in gcc 4.1 & 4.3)
00136 template<>
00137 struct upgrade_val< std::complex<double>, float >
00138   {
00139   typedef std::complex<double> T1_result;
00140   typedef double               T2_result;
00141   
00142   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00143   arma_inline static       double                apply(const float x)                 { return double(x); }
00144   };
00145 
00146 
00147 template<>
00148 struct upgrade_val< float, std::complex<double> >
00149   {
00150   typedef double               T1_result;
00151   typedef std::complex<double> T2_result;
00152   
00153   arma_inline static       double                apply(const float x)                 { return double(x); }
00154   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00155   };
00156 
00157 
00158 
00159 //! @}