EllAlgo 1.6.13
Loading...
Searching...
No Matches
arr.hpp
Go to the documentation of this file.
1
9#pragma once
10
11#include <cassert>
12#include <cmath>
13#include <cstdint> // for SIZE_MAX
14#include <initializer_list>
15#include <numeric>
16#include <utility>
17#include <vector>
18
19// ---------------------------------------------------------------------------
20// Arr — 1D or 2D array backed by std::vector<double>
21// ---------------------------------------------------------------------------
23class Arr {
24 public:
25 using value_type = double;
26
28 Arr() = default;
29
31 explicit Arr(size_t n) : _data(n, 0.0), _rows(n) {}
33 Arr(size_t r, size_t c) : _data(r * c, 0.0), _rows(r), _cols(c) {}
35 Arr(size_t r, size_t c, double val) : _data(r * c, val), _rows(r), _cols(c) {}
36 // Note: Arr(size_t, double) removed to avoid ambiguity with Arr(size_t, size_t).
37 // Use Arr(n) / zeros(n) for zero-initialized 1D arrays.
39 Arr(std::initializer_list<double> il) : _data(il), _rows(il.size()) {}
41 explicit Arr(std::vector<double> v) : _data(std::move(v)), _rows(_data.size()) {}
42
44 double& operator()(size_t i) { return _data[i]; }
46 const double& operator()(size_t i) const { return _data[i]; }
48 double& operator()(size_t i, size_t j) { return _data[i * _cols + j]; }
50 const double& operator()(size_t i, size_t j) const { return _data[i * _cols + j]; }
52 double& operator[](size_t i) { return _data[i]; }
54 const double& operator[](size_t i) const { return _data[i]; }
55
57 size_t size() const { return _data.size(); }
59 size_t rows() const { return _rows; }
61 size_t cols() const { return _cols; }
63 bool is_2d() const { return _cols > 0; }
65 double* data() { return _data.data(); }
67 const double* data() const { return _data.data(); }
69 auto begin() { return _data.begin(); }
71 auto begin() const { return _data.begin(); }
73 auto end() { return _data.end(); }
75 auto end() const { return _data.end(); }
76
78 Arr& operator+=(double s) {
79 for (auto& v : _data) v += s;
80 return *this;
81 }
83 Arr& operator-=(double s) {
84 for (auto& v : _data) v -= s;
85 return *this;
86 }
88 Arr& operator*=(double s) {
89 for (auto& v : _data) v *= s;
90 return *this;
91 }
93 Arr& operator+=(const Arr& other) {
94 assert(_data.size() == other._data.size());
95 for (size_t i = 0; i < _data.size(); ++i) _data[i] += other._data[i];
96 return *this;
97 }
99 Arr& operator-=(const Arr& other) {
100 assert(_data.size() == other._data.size());
101 for (size_t i = 0; i < _data.size(); ++i) _data[i] -= other._data[i];
102 return *this;
103 }
104
105 private:
106 std::vector<double> _data;
107 size_t _rows = 0;
108 size_t _cols = 0;
109};
110
111// ---------------------------------------------------------------------------
112// Range helper
113// ---------------------------------------------------------------------------
115struct Range {
116 size_t start = 0;
117 size_t end = 0;
118 size_t step = 1;
119
121 Range() = default;
123 explicit Range(size_t end) : end(end) {}
125 Range(size_t start, size_t end) : start(start), end(end) {}
127 Range(size_t start, size_t end, size_t step) : start(start), end(end), step(step) {}
129 static constexpr size_t ALL = SIZE_MAX;
130};
131
133inline constexpr size_t ALL = Range::ALL;
134
135// ---------------------------------------------------------------------------
136// View
137// ---------------------------------------------------------------------------
143inline Arr view(const Arr& a, const Range& rows, const Range& cols) {
144 assert(a.is_2d());
145 auto rs = rows.start;
146 auto re = (rows.end == Range::ALL) ? a.rows() : rows.end;
147 auto cs = cols.start;
148 auto ce = (cols.end == Range::ALL) ? a.cols() : cols.end;
149 auto rstep = rows.step;
150 auto cstep = cols.step;
151 size_t out_r = (re - rs + rstep - 1) / rstep;
152 size_t out_c = (ce - cs + cstep - 1) / cstep;
153 Arr out(out_r, out_c);
154 for (size_t i = 0; i < out_r; ++i)
155 for (size_t j = 0; j < out_c; ++j) out(i, j) = a(rs + i * rstep, cs + j * cstep);
156 return out;
157}
158
163inline Arr view(const Arr& a, const Range& rows) {
164 if (!a.is_2d()) {
165 auto s = rows.start;
166 auto e = (rows.end == Range::ALL) ? a.size() : rows.end;
167 auto step = rows.step;
168 size_t n = (e - s + step - 1) / step;
169 Arr out(n);
170 for (size_t i = 0; i < n; ++i) out(i) = a(s + i * step);
171 return out;
172 }
173 return view(a, rows, Range(Range::ALL));
174}
175
176// ---------------------------------------------------------------------------
177// Builder functions
178// ---------------------------------------------------------------------------
180inline Arr zeros(size_t n) {
181 Arr a(n);
182 return a;
183}
185inline Arr zeros(size_t r, size_t c) { return Arr(r, c); }
187inline Arr ones(size_t r, size_t c) { return Arr(r, c, 1.0); }
188
199inline Arr linspace(double start, double end, size_t n) {
200 Arr out(n);
201 if (n == 0) return out;
202 if (n == 1) {
203 out(0) = start;
204 return out;
205 }
206 double step = (end - start) / static_cast<double>(n - 1);
207 for (size_t i = 0; i < n; ++i) out(i) = start + step * static_cast<double>(i);
208 return out;
209}
210
213inline Arr arange(double start, double end) {
214 size_t n = (end > start) ? static_cast<size_t>(end - start) : 0;
215 Arr out(n);
216 for (size_t i = 0; i < n; ++i) out(i) = start + static_cast<double>(i);
217 return out;
218}
219
221inline Arr make_same_shape(const Arr& a) {
222 return a.is_2d() ? Arr(a.rows(), a.cols()) : Arr(a.rows());
223}
224
225// ---------------------------------------------------------------------------
226// Element-wise math
227// ---------------------------------------------------------------------------
229inline Arr cos(const Arr& a) {
230 Arr o = make_same_shape(a);
231 for (size_t i = 0; i < a.size(); ++i) o(i) = std::cos(a(i));
232 return o;
233}
235inline Arr log(const Arr& a) {
236 Arr o = make_same_shape(a);
237 for (size_t i = 0; i < a.size(); ++i) o(i) = std::log(a(i));
238 return o;
239}
241inline Arr abs(const Arr& a) {
242 Arr o = make_same_shape(a);
243 for (size_t i = 0; i < a.size(); ++i) o(i) = std::abs(a(i));
244 return o;
245}
247inline Arr exp(const Arr& a) {
248 Arr o = make_same_shape(a);
249 for (size_t i = 0; i < a.size(); ++i) o(i) = std::exp(a(i));
250 return o;
251}
253inline Arr sqrt(const Arr& a) {
254 Arr o = make_same_shape(a);
255 for (size_t i = 0; i < a.size(); ++i) o(i) = std::sqrt(a(i));
256 return o;
257}
258
260inline double sum(const Arr& a) { return std::accumulate(a.begin(), a.end(), 0.0); }
261
262// ---------------------------------------------------------------------------
263// where
264// ---------------------------------------------------------------------------
268inline std::vector<Arr> where(const Arr& condition) {
269 assert(!condition.is_2d());
270 std::vector<size_t> idx;
271 for (size_t i = 0; i < condition.size(); ++i)
272 if (condition(i) != 0.0) idx.push_back(i);
273 Arr indices(idx.size());
274 for (size_t i = 0; i < idx.size(); ++i) indices(i) = static_cast<double>(idx[i]);
275 return {indices};
276}
277
278// ---------------------------------------------------------------------------
279// Linear algebra
280// ---------------------------------------------------------------------------
289inline Arr dot(const Arr& A, const Arr& x) {
290 assert(A.is_2d() && !x.is_2d() && A.cols() == x.size());
291 Arr out(A.rows());
292 for (size_t i = 0; i < A.rows(); ++i) {
293 double s = 0.0;
294 for (size_t j = 0; j < A.cols(); ++j) s += A(i, j) * x(j);
295 out(i) = s;
296 }
297 return out;
298}
299
308inline Arr outer(const Arr& u, const Arr& v) {
309 assert(!u.is_2d() && !v.is_2d());
310 Arr out(u.size(), v.size());
311 for (size_t i = 0; i < u.size(); ++i)
312 for (size_t j = 0; j < v.size(); ++j) out(i, j) = u(i) * v(j);
313 return out;
314}
315
316// ---------------------------------------------------------------------------
317// concatenate (axis=1 only)
318// ---------------------------------------------------------------------------
323inline Arr concatenate(const Arr& a, const Arr& b, int /* axis */ = 1) {
324 assert(a.is_2d() && b.is_2d() && a.rows() == b.rows());
325 size_t m = a.rows();
326 size_t ca = a.cols();
327 size_t cb = b.cols();
328 Arr out(m, ca + cb);
329 for (size_t i = 0; i < m; ++i) {
330 for (size_t j = 0; j < ca; ++j) out(i, j) = a(i, j);
331 for (size_t j = 0; j < cb; ++j) out(i, ca + j) = b(i, j);
332 }
333 return out;
334}
335
336// ---------------------------------------------------------------------------
337// Arithmetic operators
338// ---------------------------------------------------------------------------
340inline Arr operator-(const Arr& a) {
341 Arr o = make_same_shape(a);
342 for (size_t i = 0; i < a.size(); ++i) o(i) = -a(i);
343 return o;
344}
346inline Arr operator+(const Arr& a, const Arr& b) {
347 assert(a.size() == b.size());
348 Arr o = make_same_shape(a);
349 for (size_t i = 0; i < a.size(); ++i) o(i) = a(i) + b(i);
350 return o;
351}
353inline Arr operator-(const Arr& a, const Arr& b) {
354 assert(a.size() == b.size());
355 Arr o = make_same_shape(a);
356 for (size_t i = 0; i < a.size(); ++i) o(i) = a(i) - b(i);
357 return o;
358}
360inline Arr operator*(const Arr& a, const Arr& b) {
361 assert(a.size() == b.size());
362 Arr o = make_same_shape(a);
363 for (size_t i = 0; i < a.size(); ++i) o(i) = a(i) * b(i);
364 return o;
365}
367inline Arr operator*(double s, const Arr& a) { return Arr(a) *= s; }
369inline Arr operator*(const Arr& a, double s) { return Arr(a) *= s; }
371inline Arr operator/(const Arr& a, double s) { return Arr(a) *= (1.0 / s); }
372
375inline Arr operator<=(const Arr& a, double s) {
376 Arr o = make_same_shape(a);
377 for (size_t i = 0; i < a.size(); ++i) o(i) = (a(i) <= s) ? 1.0 : 0.0;
378 return o;
379}
382inline Arr operator>=(const Arr& a, double s) {
383 Arr o = make_same_shape(a);
384 for (size_t i = 0; i < a.size(); ++i) o(i) = (a(i) >= s) ? 1.0 : 0.0;
385 return o;
386}
389inline Arr operator<(const Arr& a, double s) {
390 Arr o = make_same_shape(a);
391 for (size_t i = 0; i < a.size(); ++i) o(i) = (a(i) < s) ? 1.0 : 0.0;
392 return o;
393}
396inline Arr operator>(const Arr& a, double s) {
397 Arr o = make_same_shape(a);
398 for (size_t i = 0; i < a.size(); ++i) o(i) = (a(i) > s) ? 1.0 : 0.0;
399 return o;
400}
401
403inline Arr eval(Arr a) { return a; }
Arr ones(size_t r, size_t c)
Create 2D array of ones with r rows, c columns.
Definition arr.hpp:187
Arr dot(const Arr &A, const Arr &x)
Matrix-vector multiplication.
Definition arr.hpp:289
Arr cos(const Arr &a)
Element-wise cosine.
Definition arr.hpp:229
Arr zeros(size_t n)
Create zero-initialized 1D array of size n.
Definition arr.hpp:180
Arr operator<=(const Arr &a, double s)
Element-wise less-than-or-equal-to comparison with scalar.
Definition arr.hpp:375
Arr abs(const Arr &a)
Element-wise absolute value.
Definition arr.hpp:241
Arr operator>(const Arr &a, double s)
Element-wise greater-than comparison with scalar.
Definition arr.hpp:396
std::vector< Arr > where(const Arr &condition)
Find indices of non-zero elements.
Definition arr.hpp:268
constexpr size_t ALL
Convenience alias for Range::ALL.
Definition arr.hpp:133
double sum(const Arr &a)
Sum of all elements.
Definition arr.hpp:260
Arr arange(double start, double end)
Values from start to end-1 with step 1.
Definition arr.hpp:213
Arr operator-(const Arr &a)
Unary negation (element-wise)
Definition arr.hpp:340
Arr linspace(double start, double end, size_t n)
Linearly spaced values from start to end, inclusive.
Definition arr.hpp:199
Arr concatenate(const Arr &a, const Arr &b, int=1)
Concatenate two 2D arrays along columns (axis=1)
Definition arr.hpp:323
Arr operator*(const Arr &a, const Arr &b)
Element-wise multiplication of two arrays.
Definition arr.hpp:360
Arr make_same_shape(const Arr &a)
Create a zero-initialized Arr with the same shape as input.
Definition arr.hpp:221
Arr outer(const Arr &u, const Arr &v)
Outer product of two 1D vectors.
Definition arr.hpp:308
Arr exp(const Arr &a)
Element-wise exponential.
Definition arr.hpp:247
Arr eval(Arr a)
Identity function for Arr (for API compatibility)
Definition arr.hpp:403
Arr operator/(const Arr &a, double s)
Scalar division (array / scalar)
Definition arr.hpp:371
Arr operator<(const Arr &a, double s)
Element-wise less-than comparison with scalar.
Definition arr.hpp:389
Arr view(const Arr &a, const Range &rows, const Range &cols)
Extract a submatrix view from a 2D array using Range for rows and cols.
Definition arr.hpp:143
Arr operator+(const Arr &a, const Arr &b)
Element-wise addition of two arrays.
Definition arr.hpp:346
Arr sqrt(const Arr &a)
Element-wise square root.
Definition arr.hpp:253
Arr log(const Arr &a)
Element-wise natural logarithm.
Definition arr.hpp:235
Arr operator>=(const Arr &a, double s)
Element-wise greater-than-or-equal-to comparison with scalar.
Definition arr.hpp:382
1D or 2D array backed by std::vector<double> for small optimization problems
Definition arr.hpp:23
double * data()
Raw pointer to underlying data (mutable)
Definition arr.hpp:65
Arr(size_t n)
Construct 1D array of size n, zero-initialized.
Definition arr.hpp:31
Arr(std::initializer_list< double > il)
Construct from initializer list (1D)
Definition arr.hpp:39
bool is_2d() const
Whether this is a 2D array (cols > 0)
Definition arr.hpp:63
size_t cols() const
Number of columns (0 for 1D arrays)
Definition arr.hpp:61
const double & operator[](size_t i) const
1D element access (const)
Definition arr.hpp:54
Arr(size_t r, size_t c)
Construct 2D array with r rows, c columns, zero-initialized.
Definition arr.hpp:33
auto end() const
Iterator past the end (const)
Definition arr.hpp:75
const double & operator()(size_t i, size_t j) const
2D element access (const), row-major
Definition arr.hpp:50
auto end()
Iterator past the end (mutable)
Definition arr.hpp:73
Arr & operator-=(double s)
Subtract scalar from all elements.
Definition arr.hpp:83
Arr()=default
Default constructor (empty array)
const double * data() const
Raw pointer to underlying data (const)
Definition arr.hpp:67
double & operator()(size_t i)
1D element access (mutable)
Definition arr.hpp:44
size_t rows() const
Number of rows (1 for 1D arrays)
Definition arr.hpp:59
double & operator[](size_t i)
1D element access (mutable)
Definition arr.hpp:52
Arr(std::vector< double > v)
Construct from vector (1D)
Definition arr.hpp:41
auto begin()
Iterator to beginning (mutable)
Definition arr.hpp:69
const double & operator()(size_t i) const
1D element access (const)
Definition arr.hpp:46
double value_type
Definition arr.hpp:25
auto begin() const
Iterator to beginning (const)
Definition arr.hpp:71
Arr & operator*=(double s)
Multiply all elements by scalar.
Definition arr.hpp:88
Arr & operator-=(const Arr &other)
Element-wise subtraction with another Arr.
Definition arr.hpp:99
Arr(size_t r, size_t c, double val)
Construct 2D array with r rows, c columns, fill value val.
Definition arr.hpp:35
double & operator()(size_t i, size_t j)
2D element access (mutable), row-major
Definition arr.hpp:48
Arr & operator+=(double s)
Add scalar to all elements.
Definition arr.hpp:78
size_t size() const
Total number of elements.
Definition arr.hpp:57
Arr & operator+=(const Arr &other)
Element-wise addition with another Arr.
Definition arr.hpp:93
Index range [start, end) with step for slicing views.
Definition arr.hpp:115
size_t end
End index (exclusive)
Definition arr.hpp:117
size_t step
Step size.
Definition arr.hpp:118
Range()=default
Default range (empty)
static constexpr size_t ALL
Sentinel value meaning "all elements".
Definition arr.hpp:129
size_t start
Start index (inclusive)
Definition arr.hpp:116
Range(size_t start, size_t end, size_t step)
Range [start, end) with given step.
Definition arr.hpp:127
Range(size_t start, size_t end)
Range [start, end)
Definition arr.hpp:125
Range(size_t end)
Range from 0 to end.
Definition arr.hpp:123