2#include "qip/Methods.hpp"
18template <
typename T,
typename... Args>
19std::vector<T>
merge(std::vector<T> first,
const std::vector<T> &second,
20 const Args &...rest) {
21 first.insert(first.end(), second.cbegin(), second.cend());
22 if constexpr (
sizeof...(rest) == 0) {
25 return merge(std::move(first), rest...);
41auto compare(
const std::vector<T> &first,
const std::vector<T> &second) {
43 std::is_arithmetic_v<T>,
44 "In compare(std::vector<T>, std::vector<T>), T must be arithmetic");
45 assert(first.size() == second.size());
47 auto it1 = first.cbegin();
48 auto it2 = second.cbegin();
49 auto largest_delta =
static_cast<T
>(0);
51 auto largest_at = first.cbegin();
52 for (; it1 != first.cend(); ++it1, ++it2) {
53 const auto delta = *it1 - *it2;
54 if (std::abs(delta) > std::abs(largest_delta)) {
55 largest_delta = delta;
59 return std::make_pair(largest_delta, largest_at);
69template <
typename T,
typename U,
typename Func>
70auto compare(
const std::vector<T> &first,
const std::vector<U> &second,
72 assert(first.size() == second.size());
74 auto it1 = first.cbegin();
75 auto it2 = second.cbegin();
76 auto largest_eps = 0.0;
77 auto largest_at = first.cend();
78 for (; it1 != first.cend(); ++it1, ++it2) {
79 const auto eps = func(*it1, *it2);
80 if (std::abs(eps) > std::abs(largest_eps)) {
85 return std::make_pair(largest_eps, largest_at);
97auto compare_eps(
const std::vector<T> &first,
const std::vector<T> &second) {
99 std::is_floating_point_v<T>,
100 "In compare_eps(std::vector<T>, std::vector<T>), T must be floating pt");
101 assert(first.size() == second.size());
103 auto it1 = first.cbegin();
104 auto it2 = second.cbegin();
105 auto largest_eps =
static_cast<T
>(0);
106 auto largest_at = first.cend();
107 for (; it1 != first.cend(); ++it1, ++it2) {
108 const auto eps = (*it1 - *it2) / (*it2);
109 if (std::abs(eps) > std::abs(largest_eps)) {
114 return std::make_pair(largest_eps, largest_at);
124template <
typename T,
typename... Args>
125void add(std::vector<T> *first,
const std::vector<T> &second,
126 const Args &...rest) {
128 if (first->size() < second.size())
129 first->resize(second.size());
131 for (std::size_t i = 0; i < second.size(); ++i) {
132 (*first)[i] += second[i];
134 if constexpr (
sizeof...(rest) != 0)
139template <
typename T,
typename... Args>
140[[nodiscard]] std::vector<T>
141add(std::vector<T> first,
const std::vector<T> &second,
const Args &...rest) {
142 add(&first, second, rest...);
154template <
typename T,
typename... Args>
155void multiply(std::vector<T> *first,
const std::vector<T> &second,
156 const Args &...rest) {
158 static_assert(std::is_arithmetic_v<T>,
159 "In multiply(std::vector<T>...) : T must be arithmetic");
162 const auto size = std::min(first->size(), second.size());
163 if (first->size() < second.size())
164 first->resize(second.size());
166 for (std::size_t i = 0; i < size; ++i) {
167 (*first)[i] *= second[i];
169 for (std::size_t i = size; i < first->size(); ++i) {
170 (*first)[i] =
static_cast<T
>(0);
172 if constexpr (
sizeof...(rest) != 0)
177template <
typename T,
typename... Args>
178[[nodiscard]] std::vector<T>
multiply(std::vector<T> first,
179 const std::vector<T> &second,
180 const Args &...rest) {
195template <
typename F,
typename T,
typename... Args>
196void compose(
const F &func, std::vector<T> *first,
const std::vector<T> &second,
197 const Args &...rest) {
200 if (first->size() < second.size())
201 first->resize(second.size());
203 for (std::size_t i = 0; i < second.size(); ++i) {
204 (*first)[i] = func((*first)[i], second[i]);
206 for (std::size_t i = second.size(); i < first->size(); ++i) {
207 (*first)[i] = func((*first)[i],
static_cast<T
>(0));
209 if constexpr (
sizeof...(rest) != 0)
215template <
typename F,
typename T,
typename... Args>
216[[nodiscard]] std::vector<T>
compose(
const F &func, std::vector<T> first,
217 const std::vector<T> &second,
218 const Args &...rest) {
219 compose(func, &first, second, rest...);
227void scale(std::vector<T> *vec, T x) {
228 static_assert(std::is_arithmetic_v<T>,
229 "In scale(std::vector<T>, T) : T must be arithmetic");
236[[nodiscard]] std::vector<T>
scale(std::vector<T> vec, T x) {
251template <
typename T =
double,
typename N = std::
size_t>
253 static_assert(std::is_arithmetic_v<T>,
254 "In uniform_range(T, T, N), T must be arithmetic");
255 static_assert(std::is_integral_v<N>,
256 "In uniform_range(T, T, N), N must be integral");
257 std::vector<T> range;
260 range.reserve(
static_cast<std::size_t
>(number));
261 range.push_back(first);
264 const auto interval =
static_cast<double>(last - first);
265 for (N i = 1; i < number - 1; ++i) {
266 const auto eps =
static_cast<double>(i) /
static_cast<double>(number - 1);
267 const auto value =
static_cast<double>(first) + (eps * interval);
268 range.push_back(
static_cast<T
>(value));
270 range.push_back(last);
282template <
typename T =
double,
typename N = std::
size_t>
284 static_assert(std::is_arithmetic_v<T>,
285 "In logarithmic_range(T, T, N), T must be arithmetic");
286 static_assert(std::is_integral_v<N>,
287 "In logarithmic_range(T, T, N), N must be integral");
289 std::vector<T> range;
292 range.reserve(
static_cast<std::size_t
>(number));
293 range.push_back(first);
296 const auto log_ratio =
297 std::log(
static_cast<double>(last) /
static_cast<double>(first));
298 for (N i = 1; i < number - 1; ++i) {
299 const auto eps =
static_cast<double>(i) /
static_cast<double>(number - 1);
300 const auto value =
static_cast<double>(first) * std::exp(log_ratio * eps);
301 range.push_back(
static_cast<T
>(value));
303 range.push_back(last);
315template <
typename T =
double,
typename N = std::
size_t>
317 static_assert(std::is_floating_point_v<T>,
318 "In loglinear_range(T, T, T, N), T must be floating point");
319 static_assert(std::is_integral_v<N>,
320 "In loglinear_range(T, T, T, N), N must be integral");
322 assert(first > 0.0 && last > 0.0 && b > 0.0);
324 std::vector<T> range;
325 range.reserve(
static_cast<std::size_t
>(number));
328 (last - first + b * std::log(last / first)) / (
static_cast<T
>(number - 1));
330 auto next_r = [b](
auto u1,
auto r_guess) {
335 const auto f_u = [b, u1](
double tr) {
return tr + b * std::log(tr) - u1; };
336 const auto dr = 0.1 * r_guess;
337 const auto delta_targ = r_guess * 1.0e-18;
338 const auto [ri, delta_r] =
qip::Newtons(f_u, r_guess, delta_targ, dr, 30);
342 auto u = first + b * std::log(first);
343 range.push_back(first);
344 for (N i = 1; i < number - 1; ++i) {
346 range.push_back(next_r(u, range.back()));
348 range.push_back(last);
356template <
typename T,
typename... Args>
357constexpr auto multiply_at(std::size_t i,
const T &first,
const Args &...rest) {
359 if constexpr (
sizeof...(rest) == 0) {
367template <
typename T,
typename... Args>
370 for (std::size_t i = 1; i < first.size(); ++i) {
377template <
typename T,
typename... Args>
379 const Args &...rest) {
380 auto res =
decltype(first[0])(0);
381 for (std::size_t i = p0; i < pinf; ++i) {
390template <
typename F,
typename T>
392 for (
auto &l : list) {
405template <
typename T,
typename Func>
406std::vector<T>
select_if(
const std::vector<T> &in, Func condition) {
408 for (
const auto &el : in) {
417template <
typename T,
typename Func>
420 for (
const auto &el : in) {
422 inout->push_back(el);
434 std::size_t f = in.size();
437 std::swap(in[i], in[f - 1]);
456 for (
const auto &x : vec) {
459 return sum / T(vec.size());
470T
variance(std::vector<T> vec, std::size_t dof = 0) {
471 assert(dof < vec.size());
472 const auto xbar =
mean(vec);
474 for (
const auto &x : vec) {
475 const auto del = x - xbar;
478 return sum / T(vec.size() - dof);
483T
sdev(std::vector<T> vec, std::size_t dof = 0) {
484 return std::sqrt(
variance(vec, dof));
489T
sem(std::vector<T> vec, std::size_t dof = 0) {
490 return sdev(vec, dof) / std::sqrt(T(vec.size()));
507std::vector<T> &
operator+=(std::vector<T> &a,
const std::vector<T> &b) {
509 const auto smaller_size = std::min(a.size(), b.size());
510 if (a.size() < b.size())
511 a.insert(a.end(), b.begin() +
long(a.size()), b.end());
512 for (
auto i = 0ul; i < smaller_size; ++i) {
518std::vector<T> operator+(std::vector<T> a,
const std::vector<T> &b) {
524std::vector<T> &
operator-=(std::vector<T> &a,
const std::vector<T> &b) {
525 const auto size = std::max(a.size(), b.size());
527 for (
auto i = 0ul; i < b.size(); ++i) {
533std::vector<T> operator-(std::vector<T> a,
const std::vector<T> &b) {
538template <
typename T,
typename U>
539std::vector<T> &operator*=(std::vector<T> &v, U x) {
541 for (
auto &v_i : v) {
547template <
typename T,
typename U>
548std::vector<T> operator*(std::vector<T> v, U x) {
551template <
typename T,
typename U>
552std::vector<T> operator*(U x, std::vector<T> v) {
557template <
typename T,
typename U>
558std::vector<T> &operator/=(std::vector<T> &v, U x) {
560 for (
auto &v_i : v) {
566template <
typename T,
typename U>
567std::vector<T> operator/(std::vector<T> v, U x) {
572template <
typename T,
typename U>
573std::vector<T> &
operator+=(std::vector<T> &v, U x) {
575 for (
auto &v_i : v) {
581template <
typename T,
typename U>
582std::vector<T> operator+(std::vector<T> v, U x) {
585template <
typename T,
typename U>
586std::vector<T> operator+(U x, std::vector<T> v) {
591template <
typename T,
typename U>
592std::vector<T> &
operator-=(std::vector<T> &v, U x) {
594 for (
auto &v_i : v) {
600template <
typename T,
typename U>
601std::vector<T> operator-(std::vector<T> v, U x) {
604template <
typename T,
typename U>
605std::vector<T> operator-(U x, std::vector<T> v) {
611template <
typename T,
typename U>
612std::vector<T> operator/(U x, std::vector<T> v) {
613 for (
auto &v_i : v) {
621std::vector<T> &operator*=(std::vector<T> &a,
const std::vector<T> &b) {
622 const auto min_size = std::min(a.size(), b.size());
623 for (std::size_t i = 0; i < min_size; ++i) {
626 for (std::size_t i = min_size; i < a.size(); ++i) {
629 if (a.size() < b.size())
635std::vector<T> operator*(std::vector<T> a,
const std::vector<T> &b) {
641std::vector<T> &operator/=(std::vector<T> &a,
const std::vector<T> &b) {
642 assert(a.size() == b.size());
643 for (std::size_t i = 0; i < a.size(); ++i) {
650std::vector<T> operator/(std::vector<T> a,
const std::vector<T> &b) {
std::vector< T > & operator+=(std::vector< T > &a, const std::vector< T > &b)
Element-wise addition: a += b, a + b.
Definition Vector.hpp:507
std::vector< T > & operator-=(std::vector< T > &a, const std::vector< T > &b)
Element-wise subtraction: a -= b, a - b.
Definition Vector.hpp:524
General-purpose utility library.
Definition Array.hpp:23
void add(std::vector< T > *first, const std::vector< T > &second, const Args &...rest)
Adds any number of vectors in place (modifies *first).
Definition Vector.hpp:125
std::vector< T > logarithmic_range(T first, T last, N number)
Returns a logarithmically distributed range [first, last] with number points.
Definition Vector.hpp:283
auto compare_eps(const std::vector< T > &first, const std::vector< T > &second)
Compares two floating-point vectors element-wise relative to the second; returns {max_eps,...
Definition Vector.hpp:97
void compose(const F &func, std::vector< T > *first, const std::vector< T > &second, const Args &...rest)
Applies func element-wise across any number of vectors in place (modifies *first).
Definition Vector.hpp:196
void scale(std::vector< T > *vec, T x)
In-place scalar multiplication of a vector; types must match.
Definition Vector.hpp:227
auto inner_product_sub(std::size_t p0, std::size_t pinf, const T &first, const Args &...rest)
Inner product over the subrange [p0, pinf).
Definition Vector.hpp:378
T sem(std::vector< T > vec, std::size_t dof=0)
Standard error of the mean: sdev / sqrt(N).
Definition Vector.hpp:489
std::vector< T > select_if(const std::vector< T > &in, Func condition)
Returns a copy of in containing only elements satisfying condition.
Definition Vector.hpp:406
T mean(std::vector< T > vec)
Mean of a vector.
Definition Vector.hpp:454
T apply_to(const F &func, T list)
Applies func to each element of list in place; returns the modified list.
Definition Vector.hpp:391
std::pair< Real, Real > Newtons(Function f, Real x, Real delta_target=Real{1.0e-6}, Real dx=Real{0.01}, unsigned it_limit=250)
Solves f(x) = 0 using Newton's method; returns {root, error}.
Definition Methods.hpp:55
std::vector< T > merge(std::vector< T > first, const std::vector< T > &second, const Args &...rest)
Merges any number of vectors: {a,b,c},{d,e},{f} -> {a,b,c,d,e,f}.
Definition Vector.hpp:19
std::vector< T > uniform_range(T first, T last, N number)
Returns a uniformly distributed range [first, last] with number points.
Definition Vector.hpp:252
std::vector< T > reverse(std::vector< T > in)
Returns a reversed copy of the vector.
Definition Vector.hpp:431
constexpr auto inner_product(const T &first, const Args &...rest)
Variadic inner product: sum_i v1[i]*v2[i]*...*vn[i].
Definition Vector.hpp:368
T sdev(std::vector< T > vec, std::size_t dof=0)
Standard deviation: sqrt(variance).
Definition Vector.hpp:483
void insert_into_if(const std::vector< T > &in, std::vector< T > *inout, Func condition)
Inserts elements from in into *inout if condition is met.
Definition Vector.hpp:418
void multiply(std::vector< T > *first, const std::vector< T > &second, const Args &...rest)
Multiplies any number of arithmetic vectors in place (modifies *first).
Definition Vector.hpp:155
auto compare(const std::vector< T > &first, const std::vector< T > &second)
Compares two arithmetic vectors element-wise; returns {max_delta, iterator}.
Definition Vector.hpp:41
T variance(std::vector< T > vec, std::size_t dof=0)
Variance using the two-pass method.
Definition Vector.hpp:470
std::vector< T > loglinear_range(T first, T last, T b, N number)
Returns a log-linear distributed range [first, last] with number points.
Definition Vector.hpp:316
constexpr auto multiply_at(std::size_t i, const T &first, const Args &...rest)
Helper: returns first[i] * rest[i] * ... at index i.
Definition Vector.hpp:357