PLSSVM - Parallel Least Squares Support Vector Machine  2.0.0
A Least Squares Support Vector Machine implementation using different backends.
operators.hpp
Go to the documentation of this file.
1 
12 #ifndef PLSSVM_DETAIL_OPERATORS_HPP_
13 #define PLSSVM_DETAIL_OPERATORS_HPP_
14 #pragma once
15 
16 #include "plssvm/detail/assert.hpp" // PLSSVM_ASSERT
17 
18 #include <cmath> // std::fma
19 #include <vector> // std::vector
20 
42 // clang-format off
43 #define PLSSVM_GENERATE_ARITHMETIC_OPERATION(Op) \
44  template <typename T> \
45  inline std::vector<T> &operator Op##=(std::vector<T> &lhs, const std::vector<T> &rhs) { \
46  PLSSVM_ASSERT(lhs.size() == rhs.size(), "Sizes mismatch!: {} != {}", lhs.size(), rhs.size()); \
47  \
48  _Pragma("omp simd") \
49  for (typename std::vector<T>::size_type i = 0; i < lhs.size(); ++i) { \
50  lhs[i] Op##= rhs[i]; \
51  } \
52  return lhs; \
53  } \
54  template <typename T> \
55  [[nodiscard]] inline std::vector<T> operator Op(std::vector<T> lhs, const std::vector<T> &rhs) { \
56  return lhs Op##= rhs; \
57  } \
58  template <typename T> \
59  inline std::vector<T> &operator Op##=(std::vector<T> &lhs, const T rhs) { \
60  _Pragma("omp simd") \
61  for (typename std::vector<T>::size_type i = 0; i < lhs.size(); ++i) { \
62  lhs[i] Op##= rhs; \
63  } \
64  return lhs; \
65  } \
66  template <typename T> \
67  [[nodiscard]] inline std::vector<T> operator Op(std::vector<T> lhs, const T rhs) { \
68  return lhs Op##= rhs; \
69  } \
70  template <typename T> \
71  [[nodiscard]] inline std::vector<T> operator Op(const T lhs, std::vector<T> rhs) { \
72  _Pragma("omp simd") \
73  for (typename std::vector<T>::size_type i = 0; i < rhs.size(); ++i) { \
74  rhs[i] = lhs Op rhs[i]; \
75  } \
76  return rhs; \
77  }
78 // clang-format on
79 
80 namespace plssvm::operators {
81 
82 // define arithmetic operations +-*/ on std::vector
87 
88 
98 template <typename T>
99 struct transposed {
101  const std::vector<T> &vec;
102 };
106 template <typename T>
107 transposed(const std::vector<T> &) -> transposed<T>;
108 
117 template <typename T>
118 [[nodiscard]] inline T operator*(const transposed<T> &lhs, const std::vector<T> &rhs) {
119  PLSSVM_ASSERT(lhs.vec.size() == rhs.size(), "Sizes mismatch!: {} != {}", lhs.vec.size(), rhs.size());
120 
121  T val{};
122  for (typename std::vector<T>::size_type i = 0; i < lhs.vec.size(); ++i) {
123  val = std::fma(lhs.vec[i], rhs[i], val);
124  }
125  return val;
126 }
127 
131 template <typename T>
132 [[nodiscard]] inline T dot(const std::vector<T> &lhs, const std::vector<T> &rhs) {
133  return transposed{ lhs } * rhs;
134 }
135 
143 template <typename T>
144 [[nodiscard]] inline T sum(const std::vector<T> &vec) {
145  T val{};
146  #pragma omp simd reduction(+ : val)
147  for (typename std::vector<T>::size_type i = 0; i < vec.size(); ++i) {
148  val += vec[i];
149  }
150  return val;
151 }
152 
161 template <typename T>
162 [[nodiscard]] inline T squared_euclidean_dist(const std::vector<T> &lhs, const std::vector<T> &rhs) {
163  PLSSVM_ASSERT(lhs.size() == rhs.size(), "Sizes mismatch!: {} != {}", lhs.size(), rhs.size());
164 
165  T val{};
166  for (typename std::vector<T>::size_type i = 0; i < lhs.size(); ++i) {
167  const T diff = lhs[i] - rhs[i];
168  val = std::fma(diff, diff, val);
169  }
170  return val;
171 }
172 
178 template <typename T>
179 [[nodiscard]] inline constexpr T sign(const T x) {
180  return x > T{ 0 } ? T{ +1 } : T{ -1 };
181 }
182 
183 #undef PLSSVM_GENERATE_ARITHMETIC_OPERATION
184 
185 } // namespace plssvm::operators
186 
187 #endif // PLSSVM_DETAIL_OPERATORS_HPP_
Implements a custom assert macro PLSSVM_ASSERT.
#define PLSSVM_ASSERT(cond, msg,...)
Defines the PLSSVM_ASSERT macro if PLSSVM_ASSERT_ENABLED is defined.
Definition: assert.hpp:74
Namespace containing operator overloads for std::vector and other mathematical functions on vectors.
Definition: core.hpp:49
constexpr T sign(const T x)
Returns +1 if x is positive and -1 if x is negative or 0.
Definition: operators.hpp:179
T dot(const std::vector< T > &lhs, const std::vector< T > &rhs)
Calculate the dot product ( ) between both std::vector.
Definition: operators.hpp:132
T sum(const std::vector< T > &vec)
Accumulate all elements in the std::vector vec.
Definition: operators.hpp:144
T squared_euclidean_dist(const std::vector< T > &lhs, const std::vector< T > &rhs)
Calculates the squared Euclidean distance of both vectors: .
Definition: operators.hpp:162
T operator*(const transposed< T > &lhs, const std::vector< T > &rhs)
Calculate the dot product ( ) between both std::vector.
Definition: operators.hpp:118
transposed(const std::vector< T > &) -> transposed< T >
Deduction guide for the plssvm::operators::transposed struct needed for C++17.
#define PLSSVM_GENERATE_ARITHMETIC_OPERATION(Op)
Generate arithmetic element-wise operations using Op for std::vector (and scalars).
Definition: operators.hpp:43
Wrapper struct for overloading the dot product operator.
Definition: operators.hpp:99
const std::vector< T > & vec
The encapsulated vector.
Definition: operators.hpp:101