]> Dogcows Code - chaz/yoink/blob - src/moof/cml/matrix/class_ops.h
bugfix: win32 packaging script temp directories
[chaz/yoink] / src / moof / cml / matrix / class_ops.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 * @note GCC4 requires a copy constructor to elide---it won't elide a
13 * compiler-generated copy constructor!
14 */
15
16 #ifndef matrix_class_ops_h
17 #define matrix_class_ops_h
18
19 #if defined(_MSC_VER) && _MSC_VER < 1400
20 #pragma warning(disable:4003)
21 // XXX Horrible hack to turn off warnings about "not enough actual params"
22 // for the macros below.
23 #endif
24
25 /* This is to circumvent the problem of commas in a macro argument. It's
26 * used to instantiate CML_ACCUMULATED_MATRIX_MULT:
27 */
28 #define TEMPLATED_MATRIX_MACRO matrix<E,AT,BO,L>
29
30 /* XXX HACK!!! This is a hack to resize in the assign() functions only when
31 * auto resizing is turned off.
32 */
33 #if !defined(CML_MATRIX_RESIZE_ON_ASSIGNMENT)
34 #define _DO_MATRIX_SET_RESIZE(_R_,_C_) cml::et::detail::Resize(*this,_R_,_C_)
35 #else
36 #define _DO_MATRIX_SET_RESIZE(_R_,_C_)
37 #endif
38
39 /** Set a matrix from 2x2 values.
40 *
41 * The layout assumed for the values is that of the matrix being assigned.
42 */
43 #define CML_ASSIGN_MAT_22 \
44 matrix_type& \
45 set( \
46 ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \
47 ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11 \
48 ) \
49 { \
50 _DO_MATRIX_SET_RESIZE(2,2); \
51 /* This is overkill, but simplifies size checking: */ \
52 value_type v[2][2] = {{e00,e01},{e10,e11}}; \
53 typedef et::OpAssign<Element,Element> OpT; \
54 typedef const value_type element; \
55 cml::matrix<element, external<2,2>, basis_orient, row_major> \
56 src(&v[0][0]); \
57 et::UnrollAssignment<OpT>(*this,src); \
58 return *this; \
59 }
60
61 /** Create a matrix from 3x3 values.
62 *
63 * The layout assumed for the values is that of the matrix being assigned.
64 */
65 #define CML_ASSIGN_MAT_33 \
66 matrix_type& \
67 set( \
68 ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, ELEMENT_ARG_TYPE e02, \
69 ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, ELEMENT_ARG_TYPE e12, \
70 ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, ELEMENT_ARG_TYPE e22 \
71 ) \
72 { \
73 _DO_MATRIX_SET_RESIZE(3,3); \
74 /* This is overkill, but simplifies size checking: */ \
75 value_type v[3][3] = { \
76 {e00,e01,e02}, \
77 {e10,e11,e12}, \
78 {e20,e21,e22} \
79 }; \
80 typedef et::OpAssign<Element,Element> OpT; \
81 typedef const value_type element; \
82 cml::matrix<element, external<3,3>, basis_orient, row_major> \
83 src(&v[0][0]); \
84 et::UnrollAssignment<OpT>(*this,src); \
85 return *this; \
86 }
87
88 /** Create a matrix from 4x4 values.
89 *
90 * The layout assumed for the values is that of the matrix being assigned.
91 */
92 #define CML_ASSIGN_MAT_44 \
93 matrix_type& \
94 set( \
95 ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \
96 ELEMENT_ARG_TYPE e02, ELEMENT_ARG_TYPE e03, \
97 ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, \
98 ELEMENT_ARG_TYPE e12, ELEMENT_ARG_TYPE e13, \
99 ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, \
100 ELEMENT_ARG_TYPE e22, ELEMENT_ARG_TYPE e23, \
101 ELEMENT_ARG_TYPE e30, ELEMENT_ARG_TYPE e31, \
102 ELEMENT_ARG_TYPE e32, ELEMENT_ARG_TYPE e33 \
103 ) \
104 { \
105 _DO_MATRIX_SET_RESIZE(4,4); \
106 /* This is overkill, but simplifies size checking: */ \
107 value_type v[4][4] = { \
108 {e00,e01,e02,e03}, \
109 {e10,e11,e12,e13}, \
110 {e20,e21,e22,e23}, \
111 {e30,e31,e32,e33} \
112 }; \
113 typedef et::OpAssign<Element,Element> OpT; \
114 typedef const value_type element; \
115 cml::matrix<element, external<4,4>, basis_orient, row_major> \
116 src(&v[0][0]); \
117 et::UnrollAssignment<OpT>(*this,src); \
118 return *this; \
119 }
120
121 /** Create a matrix from 2x2 values.
122 *
123 * The layout assumed for the values is that of the matrix being assigned.
124 */
125 #define CML_CONSTRUCT_MAT_22 \
126 matrix( \
127 ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \
128 ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11 \
129 ) \
130 { \
131 set( \
132 e00,e01, \
133 e10,e11 \
134 ); \
135 }
136
137 /** Create a matrix from 3x3 values.
138 *
139 * The layout assumed for the values is that of the matrix being assigned.
140 */
141 #define CML_CONSTRUCT_MAT_33 \
142 matrix( \
143 ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, ELEMENT_ARG_TYPE e02, \
144 ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, ELEMENT_ARG_TYPE e12, \
145 ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, ELEMENT_ARG_TYPE e22 \
146 ) \
147 { \
148 set( \
149 e00,e01,e02, \
150 e10,e11,e12, \
151 e20,e21,e22 \
152 ); \
153 }
154
155 /** Create a matrix from 4x4 values.
156 *
157 * The layout assumed for the values is that of the matrix being assigned.
158 */
159 #define CML_CONSTRUCT_MAT_44 \
160 matrix( \
161 ELEMENT_ARG_TYPE e00, ELEMENT_ARG_TYPE e01, \
162 ELEMENT_ARG_TYPE e02, ELEMENT_ARG_TYPE e03, \
163 ELEMENT_ARG_TYPE e10, ELEMENT_ARG_TYPE e11, \
164 ELEMENT_ARG_TYPE e12, ELEMENT_ARG_TYPE e13, \
165 ELEMENT_ARG_TYPE e20, ELEMENT_ARG_TYPE e21, \
166 ELEMENT_ARG_TYPE e22, ELEMENT_ARG_TYPE e23, \
167 ELEMENT_ARG_TYPE e30, ELEMENT_ARG_TYPE e31, \
168 ELEMENT_ARG_TYPE e32, ELEMENT_ARG_TYPE e33 \
169 ) \
170 { \
171 set( \
172 e00,e01,e02,e03, \
173 e10,e11,e12,e13, \
174 e20,e21,e22,e23, \
175 e30,e31,e32,e33 \
176 ); \
177 }
178
179 /** Copy-construct a matrix from a fixed-size array of values. */
180 #define CML_MAT_COPY_FROM_FIXED_ARRAY(_R_,_C_) \
181 matrix(const value_type m[_R_][_C_]) { \
182 typedef et::OpAssign<Element,Element> OpT; \
183 cml::matrix<const value_type, external<_R_,_C_>, \
184 basis_orient, row_major> src(&m[0][0]); \
185 et::UnrollAssignment<OpT>(*this,src); \
186 }
187
188 /** Copy-construct a matrix from a runtime-sized array of values. */
189 #define CML_MAT_COPY_FROM_ARRAY(_add_) \
190 matrix(const value_type* const v, size_t R, size_t C) _add_ { \
191 typedef et::OpAssign<Element,Element> OpT; \
192 cml::matrix<value_type, external<>, basis_orient, \
193 row_major > src(const_cast<value_type*>(v),R,C); \
194 et::UnrollAssignment<OpT>(*this,src); \
195 }
196
197 /** Copy this matrix from another using the given elementwise op.
198 *
199 * @internal This is required for GCC4, since it won't elide the default
200 * copy constructor.
201 */
202 #define CML_MAT_COPY_FROM_MATTYPE \
203 matrix(const matrix_type& m) : array_type() { \
204 typedef et::OpAssign <Element,Element> OpT; \
205 et::UnrollAssignment<OpT>(*this,m); \
206 }
207
208 /** Copy this matrix from another using the given elementwise op.
209 *
210 * This allows copies from arbitrary matrix types.
211 */
212 #define CML_MAT_COPY_FROM_MAT \
213 template<typename E, class AT, typename BO, typename L> \
214 matrix(const TEMPLATED_MATRIX_MACRO& m) { \
215 typedef et::OpAssign <Element,E> OpT; \
216 et::UnrollAssignment<OpT>(*this,m); \
217 }
218
219 /** Declare a function to copy this matrix from a matrix expression. */
220 #define CML_MAT_COPY_FROM_MATXPR \
221 template<class XprT> \
222 matrix(MATXPR_ARG_TYPE e) { \
223 /* Verify that a promotion exists at compile time: */ \
224 typedef typename et::MatrixPromote< \
225 matrix_type, typename XprT::result_type>::type result_type; \
226 typedef typename XprT::value_type src_value_type; \
227 typedef et::OpAssign <Element,src_value_type> OpT; \
228 et::UnrollAssignment<OpT>(*this,e); \
229 }
230
231 #if defined(CML_USE_GENERATED_MATRIX_ASSIGN_OP)
232 #define CML_MAT_ASSIGN_FROM_MATTYPE
233 #else
234 /** Assign from the same matrix type.
235 *
236 * @param m the matrix to copy from.
237 *
238 * @note This is required for GCC4, otherwise it generates a slow
239 * assignment operator using memcpy.
240 *
241 * @note ICC9/Linux-x86 seems to prefer its own assignment operator (need
242 * to figure out why).
243 */
244 #define CML_MAT_ASSIGN_FROM_MATTYPE \
245 matrix_type& operator=(const matrix_type& m) { \
246 typedef et::OpAssign<Element,Element> OpT; \
247 et::UnrollAssignment<OpT>(*this,m); \
248 return *this; \
249 }
250 #endif
251
252
253 /** Assign this matrix from another using the given elementwise op.
254 *
255 * This allows assignment from arbitrary matrix types.
256 *
257 * @param _op_ the operator (e.g. +=)
258 * @param _op_name_ the op functor (e.g. et::OpAssign)
259 */
260 #define CML_MAT_ASSIGN_FROM_MAT(_op_, _op_name_) \
261 template<typename E, class AT, typename BO, typename L> matrix_type& \
262 operator _op_ (const TEMPLATED_MATRIX_MACRO& m) { \
263 typedef _op_name_ <Element,E> OpT; \
264 et::UnrollAssignment<OpT>(*this,m); \
265 return *this; \
266 }
267
268 /** Declare a function to assign this matrix from a matrix expression.
269 *
270 * @param _op_ the operator (e.g. +=)
271 * @param _op_name_ the op functor (e.g. et::OpAssign)
272 */
273 #define CML_MAT_ASSIGN_FROM_MATXPR(_op_, _op_name_) \
274 template<class XprT> matrix_type& \
275 operator _op_ (MATXPR_ARG_TYPE e) { \
276 /* Verify that a promotion exists at compile time: */ \
277 typedef typename et::MatrixPromote< \
278 matrix_type, typename XprT::result_type>::type result_type; \
279 typedef typename XprT::value_type src_value_type; \
280 typedef _op_name_ <Element,src_value_type> OpT; \
281 et::UnrollAssignment<OpT>(*this,e); \
282 return *this; \
283 }
284
285 /** Declare a function to assign this matrix from a scalar.
286 *
287 * @param _op_ the operator (e.g. +=)
288 * @param _op_name_ the op functor (e.g. et::OpAssign)
289 *
290 * @internal This shouldn't be used for ops, like +=, which aren't
291 * defined in vector algebra.
292 */
293 #define CML_MAT_ASSIGN_FROM_SCALAR(_op_, _op_name_) \
294 matrix_type& operator _op_ (ELEMENT_ARG_TYPE s) { \
295 typedef _op_name_ <Element,value_type> OpT; \
296 et::UnrollAssignment<OpT>(*this,s); \
297 return *this; \
298 }
299
300
301 /** Accumulated matrix multiplication.
302 *
303 * @throws std::invalid_argument if the matrices are not square.
304 */
305 #define CML_ACCUMULATED_MATRIX_MULT(_arg_type_) \
306 matrix_type& operator*=(_arg_type_ m) { \
307 typedef typename et::MatrixPromote< \
308 matrix_type, _arg_type_>::type result_type; \
309 cml::et::CheckedSquare(*this, typename result_type::size_tag()); \
310 return (*this = (*this)*m); \
311 }
312
313
314 /* These should only be used for testing: */
315 #define CML_MATRIX_BRACE_OPERATORS \
316 template<class Matrix> struct row_ref { \
317 typedef typename Matrix::reference reference; \
318 reference operator[](size_t col) { return m(row,col); } \
319 Matrix& m; \
320 size_t row; \
321 }; \
322 \
323 template<class Matrix> struct const_row_ref { \
324 typedef typename Matrix::const_reference const_reference; \
325 const_reference operator[](size_t col) const { return m(row,col); } \
326 const Matrix& m; \
327 size_t row; \
328 }; \
329 \
330 row_ref<matrix_type> operator[](size_t row) { \
331 row_ref<matrix_type> ref = { *this, row }; return ref; \
332 } \
333 \
334 const_row_ref<matrix_type> operator[](size_t row) const { \
335 const_row_ref<matrix_type> ref = { *this, row }; return ref; \
336 }
337
338 #endif
339
340 // -------------------------------------------------------------------------
341 // vim:ft=cpp
This page took 0.043848 seconds and 4 git commands to generate.