Home | History | Annotate | Download | only in util
      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>
     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>
    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>
    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>
    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>
    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>
    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