version bump cml to version 1.0.2
[chaz/yoink] / src / Moof / cml / et / scalar_promotions.h
1 /* -*- C++ -*- ------------------------------------------------------------
2
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
4
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
7
8 *-----------------------------------------------------------------------*/
9 /** @file
10 * @brief
11 */
12
13 #ifndef scalar_promotions_h
14 #define scalar_promotions_h
15
16 #include <complex>
17 #include <cml/core/cml_meta.h>
18
19 namespace cml {
20 namespace et {
21
22 /* The type promotion code below is a slightly modified version of:
23 * http://ubiety.uwaterloo.ca/~tveldhui/papers/techniques/techniques01.html
24 */
25 namespace detail {
26
27 template<class T>
28 struct precision_trait {
29 enum { precisionRank = 0,
30 knowPrecisionRank = 0 };
31 };
32
33 #define DECLARE_PRECISION(T,rank) \
34 template<> \
35 struct precision_trait< T > { \
36 enum { precisionRank = rank, \
37 knowPrecisionRank = 1 }; \
38 };
39
40 DECLARE_PRECISION(int,100)
41 DECLARE_PRECISION(unsigned int,200)
42 DECLARE_PRECISION(long,300)
43 DECLARE_PRECISION(unsigned long,400)
44
45 DECLARE_PRECISION(long long,425)
46 DECLARE_PRECISION(unsigned long long,475)
47
48 DECLARE_PRECISION(float,500)
49 DECLARE_PRECISION(double,600)
50 DECLARE_PRECISION(long double,700)
51 DECLARE_PRECISION(std::complex<float>,800)
52 DECLARE_PRECISION(std::complex<double>,900)
53 DECLARE_PRECISION(std::complex<long double>,1000)
54
55 template<class T>
56 struct autopromote_trait {
57 typedef T T_numtype;
58 };
59
60 #define DECLARE_AUTOPROMOTE(T1,T2) \
61 template<> \
62 struct autopromote_trait<T1> { \
63 typedef T2 T_numtype; \
64 };
65
66 // These are the odd cases where small integer types
67 // are automatically promoted to int or unsigned int for
68 // arithmetic.
69 DECLARE_AUTOPROMOTE(bool, int)
70 DECLARE_AUTOPROMOTE(char, int)
71 DECLARE_AUTOPROMOTE(unsigned char, int)
72 DECLARE_AUTOPROMOTE(short int, int)
73 DECLARE_AUTOPROMOTE(short unsigned int, unsigned int)
74
75 template<class T1, class T2, int promoteToT1>
76 struct promote2 {
77 typedef T1 T_promote;
78 };
79
80 template<class T1, class T2>
81 struct promote2<T1,T2,0> {
82 typedef T2 T_promote;
83 };
84
85 template<class T1_orig, class T2_orig>
86 struct promote_trait {
87
88 // Need to remove const-ness:
89 typedef typename cml::remove_const<T1_orig>::type T1_non_const;
90 typedef typename cml::remove_const<T2_orig>::type T2_non_const;
91
92 // Handle promotion of small integers to int/unsigned int
93 typedef typename autopromote_trait<T1_non_const>::T_numtype T1;
94 typedef typename autopromote_trait<T2_non_const>::T_numtype T2;
95
96 // True if T1 is higher ranked
97 enum {
98 T1IsBetter =
99 (int) precision_trait<T1>::precisionRank >
100 (int) precision_trait<T2>::precisionRank,
101
102 // True if we know ranks for both T1 and T2
103 knowBothRanks =
104 precision_trait<T1>::knowPrecisionRank
105 && precision_trait<T2>::knowPrecisionRank,
106
107 // True if we know T1 but not T2
108 knowT1butNotT2 = precision_trait<T1>::knowPrecisionRank
109 && !(precision_trait<T2>::knowPrecisionRank),
110
111 // True if we know T2 but not T1
112 knowT2butNotT1 = precision_trait<T2>::knowPrecisionRank
113 && !(precision_trait<T1>::knowPrecisionRank),
114
115 // True if T1 is bigger than T2
116 T1IsLarger = sizeof(T1) >= sizeof(T2),
117
118 // We know T1 but not T2: true
119 // We know T2 but not T1: false
120 // Otherwise, if T1 is bigger than T2: true
121 defaultPromotion = knowT1butNotT2 ? false :
122 (knowT2butNotT1 ? true : T1IsLarger)
123 };
124
125 // If we have both ranks, then use them.
126 // If we have only one rank, then use the unknown type.
127 // If we have neither rank, then promote to the larger type.
128
129 enum {
130 promoteToT1 = (knowBothRanks ? T1IsBetter : defaultPromotion)
131 ? 1 : 0
132 };
133
134 typedef typename promote2<T1,T2,promoteToT1>::T_promote T_promote;
135 };
136
137 } // namespace detail
138
139 /** Defers to detail::promote_trait<>. */
140 template<class E1, class E2> struct ScalarPromote
141 {
142 typedef typename detail::promote_trait<E1,E2>::T_promote type;
143 };
144
145 } // namespace et
146 } // namespace cml
147
148 #endif
149
150 // -------------------------------------------------------------------------
151 // vim:ft=cpp
This page took 0.03558 seconds and 4 git commands to generate.