Chris@49
|
1 // Copyright (C) 2009-2010 NICTA (www.nicta.com.au)
|
Chris@49
|
2 // Copyright (C) 2009-2010 Conrad Sanderson
|
Chris@49
|
3 //
|
Chris@49
|
4 // This Source Code Form is subject to the terms of the Mozilla Public
|
Chris@49
|
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
|
Chris@49
|
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
Chris@49
|
7
|
Chris@49
|
8
|
Chris@49
|
9 //! \addtogroup upgrade_val
|
Chris@49
|
10 //! @{
|
Chris@49
|
11
|
Chris@49
|
12
|
Chris@49
|
13
|
Chris@49
|
14 //! upgrade_val is used to ensure an operation such as multiplication is possible between two types.
|
Chris@49
|
15 //! values are upgraded only where necessary.
|
Chris@49
|
16
|
Chris@49
|
17 template<typename T1, typename T2>
|
Chris@49
|
18 struct upgrade_val
|
Chris@49
|
19 {
|
Chris@49
|
20 typedef typename promote_type<T1,T2>::result T1_result;
|
Chris@49
|
21 typedef typename promote_type<T1,T2>::result T2_result;
|
Chris@49
|
22
|
Chris@49
|
23 arma_inline
|
Chris@49
|
24 static
|
Chris@49
|
25 typename promote_type<T1,T2>::result
|
Chris@49
|
26 apply(const T1 x)
|
Chris@49
|
27 {
|
Chris@49
|
28 typedef typename promote_type<T1,T2>::result out_type;
|
Chris@49
|
29 return out_type(x);
|
Chris@49
|
30 }
|
Chris@49
|
31
|
Chris@49
|
32 arma_inline
|
Chris@49
|
33 static
|
Chris@49
|
34 typename promote_type<T1,T2>::result
|
Chris@49
|
35 apply(const T2 x)
|
Chris@49
|
36 {
|
Chris@49
|
37 typedef typename promote_type<T1,T2>::result out_type;
|
Chris@49
|
38 return out_type(x);
|
Chris@49
|
39 }
|
Chris@49
|
40
|
Chris@49
|
41 };
|
Chris@49
|
42
|
Chris@49
|
43
|
Chris@49
|
44 // template<>
|
Chris@49
|
45 template<typename T>
|
Chris@49
|
46 struct upgrade_val<T,T>
|
Chris@49
|
47 {
|
Chris@49
|
48 typedef T T1_result;
|
Chris@49
|
49 typedef T T2_result;
|
Chris@49
|
50
|
Chris@49
|
51 arma_inline static const T& apply(const T& x) { return x; }
|
Chris@49
|
52 };
|
Chris@49
|
53
|
Chris@49
|
54
|
Chris@49
|
55 //! upgrade a type to allow multiplication with a complex type
|
Chris@49
|
56 //! e.g. the int in "int * complex<double>" is upgraded to a double
|
Chris@49
|
57 // template<>
|
Chris@49
|
58 template<typename T, typename T2>
|
Chris@49
|
59 struct upgrade_val< std::complex<T>, T2 >
|
Chris@49
|
60 {
|
Chris@49
|
61 typedef std::complex<T> T1_result;
|
Chris@49
|
62 typedef T T2_result;
|
Chris@49
|
63
|
Chris@49
|
64 arma_inline static const std::complex<T>& apply(const std::complex<T>& x) { return x; }
|
Chris@49
|
65 arma_inline static T apply(const T2 x) { return T(x); }
|
Chris@49
|
66 };
|
Chris@49
|
67
|
Chris@49
|
68
|
Chris@49
|
69 // template<>
|
Chris@49
|
70 template<typename T1, typename T>
|
Chris@49
|
71 struct upgrade_val< T1, std::complex<T> >
|
Chris@49
|
72 {
|
Chris@49
|
73 typedef T T1_result;
|
Chris@49
|
74 typedef std::complex<T> T2_result;
|
Chris@49
|
75
|
Chris@49
|
76 arma_inline static T apply(const T1 x) { return T(x); }
|
Chris@49
|
77 arma_inline static const std::complex<T>& apply(const std::complex<T>& x) { return x; }
|
Chris@49
|
78 };
|
Chris@49
|
79
|
Chris@49
|
80
|
Chris@49
|
81 //! ensure we don't lose precision when multiplying a complex number with a higher precision real number
|
Chris@49
|
82 template<>
|
Chris@49
|
83 struct upgrade_val< std::complex<float>, double >
|
Chris@49
|
84 {
|
Chris@49
|
85 typedef std::complex<double> T1_result;
|
Chris@49
|
86 typedef double T2_result;
|
Chris@49
|
87
|
Chris@49
|
88 arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
|
Chris@49
|
89 arma_inline static double apply(const double x) { return x; }
|
Chris@49
|
90 };
|
Chris@49
|
91
|
Chris@49
|
92
|
Chris@49
|
93 template<>
|
Chris@49
|
94 struct upgrade_val< double, std::complex<float> >
|
Chris@49
|
95 {
|
Chris@49
|
96 typedef double T1_result;
|
Chris@49
|
97 typedef std::complex<float> T2_result;
|
Chris@49
|
98
|
Chris@49
|
99 arma_inline static double apply(const double x) { return x; }
|
Chris@49
|
100 arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
|
Chris@49
|
101 };
|
Chris@49
|
102
|
Chris@49
|
103
|
Chris@49
|
104 //! ensure we don't lose precision when multiplying complex numbers with different underlying types
|
Chris@49
|
105 template<>
|
Chris@49
|
106 struct upgrade_val< std::complex<float>, std::complex<double> >
|
Chris@49
|
107 {
|
Chris@49
|
108 typedef std::complex<double> T1_result;
|
Chris@49
|
109 typedef std::complex<double> T2_result;
|
Chris@49
|
110
|
Chris@49
|
111 arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
|
Chris@49
|
112 arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
|
Chris@49
|
113 };
|
Chris@49
|
114
|
Chris@49
|
115
|
Chris@49
|
116 template<>
|
Chris@49
|
117 struct upgrade_val< std::complex<double>, std::complex<float> >
|
Chris@49
|
118 {
|
Chris@49
|
119 typedef std::complex<double> T1_result;
|
Chris@49
|
120 typedef std::complex<double> T2_result;
|
Chris@49
|
121
|
Chris@49
|
122 arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
|
Chris@49
|
123 arma_inline static const std::complex<double> apply(const std::complex<float>& x) { return std::complex<double>(x); }
|
Chris@49
|
124 };
|
Chris@49
|
125
|
Chris@49
|
126
|
Chris@49
|
127 //! work around limitations in the complex class (at least as present in gcc 4.1 & 4.3)
|
Chris@49
|
128 template<>
|
Chris@49
|
129 struct upgrade_val< std::complex<double>, float >
|
Chris@49
|
130 {
|
Chris@49
|
131 typedef std::complex<double> T1_result;
|
Chris@49
|
132 typedef double T2_result;
|
Chris@49
|
133
|
Chris@49
|
134 arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
|
Chris@49
|
135 arma_inline static double apply(const float x) { return double(x); }
|
Chris@49
|
136 };
|
Chris@49
|
137
|
Chris@49
|
138
|
Chris@49
|
139 template<>
|
Chris@49
|
140 struct upgrade_val< float, std::complex<double> >
|
Chris@49
|
141 {
|
Chris@49
|
142 typedef double T1_result;
|
Chris@49
|
143 typedef std::complex<double> T2_result;
|
Chris@49
|
144
|
Chris@49
|
145 arma_inline static double apply(const float x) { return double(x); }
|
Chris@49
|
146 arma_inline static const std::complex<double>& apply(const std::complex<double>& x) { return x; }
|
Chris@49
|
147 };
|
Chris@49
|
148
|
Chris@49
|
149
|
Chris@49
|
150
|
Chris@49
|
151 //! @}
|