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