2 // Copyright 2013 Francisco Jerez
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:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
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.
23 #ifndef CLOVER_UTIL_ALGEBRA_HPP
24 #define CLOVER_UTIL_ALGEBRA_HPP
26 #include <type_traits>
28 #include "util/range.hpp"
29 #include "util/functional.hpp"
33 /// Class that identifies vectors (in the linear-algebraic sense).
35 /// There should be a definition of this class for each type that
36 /// makes sense as vector arithmetic operand.
38 template<typename V, typename = void>
42 /// References of vectors are vectors.
45 struct vector_traits<T &, typename vector_traits<T>::enable> {
50 /// Constant vectors are vectors.
53 struct vector_traits<const T, typename vector_traits<T>::enable> {
58 /// Arrays of arithmetic types are vectors.
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> {
68 template<typename... Ts>
75 /// The result of mapping a vector is a vector.
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> {
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>
91 operator+(U &&u, V &&v) {
92 return map(plus(), std::forward<U>(u), std::forward<V>(v));
96 /// Vector difference.
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>
102 operator-(U &&u, V &&v) {
103 return map(minus(), std::forward<U>(u), std::forward<V>(v));
107 /// Scalar multiplication.
109 template<typename U, typename T,
110 typename = typename vector_traits<U>::enable>
111 adaptor_range<multiplies_by_t<T>, U>
112 operator*(U &&u, T &&a) {
113 return map(multiplies_by<T>(std::forward<T>(a)), std::forward<U>(u));
117 /// Scalar multiplication.
119 template<typename U, typename T,
120 typename = typename vector_traits<U>::enable>
121 adaptor_range<multiplies_by_t<T>, U>
122 operator*(T &&a, U &&u) {
123 return map(multiplies_by<T>(std::forward<T>(a)), std::forward<U>(u));
127 /// Additive inverse.
130 typename = typename vector_traits<U>::enable>
131 adaptor_range<negate, U>
133 return map(negate(), std::forward<U>(u));
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
145 /// Dot product of two vectors.
147 /// It can also do matrix multiplication if \a u or \a v is a
148 /// vector of vectors.
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>
155 return fold(plus(), detail::dot_type<U, V>(),
156 map(multiplies(), u, v));