max@0: // Copyright (C) 2009-2010 NICTA (www.nicta.com.au) max@0: // Copyright (C) 2009-2010 Conrad Sanderson max@0: // max@0: // This file is part of the Armadillo C++ library. max@0: // It is provided without any warranty of fitness max@0: // for any purpose. You can redistribute this file max@0: // and/or modify it under the terms of the GNU max@0: // Lesser General Public License (LGPL) as published max@0: // by the Free Software Foundation, either version 3 max@0: // of the License or (at your option) any later version. max@0: // (see http://www.opensource.org/licenses for more info) max@0: max@0: max@0: //! \addtogroup upgrade_val max@0: //! @{ max@0: max@0: max@0: max@0: //! upgrade_val is used to ensure an operation such as multiplication is possible between two types. max@0: //! values are upgraded only where necessary. max@0: max@0: template max@0: struct upgrade_val max@0: { max@0: typedef typename promote_type::result T1_result; max@0: typedef typename promote_type::result T2_result; max@0: max@0: arma_inline max@0: static max@0: typename promote_type::result max@0: apply(const T1 x) max@0: { max@0: typedef typename promote_type::result out_type; max@0: return out_type(x); max@0: } max@0: max@0: arma_inline max@0: static max@0: typename promote_type::result max@0: apply(const T2 x) max@0: { max@0: typedef typename promote_type::result out_type; max@0: return out_type(x); max@0: } max@0: max@0: }; max@0: max@0: max@0: // template<> max@0: template max@0: struct upgrade_val max@0: { max@0: typedef T T1_result; max@0: typedef T T2_result; max@0: max@0: arma_inline static const T& apply(const T& x) { return x; } max@0: }; max@0: max@0: max@0: //! upgrade a type to allow multiplication with a complex type max@0: //! e.g. the int in "int * complex" is upgraded to a double max@0: // template<> max@0: template max@0: struct upgrade_val< std::complex, T2 > max@0: { max@0: typedef std::complex T1_result; max@0: typedef T T2_result; max@0: max@0: arma_inline static const std::complex& apply(const std::complex& x) { return x; } max@0: arma_inline static T apply(const T2 x) { return T(x); } max@0: }; max@0: max@0: max@0: // template<> max@0: template max@0: struct upgrade_val< T1, std::complex > max@0: { max@0: typedef T T1_result; max@0: typedef std::complex T2_result; max@0: max@0: arma_inline static T apply(const T1 x) { return T(x); } max@0: arma_inline static const std::complex& apply(const std::complex& x) { return x; } max@0: }; max@0: max@0: max@0: //! ensure we don't lose precision when multiplying a complex number with a higher precision real number max@0: template<> max@0: struct upgrade_val< std::complex, double > max@0: { max@0: typedef std::complex T1_result; max@0: typedef double T2_result; max@0: max@0: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } max@0: arma_inline static double apply(const double x) { return x; } max@0: }; max@0: max@0: max@0: template<> max@0: struct upgrade_val< double, std::complex > max@0: { max@0: typedef double T1_result; max@0: typedef std::complex T2_result; max@0: max@0: arma_inline static double apply(const double x) { return x; } max@0: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } max@0: }; max@0: max@0: max@0: //! ensure we don't lose precision when multiplying complex numbers with different underlying types max@0: template<> max@0: struct upgrade_val< std::complex, std::complex > max@0: { max@0: typedef std::complex T1_result; max@0: typedef std::complex T2_result; max@0: max@0: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } max@0: arma_inline static const std::complex& apply(const std::complex& x) { return x; } max@0: }; max@0: max@0: max@0: template<> max@0: struct upgrade_val< std::complex, std::complex > max@0: { max@0: typedef std::complex T1_result; max@0: typedef std::complex T2_result; max@0: max@0: arma_inline static const std::complex& apply(const std::complex& x) { return x; } max@0: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } max@0: }; max@0: max@0: max@0: //! work around limitations in the complex class (at least as present in gcc 4.1 & 4.3) max@0: template<> max@0: struct upgrade_val< std::complex, float > max@0: { max@0: typedef std::complex T1_result; max@0: typedef double T2_result; max@0: max@0: arma_inline static const std::complex& apply(const std::complex& x) { return x; } max@0: arma_inline static double apply(const float x) { return double(x); } max@0: }; max@0: max@0: max@0: template<> max@0: struct upgrade_val< float, std::complex > max@0: { max@0: typedef double T1_result; max@0: typedef std::complex T2_result; max@0: max@0: arma_inline static double apply(const float x) { return double(x); } max@0: arma_inline static const std::complex& apply(const std::complex& x) { return x; } max@0: }; max@0: max@0: max@0: max@0: //! @}