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 *-----------------------------------------------------------------------*/
10 * @brief Vector linear expression classes.
17 #include <cml/et/size_checking.h>
18 #include <cml/vector/vector_traits.h>
19 #include <cml/vector/vector_promotions.h>
21 /* XXX Don't know which it should be just yet, since RVO seems to obviate need
22 * for a reference type. However, copy by value copies the *entire expression
23 * tree rooted at the VectorXpr<>, so this choice is bound to affect
24 * performace for some compiler or another:
26 #define VECXPR_ARG_TYPE const et::VectorXpr<XprT>&
27 #define VECXPR_ARG_TYPE_N(_N_) const et::VectorXpr<XprT##_N_>&
29 //#define VECXPR_ARG_TYPE const et::VectorXpr<XprT>
30 //#define VECXPR_ARG_TYPE_N(_N_) const et::VectorXpr<XprT##_N_>
35 /** A placeholder for a vector expression in an expression tree. */
41 typedef VectorXpr
<ExprT
> expr_type
;
43 /* Record ary-ness of the expression: */
44 typedef typename
ExprT::expr_ary expr_ary
;
46 /* Copy the expression by value into higher-up expressions: */
47 typedef expr_type expr_const_reference
;
49 typedef typename
ExprT::value_type value_type
;
50 typedef vector_result_tag result_tag
;
51 typedef typename
ExprT::size_tag size_tag
;
53 /* Store the expression traits: */
54 typedef ExprTraits
<ExprT
> expr_traits
;
56 /* Get the reference type: */
57 typedef typename
expr_traits::const_reference expr_reference
;
59 /* Get the result type: */
60 typedef typename
expr_traits::result_type result_type
;
62 /* For matching by assignability: */
63 typedef cml::et::not_assignable_tag assignable_tag
;
65 /* Get the temporary type: */
66 typedef typename
result_type::temporary_type temporary_type
;
71 /** Record result size as an enum. */
72 enum { array_size
= ExprT::array_size
};
77 /** Return square of the length. */
78 value_type
length_squared() const {
79 return m_expr
.length_squared();
82 /** Return the length. */
83 value_type
length() const {
84 return m_expr
.length();
87 /** Return the result as a normalized vector. */
88 result_type
normalize() const {
89 return m_expr
.normalize();
92 /** Compute value at index i of the result vector. */
93 value_type
operator[](size_t i
) const {
100 /** Return size of this expression (same as subexpression's size). */
101 size_t size() const {
102 return m_expr
.size();
105 /** Return reference to contained expression. */
106 expr_reference
expression() const { return m_expr
; }
111 /** Construct from the subexpression to store. */
112 explicit VectorXpr(expr_reference expr
) : m_expr(expr
) {}
114 /** Copy constructor. */
115 VectorXpr(const expr_type
& e
) : m_expr(e
.m_expr
) {}
120 expr_reference m_expr
;
125 /* Cannot be assigned to: */
126 expr_type
& operator=(const expr_type
&);
129 /** Expression traits class for VectorXpr<>. */
130 template<class ExprT
>
131 struct ExprTraits
< VectorXpr
<ExprT
> >
133 typedef VectorXpr
<ExprT
> expr_type
;
134 typedef ExprT arg_type
;
135 typedef typename
expr_type::value_type value_type
;
136 typedef typename
expr_type::expr_const_reference const_reference
;
137 typedef typename
expr_type::result_tag result_tag
;
138 typedef typename
expr_type::size_tag size_tag
;
139 typedef typename
expr_type::result_type result_type
;
140 typedef typename
expr_type::assignable_tag assignable_tag
;
141 typedef expr_node_tag node_tag
;
143 value_type
get(const expr_type
& v
, size_t i
) const { return v
[i
]; }
144 size_t size(const expr_type
& e
) const { return e
.size(); }
148 /** A unary vector expression.
150 * The operator's operator() method must take exactly one argument.
152 template<class ExprT
, class OpT
>
157 typedef UnaryVectorOp
<ExprT
,OpT
> expr_type
;
159 /* Record ary-ness of the expression: */
160 typedef unary_expression expr_ary
;
162 /* Copy the expression by value into higher-up expressions: */
163 typedef expr_type expr_const_reference
;
165 typedef typename
OpT::value_type value_type
;
166 typedef vector_result_tag result_tag
;
167 typedef typename
ExprT::size_tag size_tag
;
169 /* Store the expression traits for the subexpression: */
170 typedef ExprTraits
<ExprT
> expr_traits
;
172 /* Reference type for the subexpression: */
173 typedef typename
expr_traits::const_reference expr_reference
;
175 /* Get the result type (same as for subexpression): */
176 typedef typename
expr_traits::result_type result_type
;
178 /* For matching by assignability: */
179 typedef cml::et::not_assignable_tag assignable_tag
;
181 /* Get the temporary type: */
182 typedef typename
result_type::temporary_type temporary_type
;
187 /** Record result size as an enum. */
188 enum { array_size
= ExprT::array_size
};
193 /** Return square of the length. */
194 value_type
length_squared() const {
196 VectorXpr
<expr_type
>(*this),
197 VectorXpr
<expr_type
>(*this));
200 /** Return the length. */
201 value_type
length() const {
202 return std::sqrt(length_squared());
205 /** Return the result as a normalized vector. */
206 result_type
normalize() const {
207 result_type
v(VectorXpr
<expr_type
>(*this));
208 return v
.normalize();
211 /** Compute value at index i of the result vector. */
212 value_type
operator[](size_t i
) const {
214 /* This uses the expression traits to figure out how to access the
215 * i'th index of the subexpression:
217 return OpT().apply(expr_traits().get(m_expr
,i
));
223 /** Return size of this expression (same as argument's size). */
224 size_t size() const {
225 return m_expr
.size();
228 /** Return reference to contained expression. */
229 expr_reference
expression() const { return m_expr
; }
234 /** Construct from the subexpression. */
235 explicit UnaryVectorOp(expr_reference expr
) : m_expr(expr
) {}
237 /** Copy constructor. */
238 UnaryVectorOp(const expr_type
& e
) : m_expr(e
.m_expr
) {}
243 expr_reference m_expr
;
248 /* Cannot be assigned to: */
249 expr_type
& operator=(const expr_type
&);
252 /** Expression traits class for UnaryVectorOp<>. */
253 template<class ExprT
, class OpT
>
254 struct ExprTraits
< UnaryVectorOp
<ExprT
,OpT
> >
256 typedef UnaryVectorOp
<ExprT
,OpT
> expr_type
;
257 typedef ExprT arg_type
;
259 typedef typename
expr_type::value_type value_type
;
260 typedef typename
expr_type::expr_const_reference const_reference
;
261 typedef typename
expr_type::result_tag result_tag
;
262 typedef typename
expr_type::size_tag size_tag
;
263 typedef typename
expr_type::result_type result_type
;
264 typedef typename
expr_type::assignable_tag assignable_tag
;
265 typedef expr_node_tag node_tag
;
267 value_type
get(const expr_type
& v
, size_t i
) const { return v
[i
]; }
268 size_t size(const expr_type
& e
) const { return e
.size(); }
272 /** A binary vector expression.
274 * The operator's operator() method must take exactly two arguments.
276 template<class LeftT
, class RightT
, class OpT
>
281 typedef BinaryVectorOp
<LeftT
,RightT
,OpT
> expr_type
;
283 /* Record ary-ness of the expression: */
284 typedef binary_expression expr_ary
;
286 /* Copy the expression by value into higher-up expressions: */
287 typedef expr_type expr_const_reference
;
289 typedef typename
OpT::value_type value_type
;
290 typedef vector_result_tag result_tag
;
292 /* Store the expression traits types for the two subexpressions: */
293 typedef ExprTraits
<LeftT
> left_traits
;
294 typedef ExprTraits
<RightT
> right_traits
;
296 /* Reference types for the two subexpressions: */
297 typedef typename
left_traits::const_reference left_reference
;
298 typedef typename
right_traits::const_reference right_reference
;
300 /* Figure out the expression's resulting (vector) type: */
301 typedef typename
left_traits::result_type left_result
;
302 typedef typename
right_traits::result_type right_result
;
303 typedef typename VectorPromote
<left_result
,right_result
>::type result_type
;
304 typedef typename
result_type::size_tag size_tag
;
306 /* For matching by assignability: */
307 typedef cml::et::not_assignable_tag assignable_tag
;
309 /* Get the temporary type: */
310 typedef typename
result_type::temporary_type temporary_type
;
312 /* Define a size checker: */
313 typedef GetCheckedSize
<LeftT
,RightT
,size_tag
> checked_size
;
318 /** Record result size as an enum (if applicable). */
319 enum { array_size
= result_type::array_size
};
324 /** Return square of the length. */
325 value_type
length_squared() const {
327 VectorXpr
<expr_type
>(*this),
328 VectorXpr
<expr_type
>(*this));
331 /** Return the length. */
332 value_type
length() const {
333 return std::sqrt(length_squared());
336 /** Return the result as a normalized vector. */
337 result_type
normalize() const {
338 result_type
v(VectorXpr
<expr_type
>(*this));
339 return v
.normalize();
342 /** Compute value at index i of the result vector. */
343 value_type
operator[](size_t i
) const {
345 /* This uses the expression traits to figure out how to access the
346 * i'th index of the two subexpressions:
349 left_traits().get(m_left
,i
),
350 right_traits().get(m_right
,i
));
356 /** Return the size of the vector result.
358 * @throws std::invalid_argument if the expressions do not have the same
361 size_t size() const {
362 /* Note: This actually does a check only if
363 * CML_CHECK_VECTOR_EXPR_SIZES is set:
365 return CheckedSize(m_left
,m_right
,size_tag());
368 /** Return reference to left expression. */
369 left_reference
left_expression() const { return m_left
; }
371 /** Return reference to right expression. */
372 right_reference
right_expression() const { return m_right
; }
377 /** Construct from the two subexpressions. */
378 explicit BinaryVectorOp(left_reference left
, right_reference right
)
379 : m_left(left
), m_right(right
) {}
381 /** Copy constructor. */
382 BinaryVectorOp(const expr_type
& e
)
383 : m_left(e
.m_left
), m_right(e
.m_right
) {}
388 left_reference m_left
;
389 right_reference m_right
;
394 /* This ensures that a compile-time size check is executed: */
395 typename
checked_size::check_type _dummy
;
400 /* Cannot be assigned to: */
401 expr_type
& operator=(const expr_type
&);
404 /** Expression traits class for BinaryVectorOp<>. */
405 template<class LeftT
, class RightT
, class OpT
>
406 struct ExprTraits
< BinaryVectorOp
<LeftT
,RightT
,OpT
> >
408 typedef BinaryVectorOp
<LeftT
,RightT
,OpT
> expr_type
;
409 typedef LeftT left_type
;
410 typedef RightT right_type
;
412 typedef typename
expr_type::value_type value_type
;
413 typedef typename
expr_type::expr_const_reference const_reference
;
414 typedef typename
expr_type::result_tag result_tag
;
415 typedef typename
expr_type::size_tag size_tag
;
416 typedef typename
expr_type::result_type result_type
;
417 typedef typename
expr_type::assignable_tag assignable_tag
;
418 typedef expr_node_tag node_tag
;
420 value_type
get(const expr_type
& v
, size_t i
) const { return v
[i
]; }
421 size_t size(const expr_type
& e
) const { return e
.size(); }
424 /* Helper struct to verify that both arguments are vector expressions: */
425 template<typename LeftTraits
, typename RightTraits
>
426 struct VectorExpressions
428 /* Require that both arguments are vector expressions: */
429 typedef typename
LeftTraits::result_tag left_result
;
430 typedef typename
RightTraits::result_tag right_result
;
431 enum { is_true
= (same_type
<left_result
,et::vector_result_tag
>::is_true
432 && same_type
<right_result
,et::vector_result_tag
>::is_true
) };
437 template<typename VecT
, typename RT
, typename MT
> inline
438 void Resize(VecT
&,size_t,RT
,MT
) {}
440 template<typename VecT
> inline
441 void Resize(VecT
& v
, size_t S
, resizable_tag
, dynamic_memory_tag
) {
445 template<typename VecT
> inline
446 void Resize(VecT
& v
, size_t S
) {
447 Resize(v
, S
, typename
VecT::resizing_tag(), typename
VecT::memory_tag());
450 } // namespace detail
457 // -------------------------------------------------------------------------