1 /* -*- C++ -*- ------------------------------------------------------------
3 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
5 The Configurable Math Library (CML) is distributed under the terms of the
6 Boost Software License, v1.0 (see cml/LICENSE for details).
8 *-----------------------------------------------------------------------*/
16 #include <cml/vector/vector_expr.h>
17 #include <cml/matrix/matrix_expr.h>
18 #include <cml/quaternion/quaternion_expr.h>
20 /* Run- and compile-time checking of argument types, values and sizes. */
22 struct function_expects_vector_arg_error
;
23 struct function_expects_matrix_arg_error
;
24 struct function_expects_quaternion_arg_error
;
26 struct function_expects_2D_vector_arg_error
;
27 struct function_expects_3D_vector_arg_error
;
28 struct function_expects_4D_vector_arg_error
;
29 struct function_expects_2D_or_3D_vector_arg_error
;
30 struct function_expects_2x2_matrix_arg_error
;
31 struct function_expects_3x3_matrix_arg_error
;
32 struct function_expects_4x4_matrix_arg_error
;
33 struct function_expects_square_matrix_arg_error
;
35 struct matrix_arg_fails_minimum_size_requirement
;
40 //////////////////////////////////////////////////////////////////////////////
41 // Vector argument checking
42 //////////////////////////////////////////////////////////////////////////////
44 /** Compile-time check for a vector argument */
45 template< class VecT
> inline void
48 typedef et::ExprTraits
<VecT
> vector_traits
;
49 typedef typename
vector_traits::result_tag result_type
;
52 (same_type
<result_type
, et::vector_result_tag
>::is_true
),
53 function_expects_vector_arg_error
);
56 /** Compile-time check for a vector of size N */
57 template< class VecT
, size_t N
, class ErrorT
> inline void
58 CheckVecN(const VecT
& v
, fixed_size_tag
) {
61 CML_STATIC_REQUIRE_M(((size_t)VecT::array_size
== N
), ErrorT
);
64 /** Run-time check for a vector of size N */
65 template< class VecT
, size_t N
, class /*ErrorT*/ > inline void
66 CheckVecN(const VecT
& v
, dynamic_size_tag
) {
69 et::GetCheckedSize
<VecT
,VecT
,dynamic_size_tag
>()
70 .equal_or_fail(v
.size(),size_t(N
));
73 /** Check for a vector of size N */
74 template< class VecT
, size_t N
, class ErrorT
> inline void
75 CheckVecN(const VecT
& v
) {
76 typedef et::ExprTraits
<VecT
> vector_traits
;
77 typedef typename
vector_traits::size_tag size_tag
;
79 detail::CheckVecN
<VecT
,N
,ErrorT
>(v
, size_tag());
82 /** Check for a vector of size 2 */
83 template< class VecT
> inline void
84 CheckVec2(const VecT
& v
) {
85 detail::CheckVecN
<VecT
,2,function_expects_2D_vector_arg_error
>(v
);
88 /** Check for a vector of size 3 */
89 template< class VecT
> inline void
90 CheckVec3(const VecT
& v
) {
91 detail::CheckVecN
<VecT
,3,function_expects_3D_vector_arg_error
>(v
);
94 /** Check for a vector of size 4 */
95 template< class VecT
> inline void
96 CheckVec4(const VecT
& v
) {
97 CheckVecN
<VecT
,4,function_expects_4D_vector_arg_error
>(v
);
100 /** Compile-time check for a vector of size 2 or 3 */
101 template< class VecT
> inline void
102 CheckVec2Or3(const VecT
& v
, fixed_size_tag
) {
105 CML_STATIC_REQUIRE_M(
106 (VecT::array_size
== 2 || VecT::array_size
== 3),
107 function_expects_2D_or_3D_vector_arg_error
);
110 /** Run-time check for a vector of size 2 or 3 */
111 template< class VecT
> inline void
112 CheckVec2Or3(const VecT
& v
, dynamic_size_tag
) {
115 if (v
.size() != 2 && v
.size() != 3) {
116 throw std::invalid_argument("2d or 3d vector arg expected");
120 /** Check for a vector of size 2 or 3 */
121 template< class VecT
> inline void
122 CheckVec2Or3(const VecT
& v
) {
123 typedef et::ExprTraits
<VecT
> vector_traits
;
124 typedef typename
vector_traits::size_tag size_tag
;
126 detail::CheckVec2Or3(v
, size_tag());
129 //////////////////////////////////////////////////////////////////////////////
130 // Matrix argument checking
131 //////////////////////////////////////////////////////////////////////////////
133 /** Compile-time check for a matrix argument */
134 template< class MatT
> inline void
135 CheckMat(const MatT
&)
137 typedef et::ExprTraits
<MatT
> matrix_traits
;
138 typedef typename
matrix_traits::result_tag result_type
;
140 CML_STATIC_REQUIRE_M(
141 (same_type
<result_type
, et::matrix_result_tag
>::is_true
),
142 function_expects_matrix_arg_error
);
145 /** Compile-time check for a matrix of size NxM */
146 template< class MatT
, size_t N
, size_t M
, class ErrorT
> inline void
147 CheckMatNxM(const MatT
& m
, fixed_size_tag
) {
150 CML_STATIC_REQUIRE_M(
151 (MatT::array_rows
== N
&& MatT::array_cols
== M
), ErrorT
);
154 /** Run-time check for a matrix of size NxM */
155 template< class MatT
, size_t N
, size_t M
, class /*ErrorT*/ > inline void
156 CheckMatNxM(const MatT
& m
, dynamic_size_tag
) {
159 et::GetCheckedSize
<MatT
,MatT
,dynamic_size_tag
>()
160 .equal_or_fail(m
.rows(),N
);
161 et::GetCheckedSize
<MatT
,MatT
,dynamic_size_tag
>()
162 .equal_or_fail(m
.cols(),M
);
165 /** Check for a matrix of size NxM */
166 template< class MatT
, size_t N
, size_t M
, class ErrorT
> inline void
167 CheckMatNxM(const MatT
& m
) {
168 typedef et::ExprTraits
<MatT
> matrix_traits
;
169 typedef typename
matrix_traits::size_tag size_tag
;
171 CheckMatNxM
<MatT
,N
,M
,ErrorT
>(m
, size_tag());
174 /** Check for a square matrix of size NxN */
175 template< class MatT
, size_t N
, class ErrorT
> inline void
176 CheckMatN(const MatT
& m
) {
177 CheckMatNxM
<MatT
,N
,N
,ErrorT
>(m
);
180 /** Check for a square matrix of size 2x2 */
181 template< class MatT
> inline void
182 CheckMat2x2(const MatT
& m
) {
183 CheckMatN
<MatT
,2,function_expects_2x2_matrix_arg_error
>(m
);
186 /** Check for a square matrix of size 3x3 */
187 template< class MatT
> inline void
188 CheckMat3x3(const MatT
& m
) {
189 CheckMatN
<MatT
,3,function_expects_3x3_matrix_arg_error
>(m
);
192 /** Check for a square matrix of size 4x4 */
193 template< class MatT
> inline void
194 CheckMat4x4(const MatT
& m
) {
195 CheckMatN
<MatT
,4,function_expects_4x4_matrix_arg_error
>(m
);
198 /** Compile-time check for a matrix with minimum dimensions NxM */
199 template< class MatT
, size_t N
, size_t M
, class ErrorT
> inline void
200 CheckMatMinNxM(const MatT
& m
, fixed_size_tag
) {
203 CML_STATIC_REQUIRE_M(
204 (MatT::array_rows
>= N
&& MatT::array_cols
>= M
), ErrorT
);
207 /** Run-time check for a matrix with minimum dimensions NxM */
208 template< class MatT
, size_t N
, size_t M
, class /*ErrorT*/ > inline void
209 CheckMatMinNxM(const MatT
& m
, dynamic_size_tag
) {
212 if (m
.rows() < N
|| m
.cols() < M
) {
213 throw std::invalid_argument(
214 "matrix does not meet minimum size requirement");
218 /** Check for a matrix with minimum dimensions NxM */
219 template< class MatT
, size_t N
, size_t M
, class ErrorT
> inline void
220 CheckMatMinNxM(const MatT
& m
) {
221 typedef et::ExprTraits
<MatT
> matrix_traits
;
222 typedef typename
matrix_traits::size_tag size_tag
;
224 CheckMatMinNxM
<MatT
,N
,M
,ErrorT
>(m
, size_tag());
227 /** Check for a matrix with minimum dimensions NxN */
228 template< class MatT
, size_t N
, class ErrorT
> inline void
229 CheckMatMinN(const MatT
& m
) {
230 CheckMatMinNxM
<MatT
,N
,N
,ErrorT
>(m
);
233 /** Check for a matrix with minimum dimensions 2x2 */
234 template< class MatT
> inline void
235 CheckMatMin2x2(const MatT
& m
) {
236 CheckMatMinN
<MatT
,2,matrix_arg_fails_minimum_size_requirement
>(m
);
239 /** Check for a matrix with minimum dimensions 3x3 */
240 template< class MatT
> inline void
241 CheckMatMin3x3(const MatT
& m
) {
242 CheckMatMinN
<MatT
,3,matrix_arg_fails_minimum_size_requirement
>(m
);
245 /** Check for a matrix with minimum dimensions 4x4 */
246 template< class MatT
> inline void
247 CheckMatMin4x4(const MatT
& m
) {
248 CheckMatMinN
<MatT
,4,matrix_arg_fails_minimum_size_requirement
>(m
);
251 /** Check for a matrix that can represent a 3D linear transform */
252 template< class MatT
> inline void
253 CheckMatLinear3D(const MatT
& m
) {
257 /** Check for a matrix that can represent a 2D linear transform */
258 template< class MatT
> inline void
259 CheckMatLinear2D(const MatT
& m
) {
263 /** Check for a matrix that can represent a 3D row-basis affine transform */
264 template< class MatT
> inline void
265 CheckMatAffine3D(const MatT
& m
, row_basis
) {
266 CheckMatMinNxM
<MatT
,4,3,matrix_arg_fails_minimum_size_requirement
>(m
);
269 /** Check for a matrix that can represent a 3D col-basis affine transform */
270 template< class MatT
> inline void
271 CheckMatAffine3D(const MatT
& m
, col_basis
) {
272 CheckMatMinNxM
<MatT
,3,4,matrix_arg_fails_minimum_size_requirement
>(m
);
275 /** Check for a matrix that can represent a 2D row-basis affine transform */
276 template< class MatT
> inline void
277 CheckMatAffine2D(const MatT
& m
, row_basis
) {
278 CheckMatMinNxM
<MatT
,3,2,matrix_arg_fails_minimum_size_requirement
>(m
);
281 /** Check for a matrix that can represent a 2D col-basis affine transform */
282 template< class MatT
> inline void
283 CheckMatAffine2D(const MatT
& m
, col_basis
) {
284 CheckMatMinNxM
<MatT
,2,3,matrix_arg_fails_minimum_size_requirement
>(m
);
287 /** Check for a matrix that can represent a 3D affine transform */
288 template< class MatT
> inline void
289 CheckMatAffine3D(const MatT
& m
) {
290 CheckMatAffine3D(m
, typename
MatT::basis_orient());
293 /** Check for a matrix that can represent a 2D affine transform */
294 template< class MatT
> inline void
295 CheckMatAffine2D(const MatT
& m
) {
296 CheckMatAffine2D(m
, typename
MatT::basis_orient());
299 /** Check for a matrix that can represent a 3D homogenous transform */
300 template< class MatT
> inline void
301 CheckMatHomogeneous3D(const MatT
& m
) {
305 /** Compile-time check for a square matrix */
306 template< class MatT
, class ErrorT
> inline void
307 CheckMatSquare(const MatT
& m
, fixed_size_tag
) {
310 CML_STATIC_REQUIRE_M(
311 (MatT::array_rows
== MatT::array_cols
), ErrorT
);
314 /** Run-time check for a square matrix */
315 template< class MatT
, class /*ErrorT*/ > inline void
316 CheckMatSquare(const MatT
& m
, dynamic_size_tag
) {
319 if (m
.rows() != m
.cols()) {
320 throw std::invalid_argument(
321 "function expects square matrix as argument");
325 /** Check for a square matrix */
326 template< class MatT
> inline void
327 CheckMatSquare(const MatT
& m
) {
328 typedef et::ExprTraits
<MatT
> matrix_traits
;
329 typedef typename
matrix_traits::size_tag size_tag
;
331 detail::CheckMatSquare
<
332 MatT
,function_expects_square_matrix_arg_error
>(m
, size_tag());
335 //////////////////////////////////////////////////////////////////////////////
336 // Quaternion argument checking
337 //////////////////////////////////////////////////////////////////////////////
339 /** Compile-time check for a quaternion argument*/
340 template< class QuatT
> inline void
341 CheckQuat(const QuatT
& /*q*/)
343 typedef et::ExprTraits
<QuatT
> quaternion_traits
;
344 typedef typename
quaternion_traits::result_tag result_type
;
346 CML_STATIC_REQUIRE_M(
347 (same_type
<result_type
, et::quaternion_result_tag
>::is_true
),
348 function_expects_quaternion_arg_error
);
351 //////////////////////////////////////////////////////////////////////////////
352 // Index argument checking
353 //////////////////////////////////////////////////////////////////////////////
355 /** Run-time check for a valid argument */
356 inline void CheckValidArg(bool valid
)
359 throw std::invalid_argument("invalid function argument");
363 /** Check for a valid integer index with value < N */
364 template < size_t N
>
365 inline void CheckIndexN(size_t index
) {
366 CheckValidArg(index
< N
);
369 /** Check for a valid integer index with value < 2 */
370 inline void CheckIndex2(size_t index
) {
371 CheckIndexN
<2>(index
);
374 /** Check for a valid integer index with value < 3 */
375 inline void CheckIndex3(size_t index
) {
376 CheckIndexN
<3>(index
);
379 } // namespace detail