/* -*- C++ -*- ------------------------------------------------------------ Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/ The Configurable Math Library (CML) is distributed under the terms of the Boost Software License, v1.0 (see cml/LICENSE for details). *-----------------------------------------------------------------------*/ /** @file * @brief */ #ifndef checking_h #define checking_h #include #include #include /* Run- and compile-time checking of argument types, values and sizes. */ struct function_expects_vector_arg_error; struct function_expects_matrix_arg_error; struct function_expects_quaternion_arg_error; struct function_expects_2D_vector_arg_error; struct function_expects_3D_vector_arg_error; struct function_expects_4D_vector_arg_error; struct function_expects_2D_or_3D_vector_arg_error; struct function_expects_2x2_matrix_arg_error; struct function_expects_3x3_matrix_arg_error; struct function_expects_4x4_matrix_arg_error; struct function_expects_square_matrix_arg_error; struct matrix_arg_fails_minimum_size_requirement; namespace cml { namespace detail { ////////////////////////////////////////////////////////////////////////////// // Vector argument checking ////////////////////////////////////////////////////////////////////////////// /** Compile-time check for a vector argument */ template< class VecT > inline void CheckVec(const VecT&) { typedef et::ExprTraits vector_traits; typedef typename vector_traits::result_tag result_type; CML_STATIC_REQUIRE_M( (same_type::is_true), function_expects_vector_arg_error); } /** Compile-time check for a vector of size N */ template< class VecT, size_t N, class ErrorT > inline void CheckVecN(const VecT& v, fixed_size_tag) { CheckVec(v); CML_STATIC_REQUIRE_M(((size_t)VecT::array_size == N), ErrorT); } /** Run-time check for a vector of size N */ template< class VecT, size_t N, class /*ErrorT*/ > inline void CheckVecN(const VecT& v, dynamic_size_tag) { CheckVec(v); et::GetCheckedSize() .equal_or_fail(v.size(),size_t(N)); } /** Check for a vector of size N */ template< class VecT, size_t N, class ErrorT > inline void CheckVecN(const VecT& v) { typedef et::ExprTraits vector_traits; typedef typename vector_traits::size_tag size_tag; detail::CheckVecN(v, size_tag()); } /** Check for a vector of size 2 */ template< class VecT > inline void CheckVec2(const VecT& v) { detail::CheckVecN(v); } /** Check for a vector of size 3 */ template< class VecT > inline void CheckVec3(const VecT& v) { detail::CheckVecN(v); } /** Check for a vector of size 4 */ template< class VecT > inline void CheckVec4(const VecT& v) { CheckVecN(v); } /** Compile-time check for a vector of size 2 or 3 */ template< class VecT > inline void CheckVec2Or3(const VecT& v, fixed_size_tag) { CheckVec(v); CML_STATIC_REQUIRE_M( (VecT::array_size == 2 || VecT::array_size == 3), function_expects_2D_or_3D_vector_arg_error); } /** Run-time check for a vector of size 2 or 3 */ template< class VecT > inline void CheckVec2Or3(const VecT& v, dynamic_size_tag) { CheckVec(v); if (v.size() != 2 && v.size() != 3) { throw std::invalid_argument("2d or 3d vector arg expected"); } } /** Check for a vector of size 2 or 3 */ template< class VecT > inline void CheckVec2Or3(const VecT& v) { typedef et::ExprTraits vector_traits; typedef typename vector_traits::size_tag size_tag; detail::CheckVec2Or3(v, size_tag()); } ////////////////////////////////////////////////////////////////////////////// // Matrix argument checking ////////////////////////////////////////////////////////////////////////////// /** Compile-time check for a matrix argument */ template< class MatT > inline void CheckMat(const MatT&) { typedef et::ExprTraits matrix_traits; typedef typename matrix_traits::result_tag result_type; CML_STATIC_REQUIRE_M( (same_type::is_true), function_expects_matrix_arg_error); } /** Compile-time check for a matrix of size NxM */ template< class MatT, size_t N, size_t M, class ErrorT > inline void CheckMatNxM(const MatT& m, fixed_size_tag) { CheckMat(m); CML_STATIC_REQUIRE_M( (MatT::array_rows == N && MatT::array_cols == M), ErrorT); } /** Run-time check for a matrix of size NxM */ template< class MatT, size_t N, size_t M, class /*ErrorT*/ > inline void CheckMatNxM(const MatT& m, dynamic_size_tag) { CheckMat(m); et::GetCheckedSize() .equal_or_fail(m.rows(),N); et::GetCheckedSize() .equal_or_fail(m.cols(),M); } /** Check for a matrix of size NxM */ template< class MatT, size_t N, size_t M, class ErrorT > inline void CheckMatNxM(const MatT& m) { typedef et::ExprTraits matrix_traits; typedef typename matrix_traits::size_tag size_tag; CheckMatNxM(m, size_tag()); } /** Check for a square matrix of size NxN */ template< class MatT, size_t N, class ErrorT > inline void CheckMatN(const MatT& m) { CheckMatNxM(m); } /** Check for a square matrix of size 2x2 */ template< class MatT > inline void CheckMat2x2(const MatT& m) { CheckMatN(m); } /** Check for a square matrix of size 3x3 */ template< class MatT > inline void CheckMat3x3(const MatT& m) { CheckMatN(m); } /** Check for a square matrix of size 4x4 */ template< class MatT > inline void CheckMat4x4(const MatT& m) { CheckMatN(m); } /** Compile-time check for a matrix with minimum dimensions NxM */ template< class MatT, size_t N, size_t M, class ErrorT > inline void CheckMatMinNxM(const MatT& m, fixed_size_tag) { CheckMat(m); CML_STATIC_REQUIRE_M( (MatT::array_rows >= N && MatT::array_cols >= M), ErrorT); } /** Run-time check for a matrix with minimum dimensions NxM */ template< class MatT, size_t N, size_t M, class /*ErrorT*/ > inline void CheckMatMinNxM(const MatT& m, dynamic_size_tag) { CheckMat(m); if (m.rows() < N || m.cols() < M) { throw std::invalid_argument( "matrix does not meet minimum size requirement"); } } /** Check for a matrix with minimum dimensions NxM */ template< class MatT, size_t N, size_t M, class ErrorT > inline void CheckMatMinNxM(const MatT& m) { typedef et::ExprTraits matrix_traits; typedef typename matrix_traits::size_tag size_tag; CheckMatMinNxM(m, size_tag()); } /** Check for a matrix with minimum dimensions NxN */ template< class MatT, size_t N, class ErrorT > inline void CheckMatMinN(const MatT& m) { CheckMatMinNxM(m); } /** Check for a matrix with minimum dimensions 2x2 */ template< class MatT > inline void CheckMatMin2x2(const MatT& m) { CheckMatMinN(m); } /** Check for a matrix with minimum dimensions 3x3 */ template< class MatT > inline void CheckMatMin3x3(const MatT& m) { CheckMatMinN(m); } /** Check for a matrix with minimum dimensions 4x4 */ template< class MatT > inline void CheckMatMin4x4(const MatT& m) { CheckMatMinN(m); } /** Check for a matrix that can represent a 3D linear transform */ template< class MatT > inline void CheckMatLinear3D(const MatT& m) { CheckMatMin3x3(m); } /** Check for a matrix that can represent a 2D linear transform */ template< class MatT > inline void CheckMatLinear2D(const MatT& m) { CheckMatMin2x2(m); } /** Check for a matrix that can represent a 3D row-basis affine transform */ template< class MatT > inline void CheckMatAffine3D(const MatT& m, row_basis) { CheckMatMinNxM(m); } /** Check for a matrix that can represent a 3D col-basis affine transform */ template< class MatT > inline void CheckMatAffine3D(const MatT& m, col_basis) { CheckMatMinNxM(m); } /** Check for a matrix that can represent a 2D row-basis affine transform */ template< class MatT > inline void CheckMatAffine2D(const MatT& m, row_basis) { CheckMatMinNxM(m); } /** Check for a matrix that can represent a 2D col-basis affine transform */ template< class MatT > inline void CheckMatAffine2D(const MatT& m, col_basis) { CheckMatMinNxM(m); } /** Check for a matrix that can represent a 3D affine transform */ template< class MatT > inline void CheckMatAffine3D(const MatT& m) { CheckMatAffine3D(m, typename MatT::basis_orient()); } /** Check for a matrix that can represent a 2D affine transform */ template< class MatT > inline void CheckMatAffine2D(const MatT& m) { CheckMatAffine2D(m, typename MatT::basis_orient()); } /** Check for a matrix that can represent a 3D homogenous transform */ template< class MatT > inline void CheckMatHomogeneous3D(const MatT& m) { CheckMatMin4x4(m); } /** Compile-time check for a square matrix */ template< class MatT, class ErrorT> inline void CheckMatSquare(const MatT& m, fixed_size_tag) { CheckMat(m); CML_STATIC_REQUIRE_M( (MatT::array_rows == MatT::array_cols), ErrorT); } /** Run-time check for a square matrix */ template< class MatT, class /*ErrorT*/ > inline void CheckMatSquare(const MatT& m, dynamic_size_tag) { CheckMat(m); if (m.rows() != m.cols()) { throw std::invalid_argument( "function expects square matrix as argument"); } } /** Check for a square matrix */ template< class MatT > inline void CheckMatSquare(const MatT& m) { typedef et::ExprTraits matrix_traits; typedef typename matrix_traits::size_tag size_tag; detail::CheckMatSquare< MatT,function_expects_square_matrix_arg_error>(m, size_tag()); } ////////////////////////////////////////////////////////////////////////////// // Quaternion argument checking ////////////////////////////////////////////////////////////////////////////// /** Compile-time check for a quaternion argument*/ template< class QuatT > inline void CheckQuat(const QuatT& /*q*/) { typedef et::ExprTraits quaternion_traits; typedef typename quaternion_traits::result_tag result_type; CML_STATIC_REQUIRE_M( (same_type::is_true), function_expects_quaternion_arg_error); } ////////////////////////////////////////////////////////////////////////////// // Index argument checking ////////////////////////////////////////////////////////////////////////////// /** Run-time check for a valid argument */ inline void CheckValidArg(bool valid) { if (!valid) { throw std::invalid_argument("invalid function argument"); } } /** Check for a valid integer index with value < N */ template < size_t N > inline void CheckIndexN(size_t index) { CheckValidArg(index < N); } /** Check for a valid integer index with value < 2 */ inline void CheckIndex2(size_t index) { CheckIndexN<2>(index); } /** Check for a valid integer index with value < 3 */ inline void CheckIndex3(size_t index) { CheckIndexN<3>(index); } } // namespace detail } // namespace cml #endif