]> Dogcows Code - chaz/yoink/blob - src/moof/cml/et/array_promotions.h
bugfix: win32 packaging script temp directories
[chaz/yoink] / src / moof / cml / et / array_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 * Defines promotions between array types.
13 *
14 * @todo Can/should an expression with a fixed-size argument promote to a
15 * fixed array instead of a dynamic array?
16 */
17
18 #ifndef array_promotions_h
19 #define array_promotions_h
20
21 #include <cml/core/cml_meta.h>
22 #include <cml/et/scalar_promotions.h>
23
24 namespace cml {
25 namespace et {
26
27 #define VAL_MAX(_a_,_b_) ( ((_a_)>(_b_))?(_a_):(_b_) )
28
29 namespace detail {
30
31 /* This is specialized for 1D and 2D promotions: */
32 template<class A1, class A2, typename DTag1, typename DTag2,
33 typename PromotedSizeTag> struct promote;
34
35 /* Promote 1D fixed-size arrays to a 1D fixed-size array: */
36 template<class A1, class A2>
37 struct promote<A1,A2,oned_tag,oned_tag,fixed_size_tag>
38 {
39 typedef typename A1::value_type left_scalar;
40 typedef typename A2::value_type right_scalar;
41
42 /* First, promote the scalar type: */
43 typedef typename ScalarPromote<
44 left_scalar,right_scalar>::type promoted_scalar;
45
46 /* Next, deduce the array size: */
47 enum { Size = VAL_MAX((size_t)A1::array_size, (size_t)A2::array_size) };
48
49 /* Finally, generate the promoted array type: */
50 typedef fixed_1D<promoted_scalar,Size> type;
51 };
52
53 /* Promote 1D dynamic arrays to a 1D dynamic array: */
54 template<class A1, class A2>
55 struct promote<A1,A2,oned_tag,oned_tag,dynamic_size_tag>
56 {
57 typedef typename A1::value_type left_scalar;
58 typedef typename A2::value_type right_scalar;
59
60 /* First, promote the scalar type: */
61 typedef typename ScalarPromote<
62 left_scalar,right_scalar>::type promoted_scalar;
63
64 /* Next, rebind to get the proper allocator: */
65 typedef typename CML_DEFAULT_ARRAY_ALLOC
66 ::rebind<promoted_scalar>::other allocator;
67
68 /* Finally, generate the promoted array type: */
69 typedef dynamic_1D<promoted_scalar,allocator> type;
70 };
71
72 /* Promote fixed 2D+1D array expressions to a fixed 1D array: */
73 template<class A1, class A2>
74 struct promote<A1,A2,twod_tag,oned_tag,fixed_size_tag>
75 {
76 typedef typename A1::value_type left_scalar;
77 typedef typename A2::value_type right_scalar;
78
79 /* First, promote the scalar type: */
80 typedef typename ScalarPromote<
81 left_scalar,right_scalar>::type promoted_scalar;
82
83 /* Next, deduce the array size: */
84 enum { Size = (size_t)A1::array_rows };
85
86 /* Finally, generate the promoted array type: */
87 typedef fixed_1D<promoted_scalar,Size> type;
88 };
89
90 /* Promote fixed 1D+2D array expressions to a fixed 1D array: */
91 template<class A1, class A2>
92 struct promote<A1,A2,oned_tag,twod_tag,fixed_size_tag>
93 {
94 typedef typename A1::value_type left_scalar;
95 typedef typename A2::value_type right_scalar;
96
97 /* First, promote the scalar type: */
98 typedef typename ScalarPromote<
99 left_scalar,right_scalar>::type promoted_scalar;
100
101 /* Next, deduce the array size: */
102 enum { Size = (size_t)A2::array_cols };
103
104 /* Finally, generate the promoted array type: */
105 typedef fixed_1D<promoted_scalar,Size> type;
106 };
107
108 /* Promote dynamic 2D+1D array expression to a 1D dynamic array: */
109 template<class A1, class A2>
110 struct promote<A1,A2,twod_tag,oned_tag,dynamic_size_tag>
111 {
112 typedef typename A1::value_type left_scalar;
113 typedef typename A2::value_type right_scalar;
114
115 /* First, promote the scalar type: */
116 typedef typename ScalarPromote<
117 left_scalar,right_scalar>::type promoted_scalar;
118
119 /* Next, rebind to get the proper allocator: */
120 typedef typename CML_DEFAULT_ARRAY_ALLOC
121 ::rebind<promoted_scalar>::other allocator;
122
123 /* Finally, generate the promoted array type: */
124 typedef dynamic_1D<promoted_scalar,allocator> type;
125 };
126
127 /* Promote dynamic 1D+2D array expression to a 1D dynamic array: */
128 template<class A1, class A2>
129 struct promote<A1,A2,oned_tag,twod_tag,dynamic_size_tag>
130 {
131 typedef typename A1::value_type left_scalar;
132 typedef typename A2::value_type right_scalar;
133
134 /* First, promote the scalar type: */
135 typedef typename ScalarPromote<
136 left_scalar,right_scalar>::type promoted_scalar;
137
138 /* Next, rebind to get the proper allocator: */
139 typedef typename CML_DEFAULT_ARRAY_ALLOC
140 ::rebind<promoted_scalar>::other allocator;
141
142 /* Finally, generate the promoted array type: */
143 typedef dynamic_1D<promoted_scalar,allocator> type;
144 };
145
146
147 /* This is a helper to deduce the result of a promoted 2D array: */
148 template<typename LeftL, typename RightL> struct deduce_layout {
149 #if defined(CML_ALWAYS_PROMOTE_TO_DEFAULT_LAYOUT)
150 typedef CML_DEFAULT_ARRAY_LAYOUT promoted_layout;
151 #else
152 typedef typename select_if<
153 same_type<LeftL,RightL>::is_true, LeftL,
154 CML_DEFAULT_ARRAY_LAYOUT>::result promoted_layout;
155 #endif
156 };
157
158 /* Promote 2D fixed-size arrays to a 2D fixed-size array. The resulting
159 * matrix has the same number of rows as A1, and the same number of
160 * columns as A2.
161 */
162 template<class A1, class A2>
163 struct promote<A1,A2,twod_tag,twod_tag,fixed_size_tag>
164 {
165 typedef typename A1::value_type left_scalar;
166 typedef typename A2::value_type right_scalar;
167
168 /* First, promote the scalar type: */
169 typedef typename ScalarPromote<
170 left_scalar,right_scalar>::type promoted_scalar;
171
172 /* Next, deduce the array size: */
173 enum {
174 Rows = (size_t)A1::array_rows,
175 Cols = (size_t)A2::array_cols
176 };
177
178 /* Then deduce the array layout: */
179 typedef typename A1::layout left_layout;
180 typedef typename A2::layout right_layout;
181 typedef typename deduce_layout<left_layout,right_layout>
182 ::promoted_layout promoted_layout;
183
184 /* Finally, generate the promoted array type: */
185 typedef fixed_2D<promoted_scalar,Rows,Cols,promoted_layout> type;
186 };
187
188 /* Promote 2D dynamic arrays to a 2D dynamic array: */
189 template<class A1, class A2>
190 struct promote<A1,A2,twod_tag,twod_tag,dynamic_size_tag>
191 {
192 typedef typename A1::value_type left_scalar;
193 typedef typename A2::value_type right_scalar;
194
195 /* First, promote the scalar type: */
196 typedef typename ScalarPromote<
197 left_scalar,right_scalar>::type promoted_scalar;
198
199 /* Next, rebind to get the proper allocator: */
200 typedef typename CML_DEFAULT_ARRAY_ALLOC
201 ::rebind<promoted_scalar>::other allocator;
202
203 /* Then deduce the array layout: */
204 typedef typename A1::layout left_layout;
205 typedef typename A2::layout right_layout;
206 typedef typename deduce_layout<left_layout,right_layout>
207 ::promoted_layout promoted_layout;
208
209 /* Finally, generate the promoted array type: */
210 typedef dynamic_2D<promoted_scalar,promoted_layout,allocator> type;
211 };
212
213 } // namespace detail
214
215 /** Class to promote array types.
216 *
217 * Both arguments must be array types.
218 *
219 * @sa fixed_1D
220 * @sa fixed_2D
221 * @sa dynamic_1D
222 * @sa dynamic_2D
223 */
224 template<class A1, class A2>
225 struct ArrayPromote
226 {
227 /* Shorthand: */
228 //typedef typename A1::value_type left_scalar;
229 //typedef typename A2::value_type right_scalar;
230 typedef typename A1::dimension_tag left_dtag;
231 typedef typename A2::dimension_tag right_dtag;
232
233 /* Deduce the proper type based upon the characteristics of AT1 and
234 * AT2. This is the table of type conversions:
235 *
236 * AT1 AT2 Result
237 * memory size memory size memory size
238 *
239 * fixed fixed fixed fixed fixed fixed
240 * fixed fixed dynamic dynamic dynamic dynamic
241 * fixed fixed external fixed fixed fixed
242 * fixed fixed external dynamic dynamic dynamic
243 *
244 * dynamic dynamic fixed fixed dynamic dynamic
245 * dynamic dynamic dynamic dynamic dynamic dynamic
246 * dynamic dynamic external fixed dynamic dynamic
247 * dynamic dynamic external dynamic dynamic dynamic
248 *
249 * external fixed external fixed fixed fixed
250 * external fixed fixed fixed fixed fixed
251 * external fixed dynamic dynamic dynamic dynamic
252 * external fixed external dynamic dynamic dynamic
253 *
254 * external dynamic external fixed dynamic dynamic
255 * external dynamic fixed fixed dynamic dynamic
256 * external dynamic dynamic dynamic dynamic dynamic
257 * external dynamic external dynamic dynamic dynamic
258 *
259 * Note that if one argument is a dynamically-sized array, the result
260 * must be a dynamically allocated and sized array. Likewise, if both
261 * arguments have fixed size, the result can be a fixed-sized array.
262 */
263
264 /* Check if both arguments are fixed-size arrays. If so, the promoted
265 * array will be a fixed array, and if not, it will be a dynamic array:
266 */
267 typedef typename select_if<
268 (same_type<typename A1::size_tag, fixed_size_tag>::is_true
269 && same_type<typename A2::size_tag, fixed_size_tag>::is_true),
270 fixed_size_tag, /* True */
271 dynamic_size_tag /* False */
272 >::result promoted_size_tag;
273
274 /* Deduce the promoted type: */
275 typedef typename detail::promote<
276 A1, A2, left_dtag, right_dtag, promoted_size_tag>::type type;
277 };
278
279 /* Cleanup internal macros: */
280 #undef VAL_MAX
281
282 } // namespace et
283 } // namespace cml
284
285 #endif
286
287 // -------------------------------------------------------------------------
288 // vim:ft=cpp
This page took 0.043677 seconds and 4 git commands to generate.