Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.