00001
00002
00003
00004
00005
00006
00007
00008
00013 #ifndef scalar_promotions_h
00014 #define scalar_promotions_h
00015
00016 #include <complex>
00017 #include <cml/core/cml_meta.h>
00018
00019 namespace cml {
00020 namespace et {
00021
00022
00023 #if !defined(CML_USE_OLD_SCALAR_PROMOTIONS)
00024
00025
00026
00027
00028 namespace detail {
00029
00030 template<class T>
00031 struct precision_trait {
00032 enum { precisionRank = 0,
00033 knowPrecisionRank = 0 };
00034 };
00035
00036 #define DECLARE_PRECISION(T,rank) \
00037 template<> \
00038 struct precision_trait< T > { \
00039 enum { precisionRank = rank, \
00040 knowPrecisionRank = 1 }; \
00041 };
00042
00043 DECLARE_PRECISION(int,100)
00044 DECLARE_PRECISION(unsigned int,200)
00045 DECLARE_PRECISION(long,300)
00046 DECLARE_PRECISION(unsigned long,400)
00047
00048 DECLARE_PRECISION(long long,425)
00049 DECLARE_PRECISION(unsigned long long,475)
00050
00051 DECLARE_PRECISION(float,500)
00052 DECLARE_PRECISION(double,600)
00053 DECLARE_PRECISION(long double,700)
00054 DECLARE_PRECISION(std::complex<float>,800)
00055 DECLARE_PRECISION(std::complex<double>,900)
00056 DECLARE_PRECISION(std::complex<long double>,1000)
00057
00058 template<class T>
00059 struct autopromote_trait {
00060 typedef T T_numtype;
00061 };
00062
00063 #define DECLARE_AUTOPROMOTE(T1,T2) \
00064 template<> \
00065 struct autopromote_trait<T1> { \
00066 typedef T2 T_numtype; \
00067 };
00068
00069
00070
00071
00072 DECLARE_AUTOPROMOTE(bool, int)
00073 DECLARE_AUTOPROMOTE(char, int)
00074 DECLARE_AUTOPROMOTE(unsigned char, int)
00075 DECLARE_AUTOPROMOTE(short int, int)
00076 DECLARE_AUTOPROMOTE(short unsigned int, unsigned int)
00077
00078 template<class T1, class T2, int promoteToT1>
00079 struct promote2 {
00080 typedef T1 T_promote;
00081 };
00082
00083 template<class T1, class T2>
00084 struct promote2<T1,T2,0> {
00085 typedef T2 T_promote;
00086 };
00087
00088 template<class T1_orig, class T2_orig>
00089 struct promote_trait {
00090
00091 typedef typename autopromote_trait<T1_orig>::T_numtype T1;
00092 typedef typename autopromote_trait<T2_orig>::T_numtype T2;
00093
00094
00095 enum {
00096 T1IsBetter =
00097 (int) precision_trait<T1>::precisionRank >
00098 (int) precision_trait<T2>::precisionRank,
00099
00100
00101 knowBothRanks =
00102 precision_trait<T1>::knowPrecisionRank
00103 && precision_trait<T2>::knowPrecisionRank,
00104
00105
00106 knowT1butNotT2 = precision_trait<T1>::knowPrecisionRank
00107 && !(precision_trait<T2>::knowPrecisionRank),
00108
00109
00110 knowT2butNotT1 = precision_trait<T2>::knowPrecisionRank
00111 && !(precision_trait<T1>::knowPrecisionRank),
00112
00113
00114 T1IsLarger = sizeof(T1) >= sizeof(T2),
00115
00116
00117
00118
00119 defaultPromotion = knowT1butNotT2 ? false :
00120 (knowT2butNotT1 ? true : T1IsLarger)
00121 };
00122
00123
00124
00125
00126
00127 enum {
00128 promoteToT1 = (knowBothRanks ? T1IsBetter : defaultPromotion)
00129 ? 1 : 0
00130 };
00131
00132 typedef typename promote2<T1,T2,promoteToT1>::T_promote T_promote;
00133 };
00134
00135 }
00136
00138 template<class E1, class E2> struct ScalarPromote
00139 {
00140 typedef typename detail::promote_trait<E1,E2>::T_promote type;
00141 };
00142
00143 #else
00144
00145 namespace detail {
00146
00150 template<class T> struct IntPromote
00151 {
00152
00153 typedef typename select_switch<T,
00154 unsigned char, unsigned int,
00155 unsigned short, unsigned int,
00156 signed char, int,
00157 char, int,
00158 short, int,
00159 T, T
00160 >::result result;
00161 };
00162
00163 }
00164
00168 template<class E1_in, class E2_in> struct ScalarPromote
00169 {
00170
00171 typedef typename detail::IntPromote<E1_in>::result E1;
00172 typedef typename detail::IntPromote<E2_in>::result E2;
00173
00174
00175
00176
00177 typedef typename select_if<sizeof(long) == sizeof(unsigned int),
00178 unsigned long,
00179 long
00180 >::result uint_promotion;
00181
00182
00183 typedef typename select_switch<
00184 type_pair<E1,E2>,
00185
00186 #if defined(CML_USE_LONG_DOUBLE)
00187 type_pair<long double,long double>, long double,
00188 type_pair<long double,E2>, long double,
00189 type_pair<E1,long double>, long double,
00190 #endif
00191
00192 type_pair<double,double>, double,
00193 type_pair<double,E2>, double,
00194 type_pair<E1,double>, double,
00195
00196 type_pair<float,float>, float,
00197 type_pair<float,E2>, float,
00198 type_pair<E1,float>, float,
00199
00200 type_pair<E1,E2>, void
00201
00202 >::result float_filter;
00203
00204
00205 typedef typename select_switch<
00206 type_pair<E1,E2>,
00207
00208 type_pair<unsigned long,unsigned long>, unsigned long,
00209 type_pair<unsigned long,E2>, unsigned long,
00210 type_pair<E1,unsigned long>, unsigned long,
00211
00212 type_pair<long,long>, long,
00213 type_pair<long,unsigned int>, uint_promotion,
00214 type_pair<unsigned int,long>, uint_promotion,
00215
00216 type_pair<long,E2>, long,
00217 type_pair<E1,long>, long,
00218
00219 type_pair<unsigned int,unsigned int>, unsigned int,
00220 type_pair<unsigned int,E2>, unsigned int,
00221 type_pair<E1,unsigned int>, unsigned int,
00222
00223 type_pair<int,int>, int,
00224 type_pair<int,E2>, int,
00225 type_pair<E1,int>, int,
00226
00227 type_pair<E1,E2>, void
00228
00229 >::result int_filter;
00230
00231
00232 typedef typename select_if<
00233 same_type<float_filter,void>::is_true,
00234 int_filter, float_filter>::result type;
00235 };
00236 #endif
00237
00238 }
00239 }
00240
00241 #endif
00242
00243
00244