traits.hpp

Go to the documentation of this file.
00001 // Copyright (C) 2009 NICTA
00002 // 
00003 // Authors:
00004 // - Conrad Sanderson (conradsand at ieee dot org)
00005 // 
00006 // This file is part of the Armadillo C++ library.
00007 // It is provided without any warranty of fitness
00008 // for any purpose. You can redistribute this file
00009 // and/or modify it under the terms of the GNU
00010 // Lesser General Public License (LGPL) as published
00011 // by the Free Software Foundation, either version 3
00012 // of the License or (at your option) any later version.
00013 // (see http://www.opensource.org/licenses for more info)
00014 
00015 
00016 //! \addtogroup traits
00017 //! @{
00018 
00019 
00020 template<typename T1>
00021 struct get_pod_type
00022   { typedef T1 pod_type; };
00023 
00024 template<typename T2>
00025 struct get_pod_type< std::complex<T2> >
00026   { typedef T2 pod_type; };
00027 
00028 
00029 
00030 template<typename T>
00031 struct is_Mat_only
00032   { static const bool value = false; };
00033 
00034 template<typename eT>
00035 struct is_Mat_only< Mat<eT> >
00036   { static const bool value = true; };
00037 
00038 
00039 
00040 template<typename T>
00041 struct is_Mat
00042   { static const bool value = false; };
00043 
00044 template<typename eT>
00045 struct is_Mat< Mat<eT> >
00046   { static const bool value = true; };
00047 
00048 template<typename eT>
00049 struct is_Mat< Row<eT> >
00050   { static const bool value = true; };
00051 
00052 template<typename eT>
00053 struct is_Mat< Col<eT> >
00054   { static const bool value = true; };
00055 
00056 
00057 
00058 template<typename T>
00059 struct is_Row
00060   { static const bool value = false; };
00061 
00062 template<typename eT>
00063 struct is_Row< Row<eT> >
00064   { static const bool value = true; };
00065 
00066 
00067 
00068 template<typename T>
00069 struct is_Col
00070   { static const bool value = false; };
00071 
00072 template<typename eT>
00073 struct is_Col< Col<eT> >
00074   { static const bool value = true; };
00075 
00076 
00077 
00078 
00079 
00080 
00081 template<typename T>
00082 struct is_subview
00083   { static const bool value = false; };
00084 
00085 template<typename eT>
00086 struct is_subview< subview<eT> >
00087   { static const bool value = true; };
00088 
00089 
00090 template<typename T>
00091 struct is_diagview
00092   { static const bool value = false; };
00093 
00094 template<typename eT>
00095 struct is_diagview< diagview<eT> >
00096   { static const bool value = true; };
00097 
00098 
00099 //
00100 //
00101 //
00102 
00103 
00104 template<typename T>
00105 struct is_Op
00106   { static const bool value = false; };
00107  
00108 template<typename T1, typename op_type>
00109 struct is_Op< Op<T1,op_type> >
00110   { static const bool value = true; };
00111  
00112  
00113 template<typename T>
00114 struct is_Glue
00115   { static const bool value = false; };
00116  
00117 template<typename T1, typename T2, typename glue_type>
00118 struct is_Glue< Glue<T1,T2,glue_type> >
00119   { static const bool value = true; };
00120 
00121 
00122 template<typename T>
00123 struct is_glue_times
00124   { static const bool value = false; };
00125 
00126 template<typename T1, typename T2>
00127 struct is_glue_times< Glue<T1,T2,glue_times> >
00128   { static const bool value = true; };
00129 
00130 
00131 //
00132 //
00133 //
00134 
00135 
00136 template<typename T1>
00137 struct is_arma_type
00138   {
00139   static const bool value
00140   =  is_Mat<T1>::value
00141   || is_Op<T1>::value
00142   || is_Glue<T1>::value
00143   || is_subview<T1>::value
00144   || is_diagview<T1>::value
00145   ;
00146   };
00147 
00148 
00149 
00150 //
00151 //
00152 //
00153 
00154 
00155 template<typename T1, typename T2>
00156 struct is_same_type
00157   { static const bool value = false; };
00158 
00159 
00160 template<typename T1>
00161 struct is_same_type<T1,T1>
00162   { static const bool value = true; };
00163 
00164 
00165 
00166 template<typename T1, typename T2>
00167 struct isnt_same_type
00168   {
00169   static const bool value = true;
00170   
00171   inline static void check()
00172     {
00173     arma_static_assert<false> ERROR___TYPE_MISMATCH;
00174     ERROR___TYPE_MISMATCH = ERROR___TYPE_MISMATCH;
00175     }
00176   };
00177 
00178 
00179 template<typename T1>
00180 struct isnt_same_type<T1,T1>
00181   {
00182   static const bool value = false;
00183   
00184   arma_inline static void check() {}
00185   };
00186 
00187 
00188 //
00189 //
00190 //
00191 
00192 
00193 template<typename T1>
00194 struct isnt_fltpt
00195   {
00196   static const bool value = true;
00197   
00198   inline static void check()
00199     {
00200     arma_static_assert<false> ERROR___TYPE_MISMATCH;
00201     ERROR___TYPE_MISMATCH = ERROR___TYPE_MISMATCH;
00202     }
00203   };
00204 
00205 
00206 
00207 struct isnt_fltpt_false
00208   {
00209   static const bool value = false;
00210   
00211   arma_inline static void check() {}
00212   };
00213 
00214 
00215 
00216 template<> struct isnt_fltpt< float >                : public isnt_fltpt_false {};
00217 template<> struct isnt_fltpt< double >               : public isnt_fltpt_false {};
00218 template<> struct isnt_fltpt< long double >          : public isnt_fltpt_false {};
00219 template<> struct isnt_fltpt< std::complex<float> >  : public isnt_fltpt_false {};
00220 template<> struct isnt_fltpt< std::complex<double> > : public isnt_fltpt_false {};
00221 
00222 
00223 
00224 template<typename T1>
00225 struct is_u8
00226   { static const bool value = false; };
00227 
00228 template<>
00229 struct is_u8<u8>
00230   { static const bool value = true; };
00231 
00232 
00233 
00234 template<typename T1>
00235 struct is_s8
00236   { static const bool value = false; };
00237 
00238 template<>
00239 struct is_s8<s8>
00240   { static const bool value = true; };
00241 
00242 
00243 
00244 template<typename T1>
00245 struct is_u16
00246   { static const bool value = false; };
00247 
00248 template<>
00249 struct is_u16<u16>
00250   { static const bool value = true; };
00251 
00252 
00253 
00254 template<typename T1>
00255 struct is_s16
00256   { static const bool value = false; };
00257 
00258 template<>
00259 struct is_s16<s16>
00260   { static const bool value = true; };
00261 
00262 
00263 
00264 template<typename T1>
00265 struct is_u32
00266   { static const bool value = false; };
00267 
00268 template<>
00269 struct is_u32<u32>
00270   { static const bool value = true; };
00271 
00272 
00273 
00274 template<typename T1>
00275 struct is_s32
00276   { static const bool value = false; };
00277 
00278 template<>
00279 struct is_s32<s32>
00280   { static const bool value = true; };
00281 
00282 
00283 
00284 
00285 template<typename T1>
00286 struct is_float
00287   { static const bool value = false; };
00288 
00289 template<>
00290 struct is_float<float>
00291   { static const bool value = true; };
00292 
00293 
00294 
00295 template<typename T1>
00296 struct is_double
00297   { static const bool value = false; };
00298 
00299 template<>
00300 struct is_double<double>
00301   { static const bool value = true; };
00302 
00303 
00304 
00305 template<typename T1>
00306 struct is_complex
00307   { static const bool value = false; };
00308 
00309 // template<>
00310 template<typename eT>
00311 struct is_complex< std::complex<eT> >
00312   { static const bool value = true; };
00313 
00314 
00315 
00316 template<typename T1>
00317 struct is_complex_float
00318   { static const bool value = false; };
00319 
00320 template<>
00321 struct is_complex< std::complex<float> >
00322   { static const bool value = true; };
00323 
00324 
00325 
00326 template<typename T1>
00327 struct is_complex_double
00328   { static const bool value = false; };
00329 
00330 template<>
00331 struct is_complex_double< std::complex<double> >
00332   { static const bool value = true; };
00333 
00334 
00335 
00336 
00337 //! check for a weird implementation of the std::complex class
00338 template<typename T1>
00339 struct is_supported_complex
00340   { static const bool value = false; };
00341 
00342 //template<>
00343 template<typename eT>
00344 struct is_supported_complex< std::complex<eT> >
00345   { static const bool value = ( sizeof(std::complex<eT>) == 2*sizeof(eT) ); };
00346 
00347 
00348 
00349 template<typename T1>
00350 struct is_supported_complex_float
00351   { static const bool value = false; };
00352 
00353 template<>
00354 struct is_supported_complex_float< std::complex<float> >
00355   { static const bool value = ( sizeof(std::complex<float>) == 2*sizeof(float) ); };
00356 
00357 
00358 
00359 template<typename T1>
00360 struct is_supported_complex_double
00361   { static const bool value = false; };
00362 
00363 template<>
00364 struct is_supported_complex_double< std::complex<double> >
00365   { static const bool value = ( sizeof(std::complex<double>) == 2*sizeof(double) ); };
00366 
00367 
00368 
00369 template<typename T1>
00370 struct is_supported_elem_type
00371   {
00372   static const bool value = \
00373     is_u8<T1>::value ||
00374     is_s8<T1>::value ||
00375     is_u16<T1>::value ||
00376     is_s16<T1>::value ||
00377     is_u32<T1>::value ||
00378     is_s32<T1>::value ||
00379     is_float<T1>::value ||
00380     is_double<T1>::value ||
00381     is_supported_complex_float<T1>::value ||
00382     is_supported_complex_double<T1>::value;
00383   };
00384 
00385 
00386 
00387 template<typename T1>
00388 struct isnt_supported_elem_type
00389   {
00390   static const bool value = true;
00391   
00392   inline static void check()
00393     {
00394     arma_static_assert<false> ERROR___UNSUPPORTED_ELEMENT_TYPE;
00395     ERROR___UNSUPPORTED_ELEMENT_TYPE = ERROR___UNSUPPORTED_ELEMENT_TYPE;
00396     }
00397   };
00398 
00399 
00400 
00401 struct isnt_supported_elem_type_false
00402   {
00403   static const bool value = false;
00404   
00405   arma_inline static void check() {}
00406   };
00407 
00408 
00409 
00410 template<> struct isnt_supported_elem_type< u8 >                   : public isnt_supported_elem_type_false {};
00411 template<> struct isnt_supported_elem_type< s8 >                   : public isnt_supported_elem_type_false {};
00412 template<> struct isnt_supported_elem_type< u16 >                  : public isnt_supported_elem_type_false {};
00413 template<> struct isnt_supported_elem_type< s16 >                  : public isnt_supported_elem_type_false {};
00414 template<> struct isnt_supported_elem_type< u32 >                  : public isnt_supported_elem_type_false {};
00415 template<> struct isnt_supported_elem_type< s32 >                  : public isnt_supported_elem_type_false {};
00416 template<> struct isnt_supported_elem_type< float >                : public isnt_supported_elem_type_false {};
00417 template<> struct isnt_supported_elem_type< double >               : public isnt_supported_elem_type_false {};
00418 template<> struct isnt_supported_elem_type< std::complex<float> >  : public isnt_supported_elem_type_false {};
00419 template<> struct isnt_supported_elem_type< std::complex<double> > : public isnt_supported_elem_type_false {};
00420 
00421 
00422 
00423 template<typename T1>
00424 struct is_supported_blas_type
00425   {
00426   static const bool value = \
00427     is_float<T1>::value ||
00428     is_double<T1>::value ||
00429     is_supported_complex_float<T1>::value ||
00430     is_supported_complex_double<T1>::value;
00431   };
00432 
00433 
00434 
00435 template<typename T>
00436 struct is_signed
00437   {
00438   static const bool value = (T(-1) < T(0));
00439   };
00440 
00441 
00442 
00443 template<typename T>
00444 struct is_non_integral
00445   {
00446   static const bool value = (T(1.0) != T(1.1));
00447   };
00448 
00449 
00450 
00451 //
00452 // type promotion
00453 
00454 template<typename T1, typename T2>
00455 struct promote_type
00456   {
00457   inline static void check()
00458     {
00459     arma_static_assert<false> ERROR___UNSUPPORTED_MIXTURE_OF_TYPES;
00460     ERROR___UNSUPPORTED_MIXTURE_OF_TYPES = ERROR___UNSUPPORTED_MIXTURE_OF_TYPES;
00461     }
00462   
00463   typedef T1 result;
00464   };
00465 
00466 
00467 
00468 struct promote_type_ok
00469   {
00470   arma_inline static void check() {}
00471   };
00472 
00473 
00474 template<typename T>
00475 struct promote_type<T, T> : public promote_type_ok { typedef T result; };
00476 
00477 template<typename T>
00478 struct promote_type<std::complex<T>,     T>      : public promote_type_ok { typedef std::complex<T> result; };
00479 
00480 template<>
00481 struct promote_type<std::complex<double>, std::complex<float> > : public promote_type_ok { typedef std::complex<double> result; };
00482 
00483 template<>
00484 struct promote_type<std::complex<double>, float> : public promote_type_ok { typedef std::complex<double> result; };
00485 
00486 template<>
00487 struct promote_type<std::complex<float>, double> : public promote_type_ok { typedef std::complex<double> result; };
00488 
00489 template<typename T>
00490 struct promote_type<std::complex<T>, s32> : public promote_type_ok { typedef std::complex<T> result; };
00491 
00492 template<typename T>
00493 struct promote_type<std::complex<T>, u32> : public promote_type_ok { typedef std::complex<T> result; };
00494 
00495 template<typename T>
00496 struct promote_type<std::complex<T>, s16> : public promote_type_ok { typedef std::complex<T> result; };
00497 
00498 template<typename T>
00499 struct promote_type<std::complex<T>, u16> : public promote_type_ok { typedef std::complex<T> result; };
00500 
00501 template<typename T>
00502 struct promote_type<std::complex<T>, s8>  : public promote_type_ok { typedef std::complex<T> result; };
00503 
00504 template<typename T>
00505 struct promote_type<std::complex<T>, u8>  : public promote_type_ok { typedef std::complex<T> result; };
00506 
00507 
00508 template<> struct promote_type<double, float> : public promote_type_ok { typedef double result; };
00509 template<> struct promote_type<double, s32  > : public promote_type_ok { typedef double result; };
00510 template<> struct promote_type<double, u32  > : public promote_type_ok { typedef double result; };
00511 template<> struct promote_type<double, s16  > : public promote_type_ok { typedef double result; };
00512 template<> struct promote_type<double, u16  > : public promote_type_ok { typedef double result; };
00513 template<> struct promote_type<double, s8   > : public promote_type_ok { typedef double result; };
00514 template<> struct promote_type<double, u8   > : public promote_type_ok { typedef double result; };
00515 
00516 template<> struct promote_type<float, s32> : public promote_type_ok { typedef float result; };
00517 template<> struct promote_type<float, u32> : public promote_type_ok { typedef float result; };
00518 template<> struct promote_type<float, s16> : public promote_type_ok { typedef float result; };
00519 template<> struct promote_type<float, u16> : public promote_type_ok { typedef float result; };
00520 template<> struct promote_type<float, s8 > : public promote_type_ok { typedef float result; };
00521 template<> struct promote_type<float, u8 > : public promote_type_ok { typedef float result; };
00522 
00523 template<> struct promote_type<s32, u32> : public promote_type_ok { typedef s32 result; };  // float ?  
00524 template<> struct promote_type<s32, s16> : public promote_type_ok { typedef s32 result; };
00525 template<> struct promote_type<s32, u16> : public promote_type_ok { typedef s32 result; };
00526 template<> struct promote_type<s32, s8 > : public promote_type_ok { typedef s32 result; };
00527 template<> struct promote_type<s32, u8 > : public promote_type_ok { typedef s32 result; };
00528 
00529 template<> struct promote_type<u32, s16> : public promote_type_ok { typedef s32 result; };  // float ?
00530 template<> struct promote_type<u32, u16> : public promote_type_ok { typedef u32 result; };
00531 template<> struct promote_type<u32, s8 > : public promote_type_ok { typedef s32 result; };  // float ?
00532 template<> struct promote_type<u32, u8 > : public promote_type_ok { typedef u32 result; };
00533 
00534 template<> struct promote_type<s16, u16> : public promote_type_ok { typedef s16 result; };  // s32 ?
00535 template<> struct promote_type<s16, s8 > : public promote_type_ok { typedef s16 result; };
00536 template<> struct promote_type<s16, u8 > : public promote_type_ok { typedef s16 result; };
00537 
00538 template<> struct promote_type<u16, s8> : public promote_type_ok { typedef s16 result; };  // s32 ?
00539 template<> struct promote_type<u16, u8> : public promote_type_ok { typedef u16 result; };
00540 
00541 template<> struct promote_type<s8, u8> : public promote_type_ok { typedef s8 result; };  // s16 ?
00542 
00543 
00544 
00545 
00546 //
00547 // type promotion, mirrored versions
00548 
00549 template<typename T>
00550 struct promote_type<T, std::complex<T> > : public promote_type_ok { typedef std::complex<T> result; };
00551 
00552 template<>
00553 struct promote_type<std::complex<float>, std::complex<double> > : public promote_type_ok { typedef std::complex<double> result; };
00554 
00555 template<>
00556 struct promote_type<float, std::complex<double> > : public promote_type_ok { typedef std::complex<double> result; };
00557 
00558 template<>
00559 struct promote_type<double, std::complex<float> > : public promote_type_ok { typedef std::complex<double> result; };
00560 
00561 template<typename T>
00562 struct promote_type<s32, std::complex<T> > : public promote_type_ok { typedef std::complex<T> result; };
00563 
00564 template<typename T>
00565 struct promote_type<u32, std::complex<T> > : public promote_type_ok { typedef std::complex<T> result; };
00566 
00567 template<typename T>
00568 struct promote_type<s16, std::complex<T> > : public promote_type_ok { typedef std::complex<T> result; };
00569 
00570 template<typename T>
00571 struct promote_type<u16, std::complex<T> > : public promote_type_ok { typedef std::complex<T> result; };
00572 
00573 template<typename T>
00574 struct promote_type<s8, std::complex<T> >  : public promote_type_ok { typedef std::complex<T> result; };
00575 
00576 template<typename T>
00577 struct promote_type<u8, std::complex<T> >  : public promote_type_ok { typedef std::complex<T> result; };
00578 
00579 
00580 template<> struct promote_type<float, double> : public promote_type_ok { typedef double result; };
00581 template<> struct promote_type<s32  , double> : public promote_type_ok { typedef double result; };
00582 template<> struct promote_type<u32  , double> : public promote_type_ok { typedef double result; };
00583 template<> struct promote_type<s16  , double> : public promote_type_ok { typedef double result; };
00584 template<> struct promote_type<u16  , double> : public promote_type_ok { typedef double result; };
00585 template<> struct promote_type<s8   , double> : public promote_type_ok { typedef double result; };
00586 template<> struct promote_type<u8   , double> : public promote_type_ok { typedef double result; };
00587 
00588 template<> struct promote_type<s32, float> : public promote_type_ok { typedef float result; };
00589 template<> struct promote_type<u32, float> : public promote_type_ok { typedef float result; };
00590 template<> struct promote_type<s16, float> : public promote_type_ok { typedef float result; };
00591 template<> struct promote_type<u16, float> : public promote_type_ok { typedef float result; };
00592 template<> struct promote_type<s8 , float> : public promote_type_ok { typedef float result; };
00593 template<> struct promote_type<u8 , float> : public promote_type_ok { typedef float result; };
00594 
00595 template<> struct promote_type<u32, s32> : public promote_type_ok { typedef s32 result; };  // float ?  
00596 template<> struct promote_type<s16, s32> : public promote_type_ok { typedef s32 result; };
00597 template<> struct promote_type<u16, s32> : public promote_type_ok { typedef s32 result; };
00598 template<> struct promote_type<s8 , s32> : public promote_type_ok { typedef s32 result; };
00599 template<> struct promote_type<u8 , s32> : public promote_type_ok { typedef s32 result; };
00600 
00601 template<> struct promote_type<s16, u32> : public promote_type_ok { typedef s32 result; };  // float ?
00602 template<> struct promote_type<u16, u32> : public promote_type_ok { typedef u32 result; };
00603 template<> struct promote_type<s8 , u32> : public promote_type_ok { typedef s32 result; };  // float ?
00604 template<> struct promote_type<u8 , u32> : public promote_type_ok { typedef u32 result; };
00605 
00606 template<> struct promote_type<u16, s16> : public promote_type_ok { typedef s16 result; };  // s32 ?
00607 template<> struct promote_type<s8 , s16> : public promote_type_ok { typedef s16 result; };
00608 template<> struct promote_type<u8 , s16> : public promote_type_ok { typedef s16 result; };
00609 
00610 template<> struct promote_type<s8, u16> : public promote_type_ok { typedef s16 result; };  // s32 ?
00611 template<> struct promote_type<u8, u16> : public promote_type_ok { typedef u16 result; };
00612 
00613 template<> struct promote_type<u8, s8> : public promote_type_ok { typedef s8 result; };  // s16 ?
00614 
00615 
00616 //
00617 //
00618 //
00619 
00620 
00621 //! upgrade_val is used to ensure an operation such as multiplication is possible between two types.
00622 //! values are upgraded only where necessary.
00623 //! used by:
00624 //! glue_div::apply_mixed(), glue_minus::apply_mixed(), glue_plus::apply_mixed(), glue_schur::apply_mixed()
00625 //! and glue_times::apply_mixed() via gemm_mixed().
00626 
00627 template<typename T1, typename T2>
00628 struct upgrade_val
00629   {
00630   typedef typename promote_type<T1,T2>::result T1_result;
00631   typedef typename promote_type<T1,T2>::result T2_result;
00632   
00633   arma_inline
00634   static
00635   const typename promote_type<T1,T2>::result
00636   apply(const T1 x)
00637     {
00638     typedef typename promote_type<T1,T2>::result out_type;
00639     return out_type(x);
00640     }
00641   
00642   arma_inline
00643   static
00644   const typename promote_type<T1,T2>::result
00645   apply(const T2 x)
00646     {
00647     typedef typename promote_type<T1,T2>::result out_type;
00648     return out_type(x);
00649     }
00650   
00651   };
00652 
00653 
00654 // template<>
00655 template<typename T>
00656 struct upgrade_val<T,T>
00657   {
00658   typedef T T1_result;
00659   typedef T T2_result;
00660   
00661   arma_inline static const T& apply(const T& x) { return x; }
00662   };
00663 
00664 
00665 //! upgrade a type to allow multiplication with a complex type
00666 //! e.g. the int in "int * complex<double>" is upgraded to a double
00667 // template<>
00668 template<typename T, typename T2>
00669 struct upgrade_val< std::complex<T>, T2 >
00670   {
00671   typedef std::complex<T> T1_result;
00672   typedef T               T2_result;
00673   
00674   arma_inline static const std::complex<T>& apply(const std::complex<T>& x) { return x;    }
00675   arma_inline static const T                apply(const T2 x)               { return T(x); }
00676   };
00677 
00678 
00679 // template<>
00680 template<typename T1, typename T>
00681 struct upgrade_val< T1, std::complex<T> >
00682   {
00683   typedef T               T1_result;
00684   typedef std::complex<T> T2_result;
00685   
00686   arma_inline static const T                apply(const T1 x)               { return T(x); }
00687   arma_inline static const std::complex<T>& apply(const std::complex<T>& x) { return x;    }
00688   };
00689 
00690 
00691 //! ensure we don't lose precision when multiplying a complex number with a higher precision real number
00692 template<>
00693 struct upgrade_val< std::complex<float>, double >
00694   {
00695   typedef std::complex<double> T1_result;
00696   typedef double               T2_result;
00697   
00698   arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
00699   arma_inline static const double               apply(const double x)               { return x; }
00700   };
00701 
00702 
00703 template<>
00704 struct upgrade_val< double, std::complex<float> >
00705   {
00706   typedef double              T1_result;
00707   typedef std::complex<float> T2_result;
00708   
00709   arma_inline static const double               apply(const double x)               { return x; }
00710   arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
00711   };
00712 
00713 
00714 //! ensure we don't lose precision when multiplying complex numbers with different underlying types
00715 template<>
00716 struct upgrade_val< std::complex<float>, std::complex<double> >
00717   {
00718   typedef std::complex<double> T1_result;
00719   typedef std::complex<double> T2_result;
00720   
00721   arma_inline static const std::complex<double>  apply(const std::complex<float>&  x) { return std::complex<double>(x); }
00722   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00723   };
00724 
00725 
00726 template<>
00727 struct upgrade_val< std::complex<double>, std::complex<float> >
00728   {
00729   typedef std::complex<double> T1_result;
00730   typedef std::complex<double> T2_result;
00731   
00732   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00733   arma_inline static const std::complex<double>  apply(const std::complex<float>&  x) { return std::complex<double>(x); }
00734   };
00735 
00736 
00737 //! work around limitations in the complex class (at least as present in gcc 4.1 & 4.3)
00738 template<>
00739 struct upgrade_val< std::complex<double>, float >
00740   {
00741   typedef std::complex<double> T1_result;
00742   typedef double               T2_result;
00743   
00744   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00745   arma_inline static const double                apply(const float x)                 { return double(x); }
00746   };
00747 
00748 
00749 template<>
00750 struct upgrade_val< float, std::complex<double> >
00751   {
00752   typedef double               T1_result;
00753   typedef std::complex<double> T2_result;
00754   
00755   arma_inline static const double                apply(const float x)                 { return double(x); }
00756   arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
00757   };
00758 
00759 
00760 //! @}