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