Chris@49: // Copyright (C) 2009-2010 NICTA (www.nicta.com.au) Chris@49: // Copyright (C) 2009-2010 Conrad Sanderson Chris@49: // Chris@49: // This Source Code Form is subject to the terms of the Mozilla Public Chris@49: // License, v. 2.0. If a copy of the MPL was not distributed with this Chris@49: // file, You can obtain one at http://mozilla.org/MPL/2.0/. Chris@49: Chris@49: Chris@49: //! \addtogroup upgrade_val Chris@49: //! @{ Chris@49: Chris@49: Chris@49: Chris@49: //! upgrade_val is used to ensure an operation such as multiplication is possible between two types. Chris@49: //! values are upgraded only where necessary. Chris@49: Chris@49: template Chris@49: struct upgrade_val Chris@49: { Chris@49: typedef typename promote_type::result T1_result; Chris@49: typedef typename promote_type::result T2_result; Chris@49: Chris@49: arma_inline Chris@49: static Chris@49: typename promote_type::result Chris@49: apply(const T1 x) Chris@49: { Chris@49: typedef typename promote_type::result out_type; Chris@49: return out_type(x); Chris@49: } Chris@49: Chris@49: arma_inline Chris@49: static Chris@49: typename promote_type::result Chris@49: apply(const T2 x) Chris@49: { Chris@49: typedef typename promote_type::result out_type; Chris@49: return out_type(x); Chris@49: } Chris@49: Chris@49: }; Chris@49: Chris@49: Chris@49: // template<> Chris@49: template Chris@49: struct upgrade_val Chris@49: { Chris@49: typedef T T1_result; Chris@49: typedef T T2_result; Chris@49: Chris@49: arma_inline static const T& apply(const T& x) { return x; } Chris@49: }; Chris@49: Chris@49: Chris@49: //! upgrade a type to allow multiplication with a complex type Chris@49: //! e.g. the int in "int * complex" is upgraded to a double Chris@49: // template<> Chris@49: template Chris@49: struct upgrade_val< std::complex, T2 > Chris@49: { Chris@49: typedef std::complex T1_result; Chris@49: typedef T T2_result; Chris@49: Chris@49: arma_inline static const std::complex& apply(const std::complex& x) { return x; } Chris@49: arma_inline static T apply(const T2 x) { return T(x); } Chris@49: }; Chris@49: Chris@49: Chris@49: // template<> Chris@49: template Chris@49: struct upgrade_val< T1, std::complex > Chris@49: { Chris@49: typedef T T1_result; Chris@49: typedef std::complex T2_result; Chris@49: Chris@49: arma_inline static T apply(const T1 x) { return T(x); } Chris@49: arma_inline static const std::complex& apply(const std::complex& x) { return x; } Chris@49: }; Chris@49: Chris@49: Chris@49: //! ensure we don't lose precision when multiplying a complex number with a higher precision real number Chris@49: template<> Chris@49: struct upgrade_val< std::complex, double > Chris@49: { Chris@49: typedef std::complex T1_result; Chris@49: typedef double T2_result; Chris@49: Chris@49: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } Chris@49: arma_inline static double apply(const double x) { return x; } Chris@49: }; Chris@49: Chris@49: Chris@49: template<> Chris@49: struct upgrade_val< double, std::complex > Chris@49: { Chris@49: typedef double T1_result; Chris@49: typedef std::complex T2_result; Chris@49: Chris@49: arma_inline static double apply(const double x) { return x; } Chris@49: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } Chris@49: }; Chris@49: Chris@49: Chris@49: //! ensure we don't lose precision when multiplying complex numbers with different underlying types Chris@49: template<> Chris@49: struct upgrade_val< std::complex, std::complex > Chris@49: { Chris@49: typedef std::complex T1_result; Chris@49: typedef std::complex T2_result; Chris@49: Chris@49: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } Chris@49: arma_inline static const std::complex& apply(const std::complex& x) { return x; } Chris@49: }; Chris@49: Chris@49: Chris@49: template<> Chris@49: struct upgrade_val< std::complex, std::complex > Chris@49: { Chris@49: typedef std::complex T1_result; Chris@49: typedef std::complex T2_result; Chris@49: Chris@49: arma_inline static const std::complex& apply(const std::complex& x) { return x; } Chris@49: arma_inline static const std::complex apply(const std::complex& x) { return std::complex(x); } Chris@49: }; Chris@49: Chris@49: Chris@49: //! work around limitations in the complex class (at least as present in gcc 4.1 & 4.3) Chris@49: template<> Chris@49: struct upgrade_val< std::complex, float > Chris@49: { Chris@49: typedef std::complex T1_result; Chris@49: typedef double T2_result; Chris@49: Chris@49: arma_inline static const std::complex& apply(const std::complex& x) { return x; } Chris@49: arma_inline static double apply(const float x) { return double(x); } Chris@49: }; Chris@49: Chris@49: Chris@49: template<> Chris@49: struct upgrade_val< float, std::complex > Chris@49: { Chris@49: typedef double T1_result; Chris@49: typedef std::complex T2_result; Chris@49: Chris@49: arma_inline static double apply(const float x) { return double(x); } Chris@49: arma_inline static const std::complex& apply(const std::complex& x) { return x; } Chris@49: }; Chris@49: Chris@49: Chris@49: Chris@49: //! @}