11#ifndef STDUTILS_ARRAY_H 
   12#define STDUTILS_ARRAY_H 
   38  template <
typename T, 
size_t R>
 
   39  std::ostream &
operator<<(std::ostream &out, std::array<T, R> 
const &a) {
 
 
   51  template <
typename T, 
size_t R>
 
   55    for (
int i = 0; i < R; ++i) fs << (i == 0 ? 
"" : 
" ") << a[i];
 
 
   69  template <
typename T, 
size_t R>
 
   70  constexpr std::array<T, R> 
operator+(std::array<T, R> 
const &lhs, std::array<T, R> 
const &rhs) {
 
   72    for (
int i = 0; i < R; ++i) res[i] = lhs[i] + rhs[i];
 
 
   85  template <
typename T, 
size_t R>
 
   86  constexpr std::array<T, R> 
operator-(std::array<T, R> 
const &lhs, std::array<T, R> 
const &rhs) {
 
   88    for (
int i = 0; i < R; ++i) res[i] = lhs[i] - rhs[i];
 
 
  102  template <
typename T, 
typename U, 
size_t R>
 
  103  constexpr auto operator*(std::array<T, R> 
const &lhs, std::array<U, R> 
const &rhs) {
 
  104    using TU = 
decltype(std::declval<T>() * std::declval<U>());
 
  106    std::array<TU, R> res;
 
  107    for (
int i = 0; i < R; ++i) res[i] = lhs[i] * rhs[i];
 
 
  119  template <
typename T, 
size_t R>
 
  120  constexpr std::array<T, R> 
operator-(std::array<T, R> 
const &a) {
 
  121    std::array<T, R> res;
 
  122    for (
int i = 0; i < R; ++i) res[i] = -a[i];
 
 
  135  template <
typename T, 
size_t R>
 
  136  constexpr std::array<T, R> 
operator*(T s, std::array<T, R> 
const &a) {
 
  137    std::array<T, R> res;
 
  138    for (
int i = 0; i < R; ++i) res[i] = s * a[i];
 
 
  144namespace nda::stdutil {
 
  154  template <
size_t R, 
typename T>
 
  156    return [&v]<
size_t... Is>(std::index_sequence<Is...>) {
 
  157      return std::array<T, R>{((void)Is, v)...}; 
 
  158    }(std::make_index_sequence<R>{});
 
 
  170  template <
typename T, 
typename U, 
size_t R>
 
  172    static_assert(std::is_constructible_v<T, U>, 
"Error in nda::stdutil::make_std_array: T must be constructible from U");
 
  174    for (
int u = 0; u < R; ++u) result[u] = a[u];
 
 
  186  template <
typename T, 
size_t R>
 
  187  constexpr std::vector<T> 
to_vector(std::array<T, R> 
const &a) {
 
  189    for (
int i = 0; i < R; ++i) V[i] = a[i];
 
 
  203  template <
typename T, auto R, 
typename U>
 
  204  constexpr std::array<T, R + 1> 
append(std::array<T, R> 
const &a, U 
const &x) {
 
  205    std::array<T, R + 1> res;
 
  206    for (
int i = 0; i < R; ++i) res[i] = a[i];
 
 
  221  template <
typename T, 
typename U, 
size_t R>
 
  222  constexpr std::array<T, R + 1> 
front_append(std::array<T, R> 
const &a, U 
const &x) {
 
  223    std::array<T, R + 1> res;
 
  225    for (
int i = 0; i < R; ++i) res[i + 1] = a[i];
 
 
  238  template <
int N, 
typename T, 
size_t R>
 
  239  constexpr std::array<T, R - N> 
mpop(std::array<T, R> 
const &a) {
 
  240    std::array<T, R - N> res;
 
  241    for (
int i = 0; i < R - N; ++i) res[i] = a[i];
 
 
  253  template <
typename T, 
size_t R>
 
  254  constexpr std::array<T, R - 1> 
pop(std::array<T, R> 
const &a) {
 
 
  267  template <
int N, 
typename T, 
size_t R>
 
  268  constexpr std::array<T, R - N> 
front_mpop(std::array<T, R> 
const &a) {
 
  269    std::array<T, R - N> res;
 
  270    for (
int i = N; i < R; ++i) res[i - N] = a[i];
 
 
  282  template <
typename T, 
size_t R>
 
  283  constexpr std::array<T, R - 1> 
front_pop(std::array<T, R> 
const &a) {
 
 
  298  template <
typename T, 
size_t R1, 
size_t R2>
 
  299  constexpr std::array<T, R1 + R2> 
join(std::array<T, R1> 
const &a1, std::array<T, R2> 
const &a2) {
 
  300    std::array<T, R1 + R2> res;
 
  301    for (
int i = 0; i < R1; ++i) res[i] = a1[i];
 
  302    for (
int i = 0; i < R2; ++i) res[R1 + i] = a2[i];
 
 
  315  template <
typename T, 
size_t R>
 
  316  constexpr auto sum(std::array<T, R> 
const &a) {
 
  317    if constexpr (R == 0)
 
  321      for (
int i = 1; i < R; ++i) res += a[i];
 
 
  334  template <
typename T, 
size_t R>
 
  335  constexpr auto product(std::array<T, R> 
const &a) {
 
  336    static_assert(R > 0, 
"Error in nda::stdutil::product: Only defined for R > 0");
 
  338    for (
int i = 1; i < R; ++i) res *= a[i];
 
 
  355  template <
typename T, 
typename U, 
size_t R>
 
  356  constexpr auto dot_product(std::array<T, R> 
const &a1, std::array<U, R> 
const &a2) {
 
  357    if constexpr (R == 0)
 
  360      auto res = a1[0] * a2[0];
 
  361      for (
int i = 1; i < R; ++i) res += a1[i] * a2[i];
 
 
constexpr auto operator*(std::array< T, R > const &lhs, std::array< U, R > const &rhs)
Multiply two std::array objects element-wise.
 
std::ostream & operator<<(std::ostream &out, std::array< T, R > const &a)
Write a std::array to an output stream.
 
constexpr std::array< T, R - N > front_mpop(std::array< T, R > const &a)
Make a new std::array by popping the first N elements of an existing std::array.
 
constexpr std::array< T, R+1 > append(std::array< T, R > const &a, U const &x)
Make a new std::array by appending one element at the end to an existing std::array.
 
constexpr std::array< T, R+1 > front_append(std::array< T, R > const &a, U const &x)
Make a new std::array by prepending one element at the front to an existing std::array.
 
constexpr std::array< T, R - 1 > pop(std::array< T, R > const &a)
Make a new std::array by popping the last element of an existing std::array.
 
constexpr std::array< T, R > operator+(std::array< T, R > const &lhs, std::array< T, R > const &rhs)
Add two std::array objects element-wise.
 
constexpr std::array< T, R1+R2 > join(std::array< T, R1 > const &a1, std::array< T, R2 > const &a2)
Make a new std::array by joining two existing std::array objects.
 
constexpr std::vector< T > to_vector(std::array< T, R > const &a)
Convert a std::array to a std::vector.
 
constexpr std::array< T, R > make_initialized_array(T v)
Create a new std::array object initialized with a specific value.
 
constexpr auto sum(std::array< T, R > const &a)
Calculate the sum of all elements in a std::array.
 
std::string to_string(std::array< T, R > const &a)
Get a string representation of a std::array.
 
constexpr std::array< T, R > operator-(std::array< T, R > const &lhs, std::array< T, R > const &rhs)
Subtract two std::array objects element-wise.
 
constexpr std::array< T, R > make_std_array(std::array< U, R > const &a)
Convert a std::array with value type U to a std::array with value type T.
 
constexpr std::array< T, R - 1 > front_pop(std::array< T, R > const &a)
Make a new std::array by popping the first element of an existing std::array.
 
constexpr auto product(std::array< T, R > const &a)
Calculate the product of all elements in a std::array.
 
constexpr auto dot_product(std::array< T, R > const &a1, std::array< U, R > const &a2)
Calculate the dot product of two std::array objects.
 
constexpr std::array< T, R - N > mpop(std::array< T, R > const &a)
Make a new std::array by popping the last N elements of an existing std::array.