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