00001
00002
00003
00004
00005
00006
00007
00008
00015 #ifndef size_checking_h
00016 #define size_checking_h
00017
00018 #include <stdexcept>
00019 #include <cml/core/cml_meta.h>
00020 #include <cml/core/cml_assert.h>
00021 #include <cml/core/fwd.h>
00022 #include <cml/et/traits.h>
00023
00024 #if defined(_MSC_VER) && _MSC_VER < 1400
00025 #pragma warning(push)
00026 #pragma warning(disable:4348)
00027
00028
00029 #endif
00030
00031
00032
00033
00034 struct incompatible_expression_size_error;
00035
00036
00037
00038
00039 struct square_matrix_arg_expected_error;
00040
00041 namespace cml {
00042 namespace et {
00043 namespace detail {
00044
00045 }
00046
00047
00048 template<typename LeftT, typename RightT, typename SizeT>
00049 struct GetCheckedSize;
00050
00051
00052 template<typename LeftT, typename RightT>
00053 struct GetCheckedSize<LeftT,RightT,fixed_size_tag>
00054 {
00055
00056 typedef ExprTraits<LeftT> left_traits;
00057 typedef ExprTraits<RightT> right_traits;
00058
00059
00060 typedef typename left_traits::result_tag left_result;
00061 typedef typename right_traits::result_tag right_result;
00062
00063
00064
00065 template<typename LR, typename RR, class X = void> struct impl;
00066
00067
00068 template<class X> struct impl<matrix_result_tag,matrix_result_tag,X> {
00069 typedef matrix_size size_type;
00070 CML_STATIC_REQUIRE_M(
00071 (size_t)LeftT::array_rows == (size_t)RightT::array_rows
00072 && (size_t)LeftT::array_cols == (size_t)RightT::array_cols,
00073 incompatible_expression_size_error);
00074
00075
00076 enum {
00077 array_rows = LeftT::array_rows,
00078 array_cols = LeftT::array_cols
00079 };
00080
00081
00082 size_type size() const { return size_type(array_rows,array_cols); }
00083 };
00084
00085
00086 template<class X> struct impl<matrix_result_tag,vector_result_tag,X> {
00087 typedef size_t size_type;
00088 CML_STATIC_REQUIRE_M(
00089 (size_t)LeftT::array_cols == (size_t)RightT::array_size,
00090 incompatible_expression_size_error);
00091
00092
00093 enum { array_size = LeftT::array_rows };
00094
00095
00096 size_type size() const { return size_type(array_size); }
00097 };
00098
00099
00100 template<class X> struct impl<vector_result_tag,matrix_result_tag,X> {
00101 typedef size_t size_type;
00102 CML_STATIC_REQUIRE_M(
00103 (size_t)LeftT::array_size == (size_t)RightT::array_rows,
00104 incompatible_expression_size_error);
00105
00106
00107 enum { array_size = RightT::array_cols };
00108
00109
00110 size_type size() const { return size_type(array_size); }
00111 };
00112
00113
00114 template<class X> struct impl<matrix_result_tag,scalar_result_tag,X> {
00115 typedef matrix_size size_type;
00116
00117
00118 enum {
00119 array_rows = LeftT::array_rows,
00120 array_cols = LeftT::array_cols
00121 };
00122
00123
00124 size_type size() const { return size_type(array_rows,array_cols); }
00125 };
00126
00127
00128 template<class X> struct impl<scalar_result_tag,matrix_result_tag,X> {
00129 typedef matrix_size size_type;
00130
00131
00132 enum {
00133 array_rows = RightT::array_rows,
00134 array_cols = RightT::array_cols
00135 };
00136
00137
00138 size_type size() const { return size_type(array_rows,array_cols); }
00139 };
00140
00141
00142
00143 template<class X> struct impl<vector_result_tag,vector_result_tag,X> {
00144 typedef size_t size_type;
00145 CML_STATIC_REQUIRE_M(
00146 (size_t)LeftT::array_size == (size_t)RightT::array_size,
00147 incompatible_expression_size_error);
00148
00149
00150 enum { array_size = LeftT::array_size };
00151
00152
00153 size_type size() const { return size_type(array_size); }
00154 };
00155
00156
00157 template<class X> struct impl<vector_result_tag,scalar_result_tag,X> {
00158 typedef size_t size_type;
00159
00160
00161 enum { array_size = LeftT::array_size };
00162
00163
00164 size_type size() const { return size_type(array_size); }
00165 };
00166
00167
00168 template<class X> struct impl<scalar_result_tag,vector_result_tag,X> {
00169 typedef size_t size_type;
00170
00171
00172 enum { array_size = RightT::array_size };
00173
00174
00175 size_type size() const { return size_type(array_size); }
00176 };
00177
00178
00179
00180 template<class X>
00181 struct impl<quaternion_result_tag,quaternion_result_tag,X> {
00182 typedef size_t size_type;
00183
00184
00185 enum { array_size = 4 };
00186
00187
00188 size_type size() const { return size_type(array_size); }
00189 };
00190
00191
00192 template<class X> struct impl<quaternion_result_tag,vector_result_tag,X> {
00193 typedef size_t size_type;
00194 CML_STATIC_REQUIRE_M(
00195 RightT::array_size == 4,
00196 incompatible_expression_size_error);
00197
00198
00199 enum { array_size = 4 };
00200
00201
00202 size_type size() const { return size_type(array_size); }
00203 };
00204
00205
00206 template<class X> struct impl<vector_result_tag,quaternion_result_tag,X> {
00207 typedef size_t size_type;
00208 CML_STATIC_REQUIRE_M(
00209 LeftT::array_size == 4,
00210 incompatible_expression_size_error);
00211
00212
00213 enum { array_size = 4 };
00214
00215
00216 size_type size() const { return size_type(array_size); }
00217 };
00218
00219
00220 template<class X> struct impl<quaternion_result_tag,scalar_result_tag,X> {
00221 typedef size_t size_type;
00222
00223
00224 enum { array_size = 4 };
00225
00226
00227 size_type size() const { return size_type(array_size); }
00228 };
00229
00230
00231 template<class X> struct impl<scalar_result_tag,quaternion_result_tag,X> {
00232 typedef size_t size_type;
00233
00234
00235 enum { array_size = 4 };
00236
00237
00238 size_type size() const { return size_type(array_size); }
00239 };
00240
00241
00242 typedef impl<left_result,right_result> check_type;
00243 typedef typename check_type::size_type size_type;
00244
00245
00246 size_type operator()(const LeftT&, const RightT&) const {
00247 return check_type().size();
00248 }
00249 };
00250
00251
00252 template<typename LeftT, typename RightT>
00253 struct GetCheckedSize<LeftT,RightT,dynamic_size_tag>
00254 {
00255
00256 typedef GetCheckedSize<LeftT,RightT,dynamic_size_tag> self;
00257
00258
00259 typedef ExprTraits<LeftT> left_traits;
00260 typedef ExprTraits<RightT> right_traits;
00261
00262
00263 typedef typename left_traits::result_tag left_result;
00264 typedef typename right_traits::result_tag right_result;
00265
00266
00267
00268 template<typename LR, typename RR, class X = void> struct impl;
00269
00270
00271 template<typename V> V equal_or_fail(V left, V right) const {
00272 if(left != right)
00273 throw std::invalid_argument(
00274 "expressions have incompatible sizes.");
00275 return left;
00276 }
00277
00278
00279 template<class X> struct impl<matrix_result_tag,matrix_result_tag,X> {
00280 typedef matrix_size size_type;
00281
00282
00283 size_type size(const LeftT& left, const RightT& right) const {
00284 #if defined(CML_CHECK_MATRIX_EXPR_SIZES)
00285 return self().equal_or_fail(left.size(), right.size());
00286 #else
00287 return left.size();
00288 #endif
00289 }
00290 };
00291
00292
00293 template<class X> struct impl<matrix_result_tag,vector_result_tag,X> {
00294 typedef size_t size_type;
00295
00296
00297 size_type size(const LeftT& left, const RightT& right) const {
00298 #if defined(CML_CHECK_MATVEC_EXPR_SIZES)
00299 self().equal_or_fail(left.cols(), right.size());
00300 #endif
00301 return left.rows();
00302 }
00303 };
00304
00305
00306 template<class X> struct impl<vector_result_tag,matrix_result_tag,X> {
00307 typedef size_t size_type;
00308
00309
00310 size_type size(const LeftT& left, const RightT& right) const {
00311 #if defined(CML_CHECK_MATVEC_EXPR_SIZES)
00312 self().equal_or_fail(left.size(), right.rows());
00313 #endif
00314 return right.cols(right);
00315 }
00316 };
00317
00318
00319 template<class X> struct impl<matrix_result_tag,scalar_result_tag,X> {
00320 typedef matrix_size size_type;
00321
00322
00323 size_type size(const LeftT& left, const RightT&) const {
00324 return left.size();
00325 }
00326 };
00327
00328
00329 template<class X> struct impl<scalar_result_tag,matrix_result_tag,X> {
00330 typedef matrix_size size_type;
00331
00332
00333 size_type size(const LeftT&, const RightT& right) const {
00334 return right.size();
00335 }
00336 };
00337
00338
00339 template<class X> struct impl<vector_result_tag,vector_result_tag,X> {
00340 typedef size_t size_type;
00341
00342
00343 size_type size(const LeftT& left, const RightT& right) const {
00344 #if defined(CML_CHECK_VECTOR_EXPR_SIZES)
00345 return self().equal_or_fail(left.size(), right.size());
00346 #else
00347 return left.size();
00348 #endif
00349 }
00350 };
00351
00352
00353 template<class X> struct impl<vector_result_tag,scalar_result_tag,X> {
00354 typedef size_t size_type;
00355
00356
00357 size_type size(const LeftT& left, const RightT&) const {
00358 return left.size();
00359 }
00360 };
00361
00362
00363 template<class X> struct impl<scalar_result_tag,vector_result_tag,X> {
00364 typedef size_t size_type;
00365
00366
00367 size_type size(const LeftT&, const RightT& right) const {
00368 return right.size();
00369 }
00370 };
00371
00372
00373 typedef impl<left_result,right_result> check_type;
00374 typedef typename check_type::size_type size_type;
00375
00376
00377 size_type operator()(const LeftT& left, const RightT& right) const {
00378 return check_type().size(left,right);
00379 }
00380 };
00381
00383 template<typename LeftT, typename RightT, typename SizeTag>
00384 inline typename et::GetCheckedSize<LeftT,RightT,SizeTag>::size_type
00385 CheckedSize(const LeftT& left, const RightT& right, SizeTag)
00386 {
00387 return et::GetCheckedSize<LeftT,RightT,SizeTag>()(left,right);
00388 }
00389
00394 template<typename MatT> inline size_t
00395 CheckedSquare(const MatT&, fixed_size_tag)
00396 {
00397 CML_STATIC_REQUIRE_M(
00398 ((size_t)MatT::array_rows == (size_t)MatT::array_cols),
00399 square_matrix_arg_expected_error);
00400 return (size_t)MatT::array_rows;
00401 }
00402
00407 template<typename MatT> inline size_t
00408 CheckedSquare(const MatT& m, dynamic_size_tag)
00409 {
00410 matrix_size N = m.size();
00411 et::GetCheckedSize<MatT,MatT,dynamic_size_tag>()
00412 .equal_or_fail(N.first, N.second);
00413 return N.first;
00414 }
00415
00416 }
00417 }
00418
00419 #if defined(_MSC_VER) && _MSC_VER < 1400
00420 #pragma warning(pop)
00421 #endif
00422
00423 #endif
00424
00425
00426