Coder Social home page Coder Social logo

mattkretz / vir-simd Goto Github PK

View Code? Open in Web Editor NEW
20.0 3.0 2.0 297 KB

improve the usage experience of std::experimental::simd (Parallelism TS 2)

License: GNU Lesser General Public License v3.0

C++ 95.23% Makefile 0.83% Shell 3.66% CMake 0.28%
cpp simd parallelism-ts cpp17-library simd-library

vir-simd's Introduction

vir::stdx::simd

CI DOI OpenSSF Best Practices fair-software.eu

This project aims to provide a fallback std::experimental::simd (Parallelism TS 2) implementation with additional features. Not every user can rely on GCC 11+ and its standard library to be present on all target systems. Therefore, the header vir/simd.h provides a fallback implementation of the TS specification that only implements the scalar and fixed_size<N> ABI tags. Thus, your code can still compile and run correctly, even if it is missing the performance gains a proper implementation provides.

Installation

This is a header-only library. Installation is a simple copy of the headers to wherever you want them. Per default make install copies the headers into /usr/local/include/vir/.

Examples:

# installs to $HOME/.local/include/vir
make install prefix=~/.local

# installs to $HOME/src/myproject/3rdparty/vir
make install includedir=~/src/myproject/3rdparty

Usage

#include <vir/simd.h>

namespace stdx = vir::stdx;

using floatv = stdx::native_simd<float>;
// ...

The vir/simd.h header will include <experimental/simd> if it is available, so you don't have to add any buildsystem support. It should just work.

Options

  • VIR_SIMD_TS_DROPIN: Define the macro VIR_SIMD_TS_DROPIN before including <vir/simd.h> to define everything in the namespace specified in the Parallelism TS 2 (namely std::experimental::parallelism_v2).

  • VIR_DISABLE_STDX_SIMD: Do not include <experimental/simd> even if it is available. This allows compiling your code with the <vir/simd.h> implementation unconditionally. This is useful for testing.

Additional Features

The TS curiously forgot to add simd_cast and static_simd_cast overloads for simd_mask. With vir::stdx::(static_)simd_cast, casts will also work for simd_mask. This does not require any additional includes.

Simple iota simd constants:

Requires Concepts (C++20).

#include <vir/simd_iota.h>

constexpr auto a = vir::iota_v<stdx::simd<float>> * 3; // 0, 3, 6, 9, ...

The variable template vir::iota_v<T> can be instantiated with arithmetic types, array types (std::array and C-arrays), and simd types. In all cases, the elements of the variable will be initialized to 0, 1, 2, 3, 4, ..., depending on the number of elements in T. For arithmetic types vir::iota_v<T> is always just 0.

Making simd conversions more convenient:

Requires Concepts (C++20).

The TS is way too strict about conversions, requiring verbose std::experimental::static_simd_cast<T>(x) instead of a concise T(x) or static_cast<T>(x). (std::simd in C++26 will fix this.)

vir::cvt(x) provides a tool to make x implicitly convertible into whatever the expression wants in order to be well-formed. This only works, if there is an unambiguous type that is required.

#include <vir/simd_cvt.h>

using floatv = stdx::native_simd<float>;
using intv = stdx::rebind_simd_t<int, floatv>;

void f(intv x) {
  using vir::cvt;
  // the floatv constructor and intv assignment operator clearly determine the
  // destination type:
  x = cvt(10 * sin(floatv(cvt(x))));

  // without vir::cvt, one would have write:
  x = stdx::static_simd_cast<intv>(10 * sin(stdx::static_simd_cast<floatv>(x)));

  // probably don't do this too often:
  auto y = cvt(x); // y is a const-ref to x, but so much more convertible
                   // y is of type cvt<intv>
}

Note that vir::cvt also works for simd_mask and non-simd types. Thus, cvt becomes an important building block for writing "simd-generic" code (i.e. well-formed for T and simd<T>).

Permutations (paper):

Requires Concepts (C++20).

#include <vir/simd_permute.h>

// v = {0, 1, 2, 3} -> {1, 0, 3, 2}
vir::simd_permute(v, vir::simd_permutations::swap_neighbors);

// v = {1, 2, 3, 4} -> {2, 2, 2, 2}
vir::simd_permute(v, [](unsigned) { return 1; });

// v = {1, 2, 3, 4} -> {3, 3, 3, 3}
vir::simd_permute(v, [](unsigned) { return -2; });

The following permutations are pre-defined:

  • vir::simd_permutations::duplicate_even: copy values at even indices to neighboring odd position

  • vir::simd_permutations::duplicate_odd: copy values at odd indices to neighboring even position

  • vir::simd_permutations::swap_neighbors<N>: swap N consecutive values with the following N consecutive values

  • vir::simd_permutations::broadcast<Idx>: copy the value at index Idx to all other values

  • vir::simd_permutations::broadcast_first: alias for broadcast<0>

  • vir::simd_permutations::broadcast_last: alias for broadcast<-1>

  • vir::simd_permutations::reverse: reverse the order of all values

  • vir::simd_permutations::rotate<Offset>: positive Offset rotates values to the left, negative Offset rotates values to the right (i.e. rotate<Offset> moves values from index (i + Offset) % size to i)

  • vir::simd_permutations::shift<Offset>: positive Offset shifts values to the left, negative Offset shifts values to the right; shifting in zeros.

A vir::simd_permute(x, idx_perm) overload, where x is of vectorizable type, is also included, facilitating generic code.

A special permutation vir::simd_shift_in<N>(x, ...) shifts by N elements shifting in elements from additional simd objects passed via the pack. Example:

// v = {1, 2, 3, 4}, w = {5, 6, 7, 8} -> {2, 3, 4, 5}
vir::simd_shift_in<1>(v, w);

SIMD execution policy (P0350):

Requires Concepts (C++20).

Adds an execution policy vir::execution::simd. The execution policy can be used with the algorithms implemented in the vir namespace. These algorithms are additionally overloaded in the std namespace.

At this point, the implementation of the execution policy requires contiguous ranges / iterators.

Usable algorithms

  • std::for_each / vir::for_each
  • std::count_if / vir::count_if
  • std::transform / vir::transform
  • std::transform_reduce / vir::transform_reduce
  • std::reduce / vir::reduce

Example

#include <vir/simd_execution.h>

void increment_all(std::vector<float> data) {
  std::for_each(vir::execution::simd, data.begin(), data.end(),
    [](auto& v) {
      v += 1.f;
    });
}

// or

void increment_all(std::vector<float> data) {
  vir::for_each(vir::execution::simd, data,
    [](auto& v) {
      v += 1.f;
    });
}

Execution policy modifiers

The vir::execution::simd execution policy supports a few settings modifying its behavior:

  • vir::execution::simd.prefer_size<N>(): Start with chunking the range into parts of N elements, calling the user-supplied function(s) with objects of type resize_simd_t<N, simd<T>>.

  • vir::execution::simd.unroll_by<M>(): Iterate over the range in chunks of simd::size() * M instead of just simd::size(). The algorithm will execute M loads (or stores) together before/after calling the user-supplied function(s). The user-supplied function may be called with M simd objects instead of one simd object. Note that prologue and epilogue will typically still call the user-supplied function with a single simd object. Algorithms like std::count_if require a return value from the user-supplied function and therefore still call the function with a single simd (to avoid the need for returning an array or tuple of simd_mask). Such algorithms will still make use of unrolling inside their implementation.

  • vir::execution::simd.prefer_aligned(): Unconditionally iterate using smaller chunks, until the main iteration can load (and store) chunks from/to aligned addresses. This can be more efficient if the range is large, avoiding cache-line splits. (e.g. with AVX-512, unaligned iteration leads to cache-line splits on every iteration; with AVX on every second iteration)

  • vir::execution::simd.auto_prologue() (still testing its viability, may be removed): Determine from run-time information (i.e. add a branch) whether a prologue for alignment of the main chunked iteration might be more efficient.

Bitwise operators for floating-point simd:

#include <vir/simd_float_ops.h>

using namespace vir::simd_float_ops;

Then the &, |, and ^ binary operators can be used with objects of type simd<floating-point, A>.

Conversion between std::bitset and simd_mask:

#include <vir/simd_bitset.h>

vir::stdx::simd_mask<int> k;
std::bitset b = vir::to_bitset(k);
vir::stdx::simd_mask k2 = vir::to_simd_mask<float>;

There are two overloads of vir::to_simd_mask:

to_simd_mask<T, A>(bitset<simd_size_v<T, A>>)

and

to_simd_mask<T, N>(bitset<N>)

vir::simd_resize and vir::simd_size_cast

The header

#include <vir/simd_resize.h>

declares the functions

  • vir::simd_resize<N>(simd),

  • vir::simd_resize<N>(simd_mask),

  • vir::simd_size_cast<V>(simd), and

  • vir::simd_size_cast<M>(simd_mask).

These functions can resize a given simd or simd_mask object. If the return type requires more elements than the input parameter, the new elements are default-initialized and appended at the end. Both functions do not allow a change of the value_type. However, implicit conversions can happen on parameter passing to simd_size_cast.

vir::simd_bit_cast

The header

#include <vir/simd_bit.h>

declares the function vir::simd_bit_cast<To>(from). This function serves the same purpose as std::bit_cast but additionally works in cases where a simd type is not trivially copyable.

Concepts

Requires Concepts (C++20).

The header

#include <vir/simd_concepts.h>

defines the following concepts:

  • vir::arithmetic<T>: What std::arithmetic<T> should be: satisfied if T is an arithmetic type (as specified by the C++ core language).

  • vir::vectorizable<T>: Satisfied if T is a valid element type for stdx::simd and stdx::simd_mask.

  • vir::simd_abi_tag<T>: Satisfied if T is a valid ABI tag for stdx::simd and stdx::simd_mask.

  • vir::any_simd<V>: Satisfied if V is a specialization of stdx::simd<T, Abi> and the types T and Abi satisfy vir::vectorizable<T> and vir::simd_abi_tag<Abi>.

  • vir::any_simd_mask<V>: Analogue to vir::any_simd<V> for stdx::simd_mask instead of stdx::simd.

  • vir::typed_simd<V, T>: Satisfied if vir::any_simd<V> and T is the element type of V.

  • vir::sized_simd<V, Width>: Satisfied if vir::any_simd<V> and Width is the width of V.

  • vir::sized_simd_mask<V, Width>: Analogue to vir::sized_simd<V, Width> for stdx::simd_mask instead of stdx::simd.

simdize type transformation

Requires Concepts (C++20).

⚠️ consider this interface under 🚧

The header

#include <vir/simdize.h>

defines the following types and constants:

  • vir::simdize<T, N>: N is optional. Type alias for a simd or vir::simd_tuple type determined from the type T.

    • If vir::vectorizable<T> is satisfied, then stdx::simd<T, Abi> is produced. Abi is determined from N and will be simd_abi::native<T> if N was omitted.

    • Otherwise, if T is a std::tuple or aggregate that can be reflected, then a specialization of vir::simd_tuple is produced. If T is a template specialization (without NTTPs), the metafunction tries vectorization via applying simdize to all template arguments. If this doesn't yield the same data structure layout as member-only vectorization, then the type behaves similar to a std::tuple with additional API to make the type similar to stdx::simd (see below). This specialization will be derived from std::tuple and the tuple elements will either be vir::simd_tuple or stdx::simd types. vir::simdize is applied recursively to the std::tuple/aggregate data members. If N was omitted, the resulting width of all simd types in the resulting type will match the largest native_simd width.

    Example: vir::simdize<std::tuple<double, short>> produces a tuple with the element types stdx::rebind_simd_t<double, stdx::native_simd<short>> and stdx::native_simd<short>.

  • vir::simd_tuple<reflectable_struct T, size_t N>: Don't use this class template directly. Let vir::simdize instantiate specializations of this class template. vir::simd_tuple mostly behaves like a std::tuple and adds the following interface on top of std::tuple:

    • value_type

    • mask_type

    • size

    • tuple-like constructors

    • broadcast and/or conversion constructors

    • load constructor

    • as_tuple(): Returns the data members as a std::tuple.

    • operator[](size_t): Copy of a single T stored in the simd_tuple. This is not a cheap operation because there are no T objects stored in the simd_tuple.

    • copy_from(std::contiguous_iterator): 🚧 unoptimized load from a contiguous array of struct (e.g. std::vector<T>).

    • copy_to(std::contiguous_iterator): 🚧 unoptimized store to a contiguous array of struct.

  • vir::simd_tuple<vectorizable_struct T, size_t N>: TODO

  • vir::get<I>(simd_tuple): Access to the I-th data member (a simd).

  • vir::simdize_size<T>, vir::simdize_size_v<T>

Benchmark support functions

Requires Concepts (C++20) and GNU compatible inline-asm.

The header

#include <vir/simd_benchmarking.h>

defines the following functions:

  • vir::fake_modify(...): Let the compiler assume that all arguments passed to this functions are modified. This inhibits constant propagation, hoisting of code sections, and dead-code elimination.

  • vir::fake_read(...): Let the compiler assume that all arguments passed to this function are read (in the cheapest manner). This inhibits dead-code elimination leading up to the results passed to this function.

constexpr_wrapper: function arguments as constant expressions

The header

#include <vir/constexpr_wrapper.h>

defines the following tools:

  • vir::constexpr_value (concept): Satisfied by any type with a static ::value member that can be used in a constant expression.

  • vir::constexpr_wrapper<auto> (class template): A type storing the value of its NTTP (non-type template parameter) and overloading all operators to return another constexpr_wrapper. constexpr_wrapper objects are implicitly convertible to their value type (a constexpr_wrapper automatically unwraps its constant expression).

  • vir::cw<auto> (variable template): Shorthand for producing constexpr_wrapper objects with the given value.

  • vir::literals (namespace with _cw UDL): Shorthand for producing constexpr_wrapper objects of the integer literal in front of the _cw suffix. The type will be deduced automatically from the value of the literal to be the smallest signed integral type, or if the value is larger, unsigned long long. If the value is too large for an unsigned long long, the program is ill-formed.

constexpr_wrapper may appear unrelated to simd. However, it is an important tool used in many places in the implementation and on interfaces of vir-simd tools. vir::constexpr_wrapper is very similar to std::integral_constant, which is used in the simd TS interface for generator constructors.

Example

#include <vir/constexpr_wrapper.h>

auto f(vir::constexpr_value auto N)
{
  std::array<int, N> x = {};
  return x;
}

std::array a = f(vir::cw<4>); // array<int, 4>

using namespace vir::literals;

std::array b = f(10_cw); // array<int, 10>

This example cannot work with a signature constexpr auto f(int n) (or consteval) because n will never be considered a constant expression in the body of the function.

Debugging

Compile with -D _GLIBCXX_DEBUG_UB to get runtime checks for undefined behavior in the simd implementation(s). Otherwise, -fsanitize=undefined without the macro definition will also find the problems, but without additional error message.

vir-simd's People

Contributors

alvarofs avatar mattkretz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

alvarofs jopadan

vir-simd's Issues

Compilation error with clang 14 on Apple silicon 13.6.4

When trying to compile the test suite on an Apple silicon with macosx 13.6.4 and Apple clang 14 I get the following error

CC=clang CXX=clang++ make

gnu++2b: test extensions (-Wall -Wextra -Wpedantic -Wno-attributes -Wno-unknown-pragmas -Wno-psabi -Wno-self-assign-overloaded -Wno-deprecated -I/Users/uhlig/vir-simd)
In file included from vir/test.cpp:7:
In file included from /Users/uhlig/vir-simd/vir/simdize.h:19:
vir/simd_permute.h:176:23: error: no template named 'bit_cast' in namespace 'std'; did you mean 'detail::bit_cast'?
                const VecType vec = std::bit_cast<VecType>(v);
                                    ^~~~~~~~~~~~~
                                    detail::bit_cast
vir/detail.h:155:5: note: 'detail::bit_cast' declared here
    bit_cast(const From& x)
    ^

Compilation error with gcc10 on Debian11

When compiling the test suite on Debian11 with g++ (Debian 10.2.1-6) 10.2.1 20210110 I get the following error

CXX=g++ make 
gnu++20: test extensions (-Wall -Wextra -Wpedantic -Wno-attributes -Wno-unknown-pragmas -Wno-psabi -I/u/uhlig/vir-simd)
gnu++20: test extensions (-Wall -Wextra -Wpedantic -Wno-attributes -Wno-unknown-pragmas -Wno-psabi -I/u/uhlig/vir-simd -DVIR_DISABLE_STDX_SIMD)
gnu++2a: test constexpr_wrapper (-Wall -Wextra -Wpedantic -Wno-attributes -Wno-unknown-pragmas -Wno-psabi -I/u/uhlig/vir-simd)
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value + Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value + Bp::value))>::type>::type> vir::operator+(Ap, Bp) [with Ap = vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >; Bp = numarray<int, 4>]’:
vir/test_constexpr_wrapper.cpp:250:40:   required from here
vir/constexpr_wrapper.h:152:60: error: invalid use of non-static data member ‘numarray<int, 4>::value’
  152 |         friend constexpr constexpr_wrapper<Ap::value + Bp::value>
      |                                                            ^~~~~
vir/test_constexpr_wrapper.cpp:172:5: note: declared here
  172 |   V value;
      |     ^~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = vir::constexpr_wrapper<Test{1}, Test>; Bp = Test]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = Test{1}; C = vir::constexpr_wrapper<Test{1}, Test>]’
vir/test_constexpr_wrapper.cpp:206:32:   required from here
vir/constexpr_wrapper.h:217:62: error: invalid use of non-static data member ‘Test::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                              ^~~~~
vir/test_constexpr_wrapper.cpp:29:7: note: declared here
   29 |   int value = 1;
      |       ^~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = Test; Bp = vir::constexpr_wrapper<Test{1}, Test>]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = Test{1}; C = vir::constexpr_wrapper<Test{1}, Test>]’
vir/test_constexpr_wrapper.cpp:206:32:   required from here
vir/constexpr_wrapper.h:217:49: error: invalid use of non-static data member ‘Test::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                 ^~~~~
vir/test_constexpr_wrapper.cpp:29:7: note: declared here
   29 |   int value = 1;
      |       ^~~~~
vir/test_constexpr_wrapper.cpp: In instantiation of ‘void check(C) [with auto Expected = strlit<char, 4>{"fo"}; C = vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >]’:
vir/test_constexpr_wrapper.cpp:215:33:   required from here
vir/test_constexpr_wrapper.cpp:119:28: error: non-constant condition for static assertion
  119 |     static_assert(C::value == Expected);
      |                      ~~~~~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:119:28:   in ‘constexpr’ expansion of ‘vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >::value.strlit<char, 4>::operator==(strlit<char, 4>{"fo"})’
vir/test_constexpr_wrapper.cpp:66:5: error: ‘((& vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >::value) == (& strlit<char, 4>{"fo"}))’ is not a constant expression
   66 |     operator==(const strlit&) const = default;
      |     ^~~~~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >; Bp = strlit<char, 4>]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = strlit<char, 4>{"fo"}; C = vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >]’
vir/test_constexpr_wrapper.cpp:215:33:   required from here
vir/constexpr_wrapper.h:217:62: error: invalid use of non-static data member ‘strlit<char, 4>::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                              ^~~~~
vir/test_constexpr_wrapper.cpp:48:10: note: declared here
   48 |     Char value[size];
      |          ^~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = strlit<char, 4>; Bp = vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = strlit<char, 4>{"fo"}; C = vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >]’
vir/test_constexpr_wrapper.cpp:215:33:   required from here
vir/constexpr_wrapper.h:217:49: error: invalid use of non-static data member ‘strlit<char, 4>::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                 ^~~~~
vir/test_constexpr_wrapper.cpp:48:10: note: declared here
   48 |     Char value[size];
      |          ^~~~~
vir/test_constexpr_wrapper.cpp: In instantiation of ‘void check(C) [with auto Expected = strlit<char, 4>{"fo"}; C = vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >]’:
vir/test_constexpr_wrapper.cpp:215:33:   required from here
vir/test_constexpr_wrapper.cpp:120:21: error: static assertion failed
  120 |     static_assert(x == Expected);
      |                   ~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:121:27: error: non-constant condition for static assertion
  121 |     static_assert(x.value == Expected);
      |                   ~~~~~~~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:121:27:   in ‘constexpr’ expansion of ‘vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >::value.strlit<char, 4>::operator==(strlit<char, 4>{"fo"})’
vir/test_constexpr_wrapper.cpp:66:5: error: ‘((& vir::constexpr_wrapper<strlit<char, 4>{"fo"}, strlit<char, 4> >::value) == (& strlit<char, 4>{"fo"}))’ is not a constant expression
   66 |     operator==(const strlit&) const = default;
      |     ^~~~~~~~
vir/test_constexpr_wrapper.cpp: In instantiation of ‘void check(C) [with auto Expected = strlit<char, 7>{"fooba"}; C = vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >]’:
vir/test_constexpr_wrapper.cpp:216:47:   required from here
vir/test_constexpr_wrapper.cpp:119:28: error: non-constant condition for static assertion
  119 |     static_assert(C::value == Expected);
      |                      ~~~~~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:119:28:   in ‘constexpr’ expansion of ‘vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >::value.strlit<char, 7>::operator==(strlit<char, 7>{"fooba"})’
vir/test_constexpr_wrapper.cpp:66:5: error: ‘((& vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >::value) == (& strlit<char, 7>{"fooba"}))’ is not a constant expression
   66 |     operator==(const strlit&) const = default;
      |     ^~~~~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >; Bp = strlit<char, 7>]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = strlit<char, 7>{"fooba"}; C = vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >]’
vir/test_constexpr_wrapper.cpp:216:47:   required from here
vir/constexpr_wrapper.h:217:62: error: invalid use of non-static data member ‘strlit<char, 7>::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                              ^~~~~
vir/test_constexpr_wrapper.cpp:48:10: note: declared here
   48 |     Char value[size];
      |          ^~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = strlit<char, 7>; Bp = vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = strlit<char, 7>{"fooba"}; C = vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >]’
vir/test_constexpr_wrapper.cpp:216:47:   required from here
vir/constexpr_wrapper.h:217:49: error: invalid use of non-static data member ‘strlit<char, 7>::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                 ^~~~~
vir/test_constexpr_wrapper.cpp:48:10: note: declared here
   48 |     Char value[size];
      |          ^~~~~
vir/test_constexpr_wrapper.cpp: In instantiation of ‘void check(C) [with auto Expected = strlit<char, 7>{"fooba"}; C = vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >]’:
vir/test_constexpr_wrapper.cpp:216:47:   required from here
vir/test_constexpr_wrapper.cpp:120:21: error: static assertion failed
  120 |     static_assert(x == Expected);
      |                   ~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:121:27: error: non-constant condition for static assertion
  121 |     static_assert(x.value == Expected);
      |                   ~~~~~~~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:121:27:   in ‘constexpr’ expansion of ‘vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >::value.strlit<char, 7>::operator==(strlit<char, 7>{"fooba"})’
vir/test_constexpr_wrapper.cpp:66:5: error: ‘((& vir::constexpr_wrapper<strlit<char, 7>{"fooba"}, strlit<char, 7> >::value) == (& strlit<char, 7>{"fooba"}))’ is not a constant expression
   66 |     operator==(const strlit&) const = default;
      |     ^~~~~~~~
vir/test_constexpr_wrapper.cpp: In instantiation of ‘void check(C) [with auto Expected = numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}; C = vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >]’:
vir/test_constexpr_wrapper.cpp:249:36:   required from here
vir/test_constexpr_wrapper.cpp:119:28: error: non-constant condition for static assertion
  119 |     static_assert(C::value == Expected);
      |                      ~~~~~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:119:28:   in ‘constexpr’ expansion of ‘operator==(vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >::value, numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}})’
vir/test_constexpr_wrapper.cpp:189:3: error: ‘((& vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >::value) == (& numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}))’ is not a constant expression
  189 |   operator==(const numarray&, const numarray&) = default;
      |   ^~~~~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >; Bp = numarray<int, 4>]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}; C = vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >]’
vir/test_constexpr_wrapper.cpp:249:36:   required from here
vir/constexpr_wrapper.h:217:62: error: invalid use of non-static data member ‘numarray<int, 4>::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                              ^~~~~
vir/test_constexpr_wrapper.cpp:172:5: note: declared here
  172 |   V value;
      |     ^~~~~
In file included from vir/test_constexpr_wrapper.cpp:6:
vir/constexpr_wrapper.h: In substitution of ‘template<class Ap, class Bp>  requires (_lhs_constexpr_wrapper<Ap, vir::constexpr_wrapper<Xp, <template-parameter-1-2> > >) && (constexpr_value<Bp, void>) constexpr vir::constexpr_wrapper<(Ap::value == Bp::value), typename std::remove_cv<typename std::remove_reference<decltype ((Ap::value == Bp::value))>::type>::type> vir::operator==(Ap, Bp) [with Ap = numarray<int, 4>; Bp = vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >]’:
vir/test_constexpr_wrapper.cpp:120:21:   required from ‘void check(C) [with auto Expected = numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}; C = vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >]’
vir/test_constexpr_wrapper.cpp:249:36:   required from here
vir/constexpr_wrapper.h:217:49: error: invalid use of non-static data member ‘numarray<int, 4>::value’
  217 |         friend constexpr constexpr_wrapper<(Ap::value == Bp::value)>
      |                                                 ^~~~~
vir/test_constexpr_wrapper.cpp:172:5: note: declared here
  172 |   V value;
      |     ^~~~~
vir/test_constexpr_wrapper.cpp: In instantiation of ‘void check(C) [with auto Expected = numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}; C = vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >]’:
vir/test_constexpr_wrapper.cpp:249:36:   required from here
vir/test_constexpr_wrapper.cpp:120:21: error: static assertion failed
  120 |     static_assert(x == Expected);
      |                   ~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:121:27: error: non-constant condition for static assertion
  121 |     static_assert(x.value == Expected);
      |                   ~~~~~~~~^~~~~~~~~~~
vir/test_constexpr_wrapper.cpp:121:27:   in ‘constexpr’ expansion of ‘operator==(vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >::value, numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}})’
vir/test_constexpr_wrapper.cpp:189:3: error: ‘((& vir::constexpr_wrapper<numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}, numarray<int, 4> >::value) == (& numarray<int, 4>{numarray<int, 4>::V{1, 2, 3, 4}}))’ is not a constant expression
  189 |   operator==(const numarray&, const numarray&) = default;
      |   ^~~~~~~~

Compilation error with gcc 12 on Debian 12

When I try to compile the test suite on Debain 12 with gcc (Debian 12.2.0-14) 12.2.0 I get the following error

CXX=g++ make
gnu++23: test extensions (-Wall -Wextra -Wpedantic -Wno-attributes -Wno-unknown-pragmas -Wno-psabi -I/home/cbm/vir-simd)
vir/test.cpp:110:12: error: non-constant condition for static assertion
  110 |   all_equal(vir::simd_permute(make_simd(0, 1, 2, 3, 4, 5), vir::simd_permutations::swap_neighbors<3>),
      |   ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  111 |             make_simd(3, 4, 5, 0, 1, 2)));
      |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/cbm/vir-simd/vir/simdize.h:19,
                 from vir/test.cpp:7:
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘vir::simd_permute(const V&, F) [with long unsigned int N = 0; V = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >; F = simd_permutations::SwapNeighbors<3>; std::experimental::parallelism_v2::resize_simd_t<((N == 0) ? V::size() : N), V> = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >]((vir::simd_permutations::swap_neighbors<3>, const vir::simd_permutations::SwapNeighbors<3>()))’
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >(<lambda closure object>vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>{idx_perm, (* & v)}, 0)’
/usr/include/c++/12/experimental/bits/simd.h:5181:36:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>((* & __gen), ((int*)std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >::_S_type_tag))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1299:38:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdTuple<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<8> >::_S_generate<>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>{(* & __gen)}, (std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:404:24:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>(std::experimental::parallelism_v2::__tuple_element_meta<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, 0>{std::experimental::parallelism_v2::_SimdImplX86<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >()})’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1305:21:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>{(* & __gen), __meta}, 0)’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1437:50:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)> >(<lambda closure object>std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>{(* & __gen)})’
/usr/include/c++/12/experimental/bits/simd.h:1833:44:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector_impl<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>, 0, 1, 2, 3>((* & __gen), (std::make_index_sequence<4>(), std::make_index_sequence<4>()))’
/usr/include/c++/12/experimental/bits/simd.h:1811:29:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1440:18:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>((__i, std::integral_constant<long unsigned int, 0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1302:32:   in ‘constexpr’ expansion of ‘(& __gen)->vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/home/cbm/vir-simd/vir/simd_permute.h:229:28: error: ‘constexpr std::experimental::parallelism_v2::simd<_Tp, _Abi>::value_type std::experimental::parallelism_v2::simd<_Tp, _Abi>::operator[](std::size_t) const [with _Tp = int; _Abi = std::experimental::parallelism_v2::simd_abi::_Fixed<6>; value_type = int; std::size_t = long unsigned int]’ called in a constant expression
  229 |                    return v[j];
      |                           ~^
In file included from /usr/include/c++/12/experimental/simd:72,
                 from /home/cbm/vir-simd/vir/simd.h:14,
                 from vir/test.cpp:6:
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘vir::simd_permute(const V&, F) [with long unsigned int N = 0; V = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >; F = simd_permutations::SwapNeighbors<3>; std::experimental::parallelism_v2::resize_simd_t<((N == 0) ? V::size() : N), V> = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >]((vir::simd_permutations::swap_neighbors<3>, const vir::simd_permutations::SwapNeighbors<3>()))’
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >(<lambda closure object>vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>{idx_perm, (* & v)}, 0)’
/usr/include/c++/12/experimental/bits/simd.h:5181:36:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>((* & __gen), ((int*)std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >::_S_type_tag))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1299:38:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdTuple<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<8> >::_S_generate<>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>{(* & __gen)}, (std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:404:24:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>(std::experimental::parallelism_v2::__tuple_element_meta<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, 0>{std::experimental::parallelism_v2::_SimdImplX86<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >()})’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1305:21:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>{(* & __gen), __meta}, 0)’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1437:50:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)> >(<lambda closure object>std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>{(* & __gen)})’
/usr/include/c++/12/experimental/bits/simd.h:1833:44:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector_impl<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>, 0, 1, 2, 3>((* & __gen), (std::make_index_sequence<4>(), std::make_index_sequence<4>()))’
/usr/include/c++/12/experimental/bits/simd.h:1811:29:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1440:18:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>((__i, std::integral_constant<long unsigned int, 0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1302:32:   in ‘constexpr’ expansion of ‘(& __gen)->vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd.h:5215:5: note: ‘constexpr std::experimental::parallelism_v2::simd<_Tp, _Abi>::value_type std::experimental::parallelism_v2::simd<_Tp, _Abi>::operator[](std::size_t) const [with _Tp = int; _Abi = std::experimental::parallelism_v2::simd_abi::_Fixed<6>; value_type = int; std::size_t = long unsigned int]’ is not usable as a ‘constexpr’ function because:
 5215 |     operator[]([[maybe_unused]] size_t __i) const
      |     ^~~~~~~~
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘vir::simd_permute(const V&, F) [with long unsigned int N = 0; V = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >; F = simd_permutations::SwapNeighbors<3>; std::experimental::parallelism_v2::resize_simd_t<((N == 0) ? V::size() : N), V> = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >]((vir::simd_permutations::swap_neighbors<3>, const vir::simd_permutations::SwapNeighbors<3>()))’
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >(<lambda closure object>vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>{idx_perm, (* & v)}, 0)’
/usr/include/c++/12/experimental/bits/simd.h:5181:36:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>((* & __gen), ((int*)std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >::_S_type_tag))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1299:38:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdTuple<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<8> >::_S_generate<>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>{(* & __gen)}, (std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:404:24:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>(std::experimental::parallelism_v2::__tuple_element_meta<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, 0>{std::experimental::parallelism_v2::_SimdImplX86<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >()})’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1305:21:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>{(* & __gen), __meta}, 0)’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1437:50:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)> >(<lambda closure object>std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>{(* & __gen)})’
/usr/include/c++/12/experimental/bits/simd.h:1833:44:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector_impl<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>, 0, 1, 2, 3>((* & __gen), (std::make_index_sequence<4>(), std::make_index_sequence<4>()))’
/usr/include/c++/12/experimental/bits/simd.h:1811:29:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1440:18:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>((__i, std::integral_constant<long unsigned int, 0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1302:32:   in ‘constexpr’ expansion of ‘(& __gen)->vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd.h:5223:23: error: call to non-‘constexpr’ function ‘_Tp std::experimental::parallelism_v2::_SimdTuple<_Tp, _A0, _As ...>::operator[](std::size_t) const [with _Tp = int; _Abi0 = std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>; _Abis = {std::experimental::parallelism_v2::simd_abi::_VecBuiltin<8>}; std::size_t = long unsigned int]’
 5223 |         return _M_data[__i];
      |                ~~~~~~~^
In file included from /usr/include/c++/12/experimental/simd:73:
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘vir::simd_permute(const V&, F) [with long unsigned int N = 0; V = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >; F = simd_permutations::SwapNeighbors<3>; std::experimental::parallelism_v2::resize_simd_t<((N == 0) ? V::size() : N), V> = std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >]((vir::simd_permutations::swap_neighbors<3>, const vir::simd_permutations::SwapNeighbors<3>()))’
vir/test.cpp:111:35:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >(<lambda closure object>vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>{idx_perm, (* & v)}, 0)’
/usr/include/c++/12/experimental/bits/simd.h:5181:36:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>((* & __gen), ((int*)std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >::_S_type_tag))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1299:38:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdTuple<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<8> >::_S_generate<>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>{(* & __gen)}, (std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:404:24:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>(std::experimental::parallelism_v2::__tuple_element_meta<int, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, 0>{std::experimental::parallelism_v2::_SimdImplX86<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >()})’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1305:21:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(<lambda closure object>std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>{(* & __gen), __meta}, 0)’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1437:50:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)> >(<lambda closure object>std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>{(* & __gen)})’
/usr/include/c++/12/experimental/bits/simd.h:1833:44:   in ‘constexpr’ expansion of ‘std::experimental::parallelism_v2::__generate_vector_impl<int, 4, _SimdImplBuiltin<simd_abi::_VecBuiltin<16>, __detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>, 0, 1, 2, 3>((* & __gen), (std::make_index_sequence<4>(), std::make_index_sequence<4>()))’
/usr/include/c++/12/experimental/bits/simd.h:1811:29:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplBuiltin<std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>, int>(std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>&&, _TypeTag<int>)::<lambda(auto:764)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_builtin.h:1440:18:   in ‘constexpr’ expansion of ‘(& __gen)->std::experimental::parallelism_v2::_SimdImplFixedSize<6, std::experimental::parallelism_v2::__detail::_MachineFlagsTemplate<7, 9> >::_S_generator<vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>, int>(vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>&&, _TypeTag<int>)::<lambda(auto:89)>::<lambda(auto:90)>((__i, std::integral_constant<long unsigned int, 0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:1302:32:   in ‘constexpr’ expansion of ‘(& __gen)->vir::simd_permute<>(const std::experimental::parallelism_v2::simd<int, std::experimental::parallelism_v2::simd_abi::_Fixed<6> >&, simd_permutations::SwapNeighbors<3>)::<lambda(auto:892)>((std::experimental::parallelism_v2::_SizeConstant<0>(), std::experimental::parallelism_v2::_SizeConstant<0>()))’
/usr/include/c++/12/experimental/bits/simd_fixed_size.h:595:9: note: ‘_Tp std::experimental::parallelism_v2::_SimdTuple<_Tp, _A0, _As ...>::operator[](std::size_t) const [with _Tp = int; _Abi0 = std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16>; _Abis = {std::experimental::parallelism_v2::simd_abi::_VecBuiltin<8>}; std::size_t = long unsigned int]’ declared here
  595 |     _Tp operator[](size_t __i) const noexcept
      |         ^~~~~~~~
vir/test.cpp:411:2: error: non-constant condition for static assertion
  387 | static_assert([] {
      |               ~~~~
  388 |   vir::simdize<Point> p1 = Point{1.f, 1.f, 1.f};
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  389 |   vir::simdize<Point> p2 {V<float>([](short i) { return i; }),
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  390 |                           V<float>([](short i) { return i; }),
      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  391 |                           V<float>([](short i) { return i; })};
      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  392 |   vir::simdize<Point> p3 {V<float>([](short i) { return i + 1; }),
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  393 |                           V<float>([](short i) { return i + 1; }),
      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  394 |                           V<float>([](short i) { return i + 1; })};
      |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  395 |   {
      |   ~
  396 |     auto p = p1 + p2;
      |     ~~~~~~~~~~~~~~~~~
  397 |     if (any_of(p != p3))
      |     ~~~~~~~~~~~~~~~~~~~~
  398 |       return false;
      |       ~~~~~~~~~~~~~
  399 |   }
      |   ~
  400 |   {
      |   ~
  401 |     auto p = Point{1.f, 1.f, 1.f} + p2;
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  402 |     if (any_of(p != p3))
      |     ~~~~~~~~~~~~~~~~~~~~
  403 |       return false;
      |       ~~~~~~~~~~~~~
  404 |   }
      |   ~
  405 |   {
      |   ~
  406 |     PointTpl<V<float>> p = p1 + p2;
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  407 |     if (any_of(p != p3))
      |     ~~~~~~~~~~~~~~~~~~~~
  408 |       return false;
      |       ~~~~~~~~~~~~~
  409 |   }
      |   ~
  410 |   return true;
      |   ~~~~~~~~~~~~
  411 | }());
      | ~^~
vir/test.cpp:411:2:   in ‘constexpr’ expansion of ‘<lambda closure object><lambda()>().<lambda()>()’
vir/test.cpp:397:21:   in ‘constexpr’ expansion of ‘vir::operator!=(p, p3)’
/home/cbm/vir-simd/vir/simdize.h:903:24: error: ‘constexpr decltype(auto) operator!=(const PointTpl<std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > >&, const PointTpl<std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > >&)’ called in a constant expression
  903 |       VIR_OPERATOR_FWD(!=)
      |                        ^
/home/cbm/vir-simd/vir/simdize.h:873:36: note: in definition of macro ‘VIR_OPERATOR_FWD’
  873 |                  a._as_base_type() op b._as_base_type());                                          \
      |                                    ^~
vir/test.cpp:265:3: note: ‘constexpr decltype(auto) operator!=(const PointTpl<std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > >&, const PointTpl<std::experimental::parallelism_v2::simd<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > >&)’ is not usable as a ‘constexpr’ function because:
  265 |   operator!=(PointTpl const& a, PointTpl const& b)
      |   ^~~~~~~~
vir/test.cpp:266:37: error: call to non-‘constexpr’ function ‘std::experimental::parallelism_v2::simd_mask<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > std::experimental::parallelism_v2::operator||(const simd_mask<float, simd_abi::_VecBuiltin<16> >&, const simd_mask<float, simd_abi::_VecBuiltin<16> >&)’
  266 |   { return a.x != b.x or a.y != b.y or a.z != b.z; }
      |            ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~
/usr/include/c++/12/experimental/bits/simd.h:4635:5: note: ‘std::experimental::parallelism_v2::simd_mask<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > std::experimental::parallelism_v2::operator||(const simd_mask<float, simd_abi::_VecBuiltin<16> >&, const simd_mask<float, simd_abi::_VecBuiltin<16> >&)’ declared here
 4635 |     operator||(const simd_mask& __x, const simd_mask& __y)
      |     ^~~~~~~~
vir/test.cpp:461:2: error: non-constant condition for static assertion
  442 | static_assert([] {
      |               ~~~~
  443 |   std::array<Point, 5> data = {};
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  444 |   vir::simdize<Point, 4> v(data.begin());
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  445 |   PointTpl<DV<float, 4>> w = v;
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  446 |   if (not all_of(w.x == 0.f and w.y == 0.f and w.z == 0.f))
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  447 |     return false;
      |     ~~~~~~~~~~~~~
  448 |   v.copy_from(data.begin() + 1);
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  449 |   w = v;
      |   ~~~~~~
  450 |   if (not all_of(w.x == 0.f and w.y == 0.f and w.z == 0.f))
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  451 |     return false;
      |     ~~~~~~~~~~~~~
  452 |   w.x = 1.f;
      |   ~~~~~~~~~~
  453 |   w.y = DV<float, 4>([](float i) { return i; });
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  454 |   v = w;
      |   ~~~~~~
  455 |   v.copy_to(data.begin());
      |   ~~~~~~~~~~~~~~~~~~~~~~~~
  456 |   if (data != std::array<Point, 5> {Point{1, 0, 0}, {1, 1, 0}, {1, 2, 0}, {1, 3, 0}, {0, 0, 0}})
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  457 |     return false;
      |     ~~~~~~~~~~~~~
  458 |   v.copy_from(data.begin() + 1);
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  459 |   v.copy_to(data.begin());
      |   ~~~~~~~~~~~~~~~~~~~~~~~~
  460 |   return data == std::array<Point, 5> {Point{1, 1, 0}, {1, 2, 0}, {1, 3, 0}, {0, 0, 0}, {0, 0, 0}};
      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  461 | }());
      | ~^~
vir/test.cpp:461:2: error: ‘<lambda()>’ called in a constant expression
vir/test.cpp:442:15: note: ‘<lambda()>’ is not usable as a ‘constexpr’ function because:
  442 | static_assert([] {
      |               ^
vir/test.cpp:446:55: error: call to non-‘constexpr’ function ‘std::experimental::parallelism_v2::simd_mask<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > std::experimental::parallelism_v2::operator&&(const simd_mask<float, simd_abi::_VecBuiltin<16> >&, const simd_mask<float, simd_abi::_VecBuiltin<16> >&)’
  446 |   if (not all_of(w.x == 0.f and w.y == 0.f and w.z == 0.f))
      |                                                       ^~~
/usr/include/c++/12/experimental/bits/simd.h:4629:5: note: ‘std::experimental::parallelism_v2::simd_mask<float, std::experimental::parallelism_v2::simd_abi::_VecBuiltin<16> > std::experimental::parallelism_v2::operator&&(const simd_mask<float, simd_abi::_VecBuiltin<16> >&, const simd_mask<float, simd_abi::_VecBuiltin<16> >&)’ declared here
 4629 |     operator&&(const simd_mask& __x, const simd_mask& __y)
      |     ^~~~~~~~

Is this library Vc 2.0?

Hi! Your previous library Vc promises that after successful standardization of std::simd, development of Vc will be rebased onto std::simd under the name Vc 2.0. However, I have been watching vir-simd for a while now and started to wonder whether this project is starting to become Vc 2.0. So I have some questions:

  • Is vir-simd just a prototyping playground for proposals around std::simd or is intended as a solid implementation of std::simd for people stuck on older compilers?
  • Would you advice against using vir-simd in production as a replacement for Vc 1.4? Some people at CERN are looking for an upgrade path.
  • How does the std-simd repository compare to vir-simd?

Depending on your answers I may want to advertise vir-simd on the Vc repository. Thx!

Compilation error with MSVC

Hi! I was trying to add vir-simd to Conan Center PR but the CI fails with MSVC when checking for C++17.
It seems that the __cplusplus macro contains a wrong value unless we specify de /Zc:__cplusplus compiler flag. It would be easy to add that flag for the package test but that would require every user of the library to set that flag. Maybe that's what you wanted or maybe that check could be defined using the MSVC macro _MSC_VER. I'm assuming MSVC support, if that is not the case please let me know and I'll update the Conan PR accordingly.

I also spent some time trying to make iota_v work until I saw that it is only available with C++20. I think that should be in the README.

I apologize I'm only complaining 😅 . I'll try to create a PR at least for the iota issue.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.