• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 
23 #ifndef CLOVER_UTIL_ALGEBRA_HPP
24 #define CLOVER_UTIL_ALGEBRA_HPP
25 
26 #include <type_traits>
27 
28 #include "util/range.hpp"
29 #include "util/functional.hpp"
30 
31 namespace clover {
32    ///
33    /// Class that identifies vectors (in the linear-algebraic sense).
34    ///
35    /// There should be a definition of this class for each type that
36    /// makes sense as vector arithmetic operand.
37    ///
38    template<typename V, typename = void>
39    struct vector_traits;
40 
41    ///
42    /// References of vectors are vectors.
43    ///
44    template<typename T>
45    struct vector_traits<T &, typename vector_traits<T>::enable> {
46       typedef void enable;
47    };
48 
49    ///
50    /// Constant vectors are vectors.
51    ///
52    template<typename T>
53    struct vector_traits<const T, typename vector_traits<T>::enable> {
54       typedef void enable;
55    };
56 
57    ///
58    /// Arrays of arithmetic types are vectors.
59    ///
60    template<typename T, std::size_t N>
61    struct vector_traits<std::array<T, N>,
62                         typename std::enable_if<
63                            std::is_arithmetic<T>::value>::type> {
64       typedef void enable;
65    };
66 
67    namespace detail {
68       template<typename... Ts>
69       struct are_defined {
70          typedef void enable;
71       };
72    }
73 
74    ///
75    /// The result of mapping a vector is a vector.
76    ///
77    template<typename F, typename... Vs>
78    struct vector_traits<adaptor_range<F, Vs...>,
79                         typename detail::are_defined<
80                            typename vector_traits<Vs>::enable...>::enable> {
81       typedef void enable;
82    };
83 
84    ///
85    /// Vector sum.
86    ///
87    template<typename U, typename V,
88             typename = typename vector_traits<U>::enable,
89             typename = typename vector_traits<V>::enable>
90    adaptor_range<plus, U, V>
operator +(U && u,V && v)91    operator+(U &&u, V &&v) {
92       return map(plus(), std::forward<U>(u), std::forward<V>(v));
93    }
94 
95    ///
96    /// Vector difference.
97    ///
98    template<typename U, typename V,
99             typename = typename vector_traits<U>::enable,
100             typename = typename vector_traits<V>::enable>
101    adaptor_range<minus, U, V>
operator -(U && u,V && v)102    operator-(U &&u, V &&v) {
103       return map(minus(), std::forward<U>(u), std::forward<V>(v));
104    }
105 
106    ///
107    /// Scalar multiplication.
108    ///
109    template<typename U, typename T,
110             typename = typename vector_traits<U>::enable>
111    adaptor_range<multiplies_by_t<T>, U>
operator *(U && u,T && a)112    operator*(U &&u, T &&a) {
113       return map(multiplies_by<T>(std::forward<T>(a)), std::forward<U>(u));
114    }
115 
116    ///
117    /// Scalar multiplication.
118    ///
119    template<typename U, typename T,
120             typename = typename vector_traits<U>::enable>
121    adaptor_range<multiplies_by_t<T>, U>
operator *(T && a,U && u)122    operator*(T &&a, U &&u) {
123       return map(multiplies_by<T>(std::forward<T>(a)), std::forward<U>(u));
124    }
125 
126    ///
127    /// Additive inverse.
128    ///
129    template<typename U,
130             typename = typename vector_traits<U>::enable>
131    adaptor_range<negate, U>
operator -(U && u)132    operator-(U &&u) {
133       return map(negate(), std::forward<U>(u));
134    }
135 
136    namespace detail {
137       template<typename U, typename V>
138       using dot_type = typename std::common_type<
139            typename std::remove_reference<U>::type::value_type,
140            typename std::remove_reference<V>::type::value_type
141          >::type;
142    }
143 
144    ///
145    /// Dot product of two vectors.
146    ///
147    /// It can also do matrix multiplication if \a u or \a v is a
148    /// vector of vectors.
149    ///
150    template<typename U, typename V,
151             typename = typename vector_traits<U>::enable,
152             typename = typename vector_traits<V>::enable>
153    detail::dot_type<U, V>
dot(U && u,V && v)154    dot(U &&u, V &&v) {
155       return fold(plus(), detail::dot_type<U, V>(),
156                   map(multiplies(), u, v));
157    }
158 }
159 
160 #endif
161