00001
00002
00003
00004
00005
00006
00007
00008
00016 #ifndef vector_products_h
00017 #define vector_products_h
00018
00019 #include <cml/core/cml_assert.h>
00020 #include <cml/et/scalar_promotions.h>
00021 #include <cml/et/size_checking.h>
00022 #include <cml/vector/vector_unroller.h>
00023 #include <cml/vector/vector_expr.h>
00024 #include <cml/matrix/matrix_expr.h>
00025
00026
00027
00028
00029 struct dot_expects_vector_args_error;
00030
00031
00032
00033
00034 struct perp_dot_expects_vector_args_error;
00035 struct perp_dot_expects_2D_vector_args_error;
00036
00037
00038
00039
00040 struct outer_expects_vector_args_error;
00041
00042
00043
00044
00045 struct cross_expects_vector_args_error;
00046 struct cross_expects_3D_vector_args_error;
00047
00048
00049 namespace cml {
00050 namespace detail {
00051
00052 template<typename LeftT, typename RightT>
00053 struct DotPromote
00054 {
00055
00056 typedef et::ExprTraits<LeftT> left_traits;
00057 typedef et::ExprTraits<RightT> right_traits;
00058 typedef typename left_traits::value_type left_value;
00059 typedef typename right_traits::value_type right_value;
00060
00061
00062 typedef et::OpMul<left_value, right_value> op_mul;
00063 typedef typename et::OpAdd<
00064 typename op_mul::value_type,
00065 typename op_mul::value_type> op_add;
00066 typedef typename op_add::value_type promoted_scalar;
00067 };
00068
00069 template<typename LeftT, typename RightT>
00070 struct CrossPromote
00071 {
00072
00073 typedef et::ExprTraits<LeftT> left_traits;
00074 typedef et::ExprTraits<RightT> right_traits;
00075 typedef typename left_traits::result_type left_type;
00076 typedef typename right_traits::result_type right_type;
00077
00078
00079 typedef typename et::VectorPromote<
00080 left_type,right_type>::temporary_type promoted_vector;
00081 };
00082
00083 template<typename LeftT, typename RightT>
00084 struct OuterPromote
00085 {
00086
00087 typedef et::ExprTraits<LeftT> left_traits;
00088 typedef et::ExprTraits<RightT> right_traits;
00089 typedef typename left_traits::result_type left_type;
00090 typedef typename right_traits::result_type right_type;
00091
00092
00093 typedef typename et::MatrixPromote<
00094 left_type,right_type>::temporary_type promoted_matrix;
00095 };
00096
00103 template<typename LeftT, typename RightT>
00104 inline typename DotPromote<LeftT,RightT>::promoted_scalar
00105 UnrollDot(const LeftT& left, const RightT& right, fixed_size_tag)
00106 {
00107
00108 typedef DotPromote<LeftT,RightT> dot_helper;
00109
00110
00111 typedef typename et::GetCheckedSize<LeftT,RightT,fixed_size_tag>
00112 ::check_type check_sizes;
00113
00114
00115 enum { Len = check_sizes::array_size };
00116
00117
00118 typedef typename dot_helper::op_mul op_mul;
00119 typedef typename dot_helper::op_add op_add;
00120 typedef typename et::detail::VectorAccumulateUnroller<
00121 op_add,op_mul,LeftT,RightT>::template
00122 Eval<0, Len-1, (Len <= CML_VECTOR_DOT_UNROLL_LIMIT)> Unroller;
00123
00124
00125
00126 return Unroller()(left,right);
00127 }
00128
00135 template<typename LeftT, typename RightT>
00136 inline typename DotPromote<LeftT,RightT>::promoted_scalar
00137 UnrollDot(const LeftT& left, const RightT& right, dynamic_size_tag)
00138 {
00139
00140 typedef DotPromote<LeftT,RightT> dot_helper;
00141 typedef et::ExprTraits<LeftT> left_traits;
00142 typedef et::ExprTraits<RightT> right_traits;
00143 typedef typename dot_helper::op_mul op_mul;
00144 typedef typename dot_helper::op_add op_add;
00145
00146
00147 typedef typename dot_helper::promoted_scalar sum_type;
00148
00149
00150 const size_t N = et::CheckedSize(left,right,dynamic_size_tag());
00151
00152
00153
00154
00155 sum_type sum(op_mul().apply(left[0],right[0]));
00156 for(size_t i = 1; i < N; ++i) {
00157
00158
00159
00160
00161
00162 sum = op_add().apply(sum, op_mul().apply(left[i], right[i]));
00163
00164
00165
00166 }
00167 return sum;
00168 }
00169
00171 template<typename VecT> inline void
00172 Require3D(const VecT&, fixed_size_tag) {
00173 CML_STATIC_REQUIRE_M(
00174 ((size_t)VecT::array_size == 3),
00175 cross_expects_3D_vector_args_error);
00176 }
00177
00179 template<typename VecT> inline void
00180 Require3D(const VecT& v, dynamic_size_tag) {
00181 et::GetCheckedSize<VecT,VecT,dynamic_size_tag>()
00182 .equal_or_fail(v.size(),size_t(3));
00183 }
00184
00186 template<typename VecT> inline void
00187 Require2D(const VecT& v, fixed_size_tag) {
00188 CML_STATIC_REQUIRE_M(
00189 ((size_t)VecT::array_size == 2),
00190 perp_dot_expects_2D_vector_args_error);
00191 }
00192
00194 template<typename VecT> inline void
00195 Require2D(const VecT& v, dynamic_size_tag) {
00196 et::GetCheckedSize<VecT,VecT,dynamic_size_tag>()
00197 .equal_or_fail(v.size(),size_t(2));
00198 }
00199
00200 }
00201
00202
00205 template<typename LeftT, typename RightT>
00206 inline typename detail::DotPromote<LeftT,RightT>::promoted_scalar
00207 dot(const LeftT& left, const RightT& right)
00208 {
00209
00210 typedef detail::DotPromote<LeftT,RightT> dot_helper;
00211 typedef et::ExprTraits<LeftT> left_traits;
00212 typedef et::ExprTraits<RightT> right_traits;
00213 typedef typename left_traits::result_type left_type;
00214 typedef typename right_traits::result_type right_type;
00215 typedef typename left_traits::size_tag left_size;
00216 typedef typename right_traits::size_tag right_size;
00217
00218
00219 CML_STATIC_REQUIRE_M(
00220 (et::VectorExpressions<LeftT,RightT>::is_true),
00221 dot_expects_vector_args_error);
00222
00223
00224
00225
00226
00227 typedef typename et::VectorPromote<
00228 left_type, right_type>::temporary_type promoted_vector;
00229 typedef typename promoted_vector::size_tag size_tag;
00230
00231
00232 return detail::UnrollDot(left,right,size_tag());
00233 }
00234
00237 template<typename LeftT, typename RightT>
00238 inline typename detail::DotPromote<LeftT,RightT>::promoted_scalar
00239 perp_dot(const LeftT& left, const RightT& right)
00240 {
00241
00242 typedef et::ExprTraits<LeftT> left_traits;
00243 typedef et::ExprTraits<RightT> right_traits;
00244 typedef typename left_traits::result_tag left_result;
00245 typedef typename right_traits::result_tag right_result;
00246
00247
00248 CML_STATIC_REQUIRE_M(
00249 (same_type<left_result, et::vector_result_tag>::is_true
00250 && same_type<right_result, et::vector_result_tag>::is_true),
00251 perp_dot_expects_vector_args_error);
00252
00253
00254
00255
00256
00257 detail::Require2D(left, typename left_traits::size_tag());
00258 detail::Require2D(right, typename right_traits::size_tag());
00259
00260
00261 typedef typename detail::DotPromote<
00262 LeftT,RightT>::promoted_scalar result_type;
00263
00264
00265 return result_type(left[0]*right[1]-left[1]*right[0]);
00266 }
00267
00268 template<typename LeftT, typename RightT>
00269 inline typename detail::CrossPromote<LeftT,RightT>::promoted_vector
00270 cross(const LeftT& left, const RightT& right)
00271 {
00272
00273 typedef et::ExprTraits<LeftT> left_traits;
00274 typedef et::ExprTraits<RightT> right_traits;
00275 typedef typename left_traits::result_tag left_result;
00276 typedef typename right_traits::result_tag right_result;
00277
00278
00279 CML_STATIC_REQUIRE_M(
00280 (same_type<left_result, et::vector_result_tag>::is_true
00281 && same_type<right_result, et::vector_result_tag>::is_true),
00282 cross_expects_vector_args_error);
00283
00284
00285
00286
00287
00288 detail::Require3D(left, typename left_traits::size_tag());
00289 detail::Require3D(right, typename right_traits::size_tag());
00290
00291
00292 typedef typename detail::CrossPromote<
00293 LeftT,RightT>::promoted_vector result_type;
00294
00295
00296 result_type result(
00297 left[1]*right[2] - left[2]*right[1],
00298 left[2]*right[0] - left[0]*right[2],
00299 left[0]*right[1] - left[1]*right[0]
00300 );
00301 return result;
00302 }
00303
00310 template < class VecT_1, class VecT_2, class VecT_3 >
00311 typename detail::DotPromote<
00312 VecT_1, typename detail::CrossPromote< VecT_2, VecT_3 >::promoted_vector
00313 >::promoted_scalar
00314 triple_product(const VecT_1& v1, const VecT_2& v2, const VecT_3& v3) {
00315 return dot(v1,cross(v2,v3));
00316 }
00317
00318 template<typename LeftT, typename RightT>
00319 inline typename detail::OuterPromote<LeftT,RightT>::promoted_matrix
00320 outer(const LeftT& left, const RightT& right)
00321 {
00322
00323 typedef et::ExprTraits<LeftT> left_traits;
00324 typedef et::ExprTraits<RightT> right_traits;
00325 typedef typename left_traits::result_tag left_result;
00326 typedef typename right_traits::result_tag right_result;
00327
00328
00329 CML_STATIC_REQUIRE_M(
00330 (same_type<left_result, et::vector_result_tag>::is_true
00331 && same_type<right_result, et::vector_result_tag>::is_true),
00332 dot_expects_vector_args_error);
00333
00334
00335
00336
00337
00338
00339
00340 typename detail::OuterPromote<LeftT,RightT>::promoted_matrix C;
00341 cml::et::detail::Resize(C, left.size(), right.size());
00342
00343
00344 for(size_t i = 0; i < left.size(); ++i) {
00345 for(size_t j = 0; j < right.size(); ++j) {
00346 C(i,j) = left[i]*right[j];
00347
00348
00349
00350 }
00351 }
00352
00353 return C;
00354 }
00355
00356 }
00357
00358 #endif
00359
00360
00361