NumericAL
A header-only C++20 lexer built on REAL
Loading...
Searching...
No Matches
vector.hpp
Go to the documentation of this file.
1
11#ifndef NUMERICAL_VECTOR_HPP
12#define NUMERICAL_VECTOR_HPP
13
14#include <algorithm>
15#include <cmath>
16#include <complex> // so std::abs resolves for a complex scalar, regardless of include order
17#include <cstddef>
18#include <functional>
19#include <initializer_list>
20#include <limits>
21#include <memory>
22#include <numeric>
23#include <stdexcept>
24#include <string>
25#include <type_traits>
26#include <utility>
27#include <vector>
28
29#include "buffer.hpp"
30
31namespace numerical {
32
34 class dimension_error : public std::runtime_error
35 {
36 public:
37
39 explicit dimension_error(const std::string& message)
40 : std::runtime_error(message)
41 {}
42 };
43
44 namespace detail {
45
50 [[nodiscard]] inline std::size_t checked_mul(std::size_t a,
51 std::size_t b)
52 {
53 if (a != 0 && b > (std::numeric_limits<std::size_t>::max() / a)) {
54 throw dimension_error("dimension product overflows std::size_t");
55 }
56 return a * b;
57 }
58
65 template <typename It>
66 [[nodiscard]] std::size_t element_count(It first,
67 It last)
68 {
69 if (std::find(first, last, std::size_t {0}) != last) {
70 return 0;
71 }
72 std::size_t count {1};
73 for (; first != last; ++first) {
74 count = checked_mul(count, *first);
75 }
76 return count;
77 }
78 } // namespace detail
79
84 template <typename T>
85 class vector
86 {
87 public:
88
90 vector() = default;
91
93 vector(std::initializer_list<T> elements)
94 : data_(elements)
95 {}
96
98 explicit vector(buffer<T> elements)
99 : data_(std::move(elements))
100 {}
101
104 explicit vector(const std::vector<T>& elements)
105 : data_(elements.begin(), elements.end())
106 {}
107
109 [[nodiscard]] std::size_t size() const noexcept
110 {
111 return data_.size();
112 }
113
115 [[nodiscard]] const T& operator[](std::size_t index) const
116 {
117 return data_[index];
118 }
119
122 {
123 return data_.begin();
124 }
125
128 {
129 return data_.end();
130 }
131
133 [[nodiscard]] bool operator==(const vector& other) const
134 {
135 return data_ == other.data_;
136 }
137
138 private:
139
141 };
142
144 template <typename T>
146 const vector<T>& b)
147 {
148 if (a.size() != b.size()) {
149 throw dimension_error("vector sizes differ in '+'");
150 }
151 buffer<T> out(a.size());
152 std::transform(a.begin(), a.end(), b.begin(), out.begin(), std::plus<T> {});
153 return vector<T> {std::move(out)};
154 }
155
157 template <typename T>
159 const vector<T>& b)
160 {
161 if (a.size() != b.size()) {
162 throw dimension_error("vector sizes differ in '-'");
163 }
164 buffer<T> out(a.size());
165 std::transform(a.begin(), a.end(), b.begin(), out.begin(), std::minus<T> {});
166 return vector<T> {std::move(out)};
167 }
168
170 template <typename T>
171 [[nodiscard]] vector<T> operator*(const T& scalar,
172 const vector<T>& v)
173 {
174 buffer<T> out(v.size());
175 std::transform(v.begin(), v.end(), out.begin(),
176 [&scalar](const T& element) { return scalar * element; });
177 return vector<T> {std::move(out)};
178 }
179
181 template <typename T>
183 const T& scalar)
184 {
185 return scalar * v;
186 }
187
189 template <typename T>
190 [[nodiscard]] T dot(const vector<T>& a,
191 const vector<T>& b)
192 {
193 if (a.size() != b.size()) {
194 throw dimension_error("vector sizes differ in 'dot'");
195 }
196 // std::inner_product is sequential (left-to-right), so the reduction order —
197 // and thus the floating-point result — stays deterministic.
198 return std::inner_product(a.begin(), a.end(), b.begin(), T {});
199 }
200
208 template <typename T>
210 const vector<T>& b,
211 double tolerance = 1e-9)
212 {
213 if (a.size() != b.size()) {
214 return false;
215 }
216 for (std::size_t i {0}; i < a.size(); ++i) {
217 // Equal, or within the tolerance: a NaN is neither, so it is never close, and two equal
218 // infinities are equal although their difference is NaN.
219 if (!(a[i] == b[i]) && !(std::abs(a[i] - b[i]) <= tolerance)) {
220 return false;
221 }
222 }
223 return true;
224 }
225} // namespace numerical
226
227#endif // NUMERICAL_VECTOR_HPP
numerical::buffer, the storage of the library's vectors, matrices and tensors: a std::vector whose el...
Thrown when an operation's operands have incompatible shapes.
Definition vector.hpp:35
dimension_error(const std::string &message)
Builds the error.
Definition vector.hpp:39
A dense vector of T with value semantics.
Definition vector.hpp:86
vector(buffer< T > elements)
From an existing buffer.
Definition vector.hpp:98
buffer< T >::const_iterator end() const noexcept
Const iterator past the last element.
Definition vector.hpp:127
const T & operator[](std::size_t index) const
The element at index.
Definition vector.hpp:115
vector(const std::vector< T > &elements)
From a std::vector, copied into the storage (a buffer moves in instead).
Definition vector.hpp:104
bool operator==(const vector &other) const
Exact element-wise equality (same size, equal elements).
Definition vector.hpp:133
buffer< T > data_
The elements.
Definition vector.hpp:140
std::size_t size() const noexcept
The number of elements.
Definition vector.hpp:109
vector(std::initializer_list< T > elements)
From a braced list of elements.
Definition vector.hpp:93
buffer< T >::const_iterator begin() const noexcept
Const iterator to the first element.
Definition vector.hpp:121
vector()=default
An empty vector (size 0).
std::size_t checked_mul(std::size_t a, std::size_t b)
a * b, throwing numerical::dimension_error if the product overflows std::size_t. Guards dimension/sha...
Definition vector.hpp:50
std::size_t element_count(It first, It last)
The elements a shape's extents [first, last) hold: 0 where one of them is 0, whatever the others,...
Definition vector.hpp:66
The NumericAL public API.
Definition amx.hpp:44
std::vector< T, detail::default_init_allocator< T > > buffer
The storage of vector, matrix and tensor, namely a std::vector whose buffer<T>(n) and resize(n) leave...
Definition buffer.hpp:157
matrix< T > operator+(const matrix< T > &a, const matrix< T > &b)
Element-wise sum.
Definition matrix.hpp:161
T dot(const vector< T > &a, const vector< T > &b)
Dot product.
Definition vector.hpp:190
matrix< T > operator*(const T &scalar, const matrix< T > &m)
Scalar times matrix.
Definition matrix.hpp:187
@ amx
The Apple AMX coprocessor, fused multiply-adds; the products it does not suit on the NEON path's tile...
matrix< T > operator-(const matrix< T > &a, const matrix< T > &b)
Element-wise difference.
Definition matrix.hpp:174
bool approx_equal(const matrix< T > &a, const matrix< T > &b, double tolerance=1e-9)
Element-wise closeness within a tolerance (for inexact scalars).
Definition matrix.hpp:278