diff --git a/Makefile b/Makefile index 2ffe9a6..08b42e1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -all: clangnosan clangsan gccnosan gccsan +all: clangnosan clangsan gccnosan gccsan gccavx2 clangavx512 #TODO: re-enable GCC once multidimensional indexing in `requires` is fixed: # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111493 @@ -13,6 +13,13 @@ buildclang/nosan/: buildclang/test/: CXXFLAGS="" CXX=clang++ cmake -S test -B buildclang/test/ -DCMAKE_BUILD_TYPE=Debug -DUSE_SANITIZER='Address;Undefined' + +buildgcc/avx2/: + CXXFLAGS="-march=haswell" CXX=g++ cmake -S test -B buildgcc/avx2/ -DCMAKE_BUILD_TYPE=Debug + +buildclang/avx512/: + CXXFLAGS="-march=skylake-avx512 -mprefer-vector-width=512" CXX=clang++ cmake -S test -B buildclang/avx512/ -DCMAKE_BUILD_TYPE=Debug + gccnosan: buildgcc/nosan/ cmake --build buildgcc/nosan/ @@ -30,5 +37,13 @@ clangsan: buildclang/test/ cmake --build buildclang/test/ cmake --build buildclang/test/ --target test +gccavx2: buildgcc/avx2/ + cmake --build buildgcc/avx2/ + cmake --build buildgcc/avx2/ --target test + +clangavx512: buildclang/avx512/ + cmake --build buildclang/avx512/ + cmake --build buildclang/avx512/ --target test + clean: rm -r buildclang #buildgcc diff --git a/README.md b/README.md index e264b85..a464bd9 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,7 @@ Copying, e.g. from an expression template to an array, is done via `destination `operator=` is reserved for copying the actual objects, rather than referenced memory, as this seems to be the behavior C++ views. Thus if `A` and `B` are views, `A = B` will make `A` the same view as `B`, while `A << B` will copy memory from `B` to `A`. +Vectors are interpreted as row vectors by default. `v.t()` or `transpose(v)` may be used to transpose. +`A[_,i]` is a column-vector, `A[i,_]` a row-vector. + This repository was created using the [ModernCppStarter](https://github.com/TheLartians/ModernCppStarter). diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt new file mode 100644 index 0000000..667902e --- /dev/null +++ b/benchmark/CMakeLists.txt @@ -0,0 +1,118 @@ +cmake_minimum_required(VERSION 3.23) + +project(MathBenchmarks LANGUAGES C CXX) + +option(ENABLE_NATIVE_COMPILATION "Compile with -march=native" ON) +option(ENABLE_WIDE_VECTORS "Compile with 512bit vectors if available" ON) +option(ENABLE_OPENMP "Use OpenMP for a multithreading benchmark" OFF) + +# --- Import tools ---- + +include(../cmake/tools.cmake) + +# ---- Dependencies ---- + +include(../cmake/CPM.cmake) + +# ---- compile_commands.json ---- +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +CPMAddPackage( + NAME benchmark + GITHUB_REPOSITORY google/benchmark + VERSION 1.8.3 + OPTIONS "BENCHMARK_ENABLE_TESTING Off" "BENCHMARK_ENABLE_LIBPFM On" "BENCHMARK_ENABLE_WERROR Off" + "BENCHMARK_ENABLE_EXCEPTIONS Off" SYSTEM TRUE +) +if(benchmark_ADDED) + # enable c++11 to avoid compilation errors + set_target_properties(benchmark PROPERTIES CXX_STANDARD 11) +endif() + +# FetchContent_Declare( Math GIT_REPOSITORY git@github.com:LoopModels/Math.git GIT_TAG origin/main ) +# FetchContent_MakeAvailable(Math) + +# file(GLOB_RECURSE headers CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp) +file(GLOB benchmarks CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) + +add_executable(${PROJECT_NAME} ${benchmarks}) + +message(STATUS "PROJECT_BINARY_DIR: ${PROJECT_BINARY_DIR}") +message(STATUS "PROJECT_SOURCE_DIR: ${PROJECT_SOURCE_DIR}") +message(STATUS "LLVM_INCLUDE_DIRS: ${LLVM_INCLUDE_DIRS}") + +target_include_directories( + ${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/../include # ${PROJECT_SOURCE_DIR}/include +) +if(ENABLE_OPENMP) + find_package(OpenMP) + target_link_libraries(${PROJECT_NAME} OpenMP::OpenMP_CXX) +endif() +target_link_libraries(${PROJECT_NAME} PRIVATE benchmark::benchmark_main) + +if((CMAKE_CXX_COMPILER_ID MATCHES "Clang") OR (CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")) + target_compile_options(${PROJECT_NAME} PRIVATE -ferror-limit=2 -fcolor-diagnostics) +elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU") + target_compile_options( + ${PROJECT_NAME} PRIVATE -fmax-errors=2 -fconcepts-diagnostics-depth=4 + -fno-semantic-interposition -fdiagnostics-color=always -fverbose-asm + ) +endif() + +if(ENABLE_NATIVE_COMPILATION) + if(CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM") + target_compile_options(${PROJECT_NAME} PRIVATE -xhost) + if(ENABLE_WIDE_VECTORS) + target_compile_options(${PROJECT_NAME} PRIVATE -qopt-zmm-usage=high) + endif() + else() + target_compile_options(${PROJECT_NAME} PRIVATE -march=native) # -fno-unroll-loops) + if(ENABLE_WIDE_VECTORS) + check_cxx_compiler_flag("-mprefer-vector-width=512" VEC512) + if(VEC512) + target_compile_options(${PROJECT_NAME} PRIVATE -mprefer-vector-width=512) + endif() + endif() + endif() +endif() +set_target_properties( + ${PROJECT_NAME} + PROPERTIES CXX_STANDARD 23 + CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN ON +) +set_target_properties( + ${PROJECT_NAME} PROPERTIES ENVIRONMENT WORKING_DIRECTORY=${PROJECT_BINARY_DIR} +) + +target_compile_options( + ${PROJECT_NAME} + PRIVATE -fno-exceptions + -fno-rtti + -fstrict-aliasing + -fno-plt + -fstrict-overflow + -fomit-frame-pointer + -fno-signed-zeros + -fassociative-math + -ffinite-math-only + -funsafe-math-optimizations + -fno-trapping-math + -Wall + -Wshadow + -Wextra + -save-temps + -Werror +) +if(ENABLE_OPENMP) + if(CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM") + target_compile_options(${PROJECT_NAME} PRIVATE -fiopenmp) + else() + target_compile_options(${PROJECT_NAME} PRIVATE -fopenmp) + endif() +else() + target_compile_options(${PROJECT_NAME} PRIVATE -fopenmp-simd) +endif() +if(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)") + target_compile_options(${PROJECT_NAME} PRIVATE -masm=intel) +endif() diff --git a/benchmark/dual_benchmark.cpp b/benchmark/dual_benchmark.cpp new file mode 100644 index 0000000..cb09df8 --- /dev/null +++ b/benchmark/dual_benchmark.cpp @@ -0,0 +1,195 @@ + +#include "include/randdual.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using poly::math::Dual, poly::math::SquareMatrix, poly::math::SquareDims, + poly::math::I, poly::math::URand; + +[[gnu::noinline]] void prod(auto &c, const auto &a, const auto &b) { + c = a * b; +} + +static void BM_dual8x2prod(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + D a = URand{}(rng0), b = URand{}(rng0), c; + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual8x2prod); + +template struct ManualDual { + T value; + poly::math::SVector partials; +}; + +template struct ManualDual { + T value; + poly::simd::Vec partials; +}; +template struct ManualDual { + T value; + poly::math::StaticArray partials; +}; +template +[[gnu::always_inline]] constexpr auto operator*(const ManualDual &a, + const ManualDual &b) + -> ManualDual { + return {a.value * b.value, a.value * b.partials + b.value * a.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator*(const ManualDual &a, + const T &b) + -> ManualDual { + return {a.value * b, b * a.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator*(const T &a, + const ManualDual &b) + -> ManualDual { + return {b.value * a, a * b.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator+(const ManualDual &a, + const ManualDual &b) + -> ManualDual { + return {a.value + b.value, a.partials + b.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator+(const ManualDual &a, + const T &b) + -> ManualDual { + return {a.value + b, a.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator+(const T &a, + const ManualDual &b) + -> ManualDual { + return {b.value + a, b.partials}; +} +// template +// [[gnu::noinline]] void prod_manual(ManualDual, N> &c, +// const ManualDual, N> &a, +// const ManualDual, N> &b) +// { +// // return {val * other.val, val * other.partials + other.val * partials}; +// c.value= a.value* b.value; +// c.partials = a.value* b.partials+ b.value* a.partials; +// } + +template auto setup_manual() { + using D = ManualDual, N>; + std::mt19937_64 rng0; + D a{}, b{}, c{}; + a.value.value = URand{}(rng0); + b.value.value = URand{}(rng0); + for (ptrdiff_t j = 0; j < M; ++j) { + a.value.partials[j] = URand{}(rng0); + b.value.partials[j] = URand{}(rng0); + } + for (ptrdiff_t i = 0; i < N; ++i) { + a.partials[i].value = URand{}(rng0); + b.partials[i].value = URand{}(rng0); + for (ptrdiff_t j = 0; j < M; ++j) { + a.partials[i].partials[j] = URand{}(rng0); + b.partials[i].partials[j] = URand{}(rng0); + } + } + return std::array{a, b, c}; +} + +static void BM_dual8x2prod_manual(benchmark::State &state) { + auto [a, b, c] = setup_manual<8, 2, false>(); + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual8x2prod_manual); + +static void BM_dual8x2prod_simdarray(benchmark::State &state) { + auto [a, b, c] = setup_manual<8, 2, true>(); + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual8x2prod_simdarray); + +static void BM_dual7x2prod(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + static_assert(std::same_as, 2, true>>>); + // static_assert(sizeof(D) == sizeof(Dual, 2>)); + static_assert(poly::utils::Compressible); + D a = URand{}(rng0), b = URand{}(rng0), c; + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual7x2prod); + +static void BM_dual7x2prod_manual(benchmark::State &state) { + auto [a, b, c] = setup_manual<7, 2, false>(); + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual7x2prod_manual); + +static void BM_dual7x2prod_simdarray(benchmark::State &state) { + auto [a, b, c] = setup_manual<7, 2, true>(); + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual7x2prod_simdarray); + +static void BM_dual6x2prod(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + // static_assert(sizeof(D) == sizeof(Dual, 2>)); + static_assert(poly::utils::Compressible); + D a = URand{}(rng0), b = URand{}(rng0), c; + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual6x2prod); + +static void BM_dual6x2prod_manual(benchmark::State &state) { + auto [a, b, c] = setup_manual<6, 2, false>(); + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual6x2prod_manual); + +static void BM_dual6x2prod_simdarray(benchmark::State &state) { + auto [a, b, c] = setup_manual<6, 2, true>(); + for (auto _ : state) { + prod(c, a, b); + benchmark::DoNotOptimize(c); + } +} +BENCHMARK(BM_dual6x2prod_simdarray); diff --git a/benchmark/dual_elt_benchmarks.cpp b/benchmark/dual_elt_benchmarks.cpp new file mode 100644 index 0000000..bbb1227 --- /dev/null +++ b/benchmark/dual_elt_benchmarks.cpp @@ -0,0 +1,149 @@ + +#include "include/randdual.hpp" +#include + +using poly::math::Dual, poly::math::SquareDims, poly::math::SquareMatrix, + poly::math::MutArray, poly::math::Array, poly::math::URand, + poly::containers::tie, poly::containers::Tuple; + +template +constexpr void tuplecheck(Tuple &, const Tuple &) { + using C = poly::math::scalarize_via_cast_t< + std::remove_cvref_t().view())>>; + static_assert( + !std::same_as && + poly::math::ScalarizeViaCastTo().view()), + Bs...>()); +} + +template +[[gnu::noinline]] void eltmul(MutArray A, double t) { + A *= t; +} + +template +[[gnu::noinline]] void eltadd(MutArray C, Array A, Array B) { + static_assert( + std::same_as>>); + static_assert( + std::same_as>); + C << A + B; +} +template +[[gnu::noinline]] void eltaddsub(MutArray C, MutArray D, + Array A, Array B) { + { + auto lval{tie(C, D)}; + tuplecheck(lval, Tuple(A + B, A - B)); + } + tie(C, D) << Tuple(A + B, A - B); +} + +template static void BM_dualNdoublemul(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + double t = 1.00000000001; + for (auto b : state) eltmul(A, t); +} + +template +static void BM_dualMxNdoublemul(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, N>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + double t = 1.00000000001; + for (auto b : state) eltmul(A, t); +} + +template static void BM_dualNadd(benchmark::State &state) { + std::mt19937_64 rng0; + using T = Dual; + SquareDims<> dim{state.range(0)}; + SquareMatrix A{dim}, B{dim}, C{dim}; + for (auto &&a : A) a = URand{}(rng0); + for (auto &&b : B) b = URand{}(rng0); + for (auto b : state) eltadd(C, A, B); +} +template +static void BM_dualMxNadd(benchmark::State &state) { + std::mt19937_64 rng0; + using T = Dual, N>; + SquareDims<> dim{state.range(0)}; + SquareMatrix A{dim}, B{dim}, C{dim}; + for (auto &&a : A) a = URand{}(rng0); + for (auto &&b : B) b = URand{}(rng0); + for (auto b : state) eltadd(C, A, B); +} +template static void BM_dualNaddsub(benchmark::State &state) { + std::mt19937_64 rng0; + using T = Dual; + SquareDims<> dim{state.range(0)}; + SquareMatrix A{dim}, B{dim}, C{dim}, D{dim}; + for (auto &&a : A) a = URand{}(rng0); + for (auto &&b : B) b = URand{}(rng0); + for (auto b : state) eltaddsub(C, D, A, B); +} +template +static void BM_dualMxNaddsub(benchmark::State &state) { + std::mt19937_64 rng0; + using T = Dual, N>; + SquareDims<> dim{state.range(0)}; + SquareMatrix A{dim}, B{dim}, C{dim}, D{dim}; + for (auto &&a : A) a = URand{}(rng0); + for (auto &&b : B) b = URand{}(rng0); + for (auto b : state) eltaddsub(C, D, A, B); +} + +BENCHMARK(BM_dualNadd<1>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNadd<2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNadd<3>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNadd<4>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNadd<5>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNadd<6>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNadd<7>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNadd<8>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<1, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<2, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<3, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<4, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<5, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<6, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<7, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNadd<8, 2>)->DenseRange(2, 10, 1); + +BENCHMARK(BM_dualNaddsub<1>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNaddsub<2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNaddsub<3>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNaddsub<4>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNaddsub<5>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNaddsub<6>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNaddsub<7>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNaddsub<8>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<1, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<2, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<3, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<4, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<5, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<6, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<7, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNaddsub<8, 2>)->DenseRange(2, 10, 1); + +BENCHMARK(BM_dualNdoublemul<1>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNdoublemul<2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNdoublemul<3>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNdoublemul<4>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNdoublemul<5>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNdoublemul<6>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNdoublemul<7>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualNdoublemul<8>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<1, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<2, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<3, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<4, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<5, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<6, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<7, 2>)->DenseRange(2, 10, 1); +BENCHMARK(BM_dualMxNdoublemul<8, 2>)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark.cpp b/benchmark/expm_benchmark.cpp new file mode 100644 index 0000000..a771b1b --- /dev/null +++ b/benchmark/expm_benchmark.cpp @@ -0,0 +1,9 @@ +#include "include/expm.hpp" + +static void BM_expm(benchmark::State &state) { + std::mt19937_64 rng0; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark1.cpp b/benchmark/expm_benchmark1.cpp new file mode 100644 index 0000000..e431e85 --- /dev/null +++ b/benchmark/expm_benchmark1.cpp @@ -0,0 +1,11 @@ +#include "include/expm.hpp" + +static void BM_expm_dual1(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} + +BENCHMARK(BM_expm_dual1)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark1x2.cpp b/benchmark/expm_benchmark1x2.cpp new file mode 100644 index 0000000..e070605 --- /dev/null +++ b/benchmark/expm_benchmark1x2.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual1x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual1x2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark2.cpp b/benchmark/expm_benchmark2.cpp new file mode 100644 index 0000000..7206515 --- /dev/null +++ b/benchmark/expm_benchmark2.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark2x2.cpp b/benchmark/expm_benchmark2x2.cpp new file mode 100644 index 0000000..ff74b54 --- /dev/null +++ b/benchmark/expm_benchmark2x2.cpp @@ -0,0 +1,11 @@ +#include "include/expm.hpp" + +static void BM_expm_dual2x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} + +BENCHMARK(BM_expm_dual2x2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark3.cpp b/benchmark/expm_benchmark3.cpp new file mode 100644 index 0000000..e88d0b8 --- /dev/null +++ b/benchmark/expm_benchmark3.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual3(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual3)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark3x2.cpp b/benchmark/expm_benchmark3x2.cpp new file mode 100644 index 0000000..65e96f9 --- /dev/null +++ b/benchmark/expm_benchmark3x2.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual3x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual3x2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark4.cpp b/benchmark/expm_benchmark4.cpp new file mode 100644 index 0000000..ac799b6 --- /dev/null +++ b/benchmark/expm_benchmark4.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual4(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual4)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark4x2.cpp b/benchmark/expm_benchmark4x2.cpp new file mode 100644 index 0000000..dca8287 --- /dev/null +++ b/benchmark/expm_benchmark4x2.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual4x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual4x2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark5.cpp b/benchmark/expm_benchmark5.cpp new file mode 100644 index 0000000..431e496 --- /dev/null +++ b/benchmark/expm_benchmark5.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual5(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual5)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark5x2.cpp b/benchmark/expm_benchmark5x2.cpp new file mode 100644 index 0000000..25ed2e1 --- /dev/null +++ b/benchmark/expm_benchmark5x2.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual5x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual5x2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark6.cpp b/benchmark/expm_benchmark6.cpp new file mode 100644 index 0000000..2ac8a16 --- /dev/null +++ b/benchmark/expm_benchmark6.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual6(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual6)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark6x2.cpp b/benchmark/expm_benchmark6x2.cpp new file mode 100644 index 0000000..5702dfd --- /dev/null +++ b/benchmark/expm_benchmark6x2.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual6x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual6x2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark7.cpp b/benchmark/expm_benchmark7.cpp new file mode 100644 index 0000000..6a0ad4f --- /dev/null +++ b/benchmark/expm_benchmark7.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual7(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual7)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark7x2.cpp b/benchmark/expm_benchmark7x2.cpp new file mode 100644 index 0000000..dcf0671 --- /dev/null +++ b/benchmark/expm_benchmark7x2.cpp @@ -0,0 +1,32 @@ +#include "include/expm.hpp" + +static void BM_expm_dual7x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + static_assert( + std::same_as, true>, + poly::math::Array, true>, std::plus<>>, + decltype(A + A)>); + static_assert( + std::same_as, true>>>); + static_assert( + std::same_as>); + static_assert( + std::same_as< + poly::math::ElementwiseBinaryOp, true>, + double, std::multiplies<>>, + decltype(A * 2.3)>); + static_assert( + std::same_as>); + static_assert( + std::same_as>); + static_assert(poly::math::ScalarizeViaCastTo< + poly::math::scalarize_via_cast_t, + decltype(2.3 * A)>()); + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual7x2)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark8.cpp b/benchmark/expm_benchmark8.cpp new file mode 100644 index 0000000..6da850d --- /dev/null +++ b/benchmark/expm_benchmark8.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual8(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual8)->DenseRange(2, 10, 1); diff --git a/benchmark/expm_benchmark8x2.cpp b/benchmark/expm_benchmark8x2.cpp new file mode 100644 index 0000000..d82b4c7 --- /dev/null +++ b/benchmark/expm_benchmark8x2.cpp @@ -0,0 +1,10 @@ +#include "include/expm.hpp" + +static void BM_expm_dual8x2(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + SquareMatrix A{SquareDims{{state.range(0)}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) expbench(A); +} +BENCHMARK(BM_expm_dual8x2)->DenseRange(2, 10, 1); diff --git a/benchmark/include/expm.hpp b/benchmark/include/expm.hpp new file mode 100644 index 0000000..4dcb818 --- /dev/null +++ b/benchmark/include/expm.hpp @@ -0,0 +1,136 @@ +#pragma once +#ifndef expm_hpp_INCLUDED +#define expm_hpp_INCLUDED + +#include "randdual.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// auto x = Dual, 2>{1.0}; +// auto y = x * 3.4; +namespace poly::math { +static_assert(std::convertible_to>); +static_assert(std::convertible_to, 2>>); + +template +constexpr void evalpoly(MutSquarePtrMatrix B, MutSquarePtrMatrix A, + SquarePtrMatrix C, const auto &p) { + ptrdiff_t N = p.size(); + invariant(N > 0); + invariant(ptrdiff_t(B.numRow()), ptrdiff_t(C.numRow())); + if (N & 1) std::swap(A, B); + B << p[0] * C + p[1] * I; + for (ptrdiff_t i = 2; i < N; ++i) { + std::swap(A, B); + B << A * C + p[i] * I; + } +} + +template constexpr auto opnorm1(const T &A) { + using S = decltype(value(std::declval>())); + auto [M, N] = shape(A); + invariant(M > 0); + invariant(N > 0); + S a{}; + for (ptrdiff_t n = 0; n < N; ++n) { + S s{}; + for (ptrdiff_t m = 0; m < M; ++m) s += std::abs(value(A[m, n])); + a = std::max(a, s); + } + return a; + // Vector v{N}; + // for (ptrdiff_t n = 0; n < N; ++n) + // v[n] = std::abs(value(A[0, n])); + // for (ptrdiff_t m = 1; m < M; ++m) + // for (ptrdiff_t n = 0; n < N; ++n) + // v[n] += std::abs(value(A[m, n])); + // return *std::max_element(v.begin(), v.end()); +} + +/// computes ceil(log2(x)) for x >= 1 +constexpr auto log2ceil(double x) -> ptrdiff_t { + invariant(x >= 1); + uint64_t u = std::bit_cast(x) - 1; + auto y = ptrdiff_t((u >> 52) - 1022); + invariant(y >= 0); + return y; +} + +template constexpr void expm(MutSquarePtrMatrix A) { + ptrdiff_t n = ptrdiff_t(A.numRow()), s = 0; + SquareMatrix A2{SquareDims<>{{n}}}, U_{SquareDims<>{{n}}}; + MutSquarePtrMatrix U{U_}; + if (double nA = opnorm1(A); nA <= 0.015) { + A2 << A * A; + U << A * (A2 + 60.0 * I); + A << 12.0 * A2 + 120.0 * I; + } else { + SquareMatrix B{SquareDims<>{{n}}}; + if (nA <= 2.1) { + A2 << A * A; + containers::TinyVector p0, p1; + if (nA > 0.95) { + p0 = {1.0, 3960.0, 2162160.0, 302702400.0, 8821612800.0}; + p1 = {90.0, 110880.0, 3.027024e7, 2.0756736e9, 1.76432256e10}; + } else if (nA > 0.25) { + p0 = {1.0, 1512.0, 277200.0, 8.64864e6}; + p1 = {56.0, 25200.0, 1.99584e6, 1.729728e7}; + } else { + p0 = {1.0, 420.0, 15120.0}; + p1 = {30.0, 3360.0, 30240.0}; + } + evalpoly(B, U, A2, p0); + U << A * B; + evalpoly(A, B, A2, p1); + } else { + // s = std::max(unsigned(std::ceil(std::log2(nA / 5.4))), 0); + s = nA > 5.4 ? log2ceil(nA / 5.4) : 0; + if (s & 1) { // we'll swap `U` and `A` an odd number of times + std::swap(A, U); // so let them switch places + A << U * exp2(-s); + } else if (s > 0) A *= exp2(-s); + A2 << A * A; + // here we take an estrin (instead of horner) approach to cut down flops + SquareMatrix A4{A2 * A2}, A6{A2 * A4}; + B << A6 * (A6 + 16380 * A4 + 40840800 * A2) + + (33522128640 * A6 + 10559470521600 * A4 + 1187353796428800 * A2) + + 32382376266240000 * I; + U << A * B; + A << A6 * (182 * A6 + 960960 * A4 + 1323241920 * A2) + + (670442572800 * A6 + 129060195264000 * A4 + + 7771770303897600 * A2) + + 64764752532480000 * I; + } + } + containers::tie(A, U) << containers::Tuple(A + U, A - U); + LU::ldiv(U, MutPtrMatrix(A)); + for (; s--; std::swap(A, U)) U << A * A; +} + +} // namespace poly::math + +using poly::math::Dual, poly::math::SquareDims, poly::math::SquareMatrix, + poly::math::URand; + +auto expwork(const auto &A) { + SquareMatrix> C{SquareDims{A.numRow()}}, + B{A}; + expm(B); + for (size_t i = 0; i < 8; ++i) { + expm(C << A * exp2(-double(i))); + B += C; + } + return B; +} +void expbench(const auto &A) { benchmark::DoNotOptimize(expwork(A)); } + +#endif // expm_hpp_INCLUDED diff --git a/benchmark/include/randdual.hpp b/benchmark/include/randdual.hpp new file mode 100644 index 0000000..2ab16dd --- /dev/null +++ b/benchmark/include/randdual.hpp @@ -0,0 +1,26 @@ +#pragma once +#ifndef randdual_hpp_INCLUDED +#define randdual_hpp_INCLUDED + +#include +#include +#include + +namespace poly::math { +template struct URand {}; + +template struct URand> { + auto operator()(std::mt19937_64 &rng) -> Dual { + Dual x{URand{}(rng)}; + for (size_t i = 0; i < N; ++i) x.gradient()[i] = URand{}(rng); + return x; + } +}; +template <> struct URand { + auto operator()(std::mt19937_64 &rng) -> double { + return std::uniform_real_distribution(-2, 2)(rng); + } +}; +} // namespace poly::math + +#endif // randdual_hpp_INCLUDED diff --git a/benchmark/integer_matrix_benchmarks.cpp b/benchmark/integer_matrix_benchmarks.cpp new file mode 100644 index 0000000..6a8e3b3 --- /dev/null +++ b/benchmark/integer_matrix_benchmarks.cpp @@ -0,0 +1,26 @@ +#include "Math/LinearAlgebra.hpp" +#include "Math/NormalForm.hpp" +#include +#include +#include + +using namespace poly; + +static void BM_normal_form(benchmark::State &state) { + using math::_; + std::mt19937_64 rng0; + std::uniform_int_distribution<> distrib(-10, 10); + ptrdiff_t d = state.range(0), numIter = 100; + math::DenseDims dim{math::DenseDims<>{{numIter * d}, {d}}}; + math::DenseMatrix A{dim}, B{dim}, C{dim}, D{dim}; + for (auto &&x : C) x = distrib(rng0); + for (auto &&x : D) x = distrib(rng0); + for (auto b : state) { + A << C; + B << D; + for (ptrdiff_t n = 0; n < numIter; ++n) + math::NormalForm::solveSystem(A[_(n * d, (n + 1) * d), _], + B[_(n * d, (n + 1) * d), _]); + } +} +BENCHMARK(BM_normal_form)->DenseRange(2, 10, 1); diff --git a/benchmark/simplex_benchmark.cpp b/benchmark/simplex_benchmark.cpp new file mode 100644 index 0000000..c09a502 --- /dev/null +++ b/benchmark/simplex_benchmark.cpp @@ -0,0 +1,1131 @@ +#include +#include +#include + +using poly::utils::operator""_mat, poly::math::_; + +static void BM_Simplex0(benchmark::State &state) { + poly::math::DenseMatrix tableau{ + "[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 1 0 1 -1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 " + "0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 1 -1 0 0 0 0 0 " + "0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 1 -1 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 -1 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 1 0 -1 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 -1 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "-1 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 " + "0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 1 -1 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 -1 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "-1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 " + "0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 1 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 -1 0 1 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 1 0 -1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 -1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 " + "-1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "-1 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + ";" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 -1 0 1 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "1 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 1 0 -1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "-1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "-1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 " + "0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 -1 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 -1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 -1 " + "0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 1 0 -1 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 1 0 -1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "1 0 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "1 0 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ;" + "1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]"_mat}; + + tableau[0, _] << -5859553999884210514; + poly::alloc::OwningArena<> alloc; + ptrdiff_t numCon = ptrdiff_t(tableau.numRow()) - 1; + ptrdiff_t numVar = ptrdiff_t(tableau.numCol()) - 1; + poly::utils::Valid simpBackup{ + poly::math::Simplex::create(&alloc, numCon, numVar)}; + simpBackup->getTableau() << tableau; + // Simplex simpBackup{tableau}; + poly::utils::Valid simp{poly::math::Simplex::create( + &alloc, simpBackup->getNumCons(), simpBackup->getNumVars())}; + // Vector sol(37); + for (auto b : state) { + *simp << *simpBackup; + bool fail = simp->initiateFeasible(); + assert(!fail); + if (!fail) simp->rLexMinLast(37); + } + alloc.reset(); +} +BENCHMARK(BM_Simplex0); + +static void BM_Simplex1(benchmark::State &state) { + poly::math::IntMatrix<> tableau{ + "[0 0 0 1 0 -1 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 1 0 -1 0 0 725849473193 " + "94205055327856 11 11 11 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 -1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 1 0 -1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "0 0 -1 0 725849473193 94205055277312 6 6 1 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 0 " + "0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 0 -1 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -2 0 -1 0 2 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 -1 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -2 0 -1 0 2 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 -1 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 1 -1 0 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 1 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 1 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 2 0 1 0 -2 0 -1 0 0 1 -1 0 0 0 0 0 0 0 -2 0 0 -1 -1 0 0 0 0 1 0 0 " + "0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 2 0 1 0 -2 0 -1 0 1 -1 0 0 0 0 0 0 0 -2 0 0 -1 -1 0 0 0 0 0 0 0 1 0 " + "0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 -1 0 -1 0 -1 0 -1 0 " + "-1 0 -1 0 -1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 -1 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 -1 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 -1 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 -1 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 -1 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 -1 0 2 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 " + "0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 -1 0 2 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 1 " + "1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 " + "0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 1 -1 0 0 0 0 0 0 1 " + "-1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 -2 0 -1 0 0 1 -1 0 0 0 0 0 0 0 -2 " + "0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 -2 0 -1 0 1 -1 0 0 0 0 0 0 0 -2 0 0 " + "-1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 " + "0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 -2 0 0 -2 2 0 0 " + "-1 0 -1 0 -1 0 -1 0 -1 -2 -1 2 -3 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 " + "0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 1 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 -1 0 2 0 1 0 " + "0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 -1 0 2 0 1 0 0 " + "0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -1 0 " + "0 0 0 0 0 1 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 -1 0 0 " + "0 0 0 1 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 " + "0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 -2 0 -1 0 " + "0 1 -1 0 0 0 0 0 0 0 -2 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 " + "0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 1 0 -2 0 -1 0 1 " + "-1 0 0 0 0 0 0 0 -2 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 " + "0 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 2 -2 0 0 -2 2 0 0 -1 0 -1 0 -1 0 -1 0 -1 -2 -1 2 -3 0 1 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 -1 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "-1 0 0 0 0 0 0 ;" + "0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 " + "0 0 0 0 0 0 0 ;" + "0 0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 -1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 -2 0 -1 0 2 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 -2 0 -1 0 2 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 0 1 0 0 0 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 0 1 0 0 0 -1 0 0 0 0 0 1 -1 0 0 0 0 0 0 1 -1 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 " + "0 0 0 0 0 0 0 0 ;" + "0 0 0 2 0 1 0 -2 0 -1 0 0 1 -1 0 0 0 0 0 0 0 -2 0 0 -1 -1 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 " + "0 0 0 0 0 0 0 0 0 ;" + "0 0 2 0 1 0 -2 0 -1 0 1 -1 0 0 0 0 0 0 0 -2 0 0 -1 -1 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 " + "0 0 0 0 0 0 0 0 0 ;" + "1 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 " + "0 0 0 0 0 0 0 0 0 ]"_mat}; + + poly::alloc::OwningArena<> alloc; + ptrdiff_t numCon = ptrdiff_t(tableau.numRow()) - 1; + ptrdiff_t numVar = ptrdiff_t(tableau.numCol()) - 1; + poly::utils::Valid simpBackup{ + poly::math::Simplex::create(&alloc, numCon, numVar, 0)}; + simpBackup->getTableau() << tableau; + poly::utils::Valid simp{poly::math::Simplex::create( + &alloc, simpBackup->getNumCons(), simpBackup->getNumVars(), 0)}; + for (auto b : state) { + *simp << *simpBackup; + bool fail = simp->initiateFeasible(); + assert(!fail); + if (!fail) simp->rLexMinLast(15); + } +} +BENCHMARK(BM_Simplex1); diff --git a/benchmark/tensor_benchmark.cpp b/benchmark/tensor_benchmark.cpp new file mode 100644 index 0000000..df06604 --- /dev/null +++ b/benchmark/tensor_benchmark.cpp @@ -0,0 +1,202 @@ + +#include "include/randdual.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using poly::math::Dual, poly::math::SquareMatrix, poly::math::SquareDims, + poly::math::I, poly::math::URand; + +static void BM_dual8x2dApI(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) benchmark::DoNotOptimize(B << 12.0 * A + 120.0 * I); +} +BENCHMARK(BM_dual8x2dApI)->DenseRange(2, 10, 1); + +static void BM_dual8x2BmApI(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + SquareMatrix C{SquareDims{{dim}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto &&b : B) b = URand{}(rng0); + for (auto b : state) benchmark::DoNotOptimize(C << B * (A + 60.0 * I)); +} +BENCHMARK(BM_dual8x2BmApI)->DenseRange(2, 10, 1); + +template +void BtimesAplusdI( + poly::math::MutSquarePtrMatrix, N>> C, + poly::math::MutSquarePtrMatrix, N>> A, + poly::math::MutSquarePtrMatrix, N>> B, + double doffset) { + using T = std::array, N>; + poly::utils::invariant(C.numRow() == A.numRow()); + poly::utils::invariant(C.numRow() == B.numRow()); + ptrdiff_t D = ptrdiff_t(C.numRow()); + POLYMATHNOVECTORIZE + for (ptrdiff_t r = 0; r < D; ++r) { + POLYMATHNOVECTORIZE + for (ptrdiff_t c = 0; c < D; ++c) { + T x{}; + POLYMATHNOVECTORIZE + for (ptrdiff_t k = 0; k < D; ++k) { + // x += B[r, k] * A[k, c]; + T &Brk = B[r, k]; + T &Akc = A[k, c]; + // x[0] += Brk[0] * Akc[0]; + x[0][0] += Brk[0][0] * (Akc[0][0] + doffset * (r == c)); + POLYMATHVECTORIZE + for (size_t i = 1; i < M; ++i) + x[0][i] += Brk[0][0] * Akc[0][i] + Brk[0][i] * Akc[0][0]; + POLYMATHNOVECTORIZE + for (size_t o = 1; o < N; ++o) { + // x[o] += Brk[0]*Akc[o]; + x[o][0] += Brk[0][0] * Akc[o][0]; + POLYMATHVECTORIZE + for (size_t i = 1; i < M; ++i) + x[o][i] += Brk[0][0] * Akc[o][i] + Brk[0][i] * Akc[o][0]; + // x[o] += Brk[o]*Akc[0]; + x[o][0] += Brk[o][0] * Akc[0][0]; + POLYMATHVECTORIZE + for (size_t i = 1; i < M; ++i) + x[o][i] += Brk[o][0] * Akc[0][i] + Brk[o][i] * Akc[0][0]; + } + } + C[r, c] = x; + } + } +} + +static void BM_dual8x2BmApI_manual(benchmark::State &state) { + std::mt19937_64 rng0; + using D = std::array, 3>; + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + SquareMatrix C{SquareDims{{dim}}}; + for (ptrdiff_t i = 0, L = dim * dim; i < L; ++i) { + for (ptrdiff_t j = 0; j < 3; ++j) { + for (ptrdiff_t k = 0; k < 9; ++k) { + A[i][j][k] = URand{}(rng0); + B[i][j][k] = URand{}(rng0); + } + } + } + for (auto b : state) BtimesAplusdI(C, A, B, 60.0); +} +BENCHMARK(BM_dual8x2BmApI_manual)->DenseRange(2, 10, 1); + +static void BM_dual7x2dApI(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + static_assert(poly::utils::Compressible>); + static_assert(poly::utils::Compressible); + static_assert(sizeof(poly::utils::compressed_t) == (24 * sizeof(double))); + static_assert(sizeof(D) == (24 * sizeof(double))); + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) benchmark::DoNotOptimize(B << 12.0 * A + 120.0 * I); +} +BENCHMARK(BM_dual7x2dApI)->DenseRange(2, 10, 1); + +static void BM_dual7x2BmApI(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + SquareMatrix C{SquareDims{{dim}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto &&b : B) b = URand{}(rng0); + for (auto b : state) benchmark::DoNotOptimize(C << B * (A + 60.0 * I)); +} +BENCHMARK(BM_dual7x2BmApI)->DenseRange(2, 10, 1); + +static void BM_dual7x2BmApI_manual(benchmark::State &state) { + std::mt19937_64 rng0; + using D = std::array, 3>; + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + SquareMatrix C{SquareDims{{dim}}}; + for (ptrdiff_t i = 0, L = dim * dim; i < L; ++i) { + for (ptrdiff_t j = 0; j < 3; ++j) { + for (ptrdiff_t k = 0; k < 8; ++k) { + A[i][j][k] = URand{}(rng0); + B[i][j][k] = URand{}(rng0); + } + } + } + for (auto b : state) BtimesAplusdI(C, A, B, 60.0); +} +BENCHMARK(BM_dual7x2BmApI_manual)->DenseRange(2, 10, 1); + +static void BM_dual6x2dApI(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + static_assert(poly::utils::Compressible>); + static_assert(poly::utils::Compressible); + static_assert(sizeof(poly::utils::compressed_t) == (21 * sizeof(double))); + static_assert(sizeof(D) == (24 * sizeof(double))); + // static_assert(sizeof(D) == sizeof(Dual, 2>)); + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto b : state) benchmark::DoNotOptimize(B << 12.0 * A + 120.0 * I); +} +BENCHMARK(BM_dual6x2dApI)->DenseRange(2, 10, 1); + +static void BM_dual6x2BmApI(benchmark::State &state) { + std::mt19937_64 rng0; + using D = Dual, 2>; + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + SquareMatrix C{SquareDims{{dim}}}; + for (auto &&a : A) a = URand{}(rng0); + for (auto &&b : B) b = URand{}(rng0); + for (auto b : state) benchmark::DoNotOptimize(C << B * (A + 60.0 * I)); +} +BENCHMARK(BM_dual6x2BmApI)->DenseRange(2, 10, 1); + +static void BM_dual6x2BmApI_manual(benchmark::State &state) { + std::mt19937_64 rng0; + constexpr size_t Dcount = 6; + constexpr size_t N = Dcount + 1; + using D = std::array, 3>; + ptrdiff_t dim = state.range(0); + SquareMatrix A{SquareDims{{dim}}}; + SquareMatrix B{SquareDims{{dim}}}; + SquareMatrix C{SquareDims{{dim}}}; + for (ptrdiff_t i = 0, L = dim * dim; i < L; ++i) { + for (ptrdiff_t j = 0; j < 3; ++j) { + for (size_t k = 0; k < N; ++k) { + A[i][j][k] = URand{}(rng0); + B[i][j][k] = URand{}(rng0); + } + } + } + for (auto b : state) BtimesAplusdI(C, A, B, 60.0); +} +BENCHMARK(BM_dual6x2BmApI_manual)->DenseRange(2, 10, 1); diff --git a/compile_commands.json b/compile_commands.json index 0397689..7657903 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -1,538 +1,917 @@ [ { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -fpch-instantiate-templates -Xclang -emit-pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -x c++-header -o CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -c /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.cxx", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -fpch-instantiate-templates -Xclang -emit-pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -x c++-header -o CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -c /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.cxx", "file": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.cxx", "output": "CMakeFiles/MathTests.dir/cmake_pch.hxx.pch" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/bitset_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/bitset_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/bitset_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/bitset_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/bitset_test.cpp", "output": "CMakeFiles/MathTests.dir/bitset_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/boxopt_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/boxopt_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/boxopt_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/boxopt_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/boxopt_test.cpp", "output": "CMakeFiles/MathTests.dir/boxopt_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/dual_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/dual_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/dual_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/dual_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/dual_test.cpp", "output": "CMakeFiles/MathTests.dir/dual_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/linear_algebra_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/linear_algebra_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/linear_algebra_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/linear_algebra_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/linear_algebra_test.cpp", "output": "CMakeFiles/MathTests.dir/linear_algebra_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/linear_diophantine_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/linear_diophantine_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/linear_diophantine_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/linear_diophantine_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/linear_diophantine_test.cpp", "output": "CMakeFiles/MathTests.dir/linear_diophantine_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/listrange_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/listrange_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/listrange_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/listrange_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/listrange_test.cpp", "output": "CMakeFiles/MathTests.dir/listrange_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/matrix_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/matrix_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/matrix_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/matrix_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/matrix_test.cpp", "output": "CMakeFiles/MathTests.dir/matrix_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/normal_form_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/normal_form_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/normal_form_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/normal_form_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/normal_form_test.cpp", "output": "CMakeFiles/MathTests.dir/normal_form_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/simplex_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/simplex_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/optional_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/optional_test.cpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/optional_test.cpp", + "output": "CMakeFiles/MathTests.dir/optional_test.cpp.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/simplex_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/simplex_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/simplex_test.cpp", "output": "CMakeFiles/MathTests.dir/simplex_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/string_to_intmat_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/string_to_intmat_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/string_to_intmat_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/string_to_intmat_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/string_to_intmat_test.cpp", "output": "CMakeFiles/MathTests.dir/string_to_intmat_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/ulist_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/ulist_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/ulist_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/ulist_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/ulist_test.cpp", "output": "CMakeFiles/MathTests.dir/ulist_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/unimodularization_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/unimodularization_test.cpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -o CMakeFiles/MathTests.dir/unimodularization_test.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/test/unimodularization_test.cpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/test/unimodularization_test.cpp", "output": "CMakeFiles/MathTests.dir/unimodularization_test.cpp.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -o CMakeFiles/gtest.dir/src/gtest-all.cc.o -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-all.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -o CMakeFiles/gtest.dir/src/gtest-all.cc.o -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-all.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-all.cc", "output": "_deps/googletest-build/googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.o" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -o CMakeFiles/gtest_main.dir/src/gtest_main.cc.o -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest_main.cc", + "command": "/bin/clang++ -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -o CMakeFiles/gtest_main.dir/src/gtest_main.cc.o -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest_main.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest_main.cc", "output": "_deps/googletest-build/googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.o" }, +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench", + "command": "/bin/clang++ -DBENCHMARK_STATIC_DEFINE -I/home/chriselrod/Documents/progwork/cxx/Math/benchmark/../include -isystem /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -O3 -DNDEBUG -std=gnu++23 -fvisibility=hidden -fvisibility-inlines-hidden -ferror-limit=2 -fcolor-diagnostics -march=native -mprefer-vector-width=512 -fno-exceptions -fno-rtti -fstrict-aliasing -fno-plt -fstrict-overflow -fomit-frame-pointer -fno-signed-zeros -fassociative-math -ffinite-math-only -funsafe-math-optimizations -fno-trapping-math -Wall -Wshadow -Wextra -save-temps -fopenmp-simd -masm=intel -o CMakeFiles/MathBenchmarks.dir/dual_benchmark.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/benchmark/dual_benchmark.cpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/benchmark/dual_benchmark.cpp", + "output": "CMakeFiles/MathBenchmarks.dir/dual_benchmark.cpp.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench", + "command": "/bin/clang++ -DBENCHMARK_STATIC_DEFINE -I/home/chriselrod/Documents/progwork/cxx/Math/benchmark/../include -isystem /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -O3 -DNDEBUG -std=gnu++23 -fvisibility=hidden -fvisibility-inlines-hidden -ferror-limit=2 -fcolor-diagnostics -march=native -mprefer-vector-width=512 -fno-exceptions -fno-rtti -fstrict-aliasing -fno-plt -fstrict-overflow -fomit-frame-pointer -fno-signed-zeros -fassociative-math -ffinite-math-only -funsafe-math-optimizations -fno-trapping-math -Wall -Wshadow -Wextra -save-temps -fopenmp-simd -masm=intel -o CMakeFiles/MathBenchmarks.dir/expm_benchmark.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/benchmark/expm_benchmark.cpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/benchmark/expm_benchmark.cpp", + "output": "CMakeFiles/MathBenchmarks.dir/expm_benchmark.cpp.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench", + "command": "/bin/clang++ -DBENCHMARK_STATIC_DEFINE -I/home/chriselrod/Documents/progwork/cxx/Math/benchmark/../include -isystem /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -O3 -DNDEBUG -std=gnu++23 -fvisibility=hidden -fvisibility-inlines-hidden -ferror-limit=2 -fcolor-diagnostics -march=native -mprefer-vector-width=512 -fno-exceptions -fno-rtti -fstrict-aliasing -fno-plt -fstrict-overflow -fomit-frame-pointer -fno-signed-zeros -fassociative-math -ffinite-math-only -funsafe-math-optimizations -fno-trapping-math -Wall -Wshadow -Wextra -save-temps -fopenmp-simd -masm=intel -o CMakeFiles/MathBenchmarks.dir/simplex_benchmark.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/benchmark/simplex_benchmark.cpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/benchmark/simplex_benchmark.cpp", + "output": "CMakeFiles/MathBenchmarks.dir/simplex_benchmark.cpp.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench", + "command": "/bin/clang++ -DBENCHMARK_STATIC_DEFINE -I/home/chriselrod/Documents/progwork/cxx/Math/benchmark/../include -isystem /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -O3 -DNDEBUG -std=gnu++23 -fvisibility=hidden -fvisibility-inlines-hidden -ferror-limit=2 -fcolor-diagnostics -march=native -mprefer-vector-width=512 -fno-exceptions -fno-rtti -fstrict-aliasing -fno-plt -fstrict-overflow -fomit-frame-pointer -fno-signed-zeros -fassociative-math -ffinite-math-only -funsafe-math-optimizations -fno-trapping-math -Wall -Wshadow -Wextra -save-temps -fopenmp-simd -masm=intel -o CMakeFiles/MathBenchmarks.dir/tensor_benchmark.cpp.o -c /home/chriselrod/Documents/progwork/cxx/Math/benchmark/tensor_benchmark.cpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/benchmark/tensor_benchmark.cpp", + "output": "CMakeFiles/MathBenchmarks.dir/tensor_benchmark.cpp.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/benchmark.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/benchmark.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/benchmark_api_internal.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_api_internal.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_api_internal.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/benchmark_api_internal.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/benchmark_name.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_name.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_name.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/benchmark_name.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/benchmark_register.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_register.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_register.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/benchmark_register.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/benchmark_runner.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_runner.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_runner.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/benchmark_runner.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/check.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/check.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/check.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/check.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/colorprint.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/colorprint.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/colorprint.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/colorprint.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/commandlineflags.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/commandlineflags.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/commandlineflags.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/commandlineflags.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/complexity.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/complexity.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/complexity.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/complexity.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/console_reporter.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/console_reporter.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/console_reporter.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/console_reporter.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/counter.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/counter.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/counter.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/counter.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/csv_reporter.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/csv_reporter.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/csv_reporter.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/csv_reporter.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/json_reporter.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/json_reporter.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/json_reporter.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/json_reporter.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/perf_counters.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/perf_counters.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/perf_counters.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/perf_counters.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/reporter.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/reporter.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/reporter.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/reporter.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/statistics.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/statistics.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/statistics.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/statistics.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/string_util.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/string_util.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/string_util.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/string_util.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/sysinfo.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/sysinfo.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/sysinfo.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/sysinfo.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark.dir/timers.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/timers.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/timers.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark.dir/timers.cc.o" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -isystem /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -o CMakeFiles/benchmark_main.dir/benchmark_main.cc.o -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_main.cc", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_main.cc", + "output": "_deps/benchmark-build/src/CMakeFiles/benchmark_main.dir/benchmark_main.cc.o" +}, + { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/BitSets.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/BitSets.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Containers/BitSets.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Array.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Array.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Array.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/Storage.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Alloc/Arena.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Alloc/Arena.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Alloc/Mallocator.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Alloc/Mallocator.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench", + "command": "/bin/clang++ -DBENCHMARK_STATIC_DEFINE -I/home/chriselrod/Documents/progwork/cxx/Math/benchmark/../include -isystem /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -O3 -DNDEBUG -std=gnu++23 -fvisibility=hidden -fvisibility-inlines-hidden -ferror-limit=2 -fcolor-diagnostics -march=native -mprefer-vector-width=512 -fno-exceptions -fno-rtti -fstrict-aliasing -fno-plt -fstrict-overflow -fomit-frame-pointer -fno-signed-zeros -fassociative-math -ffinite-math-only -funsafe-math-optimizations -fno-trapping-math -Wall -Wshadow -Wextra -save-temps -fopenmp-simd -masm=intel -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Invariant.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Invariant.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Valid.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Valid.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/Storage.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Containers/Storage.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/ArrayOps.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/ArrayOps.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/ArrayOps.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Indexing.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Indexing.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Indexing.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/AxisTypes.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/AxisTypes.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/AxisTypes.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Invariant.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Invariant.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Iterators.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Iterators.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Iterators.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Iterators.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/MatrixDimensions.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/MatrixDimensions.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/MatrixDimensions.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/MatrixDimensions.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Indexing.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Indexing.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Matrix.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Matrix.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Masks.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Masks.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Vec.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Vec.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Vector.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Vector.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Matrix.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Matrix.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/TypePromotion.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/TypePromotion.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/TypePromotion.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/UniformScaling.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/UniformScaling.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/UniformScaling.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Rational.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Unroll.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Unroll.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Intrin.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/SIMD/Intrin.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/LoopMacros.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/LoopMacros.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Assign.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Assign.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Rational.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Rational.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/GreatestCommonDivisor.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/GreatestCommonDivisor.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/GreatestCommonDivisor.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Alloc/Arena.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Alloc/Arena.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Optional.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Optional.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Valid.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Valid.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Reference.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Reference.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Optional.hpp", - "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Optional.hpp" + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/TypeCompression.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/TypeCompression.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/BoxOpt.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/BoxOpt.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/BoxOpt.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Dual.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Dual.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Dual.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Exp.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Exp.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Exp.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Constructors.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Constructors.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Constructors.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Math.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Math.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Math.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/StaticArrays.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Parameters.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/Parameters.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/StaticArrays.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/StaticArrays.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/LinearAlgebra.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/LinearAlgebra.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/LinearAlgebra.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/BoxOptInt.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/Pair.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Containers/Pair.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/BoxOptInt.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/BoxOptInt.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/TinyVector.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/TinyVector.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Containers/TinyVector.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/LinearDiophantine.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/LinearDiophantine.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/LinearDiophantine.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/ListRanges.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/ListRanges.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/ListRanges.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/SmallSparseMatrix.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/SmallSparseMatrix.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/SmallSparseMatrix.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/MatrixStringParse.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/MatrixStringParse.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Utilities/MatrixStringParse.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Comparisons.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Comparisons.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Comparisons.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/NormalForm.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/NormalForm.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/NormalForm.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/EmptyArrays.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/EmptyArrays.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/EmptyArrays.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/VectorGreatestCommonDivisor.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/VectorGreatestCommonDivisor.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/VectorGreatestCommonDivisor.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Simplex.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Simplex.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Simplex.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Constraints.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Constraints.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Constraints.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/UnrolledList.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Containers/UnrolledList.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Containers/UnrolledList.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Unimodularization.hpp", + "command": "/bin/clang++ -DUSING_MIMALLOC -I/home/chriselrod/Documents/progwork/cxx/Math/include -I/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/math-build/PackageProjectInclude -isystem /home/chriselrod/.local/include/mimalloc-2.1 -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -isystem /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -std=gnu++23 -fno-exceptions -fno-rtti -Wall -Wpedantic -Wextra -Wshadow -Werror -ferror-limit=8 -fcolor-diagnostics -D_GLIBCXX_ASSERTIONS -O0 -g --coverage -Winvalid-pch -Xclang -include-pch -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx.pch -Xclang -include -Xclang /home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/CMakeFiles/MathTests.dir/cmake_pch.hxx -c /home/chriselrod/Documents/progwork/cxx/Math/include/Math/Unimodularization.hpp", "file": "/home/chriselrod/Documents/progwork/cxx/Math/include/Math/Unimodularization.hpp" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-assertion-result.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-assertion-result.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-assertion-result.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-message.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-message.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-message.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-port.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-port.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-port.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest-port.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest-port.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest-port.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-port-arch.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-port-arch.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-port-arch.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-death-test.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-death-test.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-death-test.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-death-test-internal.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-death-test-internal.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-death-test-internal.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-matchers.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-matchers.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-matchers.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-printers.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-printers.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-printers.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-internal.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-internal.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-internal.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-filepath.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-filepath.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-filepath.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-string.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-string.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-string.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-type-util.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-type-util.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-type-util.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest-printers.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest-printers.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest-printers.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-param-test.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-param-test.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-param-test.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-param-util.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-param-util.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/gtest-param-util.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-test-part.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-test-part.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-test-part.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-typed-test.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-typed-test.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-typed-test.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest_pred_impl.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest_pred_impl.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest_pred_impl.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest_prod.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest_prod.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest_prod.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-assertion-result.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-assertion-result.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-assertion-result.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-death-test.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-death-test.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-death-test.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/internal/custom/gtest.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-internal-inl.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-internal-inl.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-internal-inl.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-spi.h", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-spi.h", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include/gtest/gtest-spi.h" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-filepath.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-filepath.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-filepath.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-matchers.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-matchers.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-matchers.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-port.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-port.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-port.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-printers.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-printers.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-printers.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-test-part.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-test-part.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-test-part.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-typed-test.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-typed-test.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest-typed-test.cc" }, { "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/nosan/_deps/googletest-build/googletest", - "command": "/usr/local/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest.cc", + "command": "/bin/clang++ -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/include -I/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest -g -fvisibility=hidden -fvisibility-inlines-hidden -Wall -Wshadow -Wconversion -DGTEST_HAS_PTHREAD=1 -fexceptions -W -Wpointer-arith -Wreturn-type -Wcast-qual -Wwrite-strings -Wswitch -Wunused-parameter -Wcast-align -Wchar-subscripts -Winline -Wredundant-decls -c /home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest.cc", "file": "/home/chriselrod/.cache/CPM/googletest/96129d89f45386492ae46d6bb8c027bc3df5f949/googletest/src/gtest.cc" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench", + "command": "/bin/clang++ -DBENCHMARK_STATIC_DEFINE -I/home/chriselrod/Documents/progwork/cxx/Math/benchmark/../include -isystem /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -O3 -DNDEBUG -std=gnu++23 -fvisibility=hidden -fvisibility-inlines-hidden -ferror-limit=2 -fcolor-diagnostics -march=native -mprefer-vector-width=512 -fno-exceptions -fno-rtti -fstrict-aliasing -fno-plt -fstrict-overflow -fomit-frame-pointer -fno-signed-zeros -fassociative-math -ffinite-math-only -funsafe-math-optimizations -fno-trapping-math -Wall -Wshadow -Wextra -save-temps -fopenmp-simd -masm=intel -c /home/chriselrod/Documents/progwork/cxx/Math/benchmark/include/randdual.hpp", + "file": "/home/chriselrod/Documents/progwork/cxx/Math/benchmark/include/randdual.hpp" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include/benchmark/benchmark.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include/benchmark/benchmark.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include/benchmark/export.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include/benchmark/export.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_api_internal.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_api_internal.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/commandlineflags.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/commandlineflags.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_runner.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_runner.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/internal_macros.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/internal_macros.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/perf_counters.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/perf_counters.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/check.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/check.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/log.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/log.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/mutex.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/mutex.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/thread_manager.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/thread_manager.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/colorprint.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/colorprint.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/complexity.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/complexity.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/counter.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/counter.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/re.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/re.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/statistics.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/statistics.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/string_util.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/string_util.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/thread_timer.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/thread_timer.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/timers.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/timers.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_register.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/benchmark_register.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/arraysize.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/arraysize.h" +}, + +{ + "directory": "/home/chriselrod/Documents/progwork/cxx/Math/buildclang/bench/_deps/benchmark-build/src", + "command": "/bin/clang++ -DBENCHMARK_HAS_PTHREAD_AFFINITY -DBENCHMARK_STATIC_DEFINE -DHAVE_POSIX_REGEX -DHAVE_PTHREAD_AFFINITY -DHAVE_STD_REGEX -DHAVE_STEADY_CLOCK -DHAVE_THREAD_SAFETY_ATTRIBUTES -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/include -I/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src -Wall -Wextra -Wshadow -Wfloat-equal -Wold-style-cast -Wsuggest-override -pedantic -pedantic-errors -Wshorten-64-to-32 -fstrict-aliasing -Wno-deprecated-declarations -fno-exceptions -Wstrict-aliasing -Wthread-safety -O3 -DNDEBUG -std=c++11 -fvisibility=hidden -fvisibility-inlines-hidden -c /home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/cycleclock.h", + "file": "/home/chriselrod/.cache/CPM/benchmark/6ab6f9ea5fa3003095935f1af4b6b363c23ce9d7/src/cycleclock.h" } ] diff --git a/include/Alloc/Mallocator.hpp b/include/Alloc/Mallocator.hpp index b4c1279..bccac0e 100644 --- a/include/Alloc/Mallocator.hpp +++ b/include/Alloc/Mallocator.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include +#include #ifdef USING_MIMALLOC // #include #include @@ -10,6 +12,9 @@ #else #include #endif +#ifdef __cpp_lib_allocate_at_least +#include +#endif namespace poly::alloc { #ifdef __cpp_lib_allocate_at_least diff --git a/include/Containers/Storage.hpp b/include/Containers/Storage.hpp index 1eb51f8..242f984 100644 --- a/include/Containers/Storage.hpp +++ b/include/Containers/Storage.hpp @@ -1,5 +1,9 @@ #pragma once +#include +#include #include +#include +#include namespace poly::containers { template struct Storage { @@ -14,4 +18,62 @@ template struct Storage { template struct alignas(T) Storage { static constexpr auto data() -> T * { return nullptr; } }; + +template +concept SizeMultiple8 = (sizeof(T) % 8) == 0; + +template struct DefaultCapacityType { + using type = int; +}; +template struct DefaultCapacityType { + using type = std::ptrdiff_t; +}; +template +using default_capacity_type_t = typename DefaultCapacityType::type; + +static_assert(!SizeMultiple8); +static_assert(SizeMultiple8); +static_assert(std::is_same_v, int32_t>); +static_assert(std::is_same_v, int64_t>); + +template consteval auto PreAllocStorage() -> ptrdiff_t { + constexpr ptrdiff_t totalBytes = 128; + constexpr ptrdiff_t remainingBytes = + totalBytes - sizeof(T *) - sizeof(S) - sizeof(default_capacity_type_t); + constexpr ptrdiff_t N = remainingBytes / sizeof(T); + return std::max(0, N); +} +consteval auto log2Floor(uint64_t x) -> uint64_t { + return 63 - std::countl_zero(x); +} +consteval auto log2Ceil(uint64_t x) -> uint64_t { + return 64 - std::countl_zero(x - 1); +} +// NOLINTNEXTLINE(misc-no-recursion) +consteval auto bisectFindSquare(uint64_t l, uint64_t h, uint64_t N) + -> uint64_t { + if (l == h) return l; + uint64_t m = (l + h) / 2; + if (m * m >= N) return bisectFindSquare(l, m, N); + return bisectFindSquare(m + 1, h, N); +} +template +consteval auto PreAllocSquareStorage() -> ptrdiff_t { + // 2* because we want to allow more space for matrices + // also removes need for other checks; log2Floor(2)==1 + constexpr ptrdiff_t SN = 2 * PreAllocStorage(); + if constexpr (SN <= 0) return 0; + else { + constexpr uint64_t N = uint64_t(SN); + static_assert(N < 128); + // a fairly naive algorirthm for computing the next square `N` + // sqrt(x) = x^(1/2) = exp2(log2(x)/2) + constexpr uint64_t R = log2Floor(N) / 2; + static_assert(R < 63); + constexpr uint64_t L = uint64_t(1) << R; + constexpr uint64_t H = uint64_t(1) << ((log2Ceil(N) + 1) / 2); + return ptrdiff_t(bisectFindSquare(L, H, N)); + } +} + } // namespace poly::containers diff --git a/include/Containers/Tuple.hpp b/include/Containers/Tuple.hpp new file mode 100644 index 0000000..44b24af --- /dev/null +++ b/include/Containers/Tuple.hpp @@ -0,0 +1,134 @@ +#pragma once +#ifndef POLY_CONTAIERS_Tuple_hpp_INCLUDED +#define POLY_CONTAIERS_Tuple_hpp_INCLUDED + +namespace poly::containers { +template struct Tuple; +template +[[gnu::always_inline]] constexpr auto cattuple(T, Tuple) + -> Tuple; + +template struct Tuple { + [[no_unique_address]] T head; + [[no_unique_address]] Tuple tail; + constexpr Tuple(T head_, Ts... tail_) : head(head_), tail(tail_...){}; + constexpr Tuple(T head_, Tuple tail_) : head(head_), tail(tail_){}; + + constexpr Tuple(const Tuple &) = default; + template auto get() -> auto & { + if constexpr (I == 0) return head; + else return tail.template get(); + } + template [[nodiscard]] auto get() const -> const auto & { + if constexpr (I == 0) return head; + else return tail.template get(); + } + constexpr void apply(const auto &f) { + f(head); + tail.apply(f); + } + template + constexpr void apply(const Tuple &x, const auto &f) + requires(sizeof...(Ts) == sizeof...(Us)) + { + f(head, x.head); + tail.apply(x.tail, f); + } + constexpr auto map(const auto &f) const { + return cattuple(f(head), tail.map(f)); + } + template + constexpr auto map(const Tuple &x, const auto &f) const + requires(sizeof...(Ts) == sizeof...(Us)) + { + return cattuple(f(head, x.head), tail.map(x.tail, f)); + } + template + inline constexpr void operator<<(const Tuple &) + requires(sizeof...(Ts) == sizeof...(Us)); + template + inline constexpr void operator+=(const Tuple &) + requires(sizeof...(Ts) == sizeof...(Us)); + template + inline constexpr void operator-=(const Tuple &) + requires(sizeof...(Ts) == sizeof...(Us)); + template + inline constexpr void operator*=(const Tuple &) + requires(sizeof...(Ts) == sizeof...(Us)); + template + inline constexpr void operator/=(const Tuple &) + requires(sizeof...(Ts) == sizeof...(Us)); + template + constexpr auto operator=(Tuple x) -> Tuple &requires( + std::assignable_from &&... &&std::assignable_from) { + head = x.head; + tail = x.tail; + return *this; + } +}; +template +[[gnu::always_inline]] constexpr auto cattuple(T x, Tuple y) + -> Tuple { + return {x, y}; +} +template struct Tuple { + [[no_unique_address]] T head; + constexpr Tuple(T head_) : head(head_){}; + constexpr Tuple(const Tuple &) = default; + template auto get() -> T & { + static_assert(I == 0); + return head; + } + template [[nodiscard]] auto get() const -> const T & { + static_assert(I == 0); + return head; + } + constexpr auto operator=(const Tuple &) -> Tuple & = default; + constexpr void apply(const auto &f) { f(head); } + template constexpr void apply(const Tuple &x, const auto &f) { + f(head, x.head); + } + constexpr auto map(const auto &f) const -> Tuple { + return {f(head)}; + } + template + constexpr auto map(const Tuple &x, const auto &f) const + -> Tuple { + return {f(head, x.head)}; + } + template inline constexpr void operator<<(const Tuple &); + template inline constexpr void operator+=(const Tuple &); + template inline constexpr void operator-=(const Tuple &); + template inline constexpr void operator*=(const Tuple &); + template inline constexpr void operator/=(const Tuple &); + + template + constexpr auto operator=(Tuple x) + -> Tuple &requires(std::assignable_from) { + head = x.head; + return *this; + } +}; + +template Tuple(Ts...) -> Tuple; + +template constexpr auto tie(Ts &...x) -> Tuple { + return {x...}; +} +} // namespace poly::containers + +template +struct std::tuple_size> + : public std::integral_constant {}; + +template +struct std::tuple_element<0, poly::containers::Tuple> { + using type = T; +}; +template +struct std::tuple_element> { + using type = + typename std::tuple_element>::type; +}; + +#endif // Tuple_hpp_INCLUDED diff --git a/include/Math/Array.hpp b/include/Math/Array.hpp index d82596c..c84dc9d 100644 --- a/include/Math/Array.hpp +++ b/include/Math/Array.hpp @@ -9,9 +9,10 @@ #include "Math/Matrix.hpp" #include "Math/MatrixDimensions.hpp" #include "Math/Rational.hpp" -#include "Math/Vector.hpp" #include "Utilities/Invariant.hpp" #include "Utilities/Optional.hpp" +#include "Utilities/Reference.hpp" +#include "Utilities/TypeCompression.hpp" #include "Utilities/TypePromotion.hpp" #include "Utilities/Valid.hpp" #include @@ -47,8 +48,12 @@ #endif namespace poly::math { -template (), - class A = alloc::Mallocator> +template +concept Dimension = VectorDimension != MatrixDimension; +template , S>(), + class A = alloc::Mallocator>> struct ManagedArray; template @@ -63,8 +68,67 @@ void print_obj(std::ostream &os, const std::pair &x) { }; using utils::Valid, utils::Optional; -template struct Array; -template struct MutArray; +template > +struct Array; +template > +struct MutArray; + +// Cases we need to consider: +// 1. Slice-indexing +// 2.a. `ptrdiff_t` indexing, not compressed +// 2.b. `ptrdiff_t` indexing, compressed +// 3.a.i. Vector indexing, contig, no mask +// 3.a.ii. Vector indexing, contig, mask +// 3.b.i. Vector indexing, discontig, no mask +// 3.b.ii. Vector indexing, discontig, mask +// all of the above for `T*` and `const T*` +template +[[gnu::flatten, gnu::always_inline]] constexpr auto index(P *ptr, S shape, + I i) noexcept + -> decltype(auto) { + auto offset = calcOffset(shape, i); + auto newDim = calcNewDim(shape, i); + invariant(ptr != nullptr); + using D = decltype(newDim); + if constexpr (simd::index::issimd) return simd::ref(ptr + offset, newDim); + else { + constexpr bool Compress = !std::same_as>; + if constexpr (!std::same_as) + if constexpr (std::is_const_v

) + return Array{ptr + offset, newDim}; + else return MutArray{ptr + offset, newDim}; + else if constexpr (!Compress) return ptr[offset]; + else if constexpr (std::is_const_v

) return T::decompress(ptr + offset); + else return utils::Reference{ptr + offset}; + } +} +// for (row/col)vectors, we drop the row/col, essentially broadcasting +template +[[gnu::flatten, gnu::always_inline]] constexpr auto index(P *ptr, S shape, R wr, + C wc) noexcept + -> decltype(auto) { + if constexpr (MatrixDimension) { + auto r = unwrapRow(wr); + auto c = unwrapCol(wc); + auto offset = calcOffset(shape, r, c); + auto newDim = calcNewDim(shape, r, c); + using D = decltype(newDim); + if constexpr (simd::index::issimd) + return simd::ref(ptr + offset, newDim); + else { + constexpr bool Compress = !std::same_as>; + if constexpr (!std::same_as) + if constexpr (std::is_const_v

) + return Array{ptr + offset, newDim}; + else return MutArray{ptr + offset, newDim}; + else if constexpr (!Compress) return ptr[offset]; + else if constexpr (std::is_const_v

) return T::decompress(ptr + offset); + else return utils::Reference{ptr + offset}; + } + } else if constexpr (std::same_as) + return index(ptr, shape, unwrapRow(wr)); + else return index(ptr, shape, unwrapCol(wc)); +} template struct SliceIterator { using stride_type = std::conditional_t; @@ -72,7 +136,8 @@ template struct SliceIterator { std::conditional_t, Array, stride_type>, MutArray, stride_type>>; - T *data; + using storage_type = utils::compressed_t; + storage_type *data; ptrdiff_t len; ptrdiff_t rowStride; ptrdiff_t idx; @@ -148,39 +213,48 @@ template struct SliceRange { } }; /// Constant Array -template struct POLY_MATH_GSL_POINTER Array { +template +struct POLY_MATH_GSL_POINTER Array { static_assert(!std::is_const_v, "T shouldn't be const"); static_assert(std::is_trivially_destructible_v, "maybe should add support for destroying"); + + using storage_type = std::conditional_t, T>; using value_type = T; using reference = T &; using const_reference = const T &; using size_type = ptrdiff_t; using difference_type = int; - using iterator = T *; - using const_iterator = const T *; - using pointer = T *; - using const_pointer = const T *; + using iterator = storage_type *; + using const_iterator = const storage_type *; + using pointer = storage_type *; + using const_pointer = const storage_type *; using concrete = std::true_type; + static constexpr bool isdense = + std::convertible_to || std::convertible_to>; + static constexpr bool flatstride = isdense || std::same_as; + static_assert(flatstride != std::same_as>); + constexpr Array() = default; constexpr Array(const Array &) = default; constexpr Array(Array &&) noexcept = default; constexpr auto operator=(const Array &) -> Array & = default; constexpr auto operator=(Array &&) noexcept -> Array & = default; - constexpr Array(const T *p, S s) : ptr(p), sz(s) {} - constexpr Array(Valid p, S s) : ptr(p), sz(s) {} + constexpr Array(const storage_type *p, S s) : ptr(p), sz(s) {} + constexpr Array(Valid p, S s) : ptr(p), sz(s) {} template - constexpr Array(const T *p, Row r, Col c) : ptr(p), sz(S{r, c}) {} + constexpr Array(const storage_type *p, Row r, Col c) + : ptr(p), sz(S{r, c}) {} template - constexpr Array(Valid p, Row r, Col c) + constexpr Array(Valid p, Row r, Col c) : ptr(p), sz(dimension(r, c)) {} template V> constexpr Array(Array a) : ptr(a.data()), sz(a.dim()) {} template constexpr Array(const std::array &a) : ptr(a.data()), sz(N) {} [[nodiscard, gnu::returns_nonnull]] constexpr auto data() const noexcept - -> const T * { + -> const storage_type * { invariant(ptr != nullptr); return ptr; } @@ -190,26 +264,33 @@ template struct POLY_MATH_GSL_POINTER Array { -> StridedIterator requires(std::is_same_v) { - const T *p = ptr; + const storage_type *p = ptr; return StridedIterator{p, sz.stride}; } [[nodiscard]] constexpr auto begin() const noexcept - -> const T *requires(!std::is_same_v) { return ptr; } + -> const storage_type *requires(isdense) { return ptr; } - [[nodiscard]] constexpr auto end() const noexcept { + [[nodiscard]] constexpr auto end() const noexcept + requires(flatstride) + { return begin() + ptrdiff_t(sz); } - [[nodiscard]] constexpr auto rbegin() const noexcept { + [[nodiscard]] constexpr auto rbegin() const noexcept + requires(flatstride) + { return std::reverse_iterator(end()); } - [[nodiscard]] constexpr auto rend() const noexcept { + [[nodiscard]] constexpr auto rend() const noexcept + requires(flatstride) + { return std::reverse_iterator(begin()); } [[nodiscard]] constexpr auto front() const noexcept -> const T & { - return *begin(); + return *ptr; } [[nodiscard]] constexpr auto back() const noexcept -> const T & { - return *(end() - 1); + if constexpr (flatstride) return *(end() - 1); + else return ptr[sride(sz) * ptrdiff_t(row(sz)) - 1]; } // indexing has two components: // 1. offsetting the pointer @@ -217,22 +298,15 @@ template struct POLY_MATH_GSL_POINTER Array { // static constexpr auto slice(Valid, Index auto i){ // auto // } - [[gnu::flatten]] constexpr auto operator[](Index auto i) const noexcept - -> decltype(auto) { - auto offset = calcOffset(sz, i); - auto newDim = calcNewDim(sz, i); - invariant(ptr != nullptr); - if constexpr (std::is_same_v) - return static_cast(ptr)[offset]; - else return Array{ptr + offset, newDim}; + [[gnu::flatten, gnu::always_inline]] constexpr auto + operator[](Index auto i) const noexcept -> decltype(auto) { + return index(ptr, sz, i); } - // for vectors, we just drop the column, essentially broadcasting + // for (row/col)vectors, we drop the row/col, essentially broadcasting template - [[gnu::flatten]] constexpr auto operator[](R r, C c) const noexcept - -> decltype(auto) { - if constexpr (MatrixDimension) - return (*this)[CartesianIndex(unwrapRow(r), unwrapCol(c))]; - else return (*this)[ptrdiff_t(r)]; + [[gnu::flatten, gnu::always_inline]] constexpr auto + operator[](R r, C c) const noexcept -> decltype(auto) { + return index(ptr, sz, r, c); } [[nodiscard]] constexpr auto minRowCol() const -> ptrdiff_t { return std::min(ptrdiff_t(numRow()), ptrdiff_t(numCol())); @@ -257,31 +331,23 @@ template struct POLY_MATH_GSL_POINTER Array { return N; } - [[nodiscard]] constexpr auto numRow() const noexcept - requires(MatrixDimension) - { - return Row(sz); + [[nodiscard]] constexpr auto numRow() const noexcept { + if constexpr (std::convertible_to) return Row<1>{}; + else return row(sz); } - [[nodiscard]] constexpr auto numCol() const noexcept - requires(MatrixDimension) - { - return Col(sz); - } - [[nodiscard]] constexpr auto rowStride() const noexcept - requires(MatrixDimension) - { - return RowStride(sz); + [[nodiscard]] constexpr auto numCol() const noexcept { return col(sz); } + [[nodiscard]] constexpr auto rowStride() const noexcept { + if constexpr (std::integral) return RowStride<1>{}; + else return stride(sz); } [[nodiscard]] constexpr auto empty() const -> bool { return sz == S{}; } [[nodiscard]] constexpr auto size() const noexcept { if constexpr (StaticInt) return S{}; - else if constexpr (std::integral) return sz; - else if constexpr (std::is_same_v) return ptrdiff_t(sz); - else return CartesianIndex{ptrdiff_t(Row(sz)), ptrdiff_t(Col(sz))}; + else return ptrdiff_t(sz); } [[nodiscard]] constexpr auto dim() const noexcept -> S { return sz; } constexpr void clear() { sz = S{}; } - [[nodiscard]] constexpr auto transpose() const { return Transpose{*this}; } + [[nodiscard]] constexpr auto t() const { return Transpose{*this}; } [[nodiscard]] constexpr auto isExchangeMatrix() const -> bool requires(MatrixDimension) { @@ -342,6 +408,39 @@ template struct POLY_MATH_GSL_POINTER Array { return ret; // return std::reduce(begin(), end()); } + // interpret a bigger object as smaller + template [[nodiscard]] auto reinterpret() const { + static_assert(sizeof(storage_type) % sizeof(U) == 0); + static_assert(std::same_as); + if constexpr (std::same_as) return *this; + else { + auto r = unwrapRow(numRow()); + auto c = unwrapCol(numCol()); + constexpr auto ratio = sizeof(storage_type) / sizeof(U); +#ifdef __cpp_lib_start_lifetime_as + U *p = std::start_lifetime_as_array(reinterpret_cast(data()), + ratio * ptrdiff_t(rowStride()) * r); +#else + const U *p = std::launder(reinterpret_cast(data())); +#endif + if constexpr (IsOne) { + if constexpr (StaticInt) + return Array>{p, {}}; + else return Array{p, c * ratio}; + } else if constexpr (DenseLayout) { + return Array>(p, DenseDims(row(r), col(c * ratio))); + } else { + ptrdiff_t stride = ptrdiff_t(rowStride()) * ratio; + if constexpr (IsOne) { + constexpr auto sr = std::integral_constant{}; + return Array>( + p, StridedDims(row(r), col(sr), rowStride(stride))); + } else + return Array>( + p, StridedDims(row(r), col(c * ratio), rowStride(stride))); + } + } + } friend inline void PrintTo(const Array &x, ::std::ostream *os) { *os << x; } #ifndef NDEBUG [[gnu::used]] void dump() const { @@ -371,7 +470,7 @@ template struct POLY_MATH_GSL_POINTER Array { #endif protected: // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) - const T *ptr; + const storage_type *ptr; // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) [[no_unique_address]] S sz{}; }; @@ -385,20 +484,22 @@ template return M <=> N; }; -template -struct POLY_MATH_GSL_POINTER MutArray : Array, - ArrayOps> { +template +struct POLY_MATH_GSL_POINTER MutArray + : Array, + ArrayOps> { using BaseT = Array; // using BaseT::BaseT; using BaseT::operator[], BaseT::data, BaseT::begin, BaseT::end, BaseT::rbegin, BaseT::rend, BaseT::front, BaseT::back; + using storage_type = typename BaseT::storage_type; constexpr MutArray(const MutArray &) = default; constexpr MutArray(MutArray &&) noexcept = default; constexpr auto operator=(const MutArray &) -> MutArray & = delete; // constexpr auto operator=(const MutArray &) -> MutArray & = default; constexpr auto operator=(MutArray &&) noexcept -> MutArray & = default; - constexpr MutArray(T *p, S s) : BaseT(p, s) {} + constexpr MutArray(storage_type *p, S s) : BaseT(p, s) {} constexpr void truncate(S nz) { S oz = this->sz; @@ -419,7 +520,7 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, ptrdiff_t rowsToCopy = newM; if (rowsToCopy && (--rowsToCopy) && (copyCols)) { // truncation, we need to copy rows to increase stride - T *src = data(), *dst = src; + storage_type *src = data(), *dst = src; do { src += oldX; dst += newX; @@ -466,15 +567,16 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, template constexpr MutArray(Args &&...args) - : Array(std::forward(args)...) {} + : Array(std::forward(args)...) {} template U, std::convertible_to V> constexpr MutArray(Array a) : Array(a) {} template constexpr MutArray(std::array &a) : Array(a.data(), N) {} - [[nodiscard, gnu::returns_nonnull]] constexpr auto data() noexcept -> T * { + [[nodiscard, gnu::returns_nonnull]] constexpr auto data() noexcept + -> storage_type * { invariant(this->ptr != nullptr); - return const_cast(this->ptr); + return const_cast(this->ptr); } [[nodiscard]] constexpr auto wrappedPtr() noexcept -> Valid { return data(); @@ -483,11 +585,12 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, [[nodiscard]] constexpr auto begin() noexcept -> StridedIterator requires(std::is_same_v) { - return StridedIterator{const_cast(this->ptr), this->sz.stride}; + return StridedIterator{const_cast(this->ptr), + this->sz.stride}; } [[nodiscard]] constexpr auto begin() noexcept - -> T *requires(!std::is_same_v) { - return const_cast(this->ptr); + -> storage_type *requires(!std::is_same_v) { + return const_cast(this->ptr); } [[nodiscard]] constexpr auto end() noexcept { @@ -498,7 +601,8 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, // { // return this->ptr; // } - // [[nodiscard, gnu::returns_nonnull]] constexpr auto end() noexcept -> T * + // [[nodiscard, gnu::returns_nonnull]] constexpr auto end() noexcept -> + // storage_type * // { // return this->ptr + ptrdiff_t(this->sz); // } @@ -510,21 +614,16 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, } constexpr auto front() noexcept -> T & { return *begin(); } constexpr auto back() noexcept -> T & { return *(end() - 1); } - [[gnu::flatten]] constexpr auto operator[](Index auto i) noexcept - -> decltype(auto) { - auto offset = calcOffset(this->sz, i); - auto newDim = calcNewDim(this->sz, i); - if constexpr (std::is_same_v) - return data()[offset]; - else return MutArray{data() + offset, newDim}; + [[gnu::flatten, gnu::always_inline]] constexpr auto + operator[](Index auto i) noexcept -> decltype(auto) { + return index(data(), this->sz, i); } // TODO: switch to operator[] when we enable c++23 template - [[gnu::flatten]] constexpr auto operator[](R r, C c) noexcept + [[gnu::flatten, gnu::always_inline]] constexpr auto operator[](R r, + C c) noexcept -> decltype(auto) { - if constexpr (MatrixDimension) - return (*this)[CartesianIndex(unwrapRow(r), unwrapCol(c))]; - else return (*this)[ptrdiff_t(r)]; + return index(data(), this->sz, r, c); } constexpr void fill(T value) { std::fill_n(this->data(), ptrdiff_t(this->dim()), value); @@ -556,7 +655,7 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, newRow = ptrdiff_t{Row(this->sz)} - 1; this->sz.set(Row<>{newRow}); if ((col == 0) || (r == newRow)) return; - T *dst = data() + ptrdiff_t(r) * col; + storage_type *dst = data() + ptrdiff_t(r) * col; std::copy_n(dst + col, (newRow - ptrdiff_t(r)) * col, dst); } else { static_assert(std::convertible_to>); @@ -567,14 +666,14 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, if ((col == 0) || (r == newRow)) return; invariant(col <= stride); if ((col + (512 / (sizeof(T)))) <= stride) { - T *dst = data() + ptrdiff_t(r) * stride; + storage_type *dst = data() + ptrdiff_t(r) * stride; for (ptrdiff_t m = ptrdiff_t(r); m < newRow; ++m) { - T *src = dst + stride; + storage_type *src = dst + stride; std::copy_n(src, col, dst); dst = src; } } else { - T *dst = data() + ptrdiff_t(r) * stride; + storage_type *dst = data() + ptrdiff_t(r) * stride; std::copy_n(dst + stride, (newRow - ptrdiff_t(r)) * stride, dst); } } @@ -592,8 +691,8 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, if ((colsToCopy == 0) || (row == 0)) return; // we only need to copy if memory shifts position for (ptrdiff_t m = 0; m < row; ++m) { - T *dst = data() + m * newCol + ptrdiff_t(c); - T *src = data() + m * oldCol + ptrdiff_t(c) + 1; + storage_type *dst = data() + m * newCol + ptrdiff_t(c); + storage_type *src = data() + m * oldCol + ptrdiff_t(c) + 1; std::copy_n(src, colsToCopy, dst); } } else { @@ -606,7 +705,7 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, if ((colsToCopy == 0) || (row == 0)) return; // we only need to copy if memory shifts position for (ptrdiff_t m = 0; m < row; ++m) { - T *dst = data() + m * stride + ptrdiff_t(c); + storage_type *dst = data() + m * stride + ptrdiff_t(c); std::copy_n(dst + 1, colsToCopy, dst); } } @@ -636,9 +735,45 @@ struct POLY_MATH_GSL_POINTER MutArray : Array, return {data(), ptrdiff_t(Row(this->sz)), ptrdiff_t(RowStride(this->sz)), ptrdiff_t(Col(this->sz))}; } + template [[nodiscard]] auto reinterpret() { + static_assert(sizeof(storage_type) % sizeof(U) == 0); + static_assert(std::same_as); + if constexpr (std::same_as) return *this; + else { + auto r = unwrapRow(this->numRow()); + auto c = unwrapCol(this->numCol()); + constexpr size_t ratio = sizeof(storage_type) / sizeof(U); +#ifdef __cpp_lib_start_lifetime_as + U *p = std::start_lifetime_as_array(reinterpret_cast(data()), + ratio * ptrdiff_t(rowStride()) * r); +#else + U *p = std::launder(reinterpret_cast(data())); +#endif + if constexpr (IsOne) { + if constexpr (StaticInt) + return MutArray>( + p, std::integral_constant{}); + else return MutArray{p, c * ratio}; + } else if constexpr (DenseLayout) { + return MutArray>(p, DenseDims(row(r), col(c * ratio))); + } else { + ptrdiff_t stride = ptrdiff_t(this->rowStride()) * ratio; + if constexpr (IsOne) { + constexpr auto sr = std::integral_constant{}; + return MutArray>( + p, StridedDims(row(r), col(sr), rowStride(stride))); + } else + return MutArray>( + p, StridedDims(row(r), col(c * ratio), rowStride(stride))); + } + } + } }; -template MutArray(T *, S) -> MutArray; +template +Array(T *, S) -> Array, S>; +template +MutArray(T *, S) -> MutArray, S>; template MutArray(MutArray) -> MutArray; @@ -662,6 +797,13 @@ static_assert(std::convertible_to>, MutArray>>); static_assert(std::convertible_to>, MutArray>>); +static_assert(AbstractVector>); +static_assert(!AbstractVector>>); +static_assert(AbstractMatrix>>); +static_assert(RowVector>); +static_assert(ColVector>>); +static_assert(ColVector>); +static_assert(RowVector>>); template auto operator*(SliceIterator it) @@ -681,15 +823,16 @@ static_assert(std::ranges::range>); /// Non-owning view of a managed array, capable of resizing, /// but not of re-allocating in case the capacity is exceeded. -template +template struct POLY_MATH_GSL_POINTER ResizeableView : MutArray { using BaseT = MutArray; - using U = default_capacity_type_t; + using U = containers::default_capacity_type_t; + using storage_type = typename BaseT::storage_type; constexpr ResizeableView() noexcept : BaseT(nullptr, 0), capacity(0) {} - constexpr ResizeableView(T *p, S s, U c) noexcept + constexpr ResizeableView(storage_type *p, S s, U c) noexcept : BaseT(p, s), capacity(c) {} constexpr ResizeableView(alloc::Arena<> *a, S s, U c) noexcept - : ResizeableView{a->template allocate(c), s, c} {} + : ResizeableView{a->template allocate(c), s, c} {} [[nodiscard]] constexpr auto isFull() const -> bool { return U(this->sz) == capacity; @@ -906,12 +1049,14 @@ static_assert(std::is_trivially_move_assignable_v>); /// Non-owning view of a managed array, capable of reallocating, etc. /// It does not own memory. Mostly, it serves to drop the inlined /// stack capacity of the `ManagedArray` from the type. -template > +template >> struct POLY_MATH_GSL_POINTER ReallocView : ResizeableView { using BaseT = ResizeableView; - using U = default_capacity_type_t; - constexpr ReallocView(T *p, S s, U c) noexcept : BaseT(p, s, c) {} - constexpr ReallocView(T *p, S s, U c, A alloc) noexcept + using U = containers::default_capacity_type_t; + using storage_type = typename BaseT::storage_type; + constexpr ReallocView(storage_type *p, S s, U c) noexcept : BaseT(p, s, c) {} + constexpr ReallocView(storage_type *p, S s, U c, A alloc) noexcept : BaseT(p, s, c), allocator(alloc) {} [[nodiscard]] constexpr auto newCapacity() const -> U { @@ -1110,12 +1255,13 @@ struct POLY_MATH_GSL_POINTER ReallocView : ResizeableView { [[no_unique_address]] A allocator{}; constexpr void allocateAtLeast(U len) { - alloc::AllocResult res = alloc::alloc_at_least(allocator, len); + alloc::AllocResult res = + alloc::alloc_at_least(allocator, len); this->ptr = res.ptr; this->capacity = res.count; } [[nodiscard]] auto firstElt() const -> const void * { - using AS = ArrayAlignmentAndSize; + using AS = ArrayAlignmentAndSize; // AS is not a standard layout type, as more than one layer of the hierarchy // contain non-static data members. Using `offsetof` is conditionally supported // by some compilers as of c++17 (it was UB prior). Both Clang and GCC support @@ -1145,7 +1291,7 @@ struct POLY_MATH_GSL_POINTER ReallocView : ResizeableView { if (wasAllocated()) allocator.deallocate(this->data(), this->capacity); } // this method should be called whenever the buffer lives - void maybeDeallocate(T *newPtr, U newCapacity) noexcept { + void maybeDeallocate(storage_type *newPtr, U newCapacity) noexcept { maybeDeallocate(); this->ptr = newPtr; this->capacity = newCapacity; @@ -1181,11 +1327,12 @@ concept AbstractSimilar = /// or at least build ManagedArrays bypassing the constructors listed here. /// This caused invalid frees, as the pointer still pointed to the old /// stack memory. -template +template struct POLY_MATH_GSL_OWNER ManagedArray : ReallocView { static_assert(std::is_trivially_destructible_v); using BaseT = ReallocView; - using U = default_capacity_type_t; + using U = containers::default_capacity_type_t; + using storage_type = typename BaseT::storage_type; // We're deliberately not initializing storage. #if !defined(__clang__) && defined(__GNUC__) #pragma GCC diagnostic push @@ -1249,32 +1396,7 @@ struct POLY_MATH_GSL_OWNER ManagedArray : ReallocView { : BaseT{memory.data(), S(b.dim()), U(N), b.get_allocator()} { U len = U(this->sz); this->growUndef(len); - if constexpr (DenseLayout && DenseLayout) { - std::copy_n(b.data(), len, this->data()); - } else if constexpr (MatrixDimension && MatrixDimension) { - invariant(b.numRow() == this->numRow()); - invariant(b.numCol() == this->numCol()); - for (ptrdiff_t m = 0; m < this->numRow(); ++m) { - POLYMATHVECTORIZE - for (ptrdiff_t n = 0; n < this->numCol(); ++n) (*this)(m, n) = b(m, n); - } - } else if constexpr (MatrixDimension) { - ptrdiff_t j = 0; - for (ptrdiff_t m = 0; m < b.numRow(); ++m) { - POLYMATHVECTORIZE - for (ptrdiff_t n = 0; n < b.numCol(); ++n) (*this)(j++) = b(m, n); - } - } else if constexpr (MatrixDimension) { - ptrdiff_t j = 0; - for (ptrdiff_t m = 0; m < this->numRow(); ++m) { - POLYMATHVECTORIZE - for (ptrdiff_t n = 0; n < this->numCol(); ++n) (*this)(m, n) = b(j++); - } - } else { - T *p = this->data(); - POLYMATHVECTORIZE - for (ptrdiff_t i = 0; i < len; ++i) p[i] = b[i]; - } + (*this) << b; } template Y, size_t M> constexpr ManagedArray(std::array il) noexcept @@ -1306,7 +1428,7 @@ struct POLY_MATH_GSL_OWNER ManagedArray : ReallocView { } template V> constexpr ManagedArray(const V &b) noexcept - : BaseT{memory.data(), S(b.size()), U(N)} { + : BaseT{memory.data(), S(shape(b)), U(N)} { U len = U(this->sz); this->growUndef(len); (*this) << b; @@ -1450,7 +1572,7 @@ struct POLY_MATH_GSL_OWNER ManagedArray : ReallocView { } private: - [[no_unique_address]] containers::Storage memory; + [[no_unique_address]] containers::Storage memory; }; static_assert(std::move_constructible>); @@ -1474,7 +1596,7 @@ static_assert( sizeof(ManagedArray, 64, alloc::Mallocator>) == 536); -template ()> +template ()> using Vector = ManagedArray; template using PtrVector = Array; template using MutPtrVector = MutArray; @@ -1506,7 +1628,8 @@ template using DenseMatrix = ManagedArray, L>; template using SquarePtrMatrix = Array>; template using MutSquarePtrMatrix = MutArray>; -template >()> +template , SquareDims<>>()> using SquareMatrix = ManagedArray, L>; static_assert(sizeof(PtrMatrix) == @@ -1720,7 +1843,7 @@ constexpr auto getMaxDigits(PtrMatrix A) -> Vector { template inline auto printMatrix(std::ostream &os, PtrMatrix A) -> std::ostream & { // std::ostream &printMatrix(std::ostream &os, T const &A) { - auto [M, N] = A.size(); + auto [M, N] = shape(A); if ((!M) || (!N)) return os << "[ ]"; // first, we determine the number of digits needed per column auto maxDigits{getMaxDigits(A)}; @@ -1749,7 +1872,7 @@ inline auto printMatrix(std::ostream &os, PtrMatrix A) -> std::ostream & { inline auto printMatrix(std::ostream &os, PtrMatrix A) -> std::ostream & { // std::ostream &printMatrix(std::ostream &os, T const &A) { - auto [M, N] = A.size(); + auto [M, N] = shape(A); if ((!M) || (!N)) return os << "[ ]"; // first, we determine the number of digits needed per column Vector digits; @@ -1823,5 +1946,6 @@ inline auto operator<<(std::ostream &os, Array> A) static_assert(std::same_as>()[0, 0])>); +static_assert(std::is_trivially_copyable_v>); } // namespace poly::math diff --git a/include/Math/ArrayOps.hpp b/include/Math/ArrayOps.hpp index f347650..1cbb1cc 100644 --- a/include/Math/ArrayOps.hpp +++ b/include/Math/ArrayOps.hpp @@ -1,26 +1,125 @@ #pragma once +#include "Containers/Tuple.hpp" #include "Math/Indexing.hpp" #include "Math/Matrix.hpp" #include "Math/UniformScaling.hpp" -#include "Math/Vector.hpp" +#include "SIMD/Unroll.hpp" +#include "Utilities/Assign.hpp" +#include "Utilities/LoopMacros.hpp" #include #include #include -#if defined __GNUC__ && __GNUC__ >= 8 -#define POLYMATHVECTORIZE _Pragma("GCC ivdep") -// #define POLYMATHVECTORIZE _Pragma("GCC unroll 2") _Pragma("GCC ivdep") -// #elif defined __clang__ -// #define POLYMATHVECTORIZE _Pragma("clang loop vectorize(enable)") -// _Pragma("clang loop vectorize(enable) interleave_count(2)") -#else -#define POLYMATHVECTORIZE -#endif +#define CASTTOSCALARIZE namespace poly::math { +// scalars broadcast +template +[[gnu::always_inline]] constexpr auto get(const auto &s, auto) { + return s; +} +template +[[gnu::always_inline]] constexpr auto get(const auto &s, auto, auto) { + return s; +} +template V> +[[gnu::always_inline]] constexpr auto get(const V &v, auto i) { + return v[i]; +} +template V> +[[gnu::always_inline]] constexpr auto get(const V &v, auto i, auto j) { + return v[i, j]; +} +template +concept OnlyLinearlyIndexable = LinearlyIndexable && !CartesianIndexable; +template V> +[[gnu::always_inline]] constexpr auto get(const V &v, auto i, auto j) { + static_assert(AbstractVector); + if constexpr (RowVector) return v[j]; + else return v[i]; +} + +template struct ScalarizeViaCast { + using type = void; +}; +template +using scalarize_via_cast_t = typename ScalarizeViaCast::type; +template +constexpr bool ScalarizeViaCastToImpl = + std::same_as>>; +template +consteval auto ScalarizeViaCastTo() -> bool { + return (... && ScalarizeViaCastToImpl); +} + +template constexpr auto reinterpret(U x) { + if constexpr (std::same_as) return x; + else return x.template reinterpret(); +} + +// returns Unroll, Iters, Remainder +template consteval auto unrollf() -> std::array { + if (R <= 5) return {0, R}; + if (R == 7) return {0, 7}; + if ((R % 4) == 0) return {4, 0}; + if ((R % 3) == 0) return {3, 0}; + if ((R % 5) == 0) return {5, 0}; + if ((R % 7) == 0) return {7, 0}; + return {4, R % 4}; +} + +template +constexpr void fastCopy(D *d, const S *s, size_t N) { + if (!N) return; + // if constexpr (std::same_as && std::is_trivially_copyable_v) + // std::memcpy(d, s, N * sizeof(D)); + // else + std::copy_n(s, N, d); +} + +template +concept IsOne = + std::same_as, std::integral_constant>; +// inputs must be `ptrdiff_t` or `std::integral_constant` +template +[[gnu::always_inline]] constexpr auto check_sizes(X x, Y y) { + if constexpr (std::same_as) { + if constexpr (std::same_as) { + invariant(x, y); + return x; + } else { + constexpr ptrdiff_t L = y; + invariant(x, L); + return std::integral_constant{}; + } + } else if constexpr (std::same_as) { + constexpr ptrdiff_t L = x; + invariant(L, y); + return std::integral_constant{}; + } else { + static_assert(x == y); + return std::integral_constant{}; + } +} +template +[[gnu::always_inline]] constexpr auto promote_shape(const A &a, const B &b) { + auto sa = shape(a); + if constexpr (!std::convertible_to>) { + auto M = unwrapRow(numRows(b)); + auto N = unwrapCol(numCols(b)); + if constexpr (IsOne) + if constexpr (IsOne) return sa; + else return CartesianIndex(sa.row, check_sizes(sa.col, N)); + else if constexpr (IsOne) + return CartesianIndex(check_sizes(sa.row, M), sa.col); + else return CartesianIndex(check_sizes(sa.row, M), check_sizes(sa.col, N)); + } else return sa; +} + template class SmallSparseMatrix; template class ArrayOps { + static_assert(std::is_copy_assignable_v || (std::is_trivially_copyable_v && std::is_trivially_move_assignable_v)); @@ -31,208 +130,376 @@ template class ArrayOps { return static_cast(this)->data(); } constexpr auto size_() const { return static_cast(this)->size(); } - constexpr auto dim_() const -> S { - return static_cast(this)->dim(); - } constexpr auto Self() -> P & { return *static_cast

(this); } [[nodiscard]] constexpr auto nr() const -> ptrdiff_t { return ptrdiff_t(static_cast(this)->numRow()); } - [[nodiscard]] constexpr auto nc() const -> ptrdiff_t { - return ptrdiff_t(static_cast(this)->numCol()); - } - [[nodiscard]] constexpr auto rs() const -> ptrdiff_t { - return ptrdiff_t(static_cast(this)->rowStride()); + [[nodiscard]] constexpr auto nc() const { + return unwrapCol(static_cast(this)->numCol()); } - -public: - template Y> - [[gnu::flatten]] constexpr auto operator<<(const UniformScaling &B) - -> P & { - static_assert(MatrixDimension); - std::fill_n(data_(), ptrdiff_t(this->dim()), T{}); - this->diag() << B.value; - return *static_cast

(this); + [[nodiscard]] constexpr auto rs() const { + return unwrapRow(static_cast(this)->rowStride()); } - [[gnu::flatten]] constexpr auto operator<<(const SmallSparseMatrix &B) - -> P &; - [[gnu::flatten]] constexpr auto operator<<(const AbstractVector auto &B) - -> P & { - P &self{Self()}; - if constexpr (MatrixDimension) { - ptrdiff_t M = nr(), N = nc(); - invariant(M, B.size()); - for (ptrdiff_t i = 0; i < M; ++i) { - T Bi = B[i]; - POLYMATHVECTORIZE - for (ptrdiff_t j = 0; j < N; ++j) self[i, j] = Bi; + template + [[gnu::always_inline]] static void vcopyToSIMD(P &self, const auto &B, I L, + R row, Op op) { + // TODO: if `R` is a row index, maybe don't fully unroll static `L` + // We're going for very short SIMD vectors to focus on small sizes + if constexpr (StaticInt) { + constexpr ptrdiff_t SL = ptrdiff_t(L); + constexpr std::array vdr = simd::VectorDivRem(); + constexpr ptrdiff_t W = vdr[0]; + constexpr ptrdiff_t fulliter = vdr[1]; + constexpr ptrdiff_t remainder = vdr[2]; + if constexpr (remainder > 0) { + auto u{simd::index::unrollmask(L, 0)}; + utils::assign(self, B, row, u, op); + } else { + simd::index::Unroll u{0}; + utils::assign(self, B, row, u, op); } } else { - ptrdiff_t L = size_(); - invariant(L, ptrdiff_t(B.size())); - if constexpr (std::is_copy_assignable_v) { - POLYMATHVECTORIZE - for (ptrdiff_t i = 0; i < L; ++i) self[i] = B[i]; - } else { - // MutArray is trivially copyable and move-assignable - // we require triviality to avoid silently being slow. - // we should fix it if hitting another case. - POLYMATHVECTORIZE - for (ptrdiff_t i = 0; i < L; ++i) self[i] = auto{B[i]}; + constexpr ptrdiff_t W = simd::Width; + for (ptrdiff_t i = 0;; i += W) { + auto u{simd::index::unrollmask<1, W>(L, i)}; + if (!u) break; + utils::assign(self, B, row, u, op); } } - return self; } - [[gnu::flatten]] constexpr auto operator<<(const AbstractMatrix auto &B) - -> P & { - static_assert(MatrixDimension); - ptrdiff_t M = nr(), N = nc(); - invariant(M, ptrdiff_t(B.numRow())); - invariant(N, ptrdiff_t(B.numCol())); + template void vcopyTo(const auto &B, Op op) { + // static_assert(sizeof(utils::eltype_t) <= 8); P &self{Self()}; - if constexpr (DenseLayout && - DataMatrix> && - DenseLayout>) { - if constexpr (std::is_copy_assignable_v) - std::copy_n(B.data(), M * N, data_()); - else std::memcpy(data_(), M * N * sizeof(T), B.data()); + auto [M, N] = promote_shape(self, B); + // if constexpr (std::same_as && DenseLayout && + // DenseTensor>) { + // if constexpr (std::is_trivially_copyable_v) + // std::memcpy(data_(), B.begin(), M * N * sizeof(T)); + // else std::copy_n(B.begin(), M * N, data_()); + // } else +#ifdef CASTTOSCALARIZE + using E = math::scalarize_via_cast_t< + std::remove_cvref_t().view())>>; + if constexpr (!std::same_as && + ((math::ScalarizeViaCastTo()) || + (std::same_as, double> && + std::same_as>))) { + auto d{reinterpret(Self())}; + if constexpr (std::same_as) d << reinterpret(B); + else d << op(d, reinterpret(B)); + } else if constexpr (simd::SIMDSupported) { +#else + if constexpr (simd::SIMDSupported) { +#endif + if constexpr (IsOne) + vcopyToSIMD(self, B, N, utils::NoRowIndex{}, op); + else if constexpr (IsOne) + vcopyToSIMD(self, B, M, utils::NoRowIndex{}, op); + else if constexpr (StaticInt) { + constexpr std::array UIR = unrollf(); + constexpr ptrdiff_t U = UIR[0]; + if constexpr (U != 0) + for (ptrdiff_t r = 0; r < (M - U + 1); r += U) + vcopyToSIMD(self, B, N, simd::index::Unroll{r}, op); + constexpr ptrdiff_t R = UIR[1]; + if constexpr (R != 0) + vcopyToSIMD(self, B, N, simd::index::Unroll{M - R}, op); + } else { + ptrdiff_t r = 0; + for (; r < (M - 3); r += 4) + vcopyToSIMD(self, B, N, simd::index::Unroll<4>{r}, op); + switch (M & 3) { + case 0: return; + case 1: return vcopyToSIMD(self, B, N, simd::index::Unroll<1>{r}, op); + case 2: return vcopyToSIMD(self, B, N, simd::index::Unroll<2>{r}, op); + default: return vcopyToSIMD(self, B, N, simd::index::Unroll<3>{r}, op); + } + } + } else if constexpr (AbstractVector

) { + ptrdiff_t L = IsOne ? M : N; + if constexpr (!std::is_copy_assignable_v && + std::same_as) { + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < L; ++j) + if constexpr (std::convertible_to) self[j] = auto{B}; + else self[j] = auto{B[j]}; + } else { + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < L; ++j) + utils::assign(self, B, utils::NoRowIndex{}, j, op); + } } else { - for (ptrdiff_t i = 0; i < M; ++i) { - if constexpr (std::is_copy_assignable_v) { - POLYMATHVECTORIZE - for (ptrdiff_t j = 0; j < N; ++j) self[i, j] = B[i, j]; + ptrdiff_t R = ptrdiff_t(M), C = ptrdiff_t(N); + POLYMATHNOVECTORIZE + for (ptrdiff_t i = 0; i < R; ++i) { + if constexpr (!std::is_copy_assignable_v && + std::same_as) { + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < C; ++j) + if constexpr (std::convertible_to) + self[i, j] = auto{B}; + else if constexpr (RowVector) self[i, j] = auto{B[j]}; + else if constexpr (ColVector) self[i, j] = auto{B[i]}; + else self[i, j] = auto{B[i, j]}; } else { - POLYMATHVECTORIZE - for (ptrdiff_t j = 0; j < N; ++j) self[i, j] = auto{B[i, j]}; + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < C; ++j) utils::assign(self, B, i, j, op); } } } - return self; } + // template constexpr void copyTo(const auto &B, Op op) { + // using C = math::scalarize_via_cast_t< + // std::remove_cvref_t().view())>>; + // if constexpr (!std::same_as && + // ((math::ScalarizeViaCastTo()) || + // (std::same_as, double> && + // std::same_as>))) { + // auto d{reinterpret(Self())}; + // if constexpr (std::same_as) d << + // reinterpret(B); else d << op(d, reinterpret(B)); + // } else vcopyTo(B, op); + // } + +public: template Y> - [[gnu::flatten]] constexpr auto operator<<(const Y &b) -> P & { - P &self{Self()}; - if constexpr (DenseLayout) { - std::fill_n(data_(), ptrdiff_t(dim_()), T(b)); - } else if constexpr (std::is_same_v) { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0, L = size_(); c < L; ++c) self[c] = b; - } else { - ptrdiff_t M = nr(), N = nc(), X = rs(); - T *p = data_(); - for (ptrdiff_t r = 0; r < M; ++r, p += X) std::fill_n(p, N, T(b)); - } - return self; - } - [[gnu::flatten]] constexpr auto operator+=(const AbstractMatrix auto &B) + [[gnu::flatten]] constexpr auto operator<<(const UniformScaling &B) -> P & { static_assert(MatrixDimension); - ptrdiff_t M = nr(), N = nc(); - invariant(M, ptrdiff_t(B.numRow())); - invariant(N, ptrdiff_t(B.numCol())); - P &self{Self()}; - for (ptrdiff_t r = 0; r < M; ++r) { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0; c < N; ++c) self[r, c] += B[r, c]; - } - return self; + std::fill_n(data_(), ptrdiff_t(this->dim()), T{}); + this->diag() << B.value; + return *static_cast

(this); } - [[gnu::flatten]] constexpr auto operator-=(const AbstractMatrix auto &B) - -> P & { - static_assert(MatrixDimension); - ptrdiff_t M = nr(), N = nc(); - invariant(M, ptrdiff_t(B.numRow())); - invariant(N, ptrdiff_t(B.numCol())); - P &self{Self()}; - for (ptrdiff_t r = 0; r < M; ++r) { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0; c < N; ++c) self[r, c] -= B[r, c]; - } - return self; + [[gnu::flatten]] constexpr auto operator<<(const SmallSparseMatrix &B) + -> P &; + + [[gnu::flatten]] constexpr auto operator<<(const auto &B) -> P & { + vcopyTo(B, utils::CopyAssign{}); + return Self(); } - [[gnu::flatten]] constexpr auto operator+=(const AbstractVector auto &B) - -> P & { - P &self{Self()}; - if constexpr (MatrixDimension) { - ptrdiff_t M = nr(), N = nc(); - invariant(M, B.size()); - for (ptrdiff_t r = 0; r < M; ++r) { - auto Br = B[r]; - POLYMATHVECTORIZE - for (ptrdiff_t c = 0; c < N; ++c) self[r, c] += Br; - } - } else { - ptrdiff_t L = size_(); - invariant(L, ptrdiff_t(B.size())); - POLYMATHVECTORIZE - for (ptrdiff_t i = 0; i < L; ++i) self[i] += B[i]; - } - return self; + [[gnu::flatten]] constexpr auto operator+=(const auto &B) -> P & { + vcopyTo(B, std::plus<>{}); + return Self(); } - template Y> - [[gnu::flatten]] constexpr auto operator+=(Y b) -> P & { - P &self{Self()}; - if constexpr (MatrixDimension && !DenseLayout) { - ptrdiff_t M = nr(), N = nc(); - for (ptrdiff_t r = 0; r < M; ++r) { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0; c < N; ++c) self[r, c] += b; - } - } else { - POLYMATHVECTORIZE - for (ptrdiff_t i = 0, L = size_(); i < L; ++i) self[i] += b; - } - return self; + [[gnu::flatten]] constexpr auto operator-=(const auto &B) -> P & { + vcopyTo(B, std::minus<>{}); + return Self(); } - [[gnu::flatten]] constexpr auto operator-=(const AbstractVector auto &B) - -> P & { - P &self{Self()}; - if constexpr (MatrixDimension) { - ptrdiff_t M = nr(), N = nc(); - invariant(M == B.size()); - for (ptrdiff_t r = 0; r < M; ++r) { - auto Br = B[r]; - POLYMATHVECTORIZE - for (ptrdiff_t c = 0; c < N; ++c) self[r, c] -= Br; - } + [[gnu::flatten]] constexpr auto operator*=(const auto &B) -> P & { + vcopyTo(B, std::multiplies<>{}); + return Self(); + } + [[gnu::flatten]] constexpr auto operator/=(const auto &B) -> P & { + vcopyTo(B, std::divides<>{}); + return Self(); + } +}; + +} // namespace poly::math + +namespace poly::containers { + +namespace tupletensorops { +// FIXME: +// Need to do all loads before all stores!!! +// This is because we want to support fusing loops where we may be overwriting +// inputs, e.g. `tie(x,y) << Tuple(x - y, x + y);` +template +[[gnu::always_inline]] inline void +vcopyToSIMD(Tuple &dst, const Tuple &src, I L, R row) { + // TODO: if `R` is a row index, maybe don't fully unroll static `L` + // We're going for very short SIMD vectors to focus on small sizes + using T = std::common_type_t, utils::eltype_t..., + utils::eltype_t, utils::eltype_t...>; + if constexpr (math::StaticInt) { + constexpr ptrdiff_t SL = ptrdiff_t(L); + constexpr std::array vdr = simd::VectorDivRem(); + constexpr ptrdiff_t W = vdr[0]; + constexpr ptrdiff_t fulliter = vdr[1]; + constexpr ptrdiff_t remainder = vdr[2]; + if constexpr (remainder > 0) { + auto u{simd::index::unrollmask(L, 0)}; + if constexpr (std::same_as) + dst.apply(src.map([=](const auto &s) { return get(s, u); }), + [=](auto &d, const auto &s) { d[u] = s; }); + else + dst.apply(src.map([=](const auto &s) { return get(s, row, u); }), + [=](auto &d, const auto &s) { d[row, u] = s; }); + } else if constexpr (std::same_as) { + simd::index::Unroll u{0}; + dst.apply(src.map([=](const auto &s) { return get(s, u); }), + [=](auto &d, const auto &s) { d[u] = s; }); } else { - ptrdiff_t L = size_(); - invariant(L == B.size()); - POLYMATHVECTORIZE - for (ptrdiff_t i = 0; i < L; ++i) self[i] -= B[i]; + simd::index::Unroll u{0}; + dst.apply(src.map([=](const auto &s) { return get(s, row, u); }), + [=](auto &d, const auto &s) { d[row, u] = s; }); + } + } else { + constexpr ptrdiff_t W = simd::Width; + for (ptrdiff_t i = 0;; i += W) { + auto u{simd::index::unrollmask<1, W>(L, i)}; + if (!u) break; + if constexpr (std::same_as) + dst.apply(src.map([=](const auto &s) { return get(s, u); }), + [=](auto &d, const auto &s) { d[u] = s; }); + else + dst.apply(src.map([=](const auto &s) { return get(s, row, u); }), + [=](auto &d, const auto &s) { d[row, u] = s; }); } - return self; } - template Y> - [[gnu::flatten]] constexpr auto operator*=(Y b) -> P & { - P &self{Self()}; - if constexpr (MatrixDimension && !DenseLayout) { - ptrdiff_t M = nr(), N = nc(); - for (ptrdiff_t r = 0; r < M; ++r) { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0; c < N; ++c) self[r, c] *= b; +} + +// template +// [[gnu::always_inline]] constexpr auto promote_shape(const Tuple &a, +// const Tuple &b) { +// return math::promote_shape(a.head, b.head); +// } +template +[[gnu::always_inline]] inline constexpr auto +promote_shape(const Tuple &a, const Tuple &b) +requires(sizeof...(As) == sizeof...(Bs)) +{ + auto h = math::promote_shape(a.head, b.head); + if constexpr (sizeof...(As) == 0) return h; + else { + auto [Mh, Nh] = h; + auto [Mt, Nt] = promote_shape(a.tail, b.tail); + return math::CartesianIndex(math::check_sizes(Mh, Mt), + math::check_sizes(Nh, Nt)); + } +} +template +[[gnu::always_inline]] inline constexpr void +vcopyTo(Tuple &dst, const Tuple &src) { + using T = std::common_type_t, utils::eltype_t..., + utils::eltype_t, utils::eltype_t...>; + // static_assert(sizeof(T) <= 8); + auto [M, N] = promote_shape(dst, src); + if constexpr (simd::SIMDSupported>) { + if constexpr (math::IsOne) + vcopyToSIMD(dst, src, N, utils::NoRowIndex{}); + else if constexpr (math::IsOne) + vcopyToSIMD(dst, src, M, utils::NoRowIndex{}); + else if constexpr (math::StaticInt) { + constexpr std::array UIR = math::unrollf(); + constexpr ptrdiff_t U = UIR[0]; + if constexpr (U != 0) + for (ptrdiff_t r = 0; r < (M - U + 1); r += U) + vcopyToSIMD(dst, src, N, simd::index::Unroll{r}); + constexpr ptrdiff_t R = UIR[1]; + if constexpr (R != 0) + vcopyToSIMD(dst, src, N, simd::index::Unroll{M - R}); + } else { + ptrdiff_t r = 0; + for (; r < (M - 3); r += 4) + vcopyToSIMD(dst, src, N, simd::index::Unroll<4>{r}); + switch (M & 3) { + case 0: return; + case 1: return vcopyToSIMD(dst, src, N, simd::index::Unroll<1>{r}); + case 2: return vcopyToSIMD(dst, src, N, simd::index::Unroll<2>{r}); + default: return vcopyToSIMD(dst, src, N, simd::index::Unroll<3>{r}); } + } + } else if constexpr (math::AbstractVector) { + ptrdiff_t L = math::IsOne ? M : N; + if constexpr (!std::is_copy_assignable_v) { + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < L; ++j) + dst.apply(src.map([=](const auto &s) { + if constexpr (std::convertible_to) return s; + else return s[j]; + }), + [=](auto &d, auto s) { d[j] = s; }); } else { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0, L = ptrdiff_t(dim_()); c < L; ++c) self[c] *= b; + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < L; ++j) + dst.apply(src.map([=](const auto &s) { return s[j]; }), + [=](auto &d, const auto &s) { d[j] = s; }); } - return self; - } - template Y> - [[gnu::flatten]] constexpr auto operator/=(Y b) -> P & { - P &self{Self()}; - if constexpr (MatrixDimension && !DenseLayout) { - ptrdiff_t M = nr(), N = nc(); - for (ptrdiff_t r = 0; r < M; ++r) { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0; c < N; ++c) self[r, c] /= b; + } else { + ptrdiff_t R = ptrdiff_t(M), C = ptrdiff_t(N); + POLYMATHNOVECTORIZE + for (ptrdiff_t i = 0; i < R; ++i) { + if constexpr (!std::is_copy_assignable_v) { + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < C; ++j) + dst.apply(src.map([=](const auto &s) { + if constexpr (std::convertible_to) return auto{s}; + else if constexpr (math::RowVector) return auto{s[j]}; + else if constexpr (math::ColVector) return auto{s[i]}; + else return auto{s[i, j]}; + }), + [=](auto &d, const auto &s) { d[i, j] = s; }); + } else { + POLYMATHIVDEP + for (ptrdiff_t j = 0; j < C; ++j) + dst.apply(src.map([=](const auto &s) { return s[i, j]; }), + [=](auto &d, const auto &s) { d[i, j] = s; }); } - } else { - POLYMATHVECTORIZE - for (ptrdiff_t c = 0, L = ptrdiff_t(dim_()); c < L; ++c) self[c] /= b; } - return self; } -}; -} // namespace poly::math +} +}; // namespace tupletensorops +// Note: these are inlined, because we want +// the compiler to be exposed to which arrays +// are identical, in case of re-use, so that +// they can share pointers. +template +template +[[gnu::flatten, gnu::always_inline]] inline constexpr void +Tuple::operator<<(const Tuple &src) +requires(sizeof...(As) == sizeof...(Bs)) +{ +#ifndef CASTTOSCALARIZE + tupletensorops::vcopyTo(*this, src); +#else + using C = math::scalarize_via_cast_t< + std::remove_cvref_t().view())>>; + if constexpr ((!std::same_as)&&math::ScalarizeViaCastTo< + C, As..., decltype(std::declval().view()), Bs...>()) { + using T = std::common_type_t, utils::eltype_t..., + utils::eltype_t, utils::eltype_t...>; + if constexpr ((sizeof(T) % (sizeof(C) * simd::Width)) != 0) { + auto dst{map([](auto &d) { return math::reinterpret(d); })}; + tupletensorops::vcopyTo( + dst, src.map([](const auto &s) { return math::reinterpret(s); })); + } else tupletensorops::vcopyTo(*this, src); + } else tupletensorops::vcopyTo(*this, src); +#endif +} +template +template +[[gnu::always_inline]] inline constexpr void +Tuple::operator+=(const Tuple &src) +requires(sizeof...(As) == sizeof...(Bs)) +{ + (*this) << map(src, [](const auto &d, const auto &s) { return d + s; }); +} +template +template +[[gnu::always_inline]] inline constexpr void +Tuple::operator-=(const Tuple &src) +requires(sizeof...(As) == sizeof...(Bs)) +{ + (*this) << map(src, [](const auto &d, const auto &s) { return d - s; }); +} +template +template +[[gnu::always_inline]] inline constexpr void +Tuple::operator*=(const Tuple &src) +requires(sizeof...(As) == sizeof...(Bs)) +{ + (*this) << map(src, [](const auto &d, const auto &s) { return d * s; }); +} +template +template +[[gnu::always_inline]] inline constexpr void +Tuple::operator/=(const Tuple &src) +requires(sizeof...(As) == sizeof...(Bs)) +{ + (*this) << map(src, [](const auto &d, const auto &s) { return d / s; }); +} + +} // namespace poly::containers diff --git a/include/Math/AxisTypes.hpp b/include/Math/AxisTypes.hpp index 45ef37e..a41510c 100644 --- a/include/Math/AxisTypes.hpp +++ b/include/Math/AxisTypes.hpp @@ -172,12 +172,10 @@ constexpr auto operator==(RowStride<> y, ptrdiff_t x) -> bool { constexpr auto operator==(RowStride<> x, RowStride<> y) -> bool { return ptrdiff_t(x) == ptrdiff_t(y); } -constexpr auto operator<=>(ptrdiff_t x, RowStride<> y) - -> std::strong_ordering { +constexpr auto operator<=>(ptrdiff_t x, RowStride<> y) -> std::strong_ordering { return x <=> ptrdiff_t(y); } -constexpr auto operator<=>(RowStride<> x, ptrdiff_t y) - -> std::strong_ordering { +constexpr auto operator<=>(RowStride<> x, ptrdiff_t y) -> std::strong_ordering { return ptrdiff_t(x) <=> y; } constexpr auto operator<=>(RowStride<> x, RowStride<> y) @@ -210,11 +208,13 @@ template constexpr auto standardizeRangeBound(Col x) { else return std::integral_constant{}; } -template constexpr auto unwrapRow(Row x) -> ptrdiff_t { - return ptrdiff_t(x); +template constexpr auto unwrapRow(Row x) { + if constexpr (M == -1) return ptrdiff_t(x); + else return std::integral_constant{}; } -template constexpr auto unwrapCol(Col x) -> ptrdiff_t { - return ptrdiff_t(x); +template constexpr auto unwrapCol(Col x) { + if constexpr (M == -1) return ptrdiff_t(x); + else return std::integral_constant{}; } constexpr auto unwrapRow(auto x) { return x; } constexpr auto unwrapCol(auto x) { return x; } diff --git a/include/Math/Constraints.hpp b/include/Math/Constraints.hpp index 6157031..12ecda0 100644 --- a/include/Math/Constraints.hpp +++ b/include/Math/Constraints.hpp @@ -69,7 +69,7 @@ constexpr void eraseConstraintImpl(MutDensePtrMatrix A, ptrdiff_t _i, ptrdiff_t _j) { invariant(_i != _j); ptrdiff_t i = std::min(_i, _j), j = std::max(_i, _j); - const auto [M, N] = A.size(); + const auto [M, N] = shape(A); ptrdiff_t lastRow = M - 1; ptrdiff_t penuRow = lastRow - 1; if (j == penuRow) { @@ -92,7 +92,7 @@ constexpr void eraseConstraint(MutDensePtrMatrix &A, ptrdiff_t i, constexpr auto substituteEqualityImpl(MutDensePtrMatrix E, const ptrdiff_t i) -> Row<> { - const auto [numConstraints, numVar] = E.size(); + const auto [numConstraints, numVar] = shape(E); ptrdiff_t minNonZero = numVar + 1; ptrdiff_t rowMinNonZero = numConstraints; for (ptrdiff_t j = 0; j < numConstraints; ++j) @@ -137,7 +137,7 @@ constexpr auto substituteEqualityPairImpl(std::array, 2> AE, ptrdiff_t i) -> Row<> { auto [A, E] = AE; - const auto [numConstraints, numVar] = E.size(); + const auto [numConstraints, numVar] = shape(E); ptrdiff_t minNonZero = numVar + 1; ptrdiff_t rowMinNonZero = numConstraints; for (ptrdiff_t j = 0; j < numConstraints; ++j) { @@ -403,7 +403,7 @@ constexpr auto uniqueConstraint(DensePtrMatrix A, Row<> r) -> bool { [[nodiscard]] constexpr auto removeRedundantRows(MutDensePtrMatrix A, MutDensePtrMatrix B) -> std::array, 2> { - auto [M, N] = B.size(); + auto [M, N] = shape(B); for (ptrdiff_t r = 0, c = 0; c++ < N && r < M;) if (!NormalForm::pivotRows(B, Col<>{c == N ? 0 : c}, Row<>{M}, Row<>{r})) NormalForm::reduceColumnStack(A, B, c == N ? 0 : c, r++); diff --git a/include/Math/Constructors.hpp b/include/Math/Constructors.hpp index 683c6af..a95c507 100644 --- a/include/Math/Constructors.hpp +++ b/include/Math/Constructors.hpp @@ -9,7 +9,7 @@ using alloc::Arena, alloc::WArena, alloc::OwningArena, utils::eltype_t; template constexpr auto vector(A a, ptrdiff_t M) -> ManagedArray, ptrdiff_t, - PreAllocStorage, ptrdiff_t>(), A> { + containers::PreAllocStorage, ptrdiff_t>(), A> { return {M, a}; } @@ -36,7 +36,7 @@ constexpr auto vector(Arena *alloc, ptrdiff_t M) template constexpr auto vector(A a, ptrdiff_t M, eltype_t x) -> ManagedArray, ptrdiff_t, - PreAllocStorage, ptrdiff_t>(), A> { + containers::PreAllocStorage, ptrdiff_t>(), A> { return {M, x, a}; } @@ -62,9 +62,9 @@ constexpr auto vector(Arena *alloc, ptrdiff_t M, T x) } template -constexpr auto matrix(A a, ptrdiff_t M) - -> ManagedArray, SquareDims<>, - PreAllocSquareStorage, SquareDims<>>(), A> { +constexpr auto matrix(A a, ptrdiff_t M) -> ManagedArray< + eltype_t, SquareDims<>, + containers::PreAllocSquareStorage, SquareDims<>>(), A> { return {SquareDims<>{{M}}, a}; } @@ -84,9 +84,9 @@ constexpr auto matrix(Arena *alloc, ptrdiff_t M) return {alloc->template allocate(M * M), SquareDims<>{{M}}}; } template -constexpr auto matrix(A a, ptrdiff_t M, eltype_t x) - -> ManagedArray, SquareDims<>, - PreAllocSquareStorage, SquareDims<>>(), A> { +constexpr auto matrix(A a, ptrdiff_t M, eltype_t x) -> ManagedArray< + eltype_t, SquareDims<>, + containers::PreAllocSquareStorage, SquareDims<>>(), A> { return {SquareDims<>{{M}}, x, a}; } template @@ -113,7 +113,8 @@ constexpr auto matrix(Arena *alloc, ptrdiff_t M, T x) template constexpr auto matrix(A a, Row M, Col N) -> ManagedArray, DenseDims, - PreAllocStorage, DenseDims>(), A> { + containers::PreAllocStorage, DenseDims>(), + A> { return {DenseDims{M, N}, a}; } template @@ -136,7 +137,8 @@ constexpr auto matrix(Arena *alloc, Row M, Col N) template constexpr auto matrix(A a, Row M, Col N, eltype_t x) -> ManagedArray, DenseDims, - PreAllocStorage, DenseDims>(), A> { + containers::PreAllocStorage, DenseDims>(), + A> { return {DenseDims{M, N}, x, a}; } template @@ -162,11 +164,12 @@ constexpr auto matrix(Arena *alloc, Row M, Col N, T x) } template -constexpr auto identity(A a, ptrdiff_t M) - -> ManagedArray, SquareDims<>, - PreAllocSquareStorage, SquareDims<>>(), A> { +constexpr auto identity(A a, ptrdiff_t M) -> ManagedArray< + eltype_t, SquareDims<>, + containers::PreAllocSquareStorage, SquareDims<>>(), A> { ManagedArray, SquareDims<>, - PreAllocSquareStorage, SquareDims<>>(), A> + containers::PreAllocSquareStorage, SquareDims<>>(), + A> B{SquareDims<>{Row<>{M}}, eltype_t{}, a}; B.diag() << eltype_t{1}; return B; diff --git a/include/Math/Dual.hpp b/include/Math/Dual.hpp index 92db0c4..ca094c1 100644 --- a/include/Math/Dual.hpp +++ b/include/Math/Dual.hpp @@ -12,11 +12,101 @@ namespace poly::math { -template class Dual { +template struct Dual { + static_assert(Compress); + utils::compressed_t val{}; + SVector partials{T{}}; + + using decompressed_type = Dual, N, false>; + constexpr operator decompressed_type() const { + return decompressed_type::decompress(this); + } + [[nodiscard]] constexpr auto value() -> T { return val; } + [[nodiscard]] constexpr auto value() const -> const T & { return val; } + [[nodiscard]] constexpr auto gradient() -> SVector & { + return partials; + } + [[nodiscard]] constexpr auto gradient() const -> const SVector & { + return partials; + } + + [[gnu::always_inline]] constexpr auto operator-() const & -> Dual { + return {-val, -partials}; + } + [[gnu::always_inline]] constexpr auto + operator+(const Dual &other) const & -> Dual { + return {val + other.val, partials + other.partials}; + } + [[gnu::always_inline]] constexpr auto operator-(const Dual &other) const + -> Dual { + return {val - other.val, partials - other.partials}; + } + [[gnu::always_inline]] constexpr auto operator+=(const Dual &other) + -> Dual & { + val += other.val; + partials += other.partials; + return *this; + } + [[gnu::always_inline]] constexpr auto operator-=(const Dual &other) + -> Dual & { + val -= other.val; + partials -= other.partials; + return *this; + } +}; + +template +requires(std::popcount(size_t(N)) > 1) +struct Dual { + SVector data{T{}}; + + using decompressed_type = Dual, N, false>; + constexpr operator decompressed_type() const { + return decompressed_type::decompress(this); + } + [[nodiscard]] constexpr auto value() -> T { return data[0]; } + [[nodiscard]] constexpr auto value() const -> const T & { return data[0]; } + [[nodiscard]] constexpr auto gradient() + -> MutArray> { + return {data.data() + 1, {}}; + } + [[nodiscard]] constexpr auto gradient() const + -> Array> { + return {data.data() + 1, {}}; + } + + [[gnu::always_inline]] constexpr auto operator-() const & -> Dual { + return {-data}; + } + [[gnu::always_inline]] constexpr auto + operator+(const Dual &other) const & -> Dual { + return {data + other.data}; + } + [[gnu::always_inline]] constexpr auto operator-(const Dual &other) const + -> Dual { + return {data - other.data}; + } + [[gnu::always_inline]] constexpr auto operator+=(const Dual &other) + -> Dual & { + data += other.data; + return *this; + } + [[gnu::always_inline]] constexpr auto operator-=(const Dual &other) + -> Dual & { + data -= other.data; + return *this; + } +}; + +template struct Dual { + // default decompressed separates the value and partials T val{}; - SVector partials{T{}}; + SVector partials{T{}}; + + using compressed_type = Dual, N, true>; + using decompressed_type = Dual, N, false>; + static_assert(std::same_as); -public: constexpr Dual() = default; constexpr Dual(T v) : val(v) {} constexpr Dual(T v, ptrdiff_t n) : val(v) { partials[n] = T{1}; } @@ -33,132 +123,589 @@ template class Dual { [[nodiscard]] constexpr auto gradient(ptrdiff_t i) const -> const T & { return partials[i]; } - constexpr auto operator-() const & -> Dual { return {-val, -partials}; } - constexpr auto operator+(const Dual &other) const & -> Dual { + [[gnu::always_inline]] constexpr auto operator-() const & -> Dual { + return {-val, -partials}; + } + [[gnu::always_inline]] constexpr auto + operator+(const Dual &other) const & -> Dual { return {val + other.val, partials + other.partials}; } - constexpr auto operator-(const Dual &other) const -> Dual { + [[gnu::always_inline]] constexpr auto operator-(const Dual &other) const + -> Dual { return {val - other.val, partials - other.partials}; } - constexpr auto operator*(const Dual &other) const -> Dual { + [[gnu::always_inline]] constexpr auto operator*(const Dual &other) const + -> Dual { return {val * other.val, val * other.partials + other.val * partials}; } - constexpr auto operator/(const Dual &other) const -> Dual { + [[gnu::always_inline]] constexpr auto operator/(const Dual &other) const + -> Dual { return {val / other.val, (other.val * partials - val * other.partials) / (other.val * other.val)}; } - constexpr auto operator+=(const Dual &other) -> Dual & { + [[gnu::always_inline]] constexpr auto + operator+(const T &other) const & -> Dual + requires(!std::same_as) + { + return {val + other, partials}; + } + [[gnu::always_inline]] constexpr auto operator-(const T &other) const -> Dual + requires(!std::same_as) + { + return {val - other, partials}; + } + [[gnu::always_inline]] constexpr auto operator*(const T &other) const -> Dual + requires(!std::same_as) + { + return {val * other, partials * other}; + } + [[gnu::always_inline]] constexpr auto operator/(const T &other) const -> Dual + requires(!std::same_as) + { + return {val / other, partials / other}; + } + [[gnu::always_inline]] constexpr auto operator+=(const Dual &other) + -> Dual & { val += other.val; partials += other.partials; return *this; } - constexpr auto operator-=(const Dual &other) -> Dual & { + [[gnu::always_inline]] constexpr auto operator-=(const Dual &other) + -> Dual & { val -= other.val; partials -= other.partials; return *this; } - constexpr auto operator*=(const Dual &other) -> Dual & { - val *= other.val; + [[gnu::always_inline]] constexpr auto operator*=(const Dual &other) + -> Dual & { partials << val * other.partials + other.val * partials; + val *= other.val; return *this; } - constexpr auto operator/=(const Dual &other) -> Dual & { - val /= other.val; + [[gnu::always_inline]] constexpr auto operator/=(const Dual &other) + -> Dual & { partials << (other.val * partials - val * other.partials) / (other.val * other.val); + val /= other.val; return *this; } - constexpr auto operator+(double other) const & -> Dual { + [[gnu::always_inline]] constexpr auto + operator+(double other) const & -> Dual { return {val + other, partials}; } - constexpr auto operator-(double other) const -> Dual { + [[gnu::always_inline]] constexpr auto operator-(double other) const -> Dual { return {val - other, partials}; } - constexpr auto operator*(double other) const -> Dual { - return {val * other, other * partials}; + [[gnu::always_inline]] constexpr auto operator*(double other) const -> Dual { + return {val * other, partials * other}; } - constexpr auto operator/(double other) const -> Dual { + [[gnu::always_inline]] constexpr auto operator/(double other) const -> Dual { return {val / other, partials / other}; } - constexpr auto operator+=(double other) -> Dual & { + [[gnu::always_inline]] constexpr auto operator+=(double other) -> Dual & { val += other; return *this; } - constexpr auto operator-=(double other) -> Dual & { + [[gnu::always_inline]] constexpr auto operator-=(double other) -> Dual & { val -= other; return *this; } - constexpr auto operator*=(double other) -> Dual & { + [[gnu::always_inline]] constexpr auto operator*=(double other) -> Dual & { val *= other; partials *= other; return *this; } - constexpr auto operator/=(double other) -> Dual & { + [[gnu::always_inline]] constexpr auto operator/=(double other) -> Dual & { val /= other; partials /= other; return *this; } - constexpr auto operator==(const Dual &other) const -> bool { + [[gnu::always_inline]] constexpr auto operator==(const Dual &other) const + -> bool { return val == other.val; // && grad == other.grad; } - constexpr auto operator!=(const Dual &other) const -> bool { + [[gnu::always_inline]] constexpr auto operator!=(const Dual &other) const + -> bool { return val != other.val; // || grad != other.grad; } + constexpr auto operator<(const Dual &other) const -> bool { + return val < other.val; + } + constexpr auto operator>(const Dual &other) const -> bool { + return val > other.val; + } + constexpr auto operator<=(const Dual &other) const -> bool { + return val <= other.val; + } + constexpr auto operator>=(const Dual &other) const -> bool { + return val >= other.val; + } constexpr auto operator==(double other) const -> bool { return val == other; } constexpr auto operator!=(double other) const -> bool { return val != other; } constexpr auto operator<(double other) const -> bool { return val < other; } constexpr auto operator>(double other) const -> bool { return val > other; } constexpr auto operator<=(double other) const -> bool { return val <= other; } constexpr auto operator>=(double other) const -> bool { return val >= other; } + constexpr auto operator==(T other) const -> bool + requires(!std::same_as) + { + return val == other; + } + constexpr auto operator!=(T other) const -> bool + requires(!std::same_as) + { + return val != other; + } + constexpr auto operator<(T other) const -> bool + requires(!std::same_as) + { + return val < other; + } + constexpr auto operator>(T other) const -> bool + requires(!std::same_as) + { + return val > other; + } + constexpr auto operator<=(T other) const -> bool + requires(!std::same_as) + { + return val <= other; + } + constexpr auto operator>=(T other) const -> bool + requires(!std::same_as) + { + return val >= other; + } + constexpr void compress(compressed_type *p) const { + utils::compress(val, &(p->val)); + partials.compress(&(p->partials)); + } + static constexpr auto decompress(const compressed_type *p) -> Dual { + return {utils::decompress(&(p->val)), + SVector::decompress(&(p->partials))}; + } + // constexpr void compress(compressed_type *p) const { + // utils::compress(val, &(p->data[0])); + // p->gradient() << partials; + // } + // static constexpr auto decompress(const compressed_type *p) -> Dual { + // return {utils::decompress(&(p->data[0])), SVector(p->gradient())}; + // } + constexpr operator compressed_type() const { + compressed_type ret; + compress(&ret); + return ret; + } +}; + +template +requires(std::popcount(size_t(N)) > 1) +struct Dual { + static constexpr ptrdiff_t value_idx = 0; // N; + static constexpr ptrdiff_t partial_offset = value_idx != N; + using data_type = SVector; + data_type data{T{}}; + using compressed_type = Dual; + using decompressed_type = Dual; + + using V = typename data_type::V; + static constexpr ptrdiff_t W = data_type::W; + // constexpr Dual() = default; + constexpr Dual() = default; + constexpr Dual(T v) { data[value_idx] = v; } + constexpr Dual(T v, ptrdiff_t n) { + data[value_idx] = v; + data[partial_offset + n] = T{1}; + } + // constexpr Dual(T v, ptrdiff_t n, T p) { + // data[value_idx] = v; + // data[partial_offset + n] = p; + // } + constexpr Dual(T v, AbstractVector auto g) { + value() = v; + gradient() << g; + } + constexpr Dual(SVector d) : data{d} {} + constexpr Dual(const AbstractVector auto &d) + requires(std::convertible_to, T>) + : data{d} {} + constexpr Dual(std::integral auto v) { value() = v; } + constexpr Dual(std::floating_point auto v) { value() = v; } + constexpr auto value() -> T & { return data[value_idx]; } + constexpr auto gradient() + -> MutArray> { + return {data.data() + partial_offset, {}}; + } + [[nodiscard]] constexpr auto value() const -> T { return data[value_idx]; } + // zeros out partial part of the vector + [[nodiscard]] constexpr auto vvalue() const -> V { + // return data[value_idx]; + return (simd::range() == simd::Vec{}) + ? data.memory_[0] + : V{}; + } + // broadcasts value across register + [[nodiscard]] constexpr auto vbvalue() const -> V { + return simd::vbroadcast(data.memory_[0]); + } + [[nodiscard]] constexpr auto gradient() const + -> Array> { + return {data.data() + partial_offset, {}}; + } + + constexpr auto operator-() const & -> Dual { return {-data}; } + constexpr auto operator+(const Dual &other) const & -> Dual { + return {data + other.data}; + } + constexpr auto operator-(const Dual &other) const -> Dual { + return {data - other.data}; + } + constexpr auto operator*(const Dual &other) const -> Dual { + // TODO: either update remaining methods to match this style, + // or figure out how to get `conditional`'s codegen quality to match + Dual ret; + V vt = vbvalue(), vo = other.vbvalue(), x = vt * other.data.memory_[0]; + x = simd::firstoff() ? x + vo * data.memory_[0] : x; + ret.data.memory_[0] = x; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 1; i < data_type::L; ++i) + ret.data.memory_[i] = vt * other.data.memory_[i] + vo * data.memory_[i]; + return ret; + // return {conditional(std::plus<>{}, + // elementwise_not_equal(_(0, N + 1), value_idx), + // value() * other.data, data * other.value())}; + } + constexpr auto operator/(const Dual &other) const -> Dual { + Dual ret; + V vt = vbvalue(), vo = other.vbvalue(), vo2 = vo * vo, + x = vo * data.memory_[0]; + ret.data.memory_[0] = + (simd::firstoff() ? x - vt * other.data.memory_[0] : x) / vo2; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 1; i < data_type::L; ++i) + ret.data.memory_[i] = + (vo * data.memory_[i] - vt * other.data.memory_[i]) / vo2; + return ret; + // val = value() / other.value() + // partials = (other.value() * gradient() - value() * other.gradient()) / + // (other.value() * other.value()) + // partials = (gradient()) / (other.value()) + // - (value() * other.gradient()) / (other.value() * other.value()) + // T v{other.value()}; + // return {conditional(std::minus<>{}, + // elementwise_not_equal(_(0, N + 1), value_idx), data / + // v, value() * other.data / (v * v))}; + } + constexpr auto operator+=(const Dual &other) -> Dual & { + data += other.data; + return *this; + } + constexpr auto operator-=(const Dual &other) -> Dual & { + data -= other.data; + return *this; + } + constexpr auto operator*=(const Dual &other) -> Dual & { + V vt = vbvalue(), vo = other.vbvalue(), x = vt * other.data.memory_[0]; + data.memory_[0] = + simd::firstoff() ? x + vo * data.memory_[0] : x; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 1; i < data_type::L; ++i) + data.memory_[i] = vt * other.data.memory_[i] + vo * data.memory_[i]; + // data << conditional(std::plus<>{}, + // elementwise_not_equal(_(0, N + 1), value_idx), + // value() * other.data, data * other.value()); + return *this; + } + constexpr auto operator/=(const Dual &other) -> Dual & { + V vt = vbvalue(), vo = other.vbvalue(), vo2 = vo * vo, + x = vo * data.memory_[0]; + data.memory_[0] = + (simd::firstoff() ? x - vt * other.data.memory_[0] : x) / vo2; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 1; i < data_type::L; ++i) + data.memory_[i] = + (vo * data.memory_[i] - vt * other.data.memory_[i]) / vo2; + // T v{other.value()}; + // data << conditional(std::minus<>{}, + // elementwise_not_equal(_(0, N + 1), value_idx), data / + // v, value() * other.data / (v * v)); + return *this; + } + constexpr auto operator+(double other) const & -> Dual { + Dual ret = *this; + ret.data.memory_[0] += simd::Vec::W, T>{other}; + return ret; + } + constexpr auto operator-(double other) const -> Dual { + Dual ret = *this; + ret.data.memory_[0] -= simd::Vec::W, T>{other}; + return ret; + } + constexpr auto operator*(double other) const -> Dual { + return {data * other}; + } + constexpr auto operator/(double other) const -> Dual { + return {data / other}; + } + constexpr auto operator+=(double other) -> Dual & { + data.memory_[0] += simd::Vec::W, T>{other}; + return *this; + } + constexpr auto operator-=(double other) -> Dual & { + data.memory_[0] -= simd::Vec::W, T>{other}; + return *this; + } + constexpr auto operator*=(double other) -> Dual & { + data *= other; + return *this; + } + constexpr auto operator/=(double other) -> Dual & { + data /= other; + return *this; + } + constexpr auto operator==(const Dual &other) const -> bool { + return value() == other.value(); // && grad == other.grad; + } + constexpr auto operator!=(const Dual &other) const -> bool { + return value() != other.value(); // || grad != other.grad; + } + constexpr auto operator==(double other) const -> bool { + return value() == other; + } + constexpr auto operator!=(double other) const -> bool { + return value() != other; + } + constexpr auto operator<(double other) const -> bool { + return value() < other; + } + constexpr auto operator>(double other) const -> bool { + return value() > other; + } + constexpr auto operator<=(double other) const -> bool { + return value() <= other; + } + constexpr auto operator>=(double other) const -> bool { + return value() >= other; + } constexpr auto operator<(const Dual &other) const -> bool { - return val < other.val; + return value() < other.value(); } constexpr auto operator>(const Dual &other) const -> bool { - return val > other.val; + return value() > other.value(); } constexpr auto operator<=(const Dual &other) const -> bool { - return val <= other.val; + return value() <= other.value(); } constexpr auto operator>=(const Dual &other) const -> bool { - return val >= other.val; + return value() >= other.value(); + } + + friend constexpr auto exp(Dual x) -> Dual { + return {conditional(std::multiplies<>{}, + elementwise_not_equal(_(0, N + 1), value_idx), + exp(x.value()), x.data)}; + } + + friend constexpr auto operator+(double other, Dual x) -> Dual { + return {other + x.data}; + } + friend constexpr auto operator-(double other, Dual x) -> Dual { + return {other - x.data}; + } + friend constexpr auto operator*(double other, Dual x) -> Dual { + return {other * x.data}; + } + friend constexpr auto operator/(double a, Dual b) -> Dual { + Dual ret; + V vt = simd::vbroadcast(a), vo = b.vbvalue(), vo2 = vo * vo, + x = vo * simd::Vec{a}; + ret.data.memory_[0] = + (simd::firstoff() ? x - vt * b.data.memory_[0] : x) / vo2; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 1; i < data_type::L; ++i) + ret.data.memory_[i] = (-vt * b.data.memory_[i]) / vo2; + return ret; + // T v = other / x.value(); + // return {conditional(std::multiplies<>{}, + // elementwise_not_equal(_(0, N + 1), value_idx), v, + // -x.data / x.value())}; + // return {v, -v * x.gradient() / (x.value())}; } + constexpr void compress(compressed_type *p) const { p->data << data; } + static constexpr auto decompress(const compressed_type *p) -> Dual { + return {SVector{p->data}}; + } + constexpr operator compressed_type() const { + compressed_type ret; + compress(&ret); + return ret; + } +}; +static_assert(!std::convertible_to, + std::integral_constant>, + Dual>); +static_assert(utils::Compressible>); +static_assert(utils::Compressible>); +static_assert( + AbstractVector< + Conditional, + long, std::not_equal_to>, + poly::math::ElementwiseBinaryOp< + double, poly::math::StaticArray, + std::multiplies>, + poly::math::ElementwiseBinaryOp< + poly::math::StaticArray, double, + std::multiplies>, + std::plus>>); + +template struct IsDualImpl : std::false_type {}; +template +struct IsDualImpl> : std::true_type {}; +template +concept IsDual = IsDualImpl::value; + +// We want to support casting compressed `Dual` arrays to `double` +// when possible as a performance optimization. +// This is possible with +// 1. Dual (+/-) Dual +// 2. Dual * double or double * Dual +// 3. Dual / double +// 4. Simple copies +template struct ScalarizeEltViaCast { + using type = void; +}; +template +using scalarize_elt_cast_t = typename ScalarizeEltViaCast::type; +template +struct ScalarizeEltViaCast> { + using type = std::conditional_t, double, + scalarize_elt_cast_t>; +}; + +template struct ScalarizeViaCast, T>> { + using type = scalarize_via_cast_t; +}; +template +concept AdditiveOp = + std::same_as> || std::same_as>; +template +concept MultiplicativeOp = + std::same_as> || std::same_as>; +template +concept EltIsDual = IsDual>; + +template struct ScalarizeViaCast> { + using type = scalarize_elt_cast_t>; +}; +template +struct ScalarizeViaCast> { + using type = scalarize_elt_cast_t>; +}; + +template +concept EltCastableDual = + EltIsDual && std::same_as, double>; +template +struct ScalarizeViaCast> { + // when we cast, we expand into rows, thus col vectors don't work + // as they'd have to become matrices, and then number of rows + // won't match up, unless both inputs were a ColVector + // It is unclear if the case where both inputs are ColVectors is worth + // the complexity, as the benefit from this optimization is being + // able to handle things contiguously, which we in that case. + using type = std::conditional_t< + (ColVector || ColVector) || + (!std::same_as, utils::eltype_t>), + void, double>; +}; +template T> +struct ScalarizeViaCast> { + using type = double; +}; +template T> +struct ScalarizeViaCast>> { + using type = double; }; + template Dual(T, SVector) -> Dual; template -constexpr auto operator+(double other, Dual x) -> Dual { +[[gnu::always_inline]] constexpr auto operator+(const T &a, const Dual &b) + -> Dual +requires(!std::same_as) +{ + return {a + b.val, b.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator-(const T &a, const Dual &b) + -> Dual +requires(!std::same_as) +{ + return {a - b.val, -b.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator*(const T &a, const Dual &b) + -> Dual +requires(!std::same_as) +{ + // Dual res; + // res.val = val * other.val; + // res.partials << val * other.partials + other.val * partials; + // return res; + return {a * b.val, a * b.partials}; +} +template +[[gnu::always_inline]] constexpr auto operator/(const T &a, const Dual &b) + -> Dual +requires(!std::same_as) +{ + return {a / b.val, (-a * b.partials) / (b.val * b.val)}; +} +template +[[gnu::always_inline]] constexpr auto operator+(double other, + const Dual &x) + -> Dual { return {x.value() + other, x.gradient()}; } template -constexpr auto operator-(double other, Dual x) -> Dual { +[[gnu::always_inline]] constexpr auto operator-(double other, + const Dual &x) + -> Dual { return {x.value() - other, -x.gradient()}; } template -constexpr auto operator*(double other, Dual x) -> Dual { +[[gnu::always_inline]] constexpr auto operator*(double other, + const Dual &x) + -> Dual { return {x.value() * other, other * x.gradient()}; } template -constexpr auto operator/(double other, Dual x) -> Dual { +[[gnu::always_inline]] constexpr auto operator/(double other, + const Dual &x) + -> Dual { return {other / x.value(), -other * x.gradient() / (x.value() * x.value())}; } -template constexpr auto exp(Dual x) -> Dual { +template +constexpr auto exp(const Dual &x) -> Dual { T expx = exp(x.value()); return {expx, expx * x.gradient()}; } template -constexpr auto sigmoid(Dual x) -> Dual { +constexpr auto sigmoid(const Dual &x) -> Dual { T s = sigmoid(x.value()); return {s, (s - s * s) * x.gradient()}; } template -constexpr auto softplus(Dual x) -> Dual { +constexpr auto softplus(const Dual &x) -> Dual { return {softplus(x.value()), sigmoid(x.value()) * x.gradient()}; } -template constexpr auto log(Dual x) -> Dual { +template +constexpr auto log(const Dual &x) -> Dual { return {log2(x.value()), x.gradient() / x.value()}; } template -constexpr auto log2(Dual x) -> Dual { +constexpr auto log2(const Dual &x) -> Dual { constexpr double log2 = 0.6931471805599453; // log(2); return {log2(x.value()), x.gradient() / (log2 * x.value())}; } @@ -221,6 +768,8 @@ template struct DualVector { return v; } [[nodiscard]] constexpr auto size() const -> ptrdiff_t { return x.size(); } + [[nodiscard]] constexpr auto numRow() const -> Row<1> { return {}; } + [[nodiscard]] constexpr auto numCol() const -> Col<> { return {x.size()}; } [[nodiscard]] constexpr auto view() const -> DualVector { return *this; } }; static_assert(AbstractVector>>); @@ -257,10 +806,15 @@ constexpr auto gradient(alloc::Arena<> *arena, PtrVector x, } } // only computes the upper triangle blocks -constexpr auto extractDualValRecurse(std::floating_point auto x) { return x; } +template +constexpr auto value(const Dual &x) { + return value(x.value()); +} +// this can call `value` on a compressed `Dual`, whichh is why we need `value` +// to be defined on it.` template -constexpr auto extractDualValRecurse(const Dual &x) { - return extractDualValRecurse(x.value()); +constexpr auto value(utils::Reference> x) { + return value(x.c->value()); } /// fills the lower triangle of the hessian diff --git a/include/Math/EmptyArrays.hpp b/include/Math/EmptyArrays.hpp index 848fdfc..3ac3dcf 100644 --- a/include/Math/EmptyArrays.hpp +++ b/include/Math/EmptyArrays.hpp @@ -17,7 +17,7 @@ template struct EmptyMatrix { static constexpr auto data() -> T * { return nullptr; } static constexpr auto operator[](ptrdiff_t, ptrdiff_t) -> T { return 0; } - static constexpr auto size() -> CartesianIndex { + static constexpr auto shape() -> CartesianIndex { return {0, 0}; } static constexpr auto view() -> EmptyMatrix { return EmptyMatrix{}; } diff --git a/include/Math/Indexing.hpp b/include/Math/Indexing.hpp index 277a29a..f665517 100644 --- a/include/Math/Indexing.hpp +++ b/include/Math/Indexing.hpp @@ -2,6 +2,7 @@ #include "Math/AxisTypes.hpp" #include "Math/Iterators.hpp" #include "Math/MatrixDimensions.hpp" +#include "SIMD/Indexing.hpp" #include namespace poly::math { @@ -16,6 +17,8 @@ namespace poly::math { return os << "end"; } } end; +/// TODO: remove `OffsetBegin` +/// We probably won't support non-zero-based indexing struct OffsetBegin { [[no_unique_address]] ptrdiff_t offset; friend inline auto operator<<(std::ostream &os, OffsetBegin r) @@ -65,7 +68,8 @@ concept ScalarIndex = [[nodiscard]] inline constexpr auto operator()(auto B, auto E) const { return Range{standardizeRangeBound(B), standardizeRangeBound(E)}; } -} _; // NOLINT(bugprone-reserved-identifier) +} _; + constexpr auto canonicalize(ptrdiff_t e, ptrdiff_t) -> ptrdiff_t { return e; } constexpr auto canonicalize(Begin, ptrdiff_t) -> ptrdiff_t { return 0; } constexpr auto canonicalize(OffsetBegin b, ptrdiff_t) -> ptrdiff_t { @@ -142,16 +146,6 @@ constexpr auto calcOffset(ptrdiff_t, Colon) -> ptrdiff_t { return 0; } constexpr auto calcOffset(SquareDims<>, ptrdiff_t i) -> ptrdiff_t { return i; } constexpr auto calcOffset(DenseDims<>, ptrdiff_t i) -> ptrdiff_t { return i; } -template -[[nodiscard]] inline constexpr auto calcOffset(StridedDims<> d, - CartesianIndex i) - -> ptrdiff_t { - ptrdiff_t r = - ptrdiff_t(RowStride<>(d)) * calcOffset(ptrdiff_t(Row<>(d)), i.row); - ptrdiff_t c = calcOffset(ptrdiff_t(Col<>(d)), i.col); - return r + c; -} - struct StridedRange { [[no_unique_address]] ptrdiff_t len; [[no_unique_address]] ptrdiff_t stride; @@ -161,35 +155,57 @@ struct StridedRange { return os << "Length: " << x.len << " (stride: " << x.stride << ")"; } }; + +template +constexpr auto calcOffset(ptrdiff_t len, simd::index::Unroll i) { + if constexpr (std::same_as>) + invariant((i.index + U * W - 1) < len); + else invariant(i.index + (U - 1) * W + i.mask.lastUnmasked() - 1 < len); + return i.index; +} + template constexpr auto calcOffset(StridedRange d, I i) -> ptrdiff_t { return d.stride * calcOffset(d.len, i); } -constexpr auto is_integral_const(auto) -> bool { return false; } -template -constexpr auto is_integral_const(std::integral_constant) -> bool { - return true; + +template +[[nodiscard]] inline constexpr auto calcOffset(StridedDims<> d, R r, C c) + -> ptrdiff_t { + return ptrdiff_t(stride(d)) * calcOffset(ptrdiff_t(Row<>(d)), r) + + calcOffset(ptrdiff_t(Col<>(d)), c); } +// constexpr auto is_integral_const(auto) -> bool { return false; } +// template +// constexpr auto is_integral_const(std::integral_constant) -> bool { +// return true; +// } +constexpr auto row(StridedRange r) -> Row<> { return {r.len}; } +constexpr auto col(StridedRange) -> Col<1> { return {}; } +constexpr auto stride(StridedRange r) -> RowStride<> { return {r.stride}; } + template concept StaticInt = std::is_same_v>; -template +template concept DenseLayout = std::integral || std::is_convertible_v> || StaticInt; static_assert(StaticInt>); static_assert(!StaticInt); -template +template concept VectorDimension = std::integral || std::same_as || StaticInt; // Concept for aligning array dimensions with indices. template concept Index = - (VectorDimension && (ScalarIndex || AbstractSlice)) || - (DenseLayout && ScalarIndex) || (MatrixDimension && requires(I i) { + (VectorDimension && + (ScalarIndex || AbstractSlice || simd::index::issimd)) || + (DenseLayout && (ScalarIndex || simd::index::issimd)) || + (MatrixDimension && requires(I i) { { i.row }; { i.col }; }); @@ -221,7 +237,7 @@ constexpr auto calcNewDim(StridedRange len, Range r) -> StridedRange { return StridedRange{ptrdiff_t(calcNewDim(len.len, r)), len.stride}; } template -constexpr auto calcNewDim(StridedDims<>, CartesianIndex) -> Empty { +constexpr auto calcNewDim(StridedDims<>, R, C) -> Empty { return {}; } constexpr auto calcNewDim(std::integral auto len, Colon) -> ptrdiff_t { @@ -231,31 +247,66 @@ constexpr auto calcNewDim(StaticInt auto len, Colon) { return len; }; constexpr auto calcNewDim(StridedRange len, Colon) { return len; }; template -constexpr auto calcNewDim(StridedDims<> d, CartesianIndex i) { - ptrdiff_t rowDims = ptrdiff_t(calcNewDim(ptrdiff_t(Row(d)), i.row)); +constexpr auto calcNewDim(StridedDims<> d, B b, C) { + ptrdiff_t rowDims = ptrdiff_t(calcNewDim(ptrdiff_t(Row(d)), b)); return StridedRange{rowDims, ptrdiff_t(RowStride(d))}; } template -constexpr auto calcNewDim(StridedDims<> d, CartesianIndex i) { - return calcNewDim(ptrdiff_t(Col(d)), i.col); +constexpr auto calcNewDim(StridedDims<> d, R, C c) { + return calcNewDim(ptrdiff_t(Col(d)), c); } template -constexpr auto calcNewDim(StridedDims<> d, CartesianIndex i) { - auto rowDims = calcNewDim(ptrdiff_t(Row(d)), i.row); - auto colDims = calcNewDim(ptrdiff_t(Col(d)), i.col); +constexpr auto calcNewDim(StridedDims<> d, B r, C c) { + auto rowDims = calcNewDim(ptrdiff_t(Row(d)), r); + auto colDims = calcNewDim(ptrdiff_t(Col(d)), c); return StridedDims(row(rowDims), col(colDims), RowStride(d)); } template -constexpr auto calcNewDim(DenseDims<> d, CartesianIndex i) { - auto rowDims = calcNewDim(ptrdiff_t(Row(d)), i.row); +constexpr auto calcNewDim(DenseDims<> d, B r, Colon) { + auto rowDims = calcNewDim(ptrdiff_t(Row(d)), r); return DenseDims(row(rowDims), Col(d)); } template -constexpr auto calcNewDim(SquareDims<> d, CartesianIndex i) { - auto rowDims = calcNewDim(ptrdiff_t(Row(d)), i.row); +constexpr auto calcNewDim(SquareDims<> d, B r, Colon) { + auto rowDims = calcNewDim(ptrdiff_t(Row(d)), r); return DenseDims(row(rowDims), Col(d)); } +template +constexpr auto calcNewDim(StridedDims<> d, simd::index::Unroll, + simd::index::Unroll c) { + return simd::index::UnrollDims{c.mask, RowStride(d)}; +} +template +constexpr auto calcNewDim(StridedDims<> d, simd::index::Unroll r, + simd::index::Unroll) { + return simd::index::UnrollDims{r.mask, RowStride(d)}; +} + +template +constexpr auto calcNewDim(StridedDims<> d, ptrdiff_t, + simd::index::Unroll c) { + return simd::index::UnrollDims<1, C, W, M>{c.mask, RowStride(d)}; +} +template +constexpr auto calcNewDim(StridedDims<> d, simd::index::Unroll r, + ptrdiff_t) { + if constexpr (W == 1) + return simd::index::UnrollDims{r.mask, RowStride(d)}; + else return simd::index::UnrollDims<1, R, W, M, true>{r.mask, RowStride(d)}; +} + +template +constexpr auto calcNewDim(ptrdiff_t, simd::index::Unroll i) { + return simd::index::UnrollDims<1, U, W, M, false, 1>{i.mask, RowStride<1>{}}; +} + +template +constexpr auto calcNewDim(StridedRange x, simd::index::Unroll i) { + if constexpr (W == 1) + return simd::index::UnrollDims{i.mask, stride(x)}; + else return simd::index::UnrollDims<1, U, W, M, true, -1>{i.mask, stride(x)}; +} } // namespace poly::math diff --git a/include/Math/Iterators.hpp b/include/Math/Iterators.hpp index c0ce5ac..606bbba 100644 --- a/include/Math/Iterators.hpp +++ b/include/Math/Iterators.hpp @@ -49,6 +49,7 @@ template struct Range { [[nodiscard]] constexpr auto operator[](value_type i) const -> value_type { return b + i; } + [[nodiscard]] constexpr auto operator[](auto i) const { return i + b; } }; constexpr auto standardizeRangeBound(auto x) { return x; } constexpr auto standardizeRangeBound(std::unsigned_integral auto x) { diff --git a/include/Math/LinearAlgebra.hpp b/include/Math/LinearAlgebra.hpp index dfa42d9..06ae35a 100644 --- a/include/Math/LinearAlgebra.hpp +++ b/include/Math/LinearAlgebra.hpp @@ -1,4 +1,5 @@ #pragma once +#include "Containers/Pair.hpp" #include "Math/Array.hpp" #include "Math/Constructors.hpp" #include "Math/Math.hpp" @@ -9,18 +10,17 @@ namespace LU { [[nodiscard]] constexpr auto ldivrat(SquarePtrMatrix F, PtrVector ipiv, MutPtrMatrix rhs) -> bool { - auto [M, N] = rhs.size(); + auto [M, N] = shape(rhs); invariant(ptrdiff_t(F.numRow()), ptrdiff_t(M)); // permute rhs - for (ptrdiff_t i = 0; i < M; ++i) { - unsigned ip = ipiv[i]; - if (i != ip) + for (ptrdiff_t i = 0; i < M; ++i) + if (unsigned ip = ipiv[i]; i != ip) for (ptrdiff_t j = 0; j < M; ++j) std::swap(rhs[ip, j], rhs[i, j]); - } + // LU x = rhs // L y = rhs // L is UnitLowerTriangular - for (ptrdiff_t n = 0; n < N; ++n) { - for (ptrdiff_t m = 0; m < M; ++m) { + for (ptrdiff_t m = 0; m < M; ++m) { + for (ptrdiff_t n = 0; n < N; ++n) { Rational Ymn = rhs[m, n]; for (ptrdiff_t k = 0; k < m; ++k) if (Ymn.fnmadd(F[m, k], rhs[k, n])) return true; @@ -28,8 +28,8 @@ namespace LU { } } // U x = y - for (ptrdiff_t n = 0; n < N; ++n) { - for (auto m = ptrdiff_t(M); m--;) { + for (ptrdiff_t m = M; m--;) { + for (ptrdiff_t n = 0; n < N; ++n) { Rational Ymn = rhs[m, n]; for (ptrdiff_t k = m + 1; k < M; ++k) if (Ymn.fnmadd(F[m, k], rhs[k, n])) return true; @@ -41,44 +41,34 @@ namespace LU { } template constexpr void ldiv(SquarePtrMatrix F, PtrVector ipiv, - MutPtrMatrix rhs) { - auto [M, N] = rhs.size(); - invariant(ptrdiff_t(F.numRow()), ptrdiff_t(M)); + MutPtrMatrix R) { + auto [M, N] = shape(R); + invariant(ptrdiff_t(F.numRow()), M); + invariant(M > 0); // permute rhs - for (ptrdiff_t i = 0; i < M; ++i) { - unsigned ip = ipiv[i]; - if (i != ip) - for (ptrdiff_t j = 0; j < M; ++j) std::swap(rhs[ip, j], rhs[i, j]); - } + for (ptrdiff_t i = 0; i < M; ++i) + if (unsigned ip = ipiv[i]; i != ip) + for (ptrdiff_t j = 0; j < M; ++j) std::swap(R[ip, j], R[i, j]); + // LU x = rhs // L y = rhs // L is UnitLowerTriangular - for (ptrdiff_t n = 0; n < N; ++n) { - for (ptrdiff_t m = 0; m < M; ++m) { - S Ymn = rhs[m, n]; - for (ptrdiff_t k = 0; k < m; ++k) Ymn -= F[m, k] * rhs[k, n]; - rhs[m, n] = Ymn; - } - } + for (ptrdiff_t m = 1; m < M; ++m) R[m, _] -= F[m, _(0, m)] * R[_(0, m), _]; // U x = y - for (ptrdiff_t n = 0; n < N; ++n) { - for (auto m = ptrdiff_t(M); m--;) { - S Ymn = rhs[m, n]; - for (ptrdiff_t k = m + 1; k < M; ++k) Ymn -= F[m, k] * rhs[k, n]; - rhs[m, n] = Ymn / F[m, m]; - } - } + R[last, _] /= F[last, last]; + for (ptrdiff_t m = M - 1; m--;) + R[m, _] << (R[m, _] - F[m, _(m + 1, end)] * R[_(m + 1, end), _]) / F[m, m]; } [[nodiscard]] constexpr auto rdivrat(SquarePtrMatrix F, PtrVector ipiv, MutPtrMatrix rhs) -> bool { - auto [M, N] = rhs.size(); + auto [M, N] = shape(rhs); invariant(ptrdiff_t(F.numCol()), ptrdiff_t(N)); // PA = LU // x LU = rhs // y U = rhs - for (ptrdiff_t n = 0; n < N; ++n) { - for (ptrdiff_t m = 0; m < M; ++m) { + for (ptrdiff_t m = 0; m < M; ++m) { + for (ptrdiff_t n = 0; n < N; ++n) { Rational Ymn = rhs[m, n]; for (ptrdiff_t k = 0; k < n; ++k) if (Ymn.fnmadd(rhs[m, k], F[k, n])) return true; @@ -87,9 +77,8 @@ constexpr void ldiv(SquarePtrMatrix F, PtrVector ipiv, } } // x L = y - for (auto n = ptrdiff_t(N); n--;) { - // for (ptrdiff_t n = 0; n < N; ++n) { - for (ptrdiff_t m = 0; m < M; ++m) { + for (ptrdiff_t m = 0; m < M; ++m) { + for (ptrdiff_t n = N; n--;) { Rational Xmn = rhs[m, n]; for (ptrdiff_t k = n + 1; k < N; ++k) if (Xmn.fnmadd(rhs[m, k], F[k, n])) return true; @@ -97,38 +86,27 @@ constexpr void ldiv(SquarePtrMatrix F, PtrVector ipiv, } } // permute rhs - for (auto j = ptrdiff_t(N); j--;) { - unsigned jp = ipiv[j]; - if (j != jp) + for (auto j = ptrdiff_t(N); j--;) + if (unsigned jp = ipiv[j]; j != jp) for (ptrdiff_t i = 0; i < M; ++i) std::swap(rhs[i, jp], rhs[i, j]); - } return false; } template constexpr void rdiv(SquarePtrMatrix F, PtrVector ipiv, MutPtrMatrix rhs) { - auto [M, N] = rhs.size(); - invariant(ptrdiff_t(F.numCol()), ptrdiff_t(N)); + auto [M, N] = shape(rhs); + invariant(ptrdiff_t(F.numCol()), N); + invariant(N > 0); // PA = LU // x LU = rhs // y U = rhs - for (ptrdiff_t n = 0; n < N; ++n) { - for (ptrdiff_t m = 0; m < M; ++m) { - S Ymn = rhs[m, n]; - for (ptrdiff_t k = 0; k < n; ++k) Ymn -= rhs[m, k] * F[k, n]; - rhs[m, n] = Ymn / F[n, n]; - } - } + rhs[_, 0] /= F[0, 0]; + for (ptrdiff_t n = 1; n < N; ++n) + rhs[_, n] << (rhs[_, n] - rhs[_, _(0, n)] * F[_(0, n), n]) / F[n, n]; // x L = y - for (auto n = ptrdiff_t(N); n--;) { - // for (ptrdiff_t n = 0; n < N; ++n) { - for (ptrdiff_t m = 0; m < M; ++m) { - S Xmn = rhs[m, n]; - for (ptrdiff_t k = n + 1; k < N; ++k) Xmn -= rhs[m, k] * F[k, n]; - rhs[m, n] = Xmn; - } - } + for (ptrdiff_t n = N - 1; n--;) + rhs[_, n] -= rhs[_, _(n + 1, end)] * F[_(n + 1, end), n]; // permute rhs for (auto j = ptrdiff_t(N); j--;) if (unsigned jp = ipiv[j]; j != jp) @@ -169,8 +147,8 @@ template class Fact { } [[nodiscard]] constexpr auto perm() const -> Vector { Col M = F.numCol(); - Vector perm; - for (ptrdiff_t m = 0; m < M; ++m) perm.push_back(m); + Vector perm{M}; + for (ptrdiff_t m = 0; m < M; ++m) perm[m] = m; for (ptrdiff_t m = 0; m < M; ++m) std::swap(perm[m], perm[ipiv[m]]); return perm; } @@ -187,16 +165,17 @@ template auto ipiv{vector(alloc::Mallocator{}, ptrdiff_t(M))}; // Vector ipiv{.s = unsigned(M)}; invariant(ptrdiff_t(ipiv.size()), ptrdiff_t(M)); - for (ptrdiff_t i = 0; i < M; ++i) ipiv[i] = i; - for (ptrdiff_t k = 0; k < M; ++k) { + for (ptrdiff_t k = 0;; ++k) { ptrdiff_t kp = k; - for (; kp < M; ++kp) { + for (;; ++kp) { + if (kp == M) return {}; if (A[kp, k] == 0) continue; ipiv[k] = kp; break; } if (kp != k) for (ptrdiff_t j = 0; j < M; ++j) std::swap(A[kp, j], A[k, j]); + if (k + 1 == M) break; Rational invAkk = A[k, k].inv(); for (ptrdiff_t i = k + 1; i < M; ++i) if (std::optional Aik = A[i, k].safeMul(invAkk)) A[i, k] = *Aik; @@ -216,23 +195,22 @@ template return Fact{std::move(A), std::move(ipiv)}; } template constexpr auto factImpl(MutSquarePtrMatrix A) { + using V = decltype(value(S{})); Row M = A.numRow(); auto ipiv{vector(alloc::Mallocator{}, ptrdiff_t(M))}; invariant(ptrdiff_t(ipiv.size()), ptrdiff_t(M)); - for (ptrdiff_t i = 0; i < M; ++i) ipiv[i] = i; - for (ptrdiff_t k = 0; k < M; ++k) { - ptrdiff_t kp = k; - for (; kp < M; ++kp) { - if (A[kp, k] == 0) continue; - ipiv[k] = kp; - break; - } - if (kp != k) - for (ptrdiff_t j = 0; j < M; ++j) std::swap(A[kp, j], A[k, j]); + for (ptrdiff_t k = 0;; ++k) { + containers::Pair mi{-1, {}}; + for (ptrdiff_t i = k; i < M; ++i) + if (V v = std::abs(value(A[i, k])); v > mi.second) mi = {i, v}; + invariant(mi.first >= 0); // TODO: return info? + ipiv[k] = mi.first; + if (mi.first != k) + for (ptrdiff_t j = 0; j < M; ++j) std::swap(A[mi.first, j], A[k, j]); + if (k + 1 == M) break; S invAkk = 1.0 / A[k, k]; - for (ptrdiff_t i = k + 1; i < M; ++i) A[i, k] = A[i, k] * invAkk; for (ptrdiff_t i = k + 1; i < M; ++i) - for (ptrdiff_t j = k + 1; j < M; ++j) A[i, j] -= A[i, k] * A[k, j]; + A[i, _(k + 1, end)] -= (A[i, k] *= invAkk) * A[k, _(k + 1, end)]; } return ipiv; } @@ -278,55 +256,49 @@ namespace LDL { /// NOT OWNING /// TODO: make the API consistent between LU and LDL template class Fact { - MutSquarePtrMatrix fact; + MutSquarePtrMatrix F; public: - constexpr Fact(MutSquarePtrMatrix A) : fact{A} {}; + constexpr Fact(MutSquarePtrMatrix A) : F{A} {}; - constexpr void ldiv(MutPtrMatrix rhs) { - ptrdiff_t M = ptrdiff_t(rhs.numRow()); - invariant(ptrdiff_t(fact.numRow()), M); + constexpr void ldiv(MutPtrMatrix R) { + ptrdiff_t M = ptrdiff_t(R.numRow()); + invariant(ptrdiff_t(F.numRow()), M); // LD^-1L' x = rhs // L y = rhs // L is UnitLowerTriangular - for (ptrdiff_t m = 0; m < M; ++m) - rhs[m, _] -= rhs[_(0, m), _].transpose() * fact[m, _(0, m)]; - + for (ptrdiff_t m = 1; m < M; ++m) R[m, _] -= F[m, _(0, m)] * R[_(0, m), _]; // D^-1 L' x = y // L' x = D y - for (ptrdiff_t m = M; m--;) { - rhs[m, _] *= fact[m, m]; - rhs[m, _] -= rhs[_(m + 1, M), _].transpose() * fact[_(m + 1, M), m]; - } + R[last, _] *= F[last, last]; + for (ptrdiff_t m = M - 1; m--;) + R[m, _] << R[m, _] * F[m, m] - F[_(m + 1, M), m].t() * R[_(m + 1, M), _]; } - constexpr void ldiv(MutPtrVector rhs) { - ptrdiff_t M = rhs.size(); - invariant(ptrdiff_t(fact.numRow()), M); + constexpr void ldiv(MutPtrVector R) { + ptrdiff_t M = R.size(); + invariant(ptrdiff_t(F.numRow()), M); // LD^-1L' x = rhs // L y = rhs // L is UnitLowerTriangular - for (ptrdiff_t m = 0; m < M; ++m) - rhs[m] -= fact[m, _(0, m)].transpose() * rhs[_(0, m)]; + for (ptrdiff_t m = 1; m < M; ++m) R[m] -= R[_(0, m)] * F[m, _(0, m)].t(); // D^-1 L' x = y // L' x = D y - for (ptrdiff_t m = M; m--;) { - rhs[m] *= fact[m, m]; - rhs[m] -= fact[_(m + 1, M), m].transpose() * rhs[_(m + 1, M)]; - } + R[last] *= F[last, last]; + for (ptrdiff_t m = M - 1; m--;) + R[m] = R[m] * F[m, m] - R[_(m + 1, M)] * F[_(m + 1, M), m]; } constexpr void ldiv(MutPtrVector dst, TrivialVec auto src) { ptrdiff_t M = dst.size(); - invariant(M == src.size()); - invariant(ptrdiff_t(fact.numRow()), M); + invariant(M, ptrdiff_t(src.size())); + invariant(ptrdiff_t(F.numRow()), M); // LD^-1L' x = rhs // L y = rhs // L is UnitLowerTriangular - for (ptrdiff_t m = 0; m < M; ++m) - dst[m] = src[m] - fact[m, _(0, m)].transpose() * dst[_(0, m)]; - + dst[0] = src[0]; + for (ptrdiff_t m = 1; m < M; ++m) + dst[m] = src[m] - dst[_(0, m)] * F[m, _(0, m)].t(); // D^-1 L' x = y // L' x = D y - for (ptrdiff_t m = M; m--;) { - dst[m] *= fact[m, m]; - dst[m] -= fact[_(m + 1, M), m].transpose() * dst[_(m + 1, M)]; - } + dst[last] *= F[last, last]; + for (ptrdiff_t m = M - 1; m--;) + dst[m] = dst[m] * F[m, m] - dst[_(m + 1, M)] * F[_(m + 1, M), m]; } }; @@ -334,15 +306,14 @@ template constexpr auto factorize(MutSquarePtrMatrix A) -> Fact { Row M = A.numRow(); invariant(ptrdiff_t(M), ptrdiff_t(A.numCol())); - for (ptrdiff_t k = 0; k < M; ++k) { + for (ptrdiff_t k = 0;; ++k) { T Akk = A[k, k]; if constexpr (ForcePD) Akk = std::max(Akk, T(0.001)); T invAkk = A[k, k] = 1.0 / Akk; + if (k + 1 == M) break; A[_(k + 1, M), k] *= invAkk; - for (ptrdiff_t i = k + 1; i < M; ++i) { - T Aik = A[i, k] * Akk; - for (ptrdiff_t j = k + 1; j <= i; ++j) A[i, j] -= Aik * A[j, k]; - } + for (ptrdiff_t i = k + 1; i < M; ++i) + A[i, _(k + 1, i + 1)] -= (A[i, k] * Akk) * A[_(k + 1, i + 1), k]; } return Fact{A}; } diff --git a/include/Math/Math.hpp b/include/Math/Math.hpp index 1a66e22..55a0425 100644 --- a/include/Math/Math.hpp +++ b/include/Math/Math.hpp @@ -7,6 +7,7 @@ #include "Math/Indexing.hpp" #include "Math/Matrix.hpp" #include "Math/MatrixDimensions.hpp" +#include "Utilities/LoopMacros.hpp" #include "Utilities/Parameters.hpp" #include "Utilities/TypePromotion.hpp" #include @@ -18,11 +19,10 @@ #include namespace poly::math { +/// Extract the value of a `Dual` number +constexpr auto value(std::floating_point auto x) { return x; } struct Rational; -template -concept VecOrMat = AbstractVector || AbstractMatrix; - template concept RangeOffsetPair = (std::convertible_to> && @@ -32,14 +32,15 @@ concept RangeOffsetPair = template concept Compatible = - (VecOrMat && std::convertible_to>) || - (VecOrMat && std::convertible_to>) || + (AbstractTensor && std::convertible_to>) || + (AbstractTensor && std::convertible_to>) || (AbstractVector && AbstractVector) || (AbstractMatrix && AbstractMatrix); template struct ElTypes { using eltype = - std::conditional_t & std::convertible_to>, + std::conditional_t & + std::convertible_to>, A, utils::eltype_t>; }; // returns the element type of `A` when used in a binary op with `B` @@ -51,14 +52,11 @@ concept Trivial = template concept TrivialCompatible = Trivial && Compatible; template -concept TrivialVecOrMat = Trivial && VecOrMat; +concept TrivialTensor = Trivial && AbstractTensor; template concept TrivialVec = Trivial && AbstractVector; template concept TrivialMat = Trivial && AbstractMatrix; -template -concept TrivialDataMatrix = Trivial && DataMatrix; - // // TODO: binary func invocable trait? // template // concept BinaryFunction = std::is_invocable_v; @@ -67,6 +65,7 @@ template concept BinaryFuncOfElts = std::is_invocable_v, indextype_t>; +// TODO: make this part of ArrayOps!!! [[gnu::flatten]] constexpr auto operator==(const AbstractMatrix auto &A, const AbstractMatrix auto &B) -> bool { @@ -82,48 +81,43 @@ concept BinaryFuncOfElts = template struct Elementwise { using value_type = decltype(std::declval()(std::declval>())); + static constexpr bool has_reduction_loop = HasInnerReduction; [[no_unique_address]] Op op; [[no_unique_address]] A a; - constexpr auto operator[](ptrdiff_t i) const { return op(a[i]); } - constexpr auto operator[](ptrdiff_t i, ptrdiff_t j) const - requires(AbstractMatrix) + constexpr auto operator[](auto i) const + requires(LinearlyIndexableOrConvertible) + { + return op(a[i]); + } + constexpr auto operator[](auto i, auto j) const + requires(CartesianIndexableOrConvertible) { return op(a[i, j]); } - [[nodiscard]] constexpr auto size() const { return a.size(); } - [[nodiscard]] constexpr auto dim() const { return a.dim(); } - [[nodiscard]] constexpr auto numRow() const -> Row<> - requires(AbstractMatrix) + [[nodiscard]] constexpr auto size() const + requires(DefinesSize) + { + return a.size(); + } + [[nodiscard]] constexpr auto numRow() const + requires(DefinesShape) { return a.numRow(); } - [[nodiscard]] constexpr auto numCol() const -> Col<> - requires(AbstractMatrix) + [[nodiscard]] constexpr auto numCol() const + requires(DefinesShape) { return a.numCol(); } [[nodiscard]] constexpr auto view() const { return *this; }; + template constexpr auto reinterpret() { + auto ra = math::reinterpret(a); + return Elementwise(op, ra); + } }; template Elementwise(Op, A) -> Elementwise; -// scalars broadcast -template constexpr auto get(const S &s, ptrdiff_t) -> S { - return s; -} -template -constexpr auto get(const S &s, ptrdiff_t, ptrdiff_t) -> S { - return s; -} -template V> -constexpr auto get(const V &v, ptrdiff_t i) -> S { - return v[i]; -} -template V> -constexpr auto get(const V &v, ptrdiff_t i, ptrdiff_t j) -> S { - return v[i, j]; -} - constexpr auto size(const std::integral auto) -> ptrdiff_t { return 1; } constexpr auto size(const std::floating_point auto) -> ptrdiff_t { return 1; } constexpr auto size(const AbstractVector auto &x) -> ptrdiff_t { @@ -156,118 +150,141 @@ struct ElementwiseBinaryOp { using elta = indextype_t; using eltb = indextype_t; - using value_type = - decltype(std::declval()(std::declval(), std::declval())); - // using value_type = utils::promote_eltype_t; + static constexpr bool has_reduction_loop = + HasInnerReduction || HasInnerReduction; + using common = std::common_type_t; + using value_type = decltype(std::declval()(std::declval(), + std::declval())); using concrete = is_concrete_t; static constexpr bool isvector = AbstractVector || AbstractVector; static constexpr bool ismatrix = AbstractMatrix || AbstractMatrix; + static_assert(isvector != ismatrix); [[no_unique_address]] Op op; [[no_unique_address]] A a; [[no_unique_address]] B b; - constexpr auto operator[](ptrdiff_t i) const -> value_type - requires LinearlyIndexableOrConvertible && - LinearlyIndexableOrConvertible + constexpr auto operator[](auto i) const + requires LinearlyIndexableOrConvertible && + LinearlyIndexableOrConvertible { - return op(get(a, i), get(b, i)); + if constexpr (LinearlyIndexable) + if constexpr (LinearlyIndexable) return op(a[i], b[i]); + else return op(a[i], b); + else if constexpr (LinearlyIndexable) return op(a, b[i]); + else return op(a, b); } - constexpr auto operator[](ptrdiff_t i, ptrdiff_t j) const -> value_type - requires CartesianIndexableOrConvertible && - CartesianIndexableOrConvertible - { - return op(get(a, i, j), get(b, i, j)); + constexpr auto operator[](auto i, auto j) const { + if constexpr (CartesianIndexable) + if constexpr (CartesianIndexable) return op(a[i, j], b[i, j]); + else if constexpr (std::convertible_to) return op(a[i, j], b); + else if constexpr (RowVector) return op(a[i, j], b[j]); + else return op(a[i, j], b[i]); + else if constexpr (std::convertible_to) + if constexpr (CartesianIndexable) return op(a, b[i, j]); + else if constexpr (std::convertible_to) return op(a, b); + else if constexpr (RowVector) return op(a, b[j]); + else return op(a, b[i]); + else if constexpr (RowVector) + if constexpr (CartesianIndexable) return op(a[j], b[i, j]); + else if constexpr (std::convertible_to) return op(a[j], b); + else if constexpr (RowVector) return op(a[j], b[j]); + else return op(a[j], b[i]); + else if constexpr (CartesianIndexable) return op(a[i], b[i, j]); + else if constexpr (std::convertible_to) return op(a[i], b); + else if constexpr (RowVector) return op(a[i], b[j]); + else return op(a[i], b[i]); } - [[nodiscard]] constexpr auto numRow() const -> Row<> + [[nodiscard]] constexpr auto numRow() const requires(ismatrix) { if constexpr (AbstractMatrix && AbstractMatrix) { if constexpr (HasConcreteSize) - if constexpr (HasConcreteSize) { - const Row N = a.numRow(); - invariant(N, b.numRow()); - return N; - } else return a.numRow(); + if constexpr (HasConcreteSize) + return row(check_sizes(unwrapRow(a.numRow()), unwrapRow(b.numRow()))); + else return a.numRow(); else if constexpr (HasConcreteSize) return b.numRow(); else return Row<>{0}; } else if constexpr (AbstractMatrix) return a.numRow(); - else if constexpr (AbstractMatrix) return b.numRow(); + else return b.numRow(); } - [[nodiscard]] constexpr auto numCol() const -> Col<> + [[nodiscard]] constexpr auto numCol() const requires(ismatrix) { if constexpr (AbstractMatrix && AbstractMatrix) { if constexpr (HasConcreteSize) - if constexpr (HasConcreteSize) { - const Col N = a.numCol(); - invariant(N, b.numCol()); - return N; - } else return a.numCol(); + if constexpr (HasConcreteSize) + return col(check_sizes(unwrapCol(a.numCol()), unwrapCol(b.numCol()))); + else return a.numCol(); else if constexpr (HasConcreteSize) return b.numCol(); else return Col<>{0}; } else if constexpr (AbstractMatrix) return a.numCol(); - else if constexpr (AbstractMatrix) return b.numCol(); - } - [[nodiscard]] constexpr auto dim() const { - if constexpr (isvector) return size(); - else return DenseDims{numRow(), numCol()}; + else return b.numCol(); } - [[nodiscard]] constexpr auto size() const { - if constexpr (AbstractVector && AbstractVector) { - const ptrdiff_t N = a.size(); - invariant(N == b.size()); - return N; - } else if constexpr (AbstractVector) return ptrdiff_t(a.size()); - else if constexpr (AbstractVector) return ptrdiff_t(b.size()); - else - return CartesianIndex{ptrdiff_t(numRow()), - ptrdiff_t(numCol())}; + if constexpr (ismatrix) return unwrapRow(numRow()) * unwrapCol(numCol()); + else if constexpr (AbstractVector && AbstractVector) + return check_sizes(a.size(), b.size()); + else if constexpr (AbstractVector) return a.size(); + else return b.size(); } [[nodiscard]] constexpr auto view() const -> auto & { return *this; }; + template constexpr auto reinterpret() { + auto ra = math::reinterpret(a); + auto rb = math::reinterpret(b); + return ElementwiseBinaryOp(op, ra, rb); + } }; -template struct AbstractSelect { +template struct AbstractSelect { using value_type = std::common_type_t, utils::eltype_t>; static constexpr bool isvector = AbstractVector; - static constexpr bool ismatrix = AbstractMatrix; [[no_unique_address]] C c; [[no_unique_address]] A a; [[no_unique_address]] B b; - [[nodiscard]] constexpr auto numRow() const -> Row<> - requires(ismatrix) - { - Row m = c.numRow(); - if constexpr (AbstractMatrix) invariant(m, a.numRow()); - if constexpr (AbstractMatrix) invariant(m, b.numRow()); - return m; - } - [[nodiscard]] constexpr auto numCol() const -> Col<> - requires(ismatrix) + [[nodiscard]] constexpr auto numRow() const + requires(!isvector) { - Col n = c.numCol(); - if constexpr (AbstractMatrix) invariant(n, a.numCol()); - if constexpr (AbstractMatrix) invariant(n, b.numCol()); - return n; + auto n = unwrapRow(c.numRow()); + if constexpr (AbstractMatrix) { + auto nn = check_sizes(n, unwrapRow(a.numRow())); + if constexpr (AbstractMatrix) + return row(check_sizes(nn, unwrapRow(b.numRow()))); + else return row(nn); + } else if (AbstractMatrix) + return row(check_sizes(n, unwrapRow(b.numRow()))); + else return row(n); } - [[nodiscard]] constexpr auto dim() const -> DenseDims<> - requires(ismatrix) + [[nodiscard]] constexpr auto numCol() const + requires(!isvector) { - return {numRow(), numCol()}; + auto n = unwrapCol(c.numCol()); + if constexpr (AbstractMatrix) { + auto nn = check_sizes(n, unwrapCol(a.numCol())); + if constexpr (AbstractMatrix) + return col(check_sizes(nn, unwrapCol(b.numCol()))); + else return col(nn); + } else if (AbstractMatrix) + return col(check_sizes(n, unwrapCol(b.numCol()))); + else return col(n); } [[nodiscard]] constexpr auto size() const { - if constexpr (ismatrix) - return CartesianIndex, Col<>>{numRow(), numCol()}; - else { - ptrdiff_t N = c.size(); - if constexpr (AbstractVector) invariant(ptrdiff_t(a.size()), N); - if constexpr (AbstractVector) invariant(ptrdiff_t(b.size()), N); - return N; + if constexpr (!isvector) { + return unwrapRow(numRow()) * unwrapCol(numCol()); + } else { + auto N = c.size(); + if constexpr (AbstractVector) { + auto M = check_sizes(N, a.size()); + if constexpr (AbstractVector) return check_sizes(M, b.size()); + else return M; + } else if constexpr (AbstractVector) { + return check_sizes(N, b.size()); + } else { + return N; + } } } - [[nodiscard]] constexpr auto view() const -> auto & { return *this; }; }; inline constexpr auto view(const Trivial auto &x) { return x; } @@ -275,40 +292,52 @@ inline constexpr auto view(const auto &x) { return x.view(); } template constexpr auto view(const Array &x) { return x; } -constexpr auto transpose(const auto &a) { return Transpose{view(a)}; } -template constexpr auto transpose(const Transpose &a) -> T { - return a.transpose(); -} -template +template struct Select : public AbstractSelect { using value_type = AbstractSelect::value_type; - constexpr auto operator[](ptrdiff_t i) const -> value_type - requires LinearlyIndexableOrConvertible && + static constexpr bool has_reduction_loop = + HasInnerReduction || HasInnerReduction; + constexpr auto operator[](auto i) const + requires LinearlyIndexable && LinearlyIndexableOrConvertible && LinearlyIndexableOrConvertible { - return get(this->c, i) ? get(this->a, i) - : get(this->b, i); + if constexpr (LinearlyIndexable) + if constexpr (LinearlyIndexable) + return this->c[i] ? this->a[i] : this->b[i]; + else return this->c[i] ? this->a[i] : this->b; + else if constexpr (LinearlyIndexable) + return this->c[i] ? this->a : this->b[i]; + else return this->c[i] ? this->a : this->b; } - constexpr auto operator[](ptrdiff_t i, ptrdiff_t j) const -> value_type + constexpr auto operator[](auto i, auto j) const requires CartesianIndexableOrConvertible && CartesianIndexableOrConvertible && CartesianIndexableOrConvertible { - return get(this->c, i, j) ? get(this->a, i, j) - : get(this->b, i, j); + if constexpr (CartesianIndexable) + if constexpr (CartesianIndexable) + return this->c[i, j] ? this->a[i, j] : this->b[i, j]; + else return this->c[i, j] ? this->a[i, j] : this->b; + else if constexpr (CartesianIndexable) + return this->c[i, j] ? this->a : this->b[i, j]; + else return this->c[i, j] ? this->a : this->b; } + [[nodiscard]] constexpr auto view() const -> Select { return *this; }; }; -template +template Select(C c, A a, B b) -> Select; -constexpr auto select(const VecOrMat auto &c, const auto &a, const auto &b) { +constexpr auto select(const AbstractTensor auto &c, const auto &a, + const auto &b) { return Select(view(c), view(a), view(b)); } -template Op> +template Op> struct Conditional : public AbstractSelect { using value_type = AbstractSelect::value_type; + static constexpr bool has_reduction_loop = + HasInnerReduction || HasInnerReduction; [[no_unique_address]] Op op; constexpr auto operator[](ptrdiff_t i) const -> value_type @@ -316,19 +345,89 @@ struct Conditional : public AbstractSelect { LinearlyIndexableOrConvertible && LinearlyIndexableOrConvertible { - auto x = get(this->a, i); - return get(this->c, i) ? op(x, get(this->b, i)) : x; + if constexpr (LinearlyIndexable) + if constexpr (LinearlyIndexable) + return this->c[i] ? op(this->a[i], this->b[i]) : this->a[i]; + else return this->c[i] ? op(this->a[i], this->b) : this->a[i]; + else if constexpr (LinearlyIndexable) + return this->c[i] ? op(this->a, this->b[i]) : this->a; + else return this->c[i] ? op(this->a, this->b) : this->a; + } + template + constexpr auto operator[](simd::index::Unroll i) const + requires LinearlyIndexableOrConvertible && + LinearlyIndexableOrConvertible && + LinearlyIndexableOrConvertible + { + if constexpr (W == 1) { + auto c = this->c[i]; + simd::Unroll x = get(this->a, i), + y = op(x, get(this->b, i)); + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + x.data[u] = c.data[u] ? y.data[u] : x.data[u]; + return x; + } else if constexpr (LinearlyIndexable) { + auto c = get(this->c, i); + simd::Unroll<1, U, W, value_type> x = get(this->a, i), + y = op(x, get(this->b, i)); + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + x.data[u] = c.data[u] ? y.data[u] : x.data[u]; + return x; + } else if constexpr (LinearlyIndexable) { + auto c = this->c[i]; + using V = simd::Vec; + value_type x_ = get(this->a, i); + V x = simd::vbroadcast(x_); + simd::Unroll<1, U, W, value_type> y = op(x, get(this->b, i)); + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + if constexpr (LinearlyIndexable) + y.data[u] = c.data[u] ? y.data[u] : x; + return y; + } else { + auto c = this->c[i]; + using V = simd::Vec; + value_type x_ = get(this->a, i); + value_type y_ = op(x_, get(this->b, i)); + V x = simd::vbroadcast(x_), + y = simd::vbroadcast(y_); + simd::Unroll<1, U, W, value_type> z; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) z.data[u] = c.data[u] ? y : x; + return z; + } + // auto c = get(this->c, i); + // auto x = get(this->a, i); + // auto y = op(x, get(this->b, i)); + // simd::Unroll<1, U, W, value_type> z; + // POLYMATHFULLUNROLL + // for (ptrdiff_t u = 0; u < U; ++u) + // if constexpr (LinearlyIndexable) + // z.data[u] = !c.data[u] ? x.data[u] : y.data[u]; + // else if constexpr (LinearlyIndexable) + // z.data[u] = !c.data[u] ? x : y.data[u]; + // else z.data[u] = c.data[u] ? y : x; + // return z; + // } } - constexpr auto operator[](ptrdiff_t i, ptrdiff_t j) const -> value_type + constexpr auto operator[](auto i, auto j) const requires CartesianIndexableOrConvertible && CartesianIndexableOrConvertible && CartesianIndexableOrConvertible { - auto x = get(this->a, i, j); - return get(this->c, i, j) ? op(x, get(this->b, i, j)) : x; + if constexpr (LinearlyIndexable) + if constexpr (LinearlyIndexable) + return this->c[i, j] ? op(this->a[i, j], this->b[i, j]) : this->a[i, j]; + else return this->c[i, j] ? op(this->a[i, j], this->b) : this->a[i, j]; + else if constexpr (LinearlyIndexable) + return this->c[i, j] ? op(this->a, this->b[i, j]) : this->a; + else return this->c[i, j] ? op(this->a, this->b) : this->a; } + [[nodiscard]] constexpr auto view() const -> Conditional { return *this; }; }; -constexpr auto conditional(auto op, const VecOrMat auto &c, const auto &a, +constexpr auto conditional(auto op, const AbstractTensor auto &c, const auto &a, const auto &b) { auto vc = view(c); auto va = view(a); @@ -337,47 +436,94 @@ constexpr auto conditional(auto op, const VecOrMat auto &c, const auto &a, {vc, va, vb}, op}; } -template struct MatMatMul { +template struct MatMatMul { using value_type = utils::promote_eltype_t; using concrete = is_concrete_t; + static constexpr bool has_reduction_loop = true; + static constexpr bool ismata = AbstractMatrix; + static constexpr bool ismatb = AbstractMatrix; + static_assert((ismata && (ismatb || ColVector)) || + (RowVector && ismatb) || (ColVector && RowVector)); + static constexpr bool ismatrix = ismata && ismatb; + // we could have + // ColVector * RowVector + // RowVector * Matrix + // Matrix * ColVector + // Matrix * Matrix [[no_unique_address]] A a; [[no_unique_address]] B b; - constexpr auto operator[](ptrdiff_t i, ptrdiff_t j) const -> value_type { + [[gnu::always_inline]] constexpr auto operator[](auto i, auto j) const + requires(ismatrix) + { static_assert(AbstractMatrix, "B should be an AbstractMatrix"); - value_type s{}; + invariant(ptrdiff_t(a.numCol()) > 0); + decltype(a[i, 0] * b[0, j] + a[i, 1] * b[1, j]) s{}; + POLYMATHNOVECTORIZE for (ptrdiff_t k = 0; k < ptrdiff_t(a.numCol()); ++k) s += a[i, k] * b[k, j]; return s; } - [[nodiscard]] constexpr auto numRow() const -> Row<> { return a.numRow(); } - [[nodiscard]] constexpr auto numCol() const -> Col<> { return b.numCol(); } - [[nodiscard]] constexpr auto size() const - -> CartesianIndex { - invariant(ptrdiff_t(a.numCol()) == ptrdiff_t(b.numRow())); - return {ptrdiff_t(numRow()), ptrdiff_t(numCol())}; + // If `T isa Dual,2>`, we would not want to construct + // intermediates that require masked loads/stores, as compilers have + // trouble optimizing these away. + // We can imagine two strategies for avoiding this: + // 1. Do not write/construct any intermediates, but write into the result + // directly. + // 2. Decompress/compress on load/store, so temporaries do not need masks. + // `1.` seems ideal, but harder to implement. + // For example, here, `s` would have to alias the result. Then we also have + // `s +=`, which would have to invoke somehow call + // `Dual,2>::operator+=` without storing. + // Or, we'd need a method that can see through it, so we operate on the + // teminal values, but still in one go to only have one instance of the + // reduction loop. Thus, `1.` seems conceptually simple but without a clear + // implementation strategy. + // + // + [[gnu::always_inline]] constexpr auto operator[](auto i) const + requires(!ismatrix) + { + if constexpr (RowVector) { + invariant(a.size() == b.numRow()); + invariant(a.size() > 0); + decltype(a[0] * b[0, i] + a[1] * b[1, i]) s{}; + POLYMATHNOVECTORIZE + for (ptrdiff_t k = 0; k < a.numCol(); ++k) { + POLYMATHFAST + s += a[k] * b[k, i]; + } + return s; + } else { // ColVector + invariant(a.numCol() == b.size()); + invariant(b.size() > 0); + decltype(a[i, 0] * b[0] + a[i, 1] * b[1]) s{}; + for (ptrdiff_t k = 0; k < a.numCol(); ++k) { + POLYMATHFAST + s += a[i, k] * b[k]; + } + return s; + } } - [[nodiscard]] constexpr auto dim() const -> DenseDims<> { - invariant(ptrdiff_t(a.numCol()) == ptrdiff_t(b.numRow())); - return {numRow(), numCol()}; + [[nodiscard]] constexpr auto numRow() const + requires(ismatrix) + { + return a.numRow(); } - [[nodiscard]] constexpr auto view() const { return *this; }; - [[nodiscard]] constexpr auto transpose() const { return Transpose{*this}; }; -}; -template struct MatVecMul { - using value_type = utils::promote_eltype_t; - using concrete = is_concrete_t; - [[no_unique_address]] A a; - [[no_unique_address]] B b; - constexpr auto operator[](ptrdiff_t i) const -> value_type { - invariant(a.numCol() == b.size()); - value_type s = 0; - for (ptrdiff_t k = 0; k < a.numCol(); ++k) s += a[i, k] * b[k]; - return s; + [[nodiscard]] constexpr auto numCol() const + requires(ismatrix) + { + return b.numCol(); } - [[nodiscard]] constexpr auto size() const -> ptrdiff_t { - return ptrdiff_t(a.numRow()); + [[nodiscard]] constexpr auto size() const { + if constexpr (ismata) + if constexpr (ismatb) + return unwrapRow(a.numRow()) * unwrapCol(b.numCol()); + else return unwrapRow(a.numRow()); + else if constexpr (RowVector) return unwrapCol(b.numCol()); + else a.size() * b.size(); } - constexpr auto view() const { return *this; }; + [[nodiscard]] constexpr auto view() const { return *this; }; + [[nodiscard]] constexpr auto t() const { return Transpose{*this}; }; }; // @@ -552,36 +698,92 @@ static_assert(AbstractMatrix, PtrMatrix>>); static_assert(AbstractMatrix>>); static_assert(AbstractMatrix>>); -constexpr auto operator*(const VecOrMat auto &a, const VecOrMat auto &b) { - auto AA{a.view()}; - auto BB{b.view()}; - if constexpr (AbstractVector) { - if constexpr (AbstractVector) { - ElementwiseBinaryOp(std::multiplies<>{}, AA, BB); - } else { - invariant(ptrdiff_t(AA.numCol()) == BB.size()); - return MatVecMul{.a = AA, .b = BB}; +constexpr auto abs2(auto x) { return x * x; } +template constexpr auto norm2(const B &A) { + utils::eltype_t s = 0; + if constexpr (!LinearlyIndexable>) { + for (ptrdiff_t i = 0; i < A.numRow(); ++i) { + for (ptrdiff_t j = 0; j < A.numCol(); ++j) { + POLYMATHFAST + s += abs2(A[i, j]); + } + } + } else + for (ptrdiff_t j = 0, L = ptrdiff_t(A.size()); j < L; ++j) { + POLYMATHFAST + s += abs2(A[j]); } - } else { - invariant(ptrdiff_t(AA.numCol()) == ptrdiff_t(BB.numRow())); - return MatMatMul{.a = AA, .b = BB}; + return s; +} + +constexpr auto norm2(const auto &a) { + decltype(a[0] * a[0] + a[1] * a[1]) s{}; + for (auto x : a) { + POLYMATHFAST + s += abs2(x, x); + } + return s; +} +constexpr auto dot(const auto &a, const auto &b) { + ptrdiff_t L = a.size(); + invariant(L, b.size()); + decltype(a[0] * b[0] + a[1] * b[1]) s{}; + for (ptrdiff_t i = 0; i < L; ++i) { + POLYMATHFAST + s += a[i] * b[i]; } + return s; +} + +// we can have RowVector*RowVector or ColVector*ColVector(elementwise) +// RowVector*ColVector (dot product) +// Matrix*ColVector +// RowVector*Matrix +// Matrix*Matrix +// We can't have vector*matrix +constexpr auto operator*(const AbstractTensor auto &a, + const AbstractTensor auto &b) { + auto AA{a.view()}; + auto BB{b.view()}; + invariant(ptrdiff_t(numCols(AA)), ptrdiff_t(numRows(BB))); + if constexpr (RowVector && ColVector) + return dot(AA, BB.t()); + else if constexpr (AbstractVector && + AbstractVector) + return ElementwiseBinaryOp(std::multiplies<>{}, AA, BB); + else return MatMatMul{.a = AA, .b = BB}; } template S> constexpr auto operator*(const M &b, S a) { - return ElementwiseBinaryOp(std::multiplies<>{}, view(b), view(a)); + using T = utils::eltype_t; + if constexpr (sizeof(T) <= 8) + return ElementwiseBinaryOp(std::multiplies<>{}, view(b), + utils::eltype_t(a)); + else return ElementwiseBinaryOp(std::multiplies<>{}, view(b), a); } template S> constexpr auto operator*(S a, const M &b) { - return ElementwiseBinaryOp(std::multiplies<>{}, view(a), view(b)); + using T = utils::eltype_t; + if constexpr (sizeof(T) <= 8) + return ElementwiseBinaryOp(std::multiplies<>{}, utils::eltype_t(a), + view(b)); + else return ElementwiseBinaryOp(std::multiplies<>{}, a, view(b)); } template S> constexpr auto operator*(S a, const M &b) { - return ElementwiseBinaryOp(std::multiplies<>{}, view(a), view(b)); + using T = utils::eltype_t; + if constexpr (sizeof(T) <= 8) + return ElementwiseBinaryOp(std::multiplies<>{}, utils::eltype_t(a), + view(b)); + else return ElementwiseBinaryOp(std::multiplies<>{}, a, view(b)); } template S> constexpr auto operator*(const M &b, S a) { - return ElementwiseBinaryOp(std::multiplies<>{}, view(b), view(a)); + using T = utils::eltype_t; + if constexpr (sizeof(T) <= 8) + return ElementwiseBinaryOp(std::multiplies<>{}, view(b), + utils::eltype_t(a)); + else return ElementwiseBinaryOp(std::multiplies<>{}, view(b), a); } template B> @@ -653,16 +855,6 @@ static_assert(AbstractMatrix, PtrMatrix>>, "MatMul is not an AbstractMatrix!"); static_assert(AbstractMatrix>>); -template -constexpr auto operator*(const Transpose &at, const AbstractVector auto &b) { - utils::promote_eltype_t s{}; - auto a = at.transpose(); - ptrdiff_t l = a.size(); - invariant(l == b.size()); - for (ptrdiff_t i = 0; i < l; ++i) s += a[i] * b[i]; - return s; -} - static_assert( AbstractVector>())>); static_assert( @@ -706,20 +898,11 @@ template struct SliceView { auto operator[](ptrdiff_t j) const -> const T & { return a[i[j]]; } [[nodiscard]] constexpr auto size() const -> ptrdiff_t { return i.size(); } constexpr auto view() -> SliceView { return *this; } + [[nodiscard]] constexpr auto numRow() const -> Row<1> { return {}; } + [[nodiscard]] constexpr auto numCol() const { return col(size()); } }; static_assert(AbstractVector>); -constexpr auto abs2(auto x) { return x * x; } - -template constexpr auto norm2(const B &A) { - utils::eltype_t s = 0; - if constexpr (!LinearlyIndexable>) { - for (ptrdiff_t i = 0; i < A.numRow(); ++i) - for (ptrdiff_t j = 0; j < A.numCol(); ++j) s += abs2(A[i, j]); - } else - for (ptrdiff_t j = 0, L = ptrdiff_t(A.dim()); j < L; ++j) s += abs2(A[j]); - return s; -} // template struct Zip { // std::array a; diff --git a/include/Math/Matrix.hpp b/include/Math/Matrix.hpp index 8ba87c2..1ddd5dd 100644 --- a/include/Math/Matrix.hpp +++ b/include/Math/Matrix.hpp @@ -1,49 +1,96 @@ #pragma once #include "Math/AxisTypes.hpp" #include "Math/MatrixDimensions.hpp" -#include "Math/Vector.hpp" #include "Utilities/TypePromotion.hpp" #include #include namespace poly::math { +template > +concept LinearlyIndexable = requires(T t, ptrdiff_t i) { + { t[i] } -> std::convertible_to; +}; template > concept CartesianIndexable = requires(T t, ptrdiff_t i) { { t[i, i] } -> std::convertible_to; }; +// The `OrConvertible` concepts are for expression templates +template +concept LinearlyIndexableOrConvertible = + LinearlyIndexable || std::convertible_to; template concept CartesianIndexableOrConvertible = CartesianIndexable || std::convertible_to; template -concept AbstractMatrixCore = - utils::HasEltype && CartesianIndexable && requires(T t) { - { t.numRow() } -> std::convertible_to>; - { t.numCol() } -> std::convertible_to>; - { t.size() } -> std::same_as>; - { t.dim() } -> std::convertible_to>; - // { - // std::remove_reference_t::canResize - // } -> std::same_as; - // {t.extendOrAssertSize(i, i)}; - }; +concept DefinesSize = requires(T t) { + { t.size() } -> std::convertible_to; +}; + template -concept AbstractMatrix = AbstractMatrixCore && requires(T t, ptrdiff_t i) { - { t.view() } -> AbstractMatrixCore; +concept DefinesShape = requires(T t) { + { t.numRow() } -> std::convertible_to>; + { t.numCol() } -> std::convertible_to>; }; + template -concept HasDataPtr = requires(T t) { - { t.data() } -> std::same_as *>; +concept ShapelessSize = DefinesSize && (!DefinesShape); +template +concept PrimitiveScalar = std::integral || std::floating_point; + +constexpr auto numRows(const DefinesShape auto &A) { return A.numRow(); } +constexpr auto numCols(const DefinesShape auto &A) { return A.numCol(); } + +constexpr auto numRows(const ShapelessSize auto &) -> Row<1> { return {}; } +constexpr auto numCols(const ShapelessSize auto &A) { return col(A.size()); } + +constexpr auto shape(const auto &x) { + return CartesianIndex(unwrapRow(numRows(x)), unwrapCol(numCols(x))); +} + +template +concept LinearlyIndexableTensor = + DefinesSize && utils::HasEltype && LinearlyIndexable; + +template +concept RowVectorCore = LinearlyIndexableTensor && requires(T t) { + { numRows(t) } -> std::same_as>; +}; +template +concept ColVectorCore = LinearlyIndexableTensor && requires(T t) { + { numCols(t) } -> std::same_as>; +}; +template +concept RowVector = RowVectorCore && requires(T t) { + { t.view() } -> RowVectorCore; }; template -concept DataMatrix = AbstractMatrix && HasDataPtr; +concept ColVector = ColVectorCore && requires(T t) { + { t.view() } -> ColVectorCore; +}; template -concept TemplateMatrix = AbstractMatrix && (!HasDataPtr); +concept AbstractVector = RowVector || ColVector; template -concept AbstractRowMajorMatrix = AbstractMatrix && requires(T t) { - { t.rowStride() } -> std::convertible_to>; +concept AbstractMatrixCore = + DefinesShape && utils::HasEltype && CartesianIndexable; +template +concept AbstractMatrix = + AbstractMatrixCore && !AbstractVector && requires(T t) { + { t.view() } -> AbstractMatrixCore; + }; + +template +concept AbstractTensor = AbstractVector || AbstractMatrix; + +template +concept HasDataPtr = requires(T t) { + { t.data() } -> std::same_as *>; +}; +template +concept DenseTensor = AbstractTensor && requires(T t) { + { t.begin() } -> std::convertible_to *>; }; template constexpr auto transpose_dim(Col c) { @@ -56,39 +103,66 @@ template constexpr auto transpose_dim(Row r) { } template struct Transpose { - static_assert(AbstractMatrix || AbstractVector, + static_assert(AbstractTensor, "Argument to transpose is not a matrix or vector."); static_assert(std::is_trivially_copyable_v, "Argument to transpose is not trivially copyable."); using value_type = utils::eltype_t; + static constexpr bool has_reduction_loop = HasInnerReduction; [[no_unique_address]] A a; - constexpr auto operator[](ptrdiff_t i, ptrdiff_t j) const -> value_type { - if constexpr (AbstractMatrix) return a[j, i]; - else { - invariant(i == 0); - return a[j]; - } + constexpr auto operator[](auto i) const + requires(AbstractVector) + { + return a[i]; + } + constexpr auto operator[](auto i, auto j) const + requires(AbstractMatrix) + { + return a[j, i]; } [[nodiscard]] constexpr auto numRow() const { - if constexpr (AbstractMatrix) return transpose_dim(a.numCol()); - else return Row<1>{}; + return transpose_dim(a.numCol()); } [[nodiscard]] constexpr auto numCol() const { - if constexpr (AbstractMatrix) return transpose_dim(a.numRow()); - else return col(a.size()); + return transpose_dim(a.numRow()); } [[nodiscard]] constexpr auto view() const -> auto & { return *this; }; - [[nodiscard]] constexpr auto size() const - -> CartesianIndex { - return {ptrdiff_t(numRow()), ptrdiff_t(numCol())}; - } + [[nodiscard]] constexpr auto size() const { return a.size(); } [[nodiscard]] constexpr auto dim() const { return DenseDims(numRow(), numCol()); } constexpr Transpose(A b) : a(b) {} - constexpr auto transpose() const -> A { return a; } + constexpr auto t() const -> A { return a; } + constexpr auto operator<<(const auto &b) -> Transpose & { + a << transpose(b); + return *this; + } + constexpr auto operator+=(const auto &b) -> Transpose & { + a += transpose(b); + return *this; + } + constexpr auto operator-=(const auto &b) -> Transpose & { + a -= transpose(b); + return *this; + } + constexpr auto operator*=(const auto &b) -> Transpose & { + a *= transpose(b); + return *this; + } + constexpr auto operator/=(const auto &b) -> Transpose & { + a /= transpose(b); + return *this; + } }; template Transpose(A) -> Transpose; +template constexpr auto transpose(const T &a) { + if constexpr (requires(T t) { + { t.t() } -> AbstractTensor; + }) + return a.t(); + else return Transpose{view(a)}; +} + } // namespace poly::math diff --git a/include/Math/MatrixDimensions.hpp b/include/Math/MatrixDimensions.hpp index 7dc6319..20d916d 100644 --- a/include/Math/MatrixDimensions.hpp +++ b/include/Math/MatrixDimensions.hpp @@ -10,18 +10,39 @@ template struct DenseDims; template struct StridedDims; +// template +// concept ConvertibleToButNot = +// std::convertible_to && (!std::same_as); + template struct CartesianIndex { [[no_unique_address]] R row; [[no_unique_address]] C col; explicit constexpr operator Row<>() const { return {row}; } explicit constexpr operator Col<>() const { return {col}; } constexpr auto operator==(const CartesianIndex &) const -> bool = default; - constexpr operator SquareDims<>() - requires(std::same_as && std::same_as); - constexpr operator DenseDims<>() - requires(std::same_as && std::same_as); - constexpr operator StridedDims<>() - requires(std::same_as && std::same_as); + constexpr operator CartesianIndex() const + requires(std::convertible_to && + std::convertible_to && + (!(std::same_as && std::same_as))) + { + return {ptrdiff_t(row), ptrdiff_t(col)}; + } + // FIXME: Do we need this?? + // Either document why, or delete this method. + constexpr operator ptrdiff_t() const + requires(std::same_as>) + { + return col; + } + constexpr operator SquareDims<>() const + requires(std::convertible_to && + std::convertible_to); + constexpr operator DenseDims<>() const + requires(std::convertible_to && + std::convertible_to); + constexpr operator StridedDims<>() const + requires(std::convertible_to && + std::convertible_to); }; template CartesianIndex(R, C) -> CartesianIndex; @@ -179,6 +200,16 @@ template struct DenseDims { { return {M, N}; } + constexpr operator ptrdiff_t() const + requires(R == 1) + { + return ptrdiff_t(N); + } + constexpr operator std::integral_constant() const + requires((R == 1) && (C != -1)) + { + return {}; + } friend inline auto operator<<(std::ostream &os, DenseDims x) -> std::ostream & { return os << x.M << " x " << x.N; @@ -300,31 +331,38 @@ constexpr inline auto DenseDims::operator=(SquareDims D) }; template -constexpr inline CartesianIndex::operator SquareDims<>() -requires(std::same_as && std::same_as) +constexpr inline CartesianIndex::operator SquareDims<>() const +requires(std::convertible_to && std::convertible_to) { invariant(row, col); return SquareDims{Row<>{row}}; } template -constexpr inline CartesianIndex::operator DenseDims<>() -requires(std::same_as && std::same_as) +constexpr inline CartesianIndex::operator DenseDims<>() const +requires(std::convertible_to && std::convertible_to) { return DenseDims{Row<>{row}, Col<>{col}}; } template -constexpr inline CartesianIndex::operator StridedDims<>() -requires(std::same_as && std::same_as) +constexpr inline CartesianIndex::operator StridedDims<>() const +requires(std::convertible_to && std::convertible_to) { return StridedDims{Row<>{row}, Col<>{col}, RowStride<>{col}}; } +template +concept different = !std::same_as; + template concept MatrixDimension = requires(D d) { { d } -> std::convertible_to>; + { Row(d) } -> different>; + { Col(d) } -> different>; }; static_assert(MatrixDimension>); static_assert(MatrixDimension>); +static_assert(!MatrixDimension>); +static_assert(!MatrixDimension>); static_assert(MatrixDimension>); static_assert(MatrixDimension>); static_assert(MatrixDimension>); @@ -340,6 +378,9 @@ concept PromoteDimFrom = (!std::same_as)&&std::convertible_to; constexpr auto row(MatrixDimension auto s) { return Row(s); } constexpr auto col(MatrixDimension auto s) { return Col(s); } -constexpr auto rowStride(MatrixDimension auto s) { return RowStride(s); } +constexpr auto stride(MatrixDimension auto s) { return RowStride(s); } + +template +concept HasInnerReduction = bool(T::has_reduction_loop); } // namespace poly::math diff --git a/include/Math/NormalForm.hpp b/include/Math/NormalForm.hpp index 20928c3..834b683 100644 --- a/include/Math/NormalForm.hpp +++ b/include/Math/NormalForm.hpp @@ -1,5 +1,6 @@ #pragma once +#include "Containers/Tuple.hpp" #include "Math/Array.hpp" #include "Math/Comparisons.hpp" #include "Math/Constructors.hpp" @@ -14,6 +15,7 @@ #include namespace poly::math::NormalForm { +using containers::Tuple, containers::tie; constexpr auto gcdxScale(int64_t a, int64_t b) -> std::array { if (constexpr_abs(a) == 1) return {a, 0, a, b}; @@ -29,32 +31,46 @@ constexpr void zeroSupDiagonal(MutPtrMatrix A, int64_t Aii = A[i, i]; if (int64_t Aji = A[j, i]) { const auto [p, q, Aiir, Aijr] = gcdxScale(Aii, Aji); - for (ptrdiff_t k = 0; k < minMN; ++k) { - int64_t Aki = A[i, k]; - int64_t Akj = A[j, k]; - int64_t Kki = K[i, k]; - int64_t Kkj = K[j, k]; - // when k == i, then - // p * Aii + q * Akj == r, so we set A(i,i) = r - A[i, k] = p * Aki + q * Akj; - // Aii/r * Akj - Aij/r * Aki = 0 - A[j, k] = Aiir * Akj - Aijr * Aki; - // Mirror for K - K[i, k] = p * Kki + q * Kkj; - K[j, k] = Aiir * Kkj - Aijr * Kki; - } - for (auto k = ptrdiff_t(N); k < M; ++k) { - int64_t Kki = K[i, k]; - int64_t Kkj = K[j, k]; - K[i, k] = p * Kki + q * Kkj; - K[j, k] = Aiir * Kkj - Aijr * Kki; + + { + MutPtrVector Ai{A[i, _(0, minMN)]}, Aj{A[j, _(0, minMN)]}, + Ki{K[i, _(0, minMN)]}, Kj{K[j, _(0, minMN)]}; + tie(Ai, Aj, Ki, Kj) << Tuple(p * Ai + q * Aj, Aiir * Aj - Aijr * Ai, + p * Ki + q * Kj, Aiir * Kj - Aijr * Ki); } - for (auto k = ptrdiff_t(M); k < N; ++k) { - int64_t Aki = A[i, k]; - int64_t Akj = A[j, k]; - A[i, k] = p * Aki + q * Akj; - A[j, k] = Aiir * Akj - Aijr * Aki; + if (ptrdiff_t(M) > ptrdiff_t(N)) { + MutPtrVector Ki{K[i, _(N, M)]}, Kj{K[j, _(N, M)]}; + tie(Ki, Kj) << Tuple(p * Ki + q * Kj, Aiir * Kj - Aijr * Ki); + } else if (ptrdiff_t(N) > ptrdiff_t(M)) { + MutPtrVector Ai{A[i, _(M, N)]}, Aj{A[j, _(M, N)]}; + tie(Ai, Aj) << Tuple(p * Ai + q * Aj, Aiir * Aj - Aijr * Ai); } + // for (ptrdiff_t k = 0; k < minMN; ++k) { + // int64_t Aki = A[i, k]; + // int64_t Akj = A[j, k]; + // int64_t Kki = K[i, k]; + // int64_t Kkj = K[j, k]; + // // when k == i, then + // // p * Aii + q * Akj == r, so we set A(i,i) = r + // A[i, k] = p * Aki + q * Akj; + // // Aii/r * Akj - Aij/r * Aki = 0 + // A[j, k] = Aiir * Akj - Aijr * Aki; + // // Mirror for K + // K[i, k] = p * Kki + q * Kkj; + // K[j, k] = Aiir * Kkj - Aijr * Kki; + // } + // for (auto k = ptrdiff_t(N); k < M; ++k) { + // int64_t Kki = K[i, k]; + // int64_t Kkj = K[j, k]; + // K[i, k] = p * Kki + q * Kkj; + // K[j, k] = Aiir * Kkj - Aijr * Kki; + // } + // for (auto k = ptrdiff_t(M); k < N; ++k) { + // int64_t Aki = A[i, k]; + // int64_t Akj = A[j, k]; + // A[i, k] = p * Aki + q * Akj; + // A[j, k] = Aiir * Akj - Aijr * Aki; + // } } } } @@ -70,20 +86,24 @@ constexpr void zeroSubDiagonal(MutPtrMatrix A, } else { invariant(Akk == 1); } - ptrdiff_t minMN = std::min(ptrdiff_t(M), ptrdiff_t(N)); + ptrdiff_t Mi = ptrdiff_t(M), Ni = ptrdiff_t(N), minMN = std::min(Mi, Ni); for (ptrdiff_t z = 0; z < k; ++z) { // eliminate `A(k,z)` - if (int64_t Akz = A[z, k]) { - // A(k, k) == 1, so A(k,z) -= Akz * 1; - // A(z,_) -= Akz * A(k,_); - // K(z,_) -= Akz * K(k,_); - for (ptrdiff_t i = 0; i < minMN; ++i) { - A[z, i] -= Akz * A[k, i]; - K[z, i] -= Akz * K[k, i]; - } - for (auto i = ptrdiff_t(N); i < M; ++i) K[z, i] -= Akz * K[k, i]; - for (auto i = ptrdiff_t(M); i < N; ++i) A[z, i] -= Akz * A[k, i]; - } + int64_t Akz = A[z, k]; + if (!Akz) continue; + // A(k, k) == 1, so A(k,z) -= Akz * 1; + // A(z,_) -= Akz * A(k,_); + // K(z,_) -= Akz * K(k,_); + Tuple(A[z, _(0, minMN)], K[z, _(0, minMN)]) -= + Tuple(Akz * A[k, _(0, minMN)], Akz * K[k, _(0, minMN)]); + if (Mi > Ni) K[z, _(Ni, Mi)] -= Akz * K[k, _(Ni, Mi)]; + else if (Ni > Mi) A[z, _(Mi, Ni)] -= Akz * A[k, _(Mi, Ni)]; + // for (ptrdiff_t i = 0; i < minMN; ++i) { + // A[z, i] -= Akz * A[k, i]; + // K[z, i] -= Akz * K[k, i]; + // } + // for (auto i = ptrdiff_t(N); i < M; ++i) K[z, i] -= Akz * K[k, i]; + // for (auto i = ptrdiff_t(M); i < N; ++i) A[z, i] -= Akz * A[k, i]; } } @@ -119,15 +139,15 @@ constexpr auto pivotRows(MutPtrMatrix A, ptrdiff_t i, Row<> N) constexpr void dropCol(MutPtrMatrix A, ptrdiff_t i, Row<> M, Col<> N) { // if any rows are left, we shift them up to replace it if (N <= i) return; - for (ptrdiff_t m = 0; m < M; ++m) - for (ptrdiff_t n = i; n < N; ++n) A[m, n] = A[m, n + 1]; + for (ptrdiff_t m = 0; m < M; ++m) A[m, _(i, N)] << A[m, _(i, N) + 1]; + // for (ptrdiff_t n = i; n < N; ++n) A[m, n] = A[m, n + 1]; } constexpr auto orthogonalizeBang(MutDensePtrMatrix &A) -> std::pair, Vector> { // we try to orthogonalize with respect to as many rows of `A` as we can // prioritizing earlier rows. - auto [M, N] = A.size(); + auto [M, N] = shape(A); SquareMatrix K{identity(alloc::Mallocator{}, unsigned(M))}; Vector included; included.reserve(std::min(ptrdiff_t(M), ptrdiff_t(N))); @@ -160,7 +180,7 @@ constexpr auto orthogonalize(IntMatrix<> A) } constexpr void zeroSupDiagonal(MutPtrMatrix A, Col<> c, Row<> r) { - auto [M, N] = A.size(); + auto [M, N] = shape(A); for (ptrdiff_t j = ptrdiff_t(r) + 1; j < M; ++j) { int64_t Aii = A[r, c]; if (int64_t Aij = A[j, c]) { @@ -176,7 +196,7 @@ constexpr void zeroSupDiagonal(MutPtrMatrix A, Col<> c, Row<> r) { constexpr void zeroSupDiagonal(std::array, 2> AB, Col<> c, Row<> r) { auto [A, B] = AB; - auto [M, N] = A.size(); + auto [M, N] = shape(A); const Col K = B.numCol(); invariant(M, ptrdiff_t(B.numRow())); for (ptrdiff_t j = ptrdiff_t(r) + 1; j < M; ++j) { @@ -317,7 +337,7 @@ constexpr void removeZeroRows(MutDensePtrMatrix &A) { // pass by value, returns number of rows to truncate constexpr auto simplifySystemImpl(MutPtrMatrix A, ptrdiff_t colInit = 0) -> Row<> { - auto [M, N] = A.size(); + auto [M, N] = shape(A); for (ptrdiff_t r = 0, c = colInit; c < N && r < M; ++c) if (!pivotRows(A, Col<>{c}, Row<>{M}, Row<>{r})) reduceColumn(A, Col<>{c}, Row<>{r++}); @@ -342,7 +362,7 @@ constexpr void reduceColumn(std::array, 2> AB, Col<> c, reduceSubDiagonal(AB, c, r); } constexpr void simplifySystemsImpl(std::array, 2> AB) { - auto [M, N] = AB[0].size(); + auto [M, N] = shape(AB[0]); for (ptrdiff_t r = 0, c = 0; c < N && r < M; ++c) if (!pivotRowsPair(AB, Col<>{c}, Row<>{M}, Row<>{r})) reduceColumn(AB, Col<>{c}, Row<>{r++}); @@ -460,7 +480,9 @@ constexpr void zeroColumn(MutPtrMatrix A, Col<> c, Row<> r) { const Row M = A.numRow(); for (ptrdiff_t j = 0; j < r; ++j) { int64_t Arc = A[r, c]; + invariant(Arc != std::numeric_limits::min()); if (int64_t Ajc = A[j, c]) { + invariant(Ajc != std::numeric_limits::min()); int64_t g = gcd(Arc, Ajc); A[j, _] << (Arc / g) * A[j, _] - (Ajc / g) * A[r, _]; } @@ -490,18 +512,19 @@ constexpr auto pivotRowsBareiss(MutPtrMatrix A, ptrdiff_t i, Row<> M, } constexpr void bareiss(MutPtrMatrix A, MutPtrVector pivots) { - const auto [M, N] = A.size(); + const auto [M, N] = shape(A); invariant(ptrdiff_t(pivots.size()), std::min(M, N)); int64_t prev = 1, pivInd = 0; for (ptrdiff_t r = 0, c = 0; c < N && r < M; ++c) { if (auto piv = pivotRowsBareiss(A, c, Row<>{M}, Row<>{r})) { pivots[pivInd++] = *piv; + auto j{_(c + 1, N)}; for (ptrdiff_t k = r + 1; k < M; ++k) { - for (ptrdiff_t j = c + 1; j < N; ++j) { - auto uAkj = A[r, c] * A[k, j] - A[k, c] * A[r, j], Akj = uAkj / prev; - invariant(uAkj, Akj * prev); - A[k, j] = Akj; - } + A[k, j] << (A[r, c] * A[k, j] - A[k, c] * A[r, j]) / prev; + // for (ptrdiff_t j = c + 1; j < N; ++j) { + // auto uAkj = A[r, c] * A[k, j] - A[k, c] * A[r, j], Akj = uAkj / + // prev; invariant(uAkj, Akj * prev); A[k, j] = Akj; + // } A[k, r] = 0; } prev = A[r++, c]; @@ -570,7 +593,7 @@ constexpr auto updateForNewRow(MutPtrMatrix A) -> ptrdiff_t { /// Once \f$\textbf{A}\f$ has been diagonalized, the solution is trivial. /// Both inputs are overwritten with the product of the left multiplications. constexpr void solveSystem(MutPtrMatrix A, MutPtrMatrix B) { - const auto [M, N] = A.size(); + const auto [M, N] = shape(A); for (ptrdiff_t r = 0, c = 0; c < N && r < M; ++c) if (!pivotRowsPair({A, B}, Col<>{c}, Row<>{M}, Row<>{r})) zeroColumnPair({A, B}, Col<>{c}, Row<>{r++}); @@ -584,7 +607,7 @@ constexpr void solveSystem(MutPtrMatrix A, ptrdiff_t K) { } // diagonalizes A(0:K,1:K+1) constexpr void solveSystemSkip(MutPtrMatrix A) { - const auto [M, N] = A.size(); + const auto [M, N] = shape(A); for (ptrdiff_t r = 0, c = 1; c < N && r < M; ++c) if (!pivotRows(A, Col<>{c}, Row<>{M}, Row<>{r})) zeroColumn(A, Col<>{c}, Row<>{r++}); diff --git a/include/Math/Simplex.hpp b/include/Math/Simplex.hpp index 0543678..b213971 100644 --- a/include/Math/Simplex.hpp +++ b/include/Math/Simplex.hpp @@ -185,6 +185,11 @@ class Simplex { inCanonicalForm = false; #endif auto C{getConstraints()}; +#ifndef NDEBUG + for (ptrdiff_t r = 0, R = ptrdiff_t(numRows(C)); r < R; ++r) + for (ptrdiff_t c = 0, N = ptrdiff_t(numCols(C)); c < N; ++c) + invariant(C[r, c] != std::numeric_limits::min()); +#endif NormalForm::solveSystemSkip(C); truncateConstraints(ptrdiff_t(NormalForm::numNonZeroRows(C))); } @@ -683,7 +688,7 @@ class Simplex { A[_, _(1, end)], B[_, _(1, end)]); auto consts{simplex->getConstants()}; consts[_(0, numSlack)] << A[_, 0]; - consts[_(numSlack, numSlack + numStrict)] << B[_, 0]; + if (numStrict) consts[_(numSlack, numSlack + numStrict)] << B[_, 0]; // for (ptrdiff_t i = 0; i < numSlack; ++i) consts[i] = A(i, 0); // for (ptrdiff_t i = 0; i < numStrict; ++i) consts[i + numSlack] = B(i, 0); if (!simplex->initiateFeasible()) return simplex; @@ -782,7 +787,7 @@ class Simplex { // subSimp.tableau(0, 1) = 0; auto fC{getTableau()}; auto sC{subSimp->getTableau()}; - sC[_, 0] << fC[_, 0] - fC[_, _(1 + off, 1 + off + numFix)] * x; + sC[_, 0] << fC[_, 0] - fC[_, _(1 + off, 1 + off + numFix)] * x.t(); // sC(_, 0) = fC(_, 0); // for (ptrdiff_t i = 0; i < numFix; ++i) // sC(_, 0) -= x(i) * fC(_, i + 1 + off); @@ -812,7 +817,7 @@ class Simplex { auto fC{getConstraints()}; auto sC{subSimp->getConstraints()}; sC[_, 0] << fC[_(begin, numRow), 0] - - fC[_(begin, numRow), _(off, off + numFix)] * x; + fC[_(begin, numRow), _(off, off + numFix)] * x.t(); sC[_, _(1, off)] << fC[_(begin, numRow), _(1, off)]; return subSimp->initiateFeasible(); } diff --git a/include/Math/SmallSparseMatrix.hpp b/include/Math/SmallSparseMatrix.hpp index 82d3cde..00b17c0 100644 --- a/include/Math/SmallSparseMatrix.hpp +++ b/include/Math/SmallSparseMatrix.hpp @@ -90,7 +90,7 @@ template [[gnu::flatten]] constexpr auto ArrayOps::operator<<(const SmallSparseMatrix &B) -> P & { static_assert(MatrixDimension); - ptrdiff_t M = nr(), N = nc(), k = 0; + ptrdiff_t M = ptrdiff_t(nr()), N = ptrdiff_t(nc()), k = 0; invariant(M, ptrdiff_t(B.numRow())); invariant(N, ptrdiff_t(B.numCol())); T *mem = data_(); @@ -98,7 +98,7 @@ ArrayOps::operator<<(const SmallSparseMatrix &B) -> P & { PtrVector rws = B.getRows(); for (ptrdiff_t i = 0; i < M; ++i) { uint32_t m = rws[i] & 0x00ffffff; - ptrdiff_t j = 0, l = rs() * i; + ptrdiff_t j = 0, l = ptrdiff_t(rs()) * i; while (m) { uint32_t tz = std::countr_zero(m); m >>= tz + 1; diff --git a/include/Math/StaticArrays.hpp b/include/Math/StaticArrays.hpp index 44f7754..299acbf 100644 --- a/include/Math/StaticArrays.hpp +++ b/include/Math/StaticArrays.hpp @@ -1,36 +1,77 @@ #pragma once #include "Math/Array.hpp" +#include "Math/Indexing.hpp" +#include "Utilities/Reference.hpp" #include #include + namespace poly::math { static_assert( AbstractSimilar, std::integral_constant>); -// TODO: add MatrixDimension support -template -concept StaticSize = StaticInt; +template +constexpr ptrdiff_t VecLen = + (N < poly::simd::Width) ? ptrdiff_t(std::bit_ceil(uint64_t(N))) + : poly::simd::Width; -template -struct StaticArray : public ArrayOps> { - static constexpr ptrdiff_t capacity = ptrdiff_t{S{}}; - T memory_[capacity]; // NOLINT(modernize-avoid-c-arrays) +template +consteval auto paddedSize() -> std::array { + constexpr ptrdiff_t WF = poly::simd::Width; + constexpr ptrdiff_t W = L < WF ? ptrdiff_t(std::bit_ceil(uint64_t(L))) : WF; + constexpr ptrdiff_t N = ((L + W - 1) / W); + return {N, W}; +} +template +consteval auto calcPaddedCols() -> ptrdiff_t { + constexpr ptrdiff_t a = Align / sizeof(T); + if constexpr (a <= 1) return L; + else return ((L + a - 1) / a) * a; +} +template consteval auto alignSIMD() -> size_t { + if constexpr (!simd::SIMDSupported) return alignof(T); + else return alignof(simd::Vec, T>); +} - using value_type = T; - using reference = T &; - using const_reference = const T &; - using size_type = unsigned; - using difference_type = int; - using iterator = T *; - using const_iterator = const T *; - using pointer = T *; - using const_pointer = const T *; +template +using StaticDims = std::conditional_t< + M == 1, std::integral_constant, + std::conditional_t< + Compress || (((N * sizeof(T)) % VecLen) == 0), DenseDims, + StridedDims()>()>>>; + +template +struct StaticArray : public ArrayOps, + StaticArray> { + using storage_type = std::conditional_t, T>; + static constexpr ptrdiff_t Align = + Compress ? alignof(storage_type) : alignSIMD(); + static constexpr ptrdiff_t PaddedCols = calcPaddedCols(); + static constexpr ptrdiff_t capacity = M * PaddedCols; + + static_assert(alignof(storage_type) <= Align); + + alignas(Align) storage_type memory_[capacity]; + + using value_type = utils::decompressed_t; + using reference = decltype(utils::ref((storage_type *)nullptr, 0)); + using const_reference = + decltype(utils::ref((const storage_type *)nullptr, 0)); + using size_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using iterator = storage_type *; + using const_iterator = const storage_type *; + using pointer = storage_type *; + using const_pointer = const storage_type *; using concrete = std::true_type; - constexpr explicit StaticArray(){}; // NOLINT(modernize-use-equals-default) - constexpr explicit StaticArray(const T &x) noexcept { - (*this) << x; - // std::fill_n(data(), capacity, x); - } + + // if Compress=false, we have a compressed_t + // if Compress=true, we should already be compressed + using compressed_type = StaticArray, M, N, true>; + using decompressed_type = StaticArray; + using S = StaticDims; + constexpr StaticArray(){}; // NOLINT(modernize-use-equals-default) + constexpr explicit StaticArray(const T &x) noexcept { (*this) << x; } constexpr explicit StaticArray( const std::convertible_to auto &x) noexcept { (*this) << x; @@ -42,12 +83,23 @@ struct StaticArray : public ArrayOps> { (*this) << *list.begin(); return; } - invariant(list.size(), size_t(capacity)); - std::copy(list.begin(), list.end(), data()); + invariant(list.size() <= size_t(capacity)); + std::copy_n(list.begin(), list.size(), data()); } template V> constexpr StaticArray(const V &b) noexcept { (*this) << b; } + + constexpr void compress(compressed_type *p) const + requires(std::same_as) + { + *p << *this; + } + static constexpr auto decompress(const compressed_type *p) -> StaticArray + requires(std::same_as) + { + return StaticArray{*p}; + } [[nodiscard]] constexpr auto data() const noexcept -> const T * { return memory_; } @@ -79,22 +131,15 @@ struct StaticArray : public ArrayOps> { // auto // } constexpr auto operator[](Index auto i) const noexcept -> decltype(auto) { - auto offset = calcOffset(S{}, i); - auto newDim = calcNewDim(S{}, i); - auto ptr = data(); - invariant(ptr != nullptr); - if constexpr (std::is_same_v) return ptr[offset]; - else return Array{ptr + offset, newDim}; + return index(data(), S{}, i); } // TODO: switch to operator[] when we enable c++23 // for vectors, we just drop the column, essentially broadcasting template constexpr auto operator[](R r, C c) const noexcept -> decltype(auto) { - if constexpr (MatrixDimension) - return (*this)[CartesianIndex{r, c}]; - else return (*this)[ptrdiff_t(r)]; + return index(data(), S{}, r, c); } - [[nodiscard]] constexpr auto minRowCol() const -> ptrdiff_t { + [[nodiscard]] static constexpr auto minRowCol() -> ptrdiff_t { return std::min(ptrdiff_t(numRow()), ptrdiff_t(numCol())); } @@ -113,31 +158,33 @@ struct StaticArray : public ArrayOps> { [[nodiscard]] static constexpr auto isSquare() noexcept -> bool { return Row(S{}) == Col(S{}); } - [[nodiscard]] constexpr auto checkSquare() const -> Optional { - ptrdiff_t N = ptrdiff_t(numRow()); - if (N != ptrdiff_t(numCol())) return {}; - return N; - } - [[nodiscard]] constexpr auto numRow() const noexcept { return row(S{}); } - [[nodiscard]] constexpr auto numCol() const noexcept { return col(S{}); } - [[nodiscard]] constexpr auto rowStride() const noexcept { - return rowStride(S{}); + [[nodiscard]] static constexpr auto checkSquare() -> Optional { + if constexpr (M == N) return M; + else return {}; + } + [[nodiscard]] static constexpr auto numRow() noexcept -> Row { return {}; } + [[nodiscard]] static constexpr auto numCol() noexcept -> Col { return {}; } + static constexpr auto safeRow() -> Row { return {}; } + static constexpr auto safeCol() -> Col { return {}; } + [[nodiscard]] static constexpr auto rowStride() noexcept + -> RowStride { + return {}; } [[nodiscard]] static constexpr auto empty() -> bool { return capacity == 0; } - [[nodiscard]] static constexpr auto size() noexcept { - if constexpr (StaticInt) return S{}; - else return CartesianIndex{Row(S{}), Col(S{})}; + [[nodiscard]] static constexpr auto size() noexcept + -> std::integral_constant { + return {}; } [[nodiscard]] static constexpr auto dim() noexcept -> S { return S{}; } - [[nodiscard]] constexpr auto transpose() const { return Transpose{*this}; } + [[nodiscard]] constexpr auto t() const { return Transpose{*this}; } [[nodiscard]] constexpr auto isExchangeMatrix() const -> bool { - ptrdiff_t N = ptrdiff_t(numRow()); - if (N != ptrdiff_t(numCol())) return false; - for (ptrdiff_t i = 0; i < N; ++i) { - for (ptrdiff_t j = 0; j < N; ++j) - if ((*this)(i, j) != (i + j == N - 1)) return false; - } + if constexpr (M == N) { + for (ptrdiff_t i = 0; i < M; ++i) { + for (ptrdiff_t j = 0; j < M; ++j) + if ((*this)(i, j) != (i + j == M - 1)) return false; + } + } else return false; } [[nodiscard]] constexpr auto isDiagonal() const -> bool { for (ptrdiff_t r = 0; r < numRow(); ++r) @@ -145,10 +192,10 @@ struct StaticArray : public ArrayOps> { if (r != c && (*this)(r, c) != 0) return false; return true; } - [[nodiscard]] constexpr auto view() const noexcept -> Array { - auto ptr = data(); + [[nodiscard]] constexpr auto view() const noexcept -> Array { + const storage_type *ptr = data(); invariant(ptr != nullptr); - return Array{const_cast(ptr), S{}}; + return {ptr, S{}}; } [[nodiscard]] constexpr auto begin() noexcept { @@ -166,21 +213,15 @@ struct StaticArray : public ArrayOps> { constexpr auto front() noexcept -> T & { return *begin(); } constexpr auto back() noexcept -> T & { return *(end() - 1); } constexpr auto operator[](Index auto i) noexcept -> decltype(auto) { - auto offset = calcOffset(S{}, i); - auto newDim = calcNewDim(S{}, i); - if constexpr (std::is_same_v) - return data()[offset]; - else return MutArray{data() + offset, newDim}; + return index(data(), S{}, i); } // TODO: switch to operator[] when we enable c++23 template constexpr auto operator[](R r, C c) noexcept -> decltype(auto) { - if constexpr (MatrixDimension) - return (*this)[CartesianIndex{r, c}]; - else return (*this)[ptrdiff_t(r)]; + return index(data(), S{}, r, c); } constexpr void fill(T value) { - std::fill_n((T *)(data()), ptrdiff_t(this->dim()), value); + std::fill_n(data(), ptrdiff_t(this->dim()), value); } [[nodiscard]] constexpr auto diag() noexcept { StridedRange r{unsigned(min(Row(S{}), Col(S{}))), @@ -202,21 +243,223 @@ struct StaticArray : public ArrayOps> { } }; -template -using SVector = StaticArray>; +template +struct StaticArray + : ArrayOps, StaticArray> { + // struct StaticArray, T>)> + // : ArrayOps, T>)>, + // StaticArray, T>)>> { + + using value_type = T; + using reference = T &; + using const_reference = const T &; + using size_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using iterator = T *; + using const_iterator = const T *; + using pointer = T *; + using const_pointer = const T *; + using concrete = std::true_type; + + using compressed_type = StaticArray; + + constexpr void compress(compressed_type *p) const { *p << *this; } + static constexpr auto decompress(const compressed_type *p) -> StaticArray { + return StaticArray{*p}; + } + static constexpr ptrdiff_t W = VecLen; + static constexpr ptrdiff_t Align = alignof(simd::Vec); + using S = StaticDims; + + [[nodiscard]] constexpr auto view() const -> StaticArray { return *this; } + + static constexpr ptrdiff_t L = (N + W - 1) / W; + static_assert(L * W == calcPaddedCols()); + using V = simd::Vec; + // simd::Vec data[M][L]; + V memory_[M * L]; + // std::array, L>, M> data; + // constexpr operator compressed_type() { return compressed_type{*this}; } + constexpr StaticArray(StaticArray const &) = default; + constexpr StaticArray(StaticArray &&) noexcept = default; + constexpr explicit StaticArray(const std::initializer_list &list) { + if (list.size() == 1) { + (*this) << *list.begin(); + return; + } + invariant(list.size() <= L * W); + size_t count = list.size() * sizeof(T); + std::memcpy(memory_, list.begin(), count); + std::memset((char *)memory_ + count, 0, (L * W - list.size()) * sizeof(T)); + } + constexpr auto data() -> T * { return reinterpret_cast(memory_); } + [[nodiscard]] constexpr auto data() const -> const T * { + return reinterpret_cast(memory_); + } + template V> constexpr StaticArray(const V &b) noexcept { + (*this) << b; + } + constexpr explicit StaticArray(T x) { + simd::Vec v = simd::Vec{} + x; + for (ptrdiff_t i = 0; i < M * L; ++i) memory_[i] = v; + } + constexpr auto operator=(StaticArray const &) -> StaticArray & = default; + constexpr auto operator=(StaticArray &&) noexcept -> StaticArray & = default; + constexpr StaticArray(){}; // NOLINT(modernize-use-equals-default) + static constexpr auto numRow() -> Row { return {}; } + static constexpr auto numCol() -> Col { return {}; } + static constexpr auto safeRow() -> Row { return {}; } + static constexpr auto safeCol() -> Col { return {}; } + [[nodiscard]] static constexpr auto rowStride() noexcept -> RowStride { + return {}; + } + [[nodiscard]] static constexpr auto size() noexcept + -> std::integral_constant { + return {}; + } + inline auto operator[](ptrdiff_t i, ptrdiff_t j) -> T & { + return reinterpret_cast(memory_ + i * L)[j]; + } + inline auto operator[](ptrdiff_t i, ptrdiff_t j) const -> T { + return reinterpret_cast(memory_ + i * L)[j]; + } + template + [[gnu::always_inline]] inline auto + operator[](ptrdiff_t i, simd::index::Unroll j) const + -> simd::Unroll<1, U, W, T> { + return (*this)[simd::index::Unroll<1>{i}, j]; + } + template + [[gnu::always_inline]] static constexpr void checkinds(ptrdiff_t i, + ptrdiff_t j) { + invariant(i >= 0); + invariant(i + (R - 1) < M); + invariant(j >= 0); + invariant(j < N); + invariant((j % W) == 0); + } + template + [[gnu::always_inline]] inline auto + operator[](simd::index::Unroll i, simd::index::Unroll j) const + -> simd::Unroll { + checkinds(i.index, j.index); + simd::Unroll ret; + ptrdiff_t k = j.index / W; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r) { + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < C; ++u) + ret[r, u] = memory_[(i.index + r) * L + k + u]; + } + return ret; + } + template struct Ref { + StaticArray *parent; + ptrdiff_t i, j; + constexpr auto operator=(simd::Unroll x) -> Ref & { + checkinds(i, j); + ptrdiff_t k = j / W; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r) { + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < C; ++u) + parent->memory_[(i + r) * L + k + u] = x[r, u]; + } + return *this; + } + constexpr auto operator=(simd::Vec x) -> Ref & { + checkinds(i, j); + ptrdiff_t k = j / W; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r) { + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < C; ++u) + parent->memory_[(i + r) * L + k + u] = x; + } + return *this; + } + constexpr auto operator=(std::convertible_to auto x) -> Ref & { + *this = simd::Vec{} + T(x); + return *this; + } + constexpr operator simd::Unroll() { + return (*const_cast( + parent))[simd::index::Unroll{i}, simd::index::Unroll{j}]; + } + constexpr auto operator+=(const auto &x) -> Ref & { + return (*this) = simd::Unroll(*this) + x; + } + constexpr auto operator-=(const auto &x) -> Ref & { + return (*this) = simd::Unroll(*this) - x; + } + constexpr auto operator*=(const auto &x) -> Ref & { + return (*this) = simd::Unroll(*this) * x; + } + constexpr auto operator/=(const auto &x) -> Ref & { + return (*this) = simd::Unroll(*this) / x; + } + }; + template + [[gnu::always_inline]] inline auto + operator[](ptrdiff_t i, simd::index::Unroll j) -> Ref<1, U> { + return Ref<1, U>{this, i, j.index}; + } + template + [[gnu::always_inline]] inline auto + operator[](simd::index::Unroll i, simd::index::Unroll j) + -> Ref { + return Ref{this, i.index, j.index}; + } + [[gnu::always_inline]] constexpr auto operator[](auto i) -> decltype(auto) + requires((N == 1) || (M == 1)) + { + if constexpr (M == 1) return (*this)[0, i]; + else return (*this)[i, 0]; + } + [[gnu::always_inline]] constexpr auto operator[](auto i) const + -> decltype(auto) + requires((N == 1) || (M == 1)) + { + if constexpr (M == 1) return (*this)[0, i]; + else return (*this)[i, 0]; + } + constexpr auto operator==(const StaticArray &other) const -> bool { + // masks return `true` if `any` are on + for (ptrdiff_t i = 0; i < M * L; ++i) + if (simd::cmp::ne(memory_[i], other.memory_[i])) return false; + return true; + } + template [[nodiscard]] constexpr auto get() const -> T { + return memory_[I / W][I % W]; + } +}; + +template +using SVector = StaticArray; +static_assert( + std::same_as, decltype(SVector::numRow())>); +static_assert(std::same_as, decltype(SVector::numRow())>); +static_assert( + std::same_as, decltype(numRows(std::declval>()))>); -static_assert(AbstractVector>); +static_assert(RowVector>); +static_assert(!ColVector>); +static_assert(!RowVector>>); +static_assert(ColVector>>); +static_assert(RowVector>); +static_assert(RowVector>); -template -inline constexpr auto view(const StaticArray &x) { +template +inline constexpr auto view(const StaticArray &x) { return x.view(); } template -StaticArray(T, U...) - -> StaticArray>; +StaticArray(T, U...) -> StaticArray; -}; // namespace poly::math +static_assert(utils::Compressible>); +static_assert(utils::Compressible>); +} // namespace poly::math template // NOLINTNEXTLINE(cert-dcl58-cpp) struct std::tuple_size<::poly::math::SVector> diff --git a/include/Math/UniformScaling.hpp b/include/Math/UniformScaling.hpp index 7ca3629..75ca505 100644 --- a/include/Math/UniformScaling.hpp +++ b/include/Math/UniformScaling.hpp @@ -1,5 +1,8 @@ #pragma once #include "Math/Matrix.hpp" +#include "SIMD/Indexing.hpp" +#include "SIMD/Masks.hpp" +#include "SIMD/Unroll.hpp" namespace poly::math { template struct UniformScaling { @@ -9,9 +12,42 @@ template struct UniformScaling { constexpr auto operator[](ptrdiff_t r, ptrdiff_t c) const -> T { return r == c ? value : T{}; } + template + [[gnu::always_inline]] constexpr auto + operator[](simd::index::Unroll r, simd::index::Unroll c) const + -> simd::Unroll { + simd::Unroll ret; + using I = simd::IntegerOfSize; + using VI = simd::Vec; + simd::Vec vz{}, vv = vz + value; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R; ++i) { + VI vr = VI{} + (i + r.index), vc = simd::range() + c.index; + POLYMATHFULLUNROLL + for (ptrdiff_t j = 0; j < C; ++j, vc += W) + ret[i, j] = (vr == vc) ? vv : vz; + } + return ret; + } + template + [[gnu::always_inline]] constexpr auto + operator[](ptrdiff_t r, simd::index::Unroll c) const + -> simd::Unroll<1, C, W, T> { + return (*this)[simd::index::Unroll<1>{r}, c]; + } + // template + // [[gnu::always_inline]] constexpr auto + // operator[](simd::index::Unroll r, ptrdiff_t c) const + // -> simd::Unroll<1, C, W, T> { + // return (*this)[r, simd::index::Unroll<1>{c}]; + // } + static constexpr auto numRow() -> Row<0> { return {}; } static constexpr auto numCol() -> Col<0> { return {}; } - static constexpr auto size() -> CartesianIndex { + static constexpr auto size() -> std::integral_constant { + return {}; + } + static constexpr auto shape() -> CartesianIndex { return {0, 0}; } static constexpr auto dim() -> DenseDims<0, 0> { return {{}, {}}; } diff --git a/include/Math/Unimodularization.hpp b/include/Math/Unimodularization.hpp index 3c0db6b..1df1e31 100644 --- a/include/Math/Unimodularization.hpp +++ b/include/Math/Unimodularization.hpp @@ -3,11 +3,6 @@ #include "Math/NormalForm.hpp" #include -// function unimod_hnf(A) -// H, U = Matrix.(hnf_with_transform(MatrixSpace(ZZ, size(A')...)(A'))) -// (isdiag(H) && all(isone, @views H[diagind(H)])) || return nothing -// [A; Int.(inv(U' .// 1))[size(A, 1)+1:end, :]] -// end namespace poly::math { // if `A` can be unimodularized, returns the inverse of the unimodularized `A` [[nodiscard]] inline auto unimodularize(IntMatrix<> A) diff --git a/include/Math/Vector.hpp b/include/Math/Vector.hpp deleted file mode 100644 index f27bde7..0000000 --- a/include/Math/Vector.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once -#include "Utilities/TypePromotion.hpp" -#include -#include -#include - -namespace poly::math { - -template > -concept LinearlyIndexable = requires(T t, ptrdiff_t i) { - { t[i] } -> std::convertible_to; -}; -template -concept LinearlyIndexableOrConvertible = - LinearlyIndexable || std::convertible_to; - -template -concept AbstractVector = - utils::HasEltype && LinearlyIndexable && requires(T t) { - { t.size() } -> std::convertible_to; - { t.view() }; - }; - -// This didn't work: #include "Math/Vector.hpp" NOLINT(unused-includes) -// so I moved some code from "Math/Array.hpp" here instead. -template -concept SizeMultiple8 = (sizeof(T) % 8) == 0; - -template struct DefaultCapacityType { - using type = int; -}; -template struct DefaultCapacityType { - using type = std::ptrdiff_t; -}; -template -using default_capacity_type_t = typename DefaultCapacityType::type; - -static_assert(!SizeMultiple8); -static_assert(SizeMultiple8); -static_assert(std::is_same_v, int32_t>); -static_assert(std::is_same_v, int64_t>); - -template consteval auto PreAllocStorage() -> ptrdiff_t { - constexpr ptrdiff_t totalBytes = 128; - constexpr ptrdiff_t remainingBytes = - totalBytes - sizeof(T *) - sizeof(S) - sizeof(default_capacity_type_t); - constexpr ptrdiff_t N = remainingBytes / sizeof(T); - return std::max(0, N); -} -constexpr auto log2Floor(uint64_t x) -> uint64_t { - return 63 - std::countl_zero(x); -} -constexpr auto log2Ceil(uint64_t x) -> uint64_t { - return 64 - std::countl_zero(x - 1); -} -// NOLINTNEXTLINE(misc-no-recursion) -consteval auto bisectFindSquare(uint64_t l, uint64_t h, uint64_t N) - -> uint64_t { - if (l == h) return l; - uint64_t m = (l + h) / 2; - if (m * m >= N) return bisectFindSquare(l, m, N); - return bisectFindSquare(m + 1, h, N); -} -template -consteval auto PreAllocSquareStorage() -> ptrdiff_t { - // 2* because we want to allow more space for matrices - // also removes need for other checks; log2Floor(2)==1 - constexpr uint64_t N = 2 * PreAllocStorage(); - if (!N) return 0; - // a fairly naive algorirthm for computing the next square `N` - // sqrt(x) = x^(1/2) = exp2(log2(x)/2) - constexpr uint64_t L = 1 << (log2Floor(N) / 2); - constexpr uint64_t H = 1 << ((log2Ceil(N) + 1) / 2); - return ptrdiff_t(bisectFindSquare(L, H, N)); -} - -constexpr auto selfDot(const auto &a) { - utils::eltype_t sum = 0; - for (auto x : a) sum += x * x; - return sum; -} - -} // namespace poly::math diff --git a/include/SIMD/Indexing.hpp b/include/SIMD/Indexing.hpp new file mode 100644 index 0000000..3e30230 --- /dev/null +++ b/include/SIMD/Indexing.hpp @@ -0,0 +1,57 @@ +#pragma once +#ifndef MATH_SIMD_INDEXING_HPP_INCLUDED +#define MATH_SIMD_INDEXING_HPP_INCLUDED + +#include "Math/AxisTypes.hpp" +#include "SIMD/Masks.hpp" +namespace poly::simd::index { +// Unroll rows by a factor of `R` and cols by `C`, vectorizing with width `W` +template > +struct Unroll { + ptrdiff_t index; + [[no_unique_address]] M mask{}; + explicit constexpr operator ptrdiff_t() const { return index; } + explicit constexpr operator bool() const { return bool(mask); } + constexpr auto operator+(ptrdiff_t b) -> Unroll { return {b + index, mask}; } +}; +template +[[gnu::always_inline]] constexpr auto unrollmask(ptrdiff_t L, ptrdiff_t i) { + // mask applies to last iter + // We can't check that the last iter is non-empty, because that + // could be the loop exit condition + auto m{mask::create(i + (U - 1) * W, L)}; + return Unroll{i, m}; +}; + +// template +// constexpr auto unroll(ptrdiff_t index, M mask, RowStride rs){ +// return Unroll{index,mask,rs}; +// } + +/// UnrollDims +/// Transposed means that the `W` dim indexes across the stride +/// !Tranposed means that the `W` dim is contiguous. +/// Note that `UnrollDims,false>` is thus morally +/// equivalent to `UnrollDims,true>` +/// +template , bool Transposed = false, ptrdiff_t X = -1> +struct UnrollDims { + static_assert(W != 1 || std::same_as>, + "Only mask vector dims"); + static_assert(W != 1 || !Transposed, + "Canonicalize scalar with Tranpose=false"); + [[no_unique_address]] M mask; + [[no_unique_address]] math::RowStride rs; +}; + +template static constexpr bool issimd = false; + +template +static constexpr bool issimd> = true; +template +static constexpr bool issimd> = true; +} // namespace poly::simd::index + +#endif diff --git a/include/SIMD/Intrin.hpp b/include/SIMD/Intrin.hpp new file mode 100644 index 0000000..6029fb2 --- /dev/null +++ b/include/SIMD/Intrin.hpp @@ -0,0 +1,688 @@ +#pragma once +#ifndef MATH_SIMD_INTRIN_HPP_INCLUDED +#define MATH_SIMD_INTRIN_HPP_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __x86_64__ +#include +#endif +namespace poly::simd { + +// Supported means by this library currently; more types may be added in the +// future as needed. +template +concept SIMDSupported = std::same_as || std::same_as; + +template +[[gnu::always_inline]] constexpr auto vbroadcast(Vec v) -> Vec { + if constexpr (W == 2) return __builtin_shufflevector(v, v, 0, 0); + else if constexpr (W == 4) return __builtin_shufflevector(v, v, 0, 0, 0, 0); + else if constexpr (W == 8) + return __builtin_shufflevector(v, v, 0, 0, 0, 0, 0, 0, 0, 0); + else if constexpr (W == 16) + return __builtin_shufflevector(v, v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0); + else if constexpr (W == 32) + return __builtin_shufflevector(v, v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0); + else if constexpr (W == 64) + return __builtin_shufflevector( + v, v, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + else static_assert(false); +} +template +[[gnu::always_inline]] constexpr auto vbroadcast(T x) -> Vec { + return vbroadcast(Vec{x}); +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::None<1>) -> T { + return *p; +} +template +constexpr auto load(const T *p, mask::None<1>, int32_t) -> const T & { + return *p; +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::None<1>, + T x) { + *p = x; +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::None<1>, + T x, int32_t) { + *p = x; +} +#ifdef __x86_64__ + +// TODO: make `consteval` when clang supports it +#ifdef __clang__ +template constexpr auto mmzero() { +#else +template consteval auto mmzero() { +#endif + // Extend if/when supporting more types + static_assert(std::popcount(size_t(W)) == 1 && W <= 8); + constexpr Vec z{}; + if constexpr (std::same_as) { + if constexpr (W == 8) return std::bit_cast<__m512d>(z); + else if constexpr (W == 4) return std::bit_cast<__m256d>(z); + else return std::bit_cast<__m128d>(z); + } else { + static_assert(std::same_as); + if constexpr (W == 8) return std::bit_cast<__m512i>(z); + else if constexpr (W == 4) return std::bit_cast<__m256i>(z); + else return std::bit_cast<__m128i>(z); + } +} +template inline auto vindex(int32_t stride) { + if constexpr (W <= 4) return std::bit_cast<__m128i>(range() * stride); + else if constexpr (W == 8) return std::bit_cast<__m256i>(range() * stride); + else { + static_assert(W == 16); + return std::bit_cast<__m512i>(range() * stride); + } +} + +#ifdef __AVX512F__ +static constexpr ptrdiff_t REGISTERS = 32; +static constexpr ptrdiff_t VECTORWIDTH = 64; +// namespace hw { +// typedef double __m512d_u __attribute__((__vector_size__(64), +// __aligned__(8))); + +// typedef int64_t __m512i_u __attribute__((__vector_size__(64), +// __aligned__(8))); } // namespace hw + +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::None<8>) + -> Vec<8, T> { + if constexpr (std::same_as) { + // hw::__m512d_u v = *reinterpret_cast(p); + // return std::bit_cast>(v); + return std::bit_cast>(_mm512_loadu_pd(p)); + } else if constexpr (std::same_as) { + // hw::__m512i_u v = *reinterpret_cast(p); + // return std::bit_cast>(v); + return std::bit_cast>(_mm512_loadu_epi64(p)); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::Bit<8> i) + -> Vec<8, T> { + if constexpr (std::same_as) + return std::bit_cast>( + _mm512_maskz_loadu_pd(uint8_t(i.mask), p)); + else if constexpr (std::same_as) + return std::bit_cast>( + _mm512_maskz_loadu_epi64(uint8_t(i.mask), p)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::None<8>, + Vec<8, T> x) { + if constexpr (std::same_as) { + // hw::__m512d_u v = std::bit_cast>(x); + // *reinterpret_cast(p) = v; + _mm512_storeu_pd(p, std::bit_cast<__m512d>(x)); + } else if constexpr (std::same_as) { + // hw::__m512i_u v = std::bit_cast>(x); + // *reinterpret_cast(p) = v; + _mm512_storeu_epi64(p, std::bit_cast<__m512i>(x)); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::Bit<8> i, + Vec<8, T> x) { + if constexpr (std::same_as) + _mm512_mask_storeu_pd(p, uint8_t(i.mask), std::bit_cast<__m512d>(x)); + else if constexpr (std::same_as) + _mm512_mask_storeu_epi64(p, uint8_t(i.mask), std::bit_cast<__m512i>(x)); + else static_assert(false); +} + +// strided memory accesses +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::None<8>, int32_t stride) -> Vec<8, T> { + if constexpr (std::same_as) + return std::bit_cast>( + _mm512_i32gather_pd(vindex<8>(stride), p, 8)); + else if constexpr (std::same_as) + return std::bit_cast>( + _mm512_i32gather_pd(vindex<8>(stride), p, 8)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Bit<8> i, int32_t stride) -> Vec<8, T> { + auto src = mmzero<8, T>(); + if constexpr (std::same_as) + return std::bit_cast>( + _mm512_mask_i32gather_pd(src, uint8_t(i.mask), vindex<8>(stride), p, 8)); + else if constexpr (std::same_as) + return std::bit_cast>(_mm512_mask_i32gather_epi64( + src, uint8_t(i.mask), vindex<8>(stride), p, 8)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::None<8>, Vec<8, T> x, int32_t stride) { + if constexpr (std::same_as) + _mm512_i32scatter_pd(p, vindex<8>(stride), std::bit_cast<__m512d>(x), 8); + else if constexpr (std::same_as) + _mm512_i32scatter_epi64(p, vindex<8>(stride), std::bit_cast<__m512i>(x), 8); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Bit<8> i, Vec<8, T> x, int32_t stride) { + if constexpr (std::same_as) + _mm512_mask_i32scatter_pd(p, uint8_t(i.mask), vindex<8>(stride), + std::bit_cast<__m512d>(x), 8); + else if constexpr (std::same_as) + _mm512_mask_i32scatter_epi64(p, uint8_t(i.mask), vindex<8>(stride), + std::bit_cast<__m512i>(x), 8); + else static_assert(false); +} +#else // no AVX512F + +static constexpr ptrdiff_t REGISTERS = 16; +#ifdef __AVX__ +static constexpr ptrdiff_t VECTORWIDTH = 32; +#else // no AVX +static constexpr ptrdiff_t VECTORWIDTH = 16; +#endif // no AVX +#endif // no AVX512F +#ifdef __AVX2__ + +// Non-masked gather/scatter are the same with AVX512VL and AVX2 +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::None<4>, int32_t stride) -> Vec<4, T> { + auto x{vindex<4>(stride)}; + if constexpr (std::same_as) + return std::bit_cast>(_mm256_i32gather_pd(p, x, 8)); + else if constexpr (std::same_as) + return std::bit_cast>(_mm256_i32gather_pd(p, x, 8)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::None<2>, int32_t stride) -> Vec<2, T> { + auto x{vindex<2>(stride)}; + if constexpr (std::same_as) + return std::bit_cast>(_mm_i64gather_pd(p, x, 8)); + else if constexpr (std::same_as) + return std::bit_cast>(_mm_i64gather_pd(p, x, 8)); + else static_assert(false); +} +#endif // AVX2 + +// Here, we handle masked loads/stores +#ifdef __AVX512VL__ +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::Bit<4> i) + -> Vec<4, T> { + if constexpr (std::same_as) + return std::bit_cast>( + _mm256_maskz_loadu_pd(uint8_t(i.mask), p)); + else if constexpr (std::same_as) + return std::bit_cast>( + _mm256_maskz_loadu_epi64(uint8_t(i.mask), p)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::Bit<4> i, + Vec<4, T> x) { + if constexpr (std::same_as) + _mm256_mask_storeu_pd(p, uint8_t(i.mask), std::bit_cast<__m256d>(x)); + else if constexpr (std::same_as) + _mm256_mask_storeu_epi64(p, uint8_t(i.mask), std::bit_cast<__m256i>(x)); + else static_assert(false); +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::Bit<2> i) + -> Vec<2, T> { + if constexpr (std::same_as) + return std::bit_cast>( + _mm_maskz_loadu_pd(uint8_t(i.mask), p)); + else if constexpr (std::same_as) + return std::bit_cast>( + _mm_maskz_loadu_epi64(uint8_t(i.mask), p)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::Bit<2> i, + Vec<2, T> x) { + if constexpr (std::same_as) + _mm_mask_storeu_pd(p, uint8_t(i.mask), std::bit_cast<__m128d>(x)); + else if constexpr (std::same_as) + _mm_mask_storeu_epi64(p, uint8_t(i.mask), std::bit_cast<__m128i>(x)); + else static_assert(false); +} +// gather/scatter +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Bit<4> i, int32_t stride) -> Vec<4, T> { + auto src{mmzero<4, T>()}; + if constexpr (std::same_as) + return std::bit_cast>( + _mm256_mmask_i32gather_pd(src, uint8_t(i.mask), vindex<4>(stride), p, 8)); + else if constexpr (std::same_as) + return std::bit_cast>(_mm256_mmask_i32gather_epi64( + src, uint8_t(i.mask), vindex<4>(stride), p, 8)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::None<4>, Vec<4, T> x, int32_t stride) { + if constexpr (std::same_as) + _mm256_i32scatter_pd(p, vindex<4>(stride), std::bit_cast<__m256d>(x), 8); + else if constexpr (std::same_as) + _mm256_i32scatter_epi64(p, vindex<4>(stride), std::bit_cast<__m256i>(x), 8); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Bit<4> i, Vec<4, T> x, int32_t stride) { + if constexpr (std::same_as) + _mm256_mask_i32scatter_pd(p, uint8_t(i.mask), vindex<4>(stride), + std::bit_cast<__m256d>(x), 8); + else if constexpr (std::same_as) + _mm256_mask_i32scatter_epi64(p, uint8_t(i.mask), vindex<4>(stride), + std::bit_cast<__m256i>(x), 8); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Bit<2> i, int32_t stride) -> Vec<2, T> { + auto src{mmzero<2, T>()}; + if constexpr (std::same_as) + return std::bit_cast>( + _mm_mmask_i64gather_pd(src, uint8_t(i.mask), vindex<2>(stride), p, 8)); + else if constexpr (std::same_as) + return std::bit_cast>( + _mm_mmask_i64gather_epi64(src, uint8_t(i.mask), vindex<2>(stride), p, 8)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::None<2>, Vec<2, T> x, int32_t stride) { + if constexpr (std::same_as) + _mm_i64scatter_pd(p, vindex<2>(stride), std::bit_cast<__m128d>(x), 8); + else if constexpr (std::same_as) + _mm_i64scatter_epi64(p, vindex<2>(stride), std::bit_cast<__m128i>(x), 8); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Bit<2> i, Vec<2, T> x, int32_t stride) { + if constexpr (std::same_as) + _mm_mask_i64scatter_pd(p, uint8_t(i.mask), vindex<2>(stride), + std::bit_cast<__m128d>(x), 8); + else if constexpr (std::same_as) + _mm_mask_i64scatter_epi64(p, uint8_t(i.mask), vindex<2>(stride), + std::bit_cast<__m128i>(x), 8); + else static_assert(false); +} + +#else // No AVX512VL + +// We need [gather, scatter, load, store] * [unmasked, masked] + +// 128 bit fallback scatters +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::None<2>, Vec<2, T> x, int32_t stride) { + p[0] = x[0]; + p[stride] = x[1]; +} + +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Vector<2> i, Vec<2, T> x, int32_t stride) { + if (i.m[0] != 0) p[0] = x[0]; + if (i.m[1] != 0) p[stride] = x[1]; +} + +#ifdef __AVX2__ +// masked gathers +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Vector<4> m, int32_t stride) -> Vec<4, T> { + __m128i x = vindex<4>(stride); + __m256i mask = __m256i(m); + if constexpr (std::same_as) { + constexpr __m256d z = mmzero<4, double>(); + return std::bit_cast>( + _mm256_mask_i32gather_pd(z, p, x, mask, 8)); + } else if constexpr (std::same_as) { + constexpr __m256i z = mmzero<4, int64_t>(); + return std::bit_cast>( + _mm256_mask_i32gather_epi64(z, p, x, mask, 8)); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Vector<2> m, int32_t stride) -> Vec<2, T> { + __m128i x = vindex<2>(stride), mask = __m128i(m); + if constexpr (std::same_as) { + constexpr __m128d z = mmzero<2, double>(); + return std::bit_cast>( + _mm_mask_i64gather_pd(z, p, x, mask, 8)); + } else if constexpr (std::same_as) { + constexpr __m128i z = mmzero<2, int64_t>(); + return std::bit_cast>( + _mm_mask_i64gather_epi64(z, p, x, mask, 8)); + } else static_assert(false); +} + +#else // no AVX2 +// fallback 128-bit gather +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::None<2>, int32_t stride) -> Vec<2, T> { + return Vec<2, T>{p[0], p[stride]}; +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Vector<2> i, int32_t stride) -> Vec<2, T> { + return Vec<2, T>{(i.m[0] != 0) ? p[0] : T{}, (i.m[1] != 0) ? p[stride] : T{}}; +} +#ifdef __AVX__ // no AVX2, but AVX +// fallback 256-bit gather +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::None<4>, int32_t stride) -> Vec<4, T> { + return Vec<4, T>{p[0], p[stride], p[2 * stride], p[3 * stride]}; +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Vector<4> i, int32_t stride) -> Vec<4, T> { + return Vec<4, T>{ + (i.m[0] != 0) ? p[0] : T{}, + (i.m[1] != 0) ? p[stride] : T{}, + (i.m[2] != 0) ? p[2 * stride] : T{}, + (i.m[3] != 0) ? p[3 * stride] : T{}, + }; +} + +#endif // AVX +#endif // no AVX2 +#ifdef __AVX__ +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::Vector<4> i) + -> Vec<4, T> { + if constexpr (std::same_as) + return std::bit_cast>(_mm256_maskload_pd(p, i)); + else if constexpr (std::same_as) + return std::bit_cast>( + _mm256_maskload_epi64((const long long *)p, i)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Vector<4> i, Vec<4, T> x) { + if constexpr (std::same_as) + _mm256_maskstore_pd(p, i, std::bit_cast<__m256d>(x)); + else if constexpr (std::same_as) + _mm256_maskstore_epi64((long long *)p, i, std::bit_cast<__m256i>(x)); + else static_assert(false); +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::Vector<2> i) + -> Vec<2, T> { + if constexpr (std::same_as) + return std::bit_cast>(_mm_maskload_pd(p, i)); + else if constexpr (std::same_as) + return std::bit_cast>( + _mm_maskload_epi64((const long long *)p, i)); + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Vector<2> i, Vec<2, T> x) { + if constexpr (std::same_as) + _mm_maskstore_pd(p, i, std::bit_cast<__m128d>(x)); + else if constexpr (std::same_as) + _mm_maskstore_epi64((long long *)p, i, std::bit_cast<__m128i>(x)); + else static_assert(false); +} + +// we need 256 bit fallback scatters +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::None<4>, Vec<4, T> x, int32_t stride) { + p[0] = x[0]; + p[stride] = x[1]; + p[2 * stride] = x[2]; + p[3 * stride] = x[3]; +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Vector<4> i, Vec<4, T> x, int32_t stride) { + if (i.m[0] != 0) p[0] = x[0]; + if (i.m[1] != 0) p[stride] = x[1]; + if (i.m[2] != 0) p[2 * stride] = x[2]; + if (i.m[3] != 0) p[3 * stride] = x[3]; +} +#else // No AVX +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::Vector<2> i) + -> Vec<2, T> { + return Vec<2, T>{(i.m[0] != 0) ? p[0] : T{}, (i.m[1] != 0) ? p[1] : T{}}; +} + +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Vector<2> i, Vec<2, T> x) { + if (i.m[0] != 0) p[0] = x[0]; + if (i.m[1] != 0) p[1] = x[1]; +} + +#endif // No AVX +#endif // No AVX512VL +#ifdef __AVX__ +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::None<4>) + -> Vec<4, T> { + if constexpr (std::same_as) + return std::bit_cast>(_mm256_loadu_pd(p)); + else if constexpr (std::same_as) +#ifdef __AVX512VL__ + return std::bit_cast>(_mm256_loadu_epi64(p)); +#else + return std::bit_cast>( + _mm256_loadu_si256((const __m256i *)p)); +#endif + else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::None<4>, + Vec<4, T> x) { + if constexpr (std::same_as) + _mm256_storeu_pd(p, std::bit_cast<__m256d>(x)); + else if constexpr (std::same_as) +#ifdef __AVX512VL__ + _mm256_storeu_epi64(p, std::bit_cast<__m256i>(x)); +#else + _mm256_storeu_si256((__m256i *)p, std::bit_cast<__m256i>(x)); +#endif + else static_assert(false); +} + +// // non-power-of-2 memory ops +// template +// constexpr auto fixupnonpow2(index::Vector i) { +// static_assert(std::popcount(size_t(N)) > 1, +// "Shouldn't be calling this if not needed."); +// static constexpr ptrdiff_t W = std::bit_ceil(size_t(N)); +// auto m = i.mask & mask(index::VectorMask{N}); +// return index::Vector{i.i, m}; +// } + +// template +// [[gnu::always_inline, gnu::artificial]] inline auto +// load(const T *p, index::Vector i) { +// return load(p, fixupnonpow2(i)); +// } +// template +// [[gnu::always_inline, gnu::artificial]] inline auto +// load(const T *p, index::Vector i, int32_t stride) { +// return load(p, fixupnonpow2(i), stride); +// } +// template +// [[gnu::always_inline, gnu::artificial]] inline void +// store(T *p, index::Vector i, Vec x) { +// store(p, fixupnonpow2(i), x); +// } +// template +// [[gnu::always_inline, gnu::artificial]] inline void +// store(T *p, index::Vector i, Vec x, int32_t stride) { +// store(p, fixupnonpow2(i), stride); +// } +#endif // AVX + +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::None<2>) + -> Vec<2, T> { + if constexpr (std::same_as) + return std::bit_cast>(_mm_loadu_pd(p)); + else if constexpr (std::same_as) +#ifdef __AVX512VL__ + return std::bit_cast>(_mm_loadu_epi64(p)); +#else + return std::bit_cast>(_mm_loadu_si128((const __m128i *)p)); +#endif + else static_assert(false); +} + +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::None<2>, + Vec<2, T> x) { + if constexpr (std::same_as) + _mm_storeu_pd(p, std::bit_cast<__m128d>(x)); + else if constexpr (std::same_as) +#ifdef __AVX512VL__ + _mm_storeu_epi64(p, std::bit_cast<__m128i>(x)); +#else + _mm_storeu_si128((__m128i *)p, std::bit_cast<__m128i>(x)); +#endif + else static_assert(false); +} + +#else // not __x86_64__ +static constexpr ptrdiff_t REGISTERS = 32; +static constexpr ptrdiff_t VECTORWIDTH = 16; +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::None) + -> Vec { + Vec ret; + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) ret[w] = p[w]; + return ret; +} +template +[[gnu::always_inline, gnu::artificial]] inline void store(T *p, mask::None, + Vec x) { + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) p[w] = x[w]; +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto load(const T *p, + mask::Vector i) + -> Vec { + Vec ret; + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) ret[w] = (i.m[w] != 0) ? p[w] : T{}; + return ret; +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Vector i, Vec x) { + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) + if (i.m[w] != 0) p[w] = x[w]; +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::None, int32_t stride) -> Vec { + Vec ret; + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) ret[w] = p[w * stride]; + return ret; +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::None, Vec x, int32_t stride) { + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) p[w * stride] = x[w]; +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto +load(const T *p, mask::Vector i, int32_t stride) -> Vec { + Vec ret; + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) + ret[w] = (i.m[w] != 0) ? p[w * stride] : T{}; + return ret; +} +template +[[gnu::always_inline, gnu::artificial]] inline void +store(T *p, mask::Vector i, Vec x, int32_t stride) { + POLYMATHFULLUNROLL + for (ptrdiff_t w = 0; w < W; ++w) + if (i.m[w] != 0) p[w * stride] = x[w]; +} + +#endif + +template +static constexpr ptrdiff_t Width = + SIMDSupported ? VECTORWIDTH / sizeof(T) : 1; + +// returns { vector_size, num_vectors, remainder } +template +consteval auto VectorDivRem() -> std::array { + constexpr ptrdiff_t W = Width; + if constexpr (L <= W) { + constexpr auto V = ptrdiff_t(std::bit_ceil(size_t(L))); + return {V, L / V, L % V}; + } else return {W, L / W, L % W}; +}; + +} // namespace poly::simd +#endif // SIMD_hpp_INCLUDED diff --git a/include/SIMD/Masks.hpp b/include/SIMD/Masks.hpp new file mode 100644 index 0000000..17f346c --- /dev/null +++ b/include/SIMD/Masks.hpp @@ -0,0 +1,512 @@ +#pragma once +#ifndef MATH_SIMD_MASKS_HPP_INCLUDED +#define MATH_SIMD_MASKS_HPP_INCLUDED +#include "SIMD/Vec.hpp" +#include +#include +#ifdef __x86_64__ +#include +#endif +namespace poly::simd { + +template +using IntegerOfSize = std::conditional_t< + sizeof(T) == 8, int64_t, + std::conditional_t>>; + +template > +consteval auto range() -> Vec { + static_assert(std::popcount(size_t(W)) == 1); + if constexpr (W == 2) return Vec{0, 1}; + else if constexpr (W == 4) return Vec{0, 1, 2, 3}; + else if constexpr (W == 8) return Vec{0, 1, 2, 3, 4, 5, 6, 7}; + else if constexpr (W == 16) + return Vec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + else { + Vec r; + for (ptrdiff_t w = 0; w < W; ++w) r[w] = I(w); + return r; + } +} +template > +consteval auto firstoff() -> Vec { + return range() != Vec{}; +} + +namespace mask { +template struct None { + static constexpr auto firstMasked() -> ptrdiff_t { return 0; } + static constexpr auto lastUnmasked() -> ptrdiff_t { return W; } +}; + +// Alternatives we can have: BitMask and VectorMask +// We use `BitMask` on AVX512, VectorMask elsewhere. +// ARM SVE(2) will eventually want bitmasks as well. +#ifdef __x86_64__ +#ifdef __AVX512F__ +template struct Bit { + uint64_t mask; + template explicit constexpr operator U() { + return U(mask); + } + explicit constexpr operator bool() const { return mask; } + [[nodiscard]] constexpr auto firstMasked() const -> ptrdiff_t { + return std::countr_zero(mask); + } + [[nodiscard]] constexpr auto lastUnmasked() const -> ptrdiff_t { + // could make this `countr_ones` if we decide to only + // support leading masks + uint64_t m = mask & ((uint64_t(1) << W) - uint64_t(1)); + return 64 - ptrdiff_t(std::countl_zero(m)); + } +}; +template constexpr auto operator&(Bit a, Bit b) -> Bit { + return {a.mask & b.mask}; +} +template constexpr auto operator&(None, Bit b) -> Bit { + return b; +} +template constexpr auto operator&(Bit a, None) -> Bit { + return a; +} +#endif // AVX512F +#ifdef __AVX512VL__ +// In: iteration count `i.i` is the total length of the loop +// Out: mask for the final iteration. Zero indicates no masked iter. +template constexpr auto create(ptrdiff_t i) -> Bit { + static_assert(std::popcount(size_t(W)) == 1); + utils::invariant(i >= 0); + return {_bzhi_u64(0xffffffffffffffff, uint64_t(i) & uint64_t(W - 1))}; +}; +// In: index::Vector where `i.i` is for the current iteration, and total loop +// length. Out: mask for the current iteration, 0 indicates exit loop. +template +constexpr auto create(ptrdiff_t i, ptrdiff_t len) -> Bit { + static_assert(std::popcount(size_t(W)) == 1); + uint64_t x; + if (__builtin_sub_overflow(len, i, &x)) x = 0; + else x = std::min(x, uint64_t(255)); + return {_bzhi_u64(0xffffffffffffffff, x)}; +}; +#else // ifdef __AVX512VL__ + +template struct Vector { + static_assert(sizeof(I) * W <= 32); + // TODO: add support for smaller mask types, we we can use smaller eltypes + Vec m; + [[nodiscard]] constexpr auto intmask() const -> int32_t { + if constexpr (sizeof(I) == 8) + if constexpr (W == 2) return _mm_movemask_pd(std::bit_cast<__m128d>(m)); + else return _mm256_movemask_pd(std::bit_cast<__m256d>(m)); + else if constexpr (sizeof(I) == 4) + if constexpr (W == 4) return _mm_movemask_ps(std::bit_cast<__m128>(m)); + else return _mm256_movemask_ps(std::bit_cast<__m256>(m)); + else if constexpr (W == 16) + return _mm_movemask_epi8(std::bit_cast<__m128i>(m)); + else return _mm256_movemask_epi8(std::bit_cast<__m256i>(m)); + } + explicit constexpr operator bool() const { return intmask(); } + [[nodiscard]] constexpr auto firstMasked() const -> ptrdiff_t { + return std::countr_zero(uint32_t(intmask())); + } + [[nodiscard]] constexpr auto lastUnmasked() const -> ptrdiff_t { + return 32 - std::countl_zero(uint32_t(intmask())); + } + constexpr operator __m128i() + requires(W == 2) + { + return std::bit_cast<__m128i>(m); + } + constexpr operator __m256i() + requires(W == 4) + { + return std::bit_cast<__m256i>(m); + } +}; +template +constexpr auto operator&(Vector a, Vector b) -> Vector { + return {a.m & b.m}; +} +template +constexpr auto operator&(mask::None, Vector b) -> Vector { + return b; +} +template +constexpr auto operator&(Vector a, mask::None) -> Vector { + return a; +} +#ifdef __AVX512F__ +// but no VL!!! xeon phi +template constexpr auto create(ptrdiff_t i) { + if constexpr (W == 8) + return Bit<8>{_bzhi_u64(0xffffffffffffffff, uint64_t(i) & uint64_t(7))}; + else return Vector{range() < (i & (W - 1))}; +} +template constexpr auto create(ptrdiff_t i, ptrdiff_t len) { + if constexpr (W == 8) + return Bit<8>{_bzhi_u64(0xffffffffffffffff, uint64_t(len - i))}; + else return Vector{range() + i < len}; +} +#else // ifdef __AVX512F__ +template constexpr auto create(ptrdiff_t i) -> Vector { + return {range() < (i & (W - 1))}; +} +template +constexpr auto create(ptrdiff_t i, ptrdiff_t len) -> Vector { + return {range() + i < len}; +} +#endif // ifdef __AVX512F__; else + +#endif // ifdef __AVX512VL__; else +#else // ifdef __x86_64__ + +template struct Vector { + Vec m; + explicit constexpr operator bool() { + bool any{false}; + for (ptrdiff_t w = 0; w < W; ++w) any |= m[w]; + return any; + } + [[nodiscard]] constexpr auto firstMasked() const -> ptrdiff_t { + for (ptrdiff_t w = 0; w < W; ++w) + if (m[w]) return w; + return W; + } + [[nodiscard]] constexpr auto lastUnmasked() const -> ptrdiff_t { + ptrdiff_t l = 0; + for (ptrdiff_t w = 0; w < W; ++w) + if (m[w]) l = w; + return l; + } +}; + +template constexpr auto create(ptrdiff_t i) -> Vector { + return {range() < (i & (W - 1))}; +} +template +constexpr auto create(ptrdiff_t i, ptrdiff_t len) -> Vector { + return {range() + i < len}; +} +#endif // ifdef __x86_64__; else +} // namespace mask + +#ifdef __AVX512VL__ + +namespace cmp { + +template +[[gnu::always_inline, gnu::artificial]] inline auto eq(Vec x, Vec y) + -> mask::Bit { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 8)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 0)}; + } else static_assert(false); + } else if constexpr (W == 4) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm256_cmp_pd_mask(std::bit_cast<__m256d>(x), + std::bit_cast<__m256d>(y), 8)}; + } else if constexpr (std::same_as) { + return {_mm256_cmp_epi64_mask(std::bit_cast<__m256i>(x), + std::bit_cast<__m256i>(y), 0)}; + } else static_assert(false); + } else if constexpr (W == 2) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm_cmp_pd_mask(std::bit_cast<__m128d>(x), + std::bit_cast<__m128d>(y), 8)}; + } else if constexpr (std::same_as) { + return {_mm_cmp_epi64_mask(std::bit_cast<__m128i>(x), + std::bit_cast<__m128i>(y), 0)}; + } else static_assert(false); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto ne(Vec x, Vec y) + -> mask::Bit { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 4)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 4)}; + } else static_assert(false); + } else if constexpr (W == 4) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm256_cmp_pd_mask(std::bit_cast<__m256d>(x), + std::bit_cast<__m256d>(y), 4)}; + } else if constexpr (std::same_as) { + return {_mm256_cmp_epi64_mask(std::bit_cast<__m256i>(x), + std::bit_cast<__m256i>(y), 4)}; + } else static_assert(false); + } else if constexpr (W == 2) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm_cmp_pd_mask(std::bit_cast<__m128d>(x), + std::bit_cast<__m128d>(y), 4)}; + } else if constexpr (std::same_as) { + return {_mm_cmp_epi64_mask(std::bit_cast<__m128i>(x), + std::bit_cast<__m128i>(y), 4)}; + } else static_assert(false); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto lt(Vec x, Vec y) + -> mask::Bit { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 25)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 1)}; + } else static_assert(false); + } else if constexpr (W == 4) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm256_cmp_pd_mask(std::bit_cast<__m256d>(x), + std::bit_cast<__m256d>(y), 25)}; + } else if constexpr (std::same_as) { + return {_mm256_cmp_epi64_mask(std::bit_cast<__m256i>(x), + std::bit_cast<__m256i>(y), 1)}; + } else static_assert(false); + } else if constexpr (W == 2) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm_cmp_pd_mask(std::bit_cast<__m128>(x), + std::bit_cast<__m128d>(y), 25)}; + } else if constexpr (std::same_as) { + return {_mm_cmp_epi64_mask(std::bit_cast<__m128i>(x), + std::bit_cast<__m128i>(y), 1)}; + } else static_assert(false); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto gt(Vec x, Vec y) + -> mask::Bit { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 22)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 6)}; + } else static_assert(false); + } else if constexpr (W == 4) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm256_cmp_pd_mask(std::bit_cast<__m256d>(x), + std::bit_cast<__m256d>(y), 22)}; + } else if constexpr (std::same_as) { + return {_mm256_cmp_epi64_mask(std::bit_cast<__m256i>(x), + std::bit_cast<__m256i>(y), 6)}; + } else static_assert(false); + } else if constexpr (W == 2) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm_cmp_pd_mask(std::bit_cast<__m128d>(x), + std::bit_cast<__m128d>(y), 22)}; + } else if constexpr (std::same_as) { + return {_mm_cmp_epi64_mask(std::bit_cast<__m128i>(x), + std::bit_cast<__m128i>(y), 6)}; + } else static_assert(false); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto le(Vec x, Vec y) + -> mask::Bit { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 26)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 2)}; + } else static_assert(false); + } else if constexpr (W == 4) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm256_cmp_pd_mask(std::bit_cast<__m256d>(x), + std::bit_cast<__m256d>(y), 26)}; + } else if constexpr (std::same_as) { + return {_mm256_cmp_epi64_mask(std::bit_cast<__m256i>(x), + std::bit_cast<__m256i>(y), 2)}; + } else static_assert(false); + } else if constexpr (W == 2) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm_cmp_pd_mask(std::bit_cast<__m128d>(x), + std::bit_cast<__m128d>(y), 26)}; + } else if constexpr (std::same_as) { + return {_mm_cmp_epi64_mask(std::bit_cast<__m128i>(x), + std::bit_cast<__m128i>(y), 2)}; + } else static_assert(false); + } else static_assert(false); +} +template +[[gnu::always_inline, gnu::artificial]] inline auto ge(Vec x, Vec y) + -> mask::Bit { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 21)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 5)}; + } else static_assert(false); + } else if constexpr (W == 4) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm256_cmp_pd_mask(std::bit_cast<__m256d>(x), + std::bit_cast<__m256d>(y), 21)}; + } else if constexpr (std::same_as) { + return {_mm256_cmp_epi64_mask(std::bit_cast<__m256i>(x), + std::bit_cast<__m256i>(y), 5)}; + } else static_assert(false); + } else if constexpr (W == 2) { + + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm_cmp_pd_mask(std::bit_cast<__m128d>(x), + std::bit_cast<__m128d>(y), 21)}; + } else if constexpr (std::same_as) { + return {_mm_cmp_epi64_mask(std::bit_cast<__m128i>(x), + std::bit_cast<__m128i>(y), 5)}; + } else static_assert(false); + } else static_assert(false); +} + +} // namespace cmp +#elif defined(__AVX512F__) + +template +[[gnu::always_inline, gnu::artificial]] inline auto eq(Vec x, + Vec y) { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 8)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 0)}; + } else static_assert(false); + } else { + return mask::Vector{x == y}; + } +} +template +[[gnu::always_inline, gnu::artificial]] inline auto ne(Vec x, + Vec y) { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 4)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 4)}; + } else static_assert(false); + } else { + return mask::Vector{x != y}; + } +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto lt(Vec x, + Vec y) { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 25)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 1)}; + } else static_assert(false); + } else { + return mask::Vector{x < y}; + } +} +template +[[gnu::always_inline, gnu::artificial]] inline auto gt(Vec x, + Vec y) { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 22)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 6)}; + } else static_assert(false); + } else { + return mask::Vector{x > y}; + } +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto le(Vec x, + Vec y) { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 26)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 2)}; + } else static_assert(false); + } else { + return mask::Vector{x <= y}; + } +} +template +[[gnu::always_inline, gnu::artificial]] inline auto ge(Vec x, + Vec y) { + if constexpr (W == 8) { + if constexpr (std::same_as) { // UQ (unordered quiet?) + return {_mm512_cmp_pd_mask(std::bit_cast<__m512d>(x), + std::bit_cast<__m512d>(y), 21)}; + } else if constexpr (std::same_as) { + return {_mm512_cmp_epi64_mask(std::bit_cast<__m512i>(x), + std::bit_cast<__m512i>(y), 5)}; + } else static_assert(false); + } else { + return mask::Vector{x >= y}; + } +} + +#else // ifdef __AVX512VL__ + +namespace cmp { + +template +[[gnu::always_inline, gnu::artificial]] inline auto eq(Vec x, Vec y) + -> mask::Vector { + return {x == y}; +} +template +[[gnu::always_inline, gnu::artificial]] inline auto ne(Vec x, Vec y) + -> mask::Vector { + return {x != y}; +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto lt(Vec x, Vec y) + -> mask::Vector { + return {x < y}; +} +template +[[gnu::always_inline, gnu::artificial]] inline auto gt(Vec x, Vec y) + -> mask::Vector { + return {x > y}; +} + +template +[[gnu::always_inline, gnu::artificial]] inline auto le(Vec x, Vec y) + -> mask::Vector { + return {x <= y}; +} +template +[[gnu::always_inline, gnu::artificial]] inline auto ge(Vec x, Vec y) + -> mask::Vector { + return {x >= y}; +} +} // namespace cmp +#endif // ifdef __AVX512VL__; else + +} // namespace poly::simd +#endif // Masks_hpp_INCLUDED diff --git a/include/SIMD/Transpose.hpp b/include/SIMD/Transpose.hpp new file mode 100644 index 0000000..7204fc9 --- /dev/null +++ b/include/SIMD/Transpose.hpp @@ -0,0 +1,73 @@ +#pragma once +#ifndef POLY_SIMD_Transpose_hpp_INCLUDED +#define POLY_SIMD_Transpose_hpp_INCLUDED + +#include "SIMD/Unroll.hpp" +namespace poly::simd { + +// 4 x 4C -> 4C x 4 +template +constexpr auto transpose(Unroll<2, C, 2, T> u) -> Unroll<2 * C, 1, 2, T> { + Unroll<2 * C, 1, 2, T> z; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < C; ++i) { + Vec<2, T> a{u[0, i]}, b{u[1, i]}; + z[0, i] = __builtin_shufflevector(a, b, 0, 2); + z[1, i] = __builtin_shufflevector(a, b, 1, 3); + } + return z; +} +template +constexpr auto transpose(Unroll<4, C, 4, T> u) -> Unroll<4 * C, 1, 4, T> { + Unroll<4 * C, 1, 4, T> z; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < C; ++i) { + Vec<4, T> a{u[0, i]}, b{u[1, i]}, c{u[2, i]}, d{u[3, i]}; + Vec<4, T> e{__builtin_shufflevector(a, b, 0, 1, 4, 5)}; + Vec<4, T> f{__builtin_shufflevector(a, b, 2, 3, 6, 7)}; + Vec<4, T> g{__builtin_shufflevector(c, d, 0, 1, 4, 5)}; + Vec<4, T> h{__builtin_shufflevector(c, d, 2, 3, 6, 7)}; + z[0, i] = __builtin_shufflevector(e, g, 0, 2, 4, 6); + z[1, i] = __builtin_shufflevector(e, g, 1, 3, 5, 7); + z[2, i] = __builtin_shufflevector(f, h, 0, 2, 4, 6); + z[3, i] = __builtin_shufflevector(f, h, 1, 3, 5, 7); + } + return z; +} +template +constexpr auto transpose(Unroll<8, C, 8, T> u) -> Unroll<8 * C, 1, 8, T> { + Unroll<8 * C, 1, 8, T> z; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < C; ++i) { + Vec<4, T> a{u[0, i]}, b{u[1, i]}, c{u[2, i]}, d{u[3, i]}, e{u[4, i]}, + f{u[5, i]}, g{u[6, i]}, h{u[7, i]}; + Vec<4, T> j{__builtin_shufflevector(a, b, 0, 8, 2, 10, 4, 12, 6, 14)}, + k{__builtin_shufflevector(a, b, 1, 9, 3, 11, 5, 13, 7, 15)}, + l{__builtin_shufflevector(c, d, 0, 8, 2, 10, 4, 12, 6, 14)}, + m{__builtin_shufflevector(c, d, 1, 9, 3, 11, 5, 13, 7, 15)}, + n{__builtin_shufflevector(e, f, 0, 8, 2, 10, 4, 12, 6, 14)}, + o{__builtin_shufflevector(e, f, 1, 9, 3, 11, 5, 13, 7, 15)}, + p{__builtin_shufflevector(g, h, 0, 8, 2, 10, 4, 12, 6, 14)}, + q{__builtin_shufflevector(g, h, 1, 9, 3, 11, 5, 13, 7, 15)}; + a = __builtin_shufflevector(j, l, 0, 1, 8, 9, 4, 5, 12, 13); + b = __builtin_shufflevector(j, l, 2, 3, 10, 11, 6, 7, 14, 15); + c = __builtin_shufflevector(k, m, 0, 1, 8, 9, 4, 5, 12, 13); + d = __builtin_shufflevector(k, m, 2, 3, 10, 11, 6, 7, 14, 15); + e = __builtin_shufflevector(n, p, 0, 1, 8, 9, 4, 5, 12, 13); + f = __builtin_shufflevector(n, p, 2, 3, 10, 11, 6, 7, 14, 15); + g = __builtin_shufflevector(o, q, 0, 1, 8, 9, 4, 5, 12, 13); + h = __builtin_shufflevector(o, q, 2, 3, 10, 11, 6, 7, 14, 15); + z[0, i] = __builtin_shufflevector(a, e, 0, 1, 2, 3, 8, 9, 10, 11); + z[1, i] = __builtin_shufflevector(a, e, 4, 5, 6, 7, 12, 13, 14, 15); + z[2, i] = __builtin_shufflevector(b, f, 0, 1, 2, 3, 8, 9, 10, 11); + z[3, i] = __builtin_shufflevector(b, f, 4, 5, 6, 7, 12, 13, 14, 15); + z[4, i] = __builtin_shufflevector(c, g, 0, 1, 2, 3, 8, 9, 10, 11); + z[5, i] = __builtin_shufflevector(c, g, 4, 5, 6, 7, 12, 13, 14, 15); + z[6, i] = __builtin_shufflevector(d, h, 0, 1, 2, 3, 8, 9, 10, 11); + z[7, i] = __builtin_shufflevector(d, h, 4, 5, 6, 7, 12, 13, 14, 15); + } + return z; +} + +} // namespace poly::simd +#endif // Transpose_hpp_INCLUDED diff --git a/include/SIMD/Unroll.hpp b/include/SIMD/Unroll.hpp new file mode 100644 index 0000000..7f4ad19 --- /dev/null +++ b/include/SIMD/Unroll.hpp @@ -0,0 +1,656 @@ +#pragma once +#ifndef POLY_SIMD_Unroll_hpp_INCLUDED +#define POLY_SIMD_Unroll_hpp_INCLUDED +#include "SIMD/Intrin.hpp" +#include +namespace poly::simd { +// template +// [[gnu::always_inline]] constexpr auto vcvt(Vec v) { +// if constexpr (std::same_as) return v; +// else if constexpr (W == 1) return T(v); +// else return __builtin_convertvector(v, Vec); +// } +// Vector goes across cols +template struct Unroll { + static constexpr ptrdiff_t W = ptrdiff_t(std::bit_ceil(size_t(N))); + using VT = Vec; + static_assert(R * C > 0); + VT data[R * C]; + constexpr auto operator[](ptrdiff_t i) -> VT & { return data[i]; } + constexpr auto operator[](ptrdiff_t r, ptrdiff_t c) -> VT & { + return data[r * C + c]; + } + constexpr auto operator[](ptrdiff_t i) const -> VT { return data[i]; } + constexpr auto operator[](ptrdiff_t r, ptrdiff_t c) const -> VT { + return data[r * C + c]; + } + template + [[gnu::always_inline]] constexpr operator Unroll() const + requires(!std::same_as) + { + Unroll x; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) + if constexpr (W == 1) x.data[i] = U(data[i]); + else x.data[i] = __builtin_convertvector(data[i], Vec); + return x; + } + [[gnu::always_inline]] constexpr auto operator-() { + Unroll a; + for (ptrdiff_t i = 0; i < R * C; ++i) a.data[i] = -data[i]; + return a; + } + [[gnu::always_inline]] constexpr auto operator+=(const Unroll &a) + -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] += a.data[i]; + return *this; + } + [[gnu::always_inline]] constexpr auto operator-=(const Unroll &a) + -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] -= a.data[i]; + return *this; + } + [[gnu::always_inline]] constexpr auto operator*=(const Unroll &a) + -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] *= a.data[i]; + return *this; + } + [[gnu::always_inline]] constexpr auto operator/=(const Unroll &a) + -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] /= a.data[i]; + return *this; + } + [[gnu::always_inline]] constexpr auto operator+=(VT a) -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] += a; + return *this; + } + [[gnu::always_inline]] constexpr auto operator-=(VT a) -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] -= a; + return *this; + } + [[gnu::always_inline]] constexpr auto operator*=(VT a) -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] *= a; + return *this; + } + [[gnu::always_inline]] constexpr auto operator/=(VT a) -> Unroll & { + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) data[i] /= a; + return *this; + } + [[gnu::always_inline]] constexpr auto + operator+=(std::convertible_to auto a) -> Unroll & + requires(W != 1) + { + return (*this) += (typename Unroll::VT{} + T(a)); + } + [[gnu::always_inline]] constexpr auto + operator-=(std::convertible_to auto a) -> Unroll & + requires(W != 1) + { + return (*this) -= (typename Unroll::VT{} + T(a)); + } + [[gnu::always_inline]] constexpr auto + operator*=(std::convertible_to auto a) -> Unroll & + requires(W != 1) + { + return (*this) *= (typename Unroll::VT{} + T(a)); + } + [[gnu::always_inline]] constexpr auto + operator/=(std::convertible_to auto a) -> Unroll & + requires(W != 1) + { + return (*this) /= (typename Unroll::VT{} + T(a)); + } +}; + +template +[[gnu::always_inline]] constexpr auto applyop(const Unroll &a, + const Unroll &b, + Op op) { + // Possibilities: + // 1. All match + // 2. We had separate unrolls across rows and columns, and some arrays + // were indexed by one or two of them. + // In the latter case, we could have arrays indexed by rows, cols, or both. + if constexpr (!std::same_as) { + using T = std::common_type_t; + return applyop(Unroll(a), Unroll(b), op); + } else if constexpr (W0 == W1) { + // both were indexed by cols, and `C`s should also match + // or neither were, and they should still match. + static_assert(C0 == C1); + if constexpr (R0 == R1) { + // Both have the same index across rows + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R0 * C0; ++i) + c.data[i] = op(a.data[i], b.data[i]); + return c; + } else if constexpr (R0 == 1) { + // `a` was indexed across cols only + Unroll z; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R1; ++r) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C0; ++c) z[r, c] = op(a.data[c], b[r, c]); + } + return z; + } else { + static_assert(R1 == 1); + // `b` was indexed across cols only + Unroll z; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R0; ++r) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C0; ++c) z[r, c] = op(a[r, c], b.data[c]); + } + return z; + } + } else if constexpr (W0 == 1) { + static_assert(R0 == 1 || C0 == 1); + constexpr ptrdiff_t R = R0 == 1 ? C0 : R0; + // `a` was indexed by row only + Unroll z; + static_assert(R1 == R || R1 == 1); + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C1; ++c) + if constexpr (R == R1) z[r, c] = op(a.data[r], b[r, c]); + else z[r, c] = op(a.data[r], b.data[c]); + } + return z; + } else { + static_assert(W1 == 1); + static_assert(R1 == 1 || C1 == 1); + constexpr ptrdiff_t R = R1 == 1 ? C1 : R1; + // `b` was indexed by row only + Unroll z; + static_assert(R0 == R || R0 == 1); + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C0; ++c) + if constexpr (R0 == R) z[r, c] = op(a[r, c], b.data[r]); + else z[r, c] = op(a.data[c], b.data[r]); + } + return z; + } +} + +template +[[gnu::always_inline]] constexpr auto +operator+(const Unroll &a, const Unroll &b) { + return applyop(a, b, std::plus<>{}); +} + +template +[[gnu::always_inline]] constexpr auto +operator-(const Unroll &a, const Unroll &b) { + return applyop(a, b, std::minus<>{}); +} + +template +[[gnu::always_inline]] constexpr auto +operator*(const Unroll &a, const Unroll &b) { + return applyop(a, b, std::multiplies<>{}); +} + +template +[[gnu::always_inline]] constexpr auto +operator/(const Unroll &a, const Unroll &b) { + return applyop(a, b, std::divides<>{}); +} + +template +[[gnu::always_inline]] constexpr auto +operator+(const Unroll &a, typename Unroll::VT b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a.data[i] + b; + return c; +} +template +[[gnu::always_inline]] constexpr auto +operator-(const Unroll &a, typename Unroll::VT b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a.data[i] - b; + return c; +} +template +[[gnu::always_inline]] constexpr auto +operator*(const Unroll &a, typename Unroll::VT b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a.data[i] * b; + return c; +} +template +[[gnu::always_inline]] constexpr auto +operator/(const Unroll &a, typename Unroll::VT b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a.data[i] / b; + return c; +} +template +[[gnu::always_inline]] constexpr auto operator+(const Unroll &a, + std::convertible_to auto b) + -> Unroll +requires(W != 1) +{ + return a + (typename Unroll::VT{} + T(b)); +} +template +[[gnu::always_inline]] constexpr auto operator-(const Unroll &a, + std::convertible_to auto b) + -> Unroll +requires(W != 1) +{ + return a - (typename Unroll::VT{} + T(b)); +} +template +[[gnu::always_inline]] constexpr auto operator*(const Unroll &a, + std::convertible_to auto b) + -> Unroll +requires(W != 1) +{ + return a * (typename Unroll::VT{} + T(b)); +} +template +[[gnu::always_inline]] constexpr auto operator/(const Unroll &a, + std::convertible_to auto b) + -> Unroll +requires(W != 1) +{ + return a / (typename Unroll::VT{} + T(b)); +} + +template +[[gnu::always_inline]] constexpr auto +operator+(typename Unroll::VT a, const Unroll &b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a + b.data[i]; + return c; +} +template +[[gnu::always_inline]] constexpr auto +operator-(typename Unroll::VT a, const Unroll &b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a - b.data[i]; + return c; +} +template +[[gnu::always_inline]] constexpr auto +operator*(typename Unroll::VT a, const Unroll &b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a * b.data[i]; + return c; +} +template +[[gnu::always_inline]] constexpr auto +operator/(typename Unroll::VT a, const Unroll &b) + -> Unroll { + Unroll c; + POLYMATHFULLUNROLL + for (ptrdiff_t i = 0; i < R * C; ++i) c.data[i] = a / b.data[i]; + return c; +} +template +[[gnu::always_inline]] constexpr auto operator+(T b, + const Unroll &a) + -> Unroll +requires(W != 1) +{ + return (typename Unroll::VT{} + b) + a; +} +template +[[gnu::always_inline]] constexpr auto operator-(T b, + const Unroll &a) + -> Unroll +requires(W != 1) +{ + return (typename Unroll::VT{} + b) - a; +} +template +[[gnu::always_inline]] constexpr auto operator*(T b, + const Unroll &a) + -> Unroll +requires(W != 1) +{ + return (typename Unroll::VT{} + b) * a; +} +template +[[gnu::always_inline]] constexpr auto operator/(T b, + const Unroll &a) + -> Unroll +requires(W != 1) +{ + return (typename Unroll::VT{} + b) / a; +} + +template > +[[gnu::always_inline]] constexpr auto +loadunroll(const T *ptr, math::RowStride rowStride, std::array masks) + -> Unroll { + static constexpr auto W = ptrdiff_t(std::bit_ceil(size_t(N))); + auto rs = ptrdiff_t(rowStride); + Unroll ret; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r, ptr += rs) { + if constexpr (NM == 0) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + ret[r, c] = load(ptr + c * W, mask::None{}); + } else if constexpr (NM == C) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) ret[r, c] = load(ptr + c * W, masks[c]); + } else { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C - 1; ++c) + ret[r, c] = load(ptr + c * W, mask::None{}); + ret[r, C - 1] = load(ptr + (C - 1) * W, masks[0]); + } + } + return ret; +} +template > +[[gnu::always_inline]] constexpr auto +loadstrideunroll(const T *ptr, math::RowStride rowStride, + std::array masks) -> Unroll { + static constexpr auto W = ptrdiff_t(std::bit_ceil(size_t(N))); + Unroll ret; + auto s = int32_t(ptrdiff_t(rowStride)); + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r, ++ptr) { + if constexpr (NM == 0) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + ret[r, c] = load(ptr + c * W * s, mask::None{}, s); + } else if constexpr (NM == C) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + ret[r, c] = load(ptr + c * W * s, masks[c], s); + } else { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C - 1; ++c) + ret[r, c] = load(ptr + c * W * s, mask::None{}, s); + ret[r, C - 1] = load(ptr + (C - 1) * W * s, masks[0], s); + } + } + return ret; +} + +// Represents a reference for a SIMD load, in particular so that we can store. +// Needs to support masking +template , bool Transposed = false> +struct UnrollRef { + static constexpr ptrdiff_t W = ptrdiff_t(std::bit_ceil(size_t(N))); + static_assert(N == W || C == 1, + "If N != the next power of `2`, then `C` should be `1`"); + static_assert( + NM == 0 || NM == 1 || NM == C, + "Should have no masks, one mask for last `C`, or one mask per `C`"); + T *ptr; + [[no_unique_address]] math::RowStride rowStride; + [[no_unique_address]] std::array masks; + constexpr operator Unroll() { + if constexpr (!Transposed) + return loadunroll(ptr, rowStride, masks); + else return loadstrideunroll(ptr, rowStride, masks); + } + constexpr auto operator=(Unroll x) -> UnrollRef & + requires(!Transposed) + { + auto rs = ptrdiff_t(rowStride); + T *p = ptr; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r, p += rs) { + if constexpr (NM == 0) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + store(p + c * W, mask::None{}, x[r, c]); + } else if constexpr (NM == C) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + store(p + c * W, masks[c], x[r, c]); + } else { // NM == 1 + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C - 1; ++c) + store(p + c * W, mask::None{}, x[r, c]); + store(p + (C - 1) * W, masks[0], x[r, C - 1]); + } + } + return *this; + } + constexpr auto operator=(Vec v) -> UnrollRef & + requires(!Transposed) + { + auto rs = ptrdiff_t(rowStride); + T *p = ptr; + POLYMATHFULLUNROLL + for (ptrdiff_t r = 0; r < R; ++r, p += rs) { + if constexpr (NM == 0) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + store(p + c * W, mask::None{}, v); + } else if constexpr (NM == C) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) store(p + c * W, masks[c], v); + } else { // NM == 1 + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C - 1; ++c) + store(p + c * W, mask::None{}, v); + store(p + (C - 1) * W, masks[0], v); + } + } + return *this; + } + constexpr auto operator=(Unroll x) -> UnrollRef & + requires(Transposed) + { + auto s = int32_t(ptrdiff_t(rowStride)); + T *p = ptr; + for (ptrdiff_t r = 0; r < R; ++r, ++p) { + if constexpr (NM == 0) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + store(p + c * W * s, mask::None{}, x[0, c], s); + } else if constexpr (NM == C) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + store(p + c * W * s, masks[c], x[0, c], s); + } else { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C - 1; ++c) + store(p + c * W * s, mask::None{}, x[0, c], s); + store(p + (C - 1) * W * s, masks[0], x[0, C - 1], s); + } + } + return *this; + } + constexpr auto operator=(Vec v) -> UnrollRef & + requires(Transposed) + { + auto s = int32_t(ptrdiff_t(rowStride)); + T *p = ptr; + for (ptrdiff_t r = 0; r < R; ++r, ++p) { + if constexpr (NM == 0) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + store(p + c * W * s, mask::None{}, v, s); + } else if constexpr (NM == C) { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C; ++c) + store(p + c * W * s, masks[c], v, s); + } else { + POLYMATHFULLUNROLL + for (ptrdiff_t c = 0; c < C - 1; ++c) + store(p + c * W * s, mask::None{}, v, s); + store(p + (C - 1) * W * s, masks[0], v, s); + } + } + return *this; + } + constexpr auto operator=(std::convertible_to auto x) -> UnrollRef & { + *this = Vec{} + T(x); + return *this; + } + constexpr auto operator+=(const auto &x) -> UnrollRef & { + return (*this) = Unroll(*this) + x; + } + constexpr auto operator-=(const auto &x) -> UnrollRef & { + return (*this) = Unroll(*this) - x; + } + constexpr auto operator*=(const auto &x) -> UnrollRef & { + return (*this) = Unroll(*this) * x; + } + constexpr auto operator/=(const auto &x) -> UnrollRef & { + return (*this) = Unroll(*this) / x; + } +}; +template +[[gnu::always_inline]] constexpr auto +ref(const T *p, index::UnrollDims i) + -> Unroll { + if constexpr (Transposed) + return loadstrideunroll(p, i.rs, std::array{i.mask}); + else return loadunroll(p, i.rs, std::array{i.mask}); +} +template +[[gnu::always_inline]] constexpr auto +ref(T *p, index::UnrollDims i) + -> UnrollRef { + return {p, i.rs, std::array{i.mask}}; +} +namespace index { + +template +constexpr auto operator==(Unroll x, ptrdiff_t y) { + if constexpr (W == 1) { + poly::simd::Unroll ret; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) ret.data[u] = (x.index + u) == y; + return ret; + } else { + poly::simd::Unroll<1, U, W, int64_t> ret; + Vec v = Vec{} + y; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + ret.data[u] = range() == (v - u * W); + return ret; + } +} +template +constexpr auto operator!=(Unroll x, ptrdiff_t y) { + if constexpr (W == 1) { + poly::simd::Unroll ret; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) ret.data[u] = (x.index + u) != y; + return ret; + } else { + poly::simd::Unroll<1, U, W, int64_t> ret; + Vec v = Vec{} + y; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + ret.data[u] = range() != (v - u * W); + return ret; + } +} +template +constexpr auto operator<(Unroll x, ptrdiff_t y) { + if constexpr (W == 1) { + poly::simd::Unroll ret; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) ret.data[u] = (x.index + u) < y; + return ret; + } else { + poly::simd::Unroll<1, U, W, int64_t> ret; + Vec v = Vec{} + y; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + ret.data[u] = range() < (v - u * W); + return ret; + } +} +template +constexpr auto operator>(Unroll x, ptrdiff_t y) { + if constexpr (W == 1) { + poly::simd::Unroll ret; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) ret.data[u] = (x.index + u) > y; + return ret; + } else { + poly::simd::Unroll<1, U, W, int64_t> ret; + Vec v = Vec{} + y; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + ret.data[u] = range() > (v - u * W); + return ret; + } +} +template +constexpr auto operator<=(Unroll x, ptrdiff_t y) { + if constexpr (W == 1) { + poly::simd::Unroll ret; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) ret.data[u] = (x.index + u) <= y; + return ret; + } else { + poly::simd::Unroll<1, U, W, int64_t> ret; + Vec v = Vec{} + y; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + ret.data[u] = range() <= (v - u * W); + return ret; + } +} +template +constexpr auto operator>=(Unroll x, ptrdiff_t y) { + if constexpr (W == 1) { + poly::simd::Unroll ret; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) ret.data[u] = (x.index + u) >= y; + return ret; + } else { + poly::simd::Unroll<1, U, W, int64_t> ret; + Vec v = Vec{} + y; + POLYMATHFULLUNROLL + for (ptrdiff_t u = 0; u < U; ++u) + ret.data[u] = range() >= (v - u * W); + return ret; + } +} + +} // namespace index + +} // namespace poly::simd +#endif // Unroll_hpp_INCLUDED diff --git a/include/SIMD/Vec.hpp b/include/SIMD/Vec.hpp new file mode 100644 index 0000000..25f887e --- /dev/null +++ b/include/SIMD/Vec.hpp @@ -0,0 +1,14 @@ +#pragma once +#ifndef MATH_SIMD_VEC_HPP_INCLUDED +#define MATH_SIMD_VEC_HPP_INCLUDED + +namespace poly::simd { +template +using Vec_ [[gnu::vector_size(W * sizeof(T))]] = T; + +template +using Vec = std::conditional_t>; + +} // namespace poly::simd + +#endif diff --git a/include/Utilities/Assign.hpp b/include/Utilities/Assign.hpp new file mode 100644 index 0000000..6a0e574 --- /dev/null +++ b/include/Utilities/Assign.hpp @@ -0,0 +1,56 @@ +#pragma once +#ifndef POLY_UTILITIES_Assign_hpp_INCLUDED +#define POLY_UTILITIES_Assign_hpp_INCLUDED +#include +#include +#include +namespace poly::utils { + +struct CopyAssign {}; +struct NoRowIndex {}; + +template +[[gnu::always_inline]] constexpr void assign(D &&d, const S &s, Op op) { + if constexpr (std::same_as) d = s; + else if constexpr (std::same_as>) d += s; + else if constexpr (std::same_as>) d -= s; + else if constexpr (std::same_as>) d *= s; + else if constexpr (std::same_as>) d /= s; + else d = op(d, s); +} + +template +[[gnu::always_inline]] constexpr void assign(D &d, const S &s, R r, C c, + Op op) { + constexpr bool norowind = std::same_as; + if constexpr (std::convertible_to>) + if constexpr (norowind) assign(d[c], s, op); + else assign(d[r, c], s, op); + else if constexpr (math::RowVector) + if constexpr (norowind) assign(d[c], s[c], op); + else assign(d[r, c], s[c], op); + else if constexpr (math::ColVector) + if constexpr (norowind) assign(d[c], s[c], op); + else assign(d[r, c], s[r], op); + else if constexpr (std::same_as) + if constexpr (norowind) d[c] = s[c]; + else d[r, c] = s[r, c]; + else if constexpr (std::same_as>) + if constexpr (norowind) d[c] += s[c]; + else d[r, c] += s[r, c]; + else if constexpr (std::same_as>) + if constexpr (norowind) d[c] -= s[c]; + else d[r, c] -= s[r, c]; + else if constexpr (std::same_as>) + if constexpr (norowind) d[c] *= s[c]; + else d[r, c] *= s[r, c]; + else if constexpr (std::same_as>) + if constexpr (norowind) d[c] /= s[c]; + else d[r, c] /= s[r, c]; + else if constexpr (norowind) d[c] = op(const_cast(d)[c], s[c]); + else d[r, c] = op(const_cast(d)[r, c], s[r, c]); +} + +} // namespace poly::utils + +#endif // Assign_hpp_INCLUDED diff --git a/include/Utilities/LoopMacros.hpp b/include/Utilities/LoopMacros.hpp new file mode 100644 index 0000000..36a52b1 --- /dev/null +++ b/include/Utilities/LoopMacros.hpp @@ -0,0 +1,38 @@ +#pragma once +#ifndef LoopMacros_hpp_INCLUDED +#define LoopMacros_hpp_INCLUDED + +// clang-format off + +#if !defined(__clang__) && defined(__GNUC__) +#define POLYMATHVECTORIZE _Pragma("GCC ivdep") +#define POLYMATHIVDEP _Pragma("GCC ivdep") +#define POLYMATHNOUNROLL _Pragma("GCC unroll 0") +#define POLYMATHFULLUNROLL _Pragma("GCC unroll 16") +#if __GNUC__ >= 14 +#define POLYMATHNOVECTORIZE _Pragma("GCC novector") +#else +#define POLYMATHNOVECTORIZE +#endif +#define POLYMATHFAST +// #define POLYMATHVECTORIZE _Pragma("GCC unroll 2") _Pragma("GCC ivdep") +#elif defined (__clang__) +#define POLYMATHVECTORIZE _Pragma("omp simd")\ + _Pragma("clang loop vectorize(enable) interleave_count(2) vectorize_predicate(enable)") +#define POLYMATHIVDEP +// _Pragma("clang loop vectorize(disable)") +#define POLYMATHNOUNROLL _Pragma("nounroll") +#define POLYMATHFULLUNROLL _Pragma("unroll") +#define POLYMATHNOVECTORIZE _Pragma("clang loop vectorize(disable)") +#define POLYMATHFAST _Pragma("clang fp reassociate(on) contract(fast)") +#else +#define POLYMATHVECTORIZE +#define POLYMATHIVDEP +#define POLYMATHFULLUNROLL +#define POLYMATHNOUNROLL +#define POLYMATHNOVECTORIZE +#define POLYMATHFAST +#endif + +// clang-format on +#endif // LoopMacros_hpp_INCLUDED diff --git a/include/Utilities/Reference.hpp b/include/Utilities/Reference.hpp new file mode 100644 index 0000000..5081fe9 --- /dev/null +++ b/include/Utilities/Reference.hpp @@ -0,0 +1,190 @@ +#pragma once +#include "Utilities/TypeCompression.hpp" + +namespace poly::utils { +template struct Reference { + using C = utils::compressed_t; + static_assert(!std::same_as); + C *c; + constexpr operator T() const { return T::decompress(c); } + constexpr auto view() const -> T { return T::decompress(c); } + // constexpr operator T &() const { return *t; } + constexpr auto operator=(const T &t) -> Reference & { + t.compress(c); + return *this; + } + constexpr auto operator=(const C &x) -> Reference & { + // Probably shouldn't be needed? + // TODO: try removing this method + *c = x; + return *this; + } + constexpr auto operator==(const T &t) const -> bool { + return T::decompress(c) == t; + } + [[gnu::always_inline]] constexpr auto operator+=(const auto &x) { + T y{T::decompress(c)}; + y += x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator-=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y -= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator*=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y *= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator/=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y /= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator%=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y %= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator<<=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y <<= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator>>=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y >>= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator&=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y &= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator^=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y ^= x; + y.compress(c); + return y; + // return *this; + } + [[gnu::always_inline]] constexpr auto operator|=(const auto &x) { + // -> Reference & { + T y{T::decompress(c)}; + y |= x; + y.compress(c); + return y; + // return *this; + } + + constexpr auto operator[](auto i) -> decltype(auto) { + return c->operator[](i); + } + constexpr auto operator[](auto i) const -> decltype(auto) { + return c->operator[](i); + } + constexpr auto operator[](auto i, auto j) -> decltype(auto) { + return c->operator[](i, j); + } + constexpr auto operator[](auto i, auto j) const -> decltype(auto) { + return c->operator[](i, j); + } + + // TODO:: are these really needed / can we rely on implicit conversion? + constexpr auto operator+(const auto &x) { return T::decompress(c) + x; } + constexpr auto operator-(const auto &x) { return T::decompress(c) - x; } + constexpr auto operator*(const auto &x) { return T::decompress(c) * x; } + constexpr auto operator/(const auto &x) { return T::decompress(c) / x; } + constexpr auto operator%(const auto &x) { return T::decompress(c) % x; } + constexpr auto operator>>(const auto &x) { return T::decompress(c) >> x; } + constexpr auto operator<<(const auto &x) { return T::decompress(c) << x; } + constexpr auto operator&(const auto &x) { return T::decompress(c) & x; } + constexpr auto operator^(const auto &x) { return T::decompress(c) ^ x; } + constexpr auto operator|(const auto &x) { return T::decompress(c) | x; } + + friend constexpr auto operator+(const auto &x, Reference y) { + return x + T::decompress(y.c); + } + friend constexpr auto operator-(const auto &x, Reference y) { + return x - T::decompress(y.c); + } + friend constexpr auto operator*(const auto &x, Reference y) { + return x * T::decompress(y.c); + } + friend constexpr auto operator/(const auto &x, Reference y) { + return x / T::decompress(y.c); + } + friend constexpr auto operator%(const auto &x, Reference y) { + return x % T::decompress(y.c); + } + friend constexpr auto operator>>(const auto &x, Reference y) { + return x >> T::decompress(y.c); + } + friend constexpr auto operator<<(const auto &x, Reference y) { + return x << T::decompress(y.c); + } + friend constexpr auto operator&(const auto &x, Reference y) { + return x & T::decompress(y.c); + } + friend constexpr auto operator^(const auto &x, Reference y) { + return x ^ T::decompress(y.c); + } + friend constexpr auto operator|(const auto &x, Reference y) { + return x | T::decompress(y.c); + } +}; + +template +[[gnu::always_inline]] constexpr auto ref(T *p, ptrdiff_t i) -> T & { + return p[i]; +} +template +[[gnu::always_inline]] constexpr auto ref(const T *p, ptrdiff_t i) + -> const T & { + return p[i]; +} +template +[[gnu::always_inline]] constexpr auto ref(utils::compressed_t *p, + ptrdiff_t i) -> Reference { + return Reference{p + i}; +} + +template +[[gnu::always_inline]] constexpr auto ref(const utils::compressed_t *p, + ptrdiff_t i) -> T { + return T::decompress(p + i); +} + +} // namespace poly::utils + +namespace std { +template +constexpr void swap(poly::utils::Reference x, poly::utils::Reference y) { + std::swap(*x.c, *y.c); +} +} // namespace std diff --git a/include/Utilities/TypeCompression.hpp b/include/Utilities/TypeCompression.hpp new file mode 100644 index 0000000..42a9b69 --- /dev/null +++ b/include/Utilities/TypeCompression.hpp @@ -0,0 +1,69 @@ +#pragma once + +namespace poly::utils { + +/// The idea here is that some types may have a compression/decompression that +/// is potentially costly. To work around this, temporaries can live in +/// uncompressed form, while longer term storage can be compressed/decompressed. +/// E.g., we have have an array of a compressed type. +/// When loading, the uncompressed form is returned. +/// The particular motivating example is around using SIMD types with arrays +/// that are themselves not a perfect multiple of the SIMD-width. +/// Writing/reading from temporary locations thus requires masking. For +/// compilers to be able to optimize these loads and stores, they'd have need to +/// track provenance using these masks to see that they don't alias, and be able +/// to actually eliminate the temporaries. Compilers do not seem to do this. +/// +/// The canonical type is the decompressed form. +/// + +/// `T` is the canonical type, which may define `compress` +template +concept Compressible = + (!std::same_as)&&requires( + T t, typename T::compressed_type *p) { + { t.compress(p) }; + { T::decompress(p) } -> std::same_as; + { t = *p }; // need generic code to work reasonably well with pointers `p` + { T{*p} }; // and value_type `T` + }; + +template struct Uncompressed { + using compressed = T; +}; +template struct Uncompressed { + using compressed = typename T::compressed_type; +}; +template +using compressed_t = typename Uncompressed>::compressed; + +template +concept Decompressible = + Compressible && + std::same_as>; + +template struct Compressed { + using uncompressed = T; +}; +template struct Compressed { + using uncompressed = typename T::decompressed_type; +}; +template +using decompressed_t = + typename Compressed>::uncompressed; + +static_assert(std::same_as, double>); +static_assert(!Decompressible); +static_assert(!Compressible); + +template constexpr void compress(const T &x, compressed_t *p) { + if constexpr (Compressible) x.compress(p); + else *p = x; +} +template +constexpr auto decompress(const compressed_t *p) -> decltype(auto) { + if constexpr (Compressible) return T::decompress(p); + else return *p; +} + +} // namespace poly::utils diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index b072321..b396473 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,14 +1,9 @@ cmake_minimum_required(VERSION 3.14) -# # ---- Static Analyzers ---- -# find_program(CLANGTIDY clang-tidy) -# if(NOT CLANGTIDY MATCHES CLANGTIDY-NOTFOUND) -# set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY}) -# endif() -# find_program(CPPCHECK cppcheck) -# if(NOT CPPCHECK MATCHES CPPCHECK-NOTFOUND) -# set(CMAKE_CXX_CPPCHECK "${CPPCHECK} --language=c++ --enable=warning,style,performance,information") -# endif() +# # ---- Static Analyzers ---- find_program(CLANGTIDY clang-tidy) if(NOT CLANGTIDY MATCHES +# CLANGTIDY-NOTFOUND) set(CMAKE_CXX_CLANG_TIDY ${CLANGTIDY}) endif() find_program(CPPCHECK cppcheck) +# if(NOT CPPCHECK MATCHES CPPCHECK-NOTFOUND) set(CMAKE_CXX_CPPCHECK "${CPPCHECK} --language=c++ +# --enable=warning,style,performance,information") endif() project(MathTests LANGUAGES CXX) @@ -31,9 +26,12 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if(((USE_SANITIZER MATCHES "([Aa]ddress)") OR (USE_SANITIZER MATCHES "([Aa]ddress);([Uu]ndefined)")) AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang") ) - find_library(LUNWIND_LIB lunwind) + find_library(LUNWIND_LIB unwind) + message(STATUS "Found unwindlib ${LUNWIND_LIB}") if(LUNWIND_LIB) - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lunwind -Wno-unused-command-line-argument") + set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -lunwind -Wno-unused-command-line-argument" + ) endif() endif() diff --git a/test/dual_test.cpp b/test/dual_test.cpp index 8d566d9..43b84e2 100644 --- a/test/dual_test.cpp +++ b/test/dual_test.cpp @@ -22,11 +22,11 @@ TEST(DualTest, BasicAssertions) { Vector x(15); for (auto &a : A) a = dist(gen); for (auto &xx : x) xx = dist(gen); - SquareMatrix B = A + A.transpose(); + SquareMatrix B = A + A.t(); const auto halfquadform = [&](const auto &y) { - return 0.5 * (transpose(y) * (B * y)); + return 0.5 * ((y * B) * transpose(y)); }; - Vector g = B * x; + Vector g = x * B; auto f = halfquadform(x); auto [fx, gx] = gradient(&arena, x, halfquadform); @@ -43,27 +43,12 @@ TEST(DualTest, BasicAssertions) { EXPECT_TRUE(norm2(B - hxx) < 1e-10); }; -constexpr ptrdiff_t L = 16; template -constexpr auto evalpoly(MutSquarePtrMatrix C, const auto &p) { - using U = eltype_t; - using S = SquareMatrix; - assert(C.numRow() == C.numCol()); - S B{SquareDims{C.numRow()}}; - evalpoly(B, C, p); - return B; -} -template -constexpr void evalpoly(MutSquarePtrMatrix B, SquarePtrMatrix C, - const auto &p) { - using S = SquareMatrix; +constexpr void evalpoly(MutSquarePtrMatrix B, MutSquarePtrMatrix A, + SquarePtrMatrix C, const auto &p) { ptrdiff_t N = p.size(); invariant(N > 0); - invariant(ptrdiff_t(C.numRow()), ptrdiff_t(C.numCol())); - invariant(ptrdiff_t(B.numRow()), ptrdiff_t(B.numCol())); invariant(ptrdiff_t(B.numRow()), ptrdiff_t(C.numRow())); - S Atm{SquareDims{N == 2 ? Row<>{0} : B.numRow()}}; - MutSquarePtrMatrix A{Atm}; if (N & 1) std::swap(A, B); B << p[0] * C + p[1] * I; for (ptrdiff_t i = 2; i < N; ++i) { @@ -73,18 +58,17 @@ constexpr void evalpoly(MutSquarePtrMatrix B, SquarePtrMatrix C, } template constexpr auto opnorm1(const T &A) { - using S = decltype(extractDualValRecurse(std::declval>())); - ptrdiff_t n = ptrdiff_t(A.numRow()); - invariant(n > 0); - Vector v; - v.resizeForOverwrite(n); - invariant(A.numRow() > 0); - for (ptrdiff_t j = 0; j < n; ++j) - v[j] = std::abs(extractDualValRecurse(A[0, j])); - for (ptrdiff_t i = 1; i < n; ++i) - for (ptrdiff_t j = 0; j < n; ++j) - v[j] += std::abs(extractDualValRecurse(A[i, j])); - return *std::max_element(v.begin(), v.end()); + using S = decltype(value(std::declval>())); + auto [M, N] = shape(A); + invariant(M > 0); + invariant(N > 0); + S a{}; + for (ptrdiff_t n = 0; n < N; ++n) { + S s{}; + for (ptrdiff_t m = 0; m < M; ++m) s += std::abs(value(A[m, n])); + a = std::max(a, s); + } + return a; } /// computes ceil(log2(x)) for x >= 1 @@ -94,66 +78,61 @@ constexpr auto log2ceil(double x) -> unsigned { return (u >> 52) - 1022; } -template -constexpr void expm(MutSquarePtrMatrix V, SquarePtrMatrix A) { - invariant(ptrdiff_t(V.numRow()), ptrdiff_t(A.numRow())); - ptrdiff_t n = ptrdiff_t(A.numRow()); - auto nA = opnorm1(A); - SquareMatrix prodA{A * A}, Utm{SquareDims<>{{n}}}; - MutSquarePtrMatrix A2{prodA}, U{Utm}; - unsigned int s = 0; - if (nA <= 2.1) { - poly::containers::TinyVector p0, p1; - if (nA > 0.95) { - p0 = {1.0, 3960.0, 2162160.0, 302702400.0, 8821612800.0}; - p1 = {90.0, 110880.0, 3.027024e7, 2.0756736e9, 1.76432256e10}; - } else if (nA > 0.25) { - p0 = {1.0, 1512.0, 277200.0, 8.64864e6}; - p1 = {56.0, 25200.0, 1.99584e6, 1.729728e7}; - } else if (nA > 0.015) { - p0 = {1.0, 420.0, 15120.0}; - p1 = {30.0, 3360.0, 30240.0}; - } else { - p0 = {1.0, 60.0}; - p1 = {12.0, 120.0}; - } - evalpoly(V, A2, p0); - U << A * V; - evalpoly(V, A2, p1); +template constexpr void expmimpl(MutSquarePtrMatrix A) { + ptrdiff_t n = ptrdiff_t(A.numRow()), s = 0; + SquareMatrix A2{SquareDims<>{{n}}}, U_{SquareDims<>{{n}}}; + MutSquarePtrMatrix U{U_}; + if (double nA = opnorm1(A); nA <= 0.015) { + A2 << A * A; + U << A * (A2 + 60.0 * I); + A << 12.0 * A2 + 120.0 * I; } else { - // s = std::max(unsigned(std::ceil(std::log2(nA / 5.4))), unsigned(0)); - s = nA > 5.4 ? log2ceil(nA / 5.4) : unsigned(0); - double t = 1.0; - if (s > 0) { - t = 1.0 / poly::math::exp2(s); - A2 *= (t * t); - if (s & 1) std::swap(U, V); + SquareMatrix B{SquareDims<>{{n}}}; + if (nA <= 2.1) { + A2 << A * A; + poly::containers::TinyVector p0, p1; + if (nA > 0.95) { + p0 = {1.0, 3960.0, 2162160.0, 302702400.0, 8821612800.0}; + p1 = {90.0, 110880.0, 3.027024e7, 2.0756736e9, 1.76432256e10}; + } else if (nA > 0.25) { + p0 = {1.0, 1512.0, 277200.0, 8.64864e6}; + p1 = {56.0, 25200.0, 1.99584e6, 1.729728e7}; + } else { + p0 = {1.0, 420.0, 15120.0}; + p1 = {30.0, 3360.0, 30240.0}; + } + evalpoly(B, U, A2, p0); + U << A * B; + evalpoly(A, B, A2, p1); + } else { + // s = std::max(unsigned(std::ceil(std::log2(nA / 5.4))), 0); + s = nA > 5.4 ? log2ceil(nA / 5.4) : 0; + if (s & 1) { // we'll swap `U` and `A` an odd number of times + std::swap(A, U); // so let them switch places + A << U * exp2(-s); + } else if (s > 0) A *= exp2(-s); + A2 << A * A; + // here we take an estrin (instead of horner) approach to cut down flops + SquareMatrix A4{A2 * A2}, A6{A2 * A4}; + B << A6 * (A6 + 16380 * A4 + 40840800 * A2) + + (33522128640 * A6 + 10559470521600 * A4 + 1187353796428800 * A2) + + 32382376266240000 * I; + U << A * B; + A << A6 * (182 * A6 + 960960 * A4 + 1323241920 * A2) + + (670442572800 * A6 + 129060195264000 * A4 + + 7771770303897600 * A2) + + 64764752532480000 * I; } - SquareMatrix A4{A2 * A2}, A6{A2 * A4}; - - V << A6 * (A6 + 16380 * A4 + 40840800 * A2) + - (33522128640 * A6 + 10559470521600 * A4 + 1187353796428800 * A2) + - 32382376266240000 * I; - U << A * V; - if (s > 0) U *= t; - V << A6 * (182 * A6 + 960960 * A4 + 1323241920 * A2) + - (670442572800 * A6 + 129060195264000 * A4 + 7771770303897600 * A2) + - 64764752532480000 * I; - } - for (auto v = V.begin(), u = U.begin(), e = V.end(); v != e; ++v, ++u) { - auto &&d = *v - *u; - *v += *u; - *u = d; - } - LU::ldiv(U, MutPtrMatrix(V)); - for (; s--;) { - U << V * V; - std::swap(U, V); } + poly::containers::tie(A, U) << poly::containers::Tuple(A + U, A - U); + LU::ldiv(U, MutPtrMatrix(A)); + for (; s--; std::swap(A, U)) U << A * A; } + template constexpr auto expm(SquarePtrMatrix A) { - SquareMatrix V{SquareDims{A.numRow()}}; - expm(V, A); + SquareMatrix V{SquareDims{A.numRow()}}; + V << A; + expmimpl(V); return V; } constexpr auto dualDeltaCmp(double x, double y) -> bool { return x < y; } @@ -167,7 +146,7 @@ constexpr auto dualDeltaCmp(Dual x, double y) -> bool { // NOLINTNEXTLINE(modernize-use-trailing-return-type) TEST(ExpMatTest, BasicAssertions) { - SquareMatrix A(4); + SquareMatrix A(4); A[0, 0] = 0.13809508135032297; A[0, 1] = -0.10597225613986219; A[0, 2] = -0.5623996136438215; @@ -184,7 +163,7 @@ TEST(ExpMatTest, BasicAssertions) { A[3, 1] = 0.6550780207685463; A[3, 2] = -0.6227535845719466; A[3, 3] = 0.2280514374580733; - SquareMatrix B(4); + SquareMatrix B(4); B[0, 0] = 0.2051199361909877; B[0, 1] = -0.049831094437687434; B[0, 2] = -0.3980657896416266; @@ -201,9 +180,10 @@ TEST(ExpMatTest, BasicAssertions) { B[3, 1] = 0.4472989810307132; B[3, 2] = -0.11106692926404803; B[3, 3] = 0.3930685232252409; - EXPECT_TRUE(norm2(B - expm(A)) < 1e-10); + EXPECT_LE(norm2(B - expm(A)), 1e-10); - SquareMatrix, L> Ad(4); + static_assert(poly::utils::Compressible>); + SquareMatrix> Ad(4); Ad[0, 0] = Dual{ 0.13809508135032297, SVector{0.23145585885555967, 0.6736099502056541}}; @@ -252,7 +232,7 @@ TEST(ExpMatTest, BasicAssertions) { Ad[3, 3] = Dual{ 0.2280514374580733, SVector{-1.2001994532706792, 0.03274459682369542}}; - SquareMatrix, L> Bd(4); + SquareMatrix> Bd(4); Bd[0, 0] = Dual{ 0.20511993619098767, SVector{0.09648410552837837, -2.2538795735050865}}; diff --git a/test/linear_algebra_test.cpp b/test/linear_algebra_test.cpp index 59beaf4..215eef3 100644 --- a/test/linear_algebra_test.cpp +++ b/test/linear_algebra_test.cpp @@ -38,12 +38,12 @@ TEST(LinearAlgebraTest, BasicAssertions) { auto copyB = B; EXPECT_FALSE(LUF.ldivrat(copyB)); std::cout << "LUF.ldiv(B) = \n" << copyB << "\n"; - EXPECT_TRUE(copyB == identity); + EXPECT_EQ(copyB, identity); std::cout << "I = " << identity << "\n"; EXPECT_FALSE(LUF.rdivrat(B)); std::cout << "LUF.rdiv(B) = \n" << B << "\n"; - EXPECT_TRUE(B == identity); + EXPECT_EQ(B, identity); } // NOLINTNEXTLINE(modernize-use-trailing-return-type) @@ -59,23 +59,23 @@ TEST(DoubleFactorization, BasicAssertions) { // B = A \ B // C == A*B == A * (A \ B) LU::fact(A).ldiv(MutPtrMatrix(B)); - EXPECT_TRUE(norm2(A * B - C) < 1e-10); + EXPECT_LT(norm2(A * B - C), 1e-10); B << C; D << A; LU::ldiv(A, MutPtrMatrix(B)); - EXPECT_TRUE(norm2(D * B - C) < 1e-10); + EXPECT_LT(norm2(D * B - C), 1e-10); // LDL; make `A` symmetric - D << A + A.transpose(); + D << A + A.t(); A << D; B << C; // B = A \ B // C == A*B == A * (A \ B) LDL::factorize<>(D).ldiv(MutPtrMatrix(B)); - EXPECT_TRUE(norm2(A * B - C) < 1e-10); + EXPECT_LT(norm2(A * B - C), 1e-10); B << C; D << A; LDL::ldiv<>(A, MutPtrMatrix(B)); - EXPECT_TRUE(norm2(D * B - C) < 1e-10); + EXPECT_LT(norm2(D * B - C), 1e-10); } } diff --git a/test/matrix_test.cpp b/test/matrix_test.cpp index 94683c3..12d86d1 100644 --- a/test/matrix_test.cpp +++ b/test/matrix_test.cpp @@ -80,19 +80,20 @@ TEST(SparseIndexingTest, BasicAssertions) { IntMatrix<> C2{A * B}; std::cout << "C=" << C << "\nC2=" << C2 << "\n"; EXPECT_TRUE(C == C2); - IntMatrix<> At{A.transpose()}, Bt{B.transpose()}; - // At << A.transpose(); - // Bt << B.transpose(); - C2 += At.transpose() * Bt.transpose(); - EXPECT_TRUE(C * 2 == C2); - EXPECT_TRUE(C == At.transpose() * B); - EXPECT_TRUE(C == A * Bt.transpose()); - EXPECT_TRUE(C == At.transpose() * Bt.transpose()); - C2 -= A * Bt.transpose(); - EXPECT_TRUE(C == C2); + IntMatrix<> At{A.t()}, Bt{B.t()}; + // At << A.t(); + // Bt << B.t(); + C2 += At.t() * Bt.t(); + EXPECT_EQ(C * 2, C2); + EXPECT_EQ(C, At.t() * B); + EXPECT_EQ(C, A * Bt.t()); + EXPECT_EQ(C, At.t() * Bt.t()); + C2 -= A * Bt.t(); + EXPECT_EQ(C, C2); int64_t i = 0; IntMatrix<> D{C}; std::cout << "C=" << C << "\n"; + static_assert(std::same_as>); for (ptrdiff_t r : _(0, D.numRow())) D[r, _] += ptrdiff_t(r) + 1; for (auto r : C.eachRow()) { EXPECT_EQ(r.size(), ptrdiff_t(C.numCol())); @@ -172,6 +173,53 @@ TEST(ExpressionTemplateTest, BasicAssertions) { for (ptrdiff_t k = 0; k < i; ++k) EXPECT_EQ((F[j, k]), k + j == i - 1); } } +// NOLINTNEXTLINE(modernize-use-trailing-return-type) +TEST(ExpressionTemplateTest2, BasicAssertions) { + ManagedArray> W{{{3}, {3}}, 0}, X{{{3}, {3}}, 0}, + Y{{{3}, {3}}, 0}, Z{{{3}, {3}}, 0}; + W[0, 0] = 0.29483432115939806; + W[0, 1] = 1.5777027461040212; + W[0, 2] = 0.8171761007267028; + W[1, 0] = 1.0463632179853855; + W[1, 1] = 0.9503214631611095; + W[1, 2] = -0.17890983978584624; + W[2, 0] = 1.5853551451194254; + W[2, 1] = -0.784875301203305; + W[2, 2] = 1.7033024094365752; + X[0, 0] = -1.1175097244313117; + X[0, 1] = -0.21769215316295054; + X[0, 2] = -0.7340630927749082; + X[1, 0] = -0.5750426169922397; + X[1, 1] = 0.27174064995044767; + X[1, 2] = -1.0669896577273217; + X[2, 0] = 0.9302424251181362; + X[2, 1] = -1.3157431480603476; + X[2, 2] = 1.546836705770486; + Y[0, 0] = 1.1701212478097331; + Y[0, 1] = 0.7747688878004019; + Y[0, 2] = -0.926815554991563; + Y[1, 0] = -1.4441713498640656; + Y[1, 1] = -1.3615487160168993; + Y[1, 2] = 0.7908183008408143; + Y[2, 0] = -0.7626497248468547; + Y[2, 1] = -0.21682371102755368; + Y[2, 2] = -0.07604892144743511; + Z[0, 0] = 3.3759933640164708e16; + Z[0, 1] = 9.176788687153845e14; + Z[0, 2] = -1.1081818546676994e15; + Z[1, 0] = -1.7207794047001762e15; + Z[1, 1] = 3.0768637505289172e16; + Z[1, 2] = 9.277082601207064e14; + Z[2, 0] = -8.956589651911538e14; + Z[2, 1] = -2.7136623944168075e14; + Z[2, 2] = 3.2308470074953084e16; + ManagedArray> A{ + W * (W + 16380 * X + 40840800 * Y) + + (33522128640 * W + 10559470521600 * X + 1187353796428800 * Y) + + 32382376266240000 * I}; + + EXPECT_EQ(A, Z); +} // NOLINTNEXTLINE(modernize-use-trailing-return-type) TEST(ArrayPrint, BasicAssertions) { @@ -208,7 +256,7 @@ TEST(SquareMatrixTest, BasicAssertions) { for (ptrdiff_t i = 0; i < 4; ++i) for (ptrdiff_t j = 0; j < 4; ++j) A[i, j] = 4 * i + j; DenseMatrix B{DenseDims<>{{4}, {2}}}; - B << A[_(end - 2, end), _].transpose(); + B << A[_(end - 2, end), _].t(); for (ptrdiff_t j = 0; j < 4; ++j) for (ptrdiff_t i = 0; i < 2; ++i) EXPECT_EQ((B[j, i]), 4 * (i + 2) + j); } @@ -225,6 +273,7 @@ TEST(VectorTest, BasicAssertions) { } TEST(SVectorTest, BasicAssertions) { SVector x{1, 2, 3}; + static_assert(poly::utils::Compressible>); static_assert(std::tuple_size_v == 3); static_assert(std::same_as, int64_t>); SVector y{10, 20, 30}; diff --git a/test/normal_form_test.cpp b/test/normal_form_test.cpp index bd33c43..300f684 100644 --- a/test/normal_form_test.cpp +++ b/test/normal_form_test.cpp @@ -122,7 +122,7 @@ TEST(OrthogonalizationTest, BasicAssertions) { } auto isHNF(PtrMatrix A) -> bool { - const auto [M, N] = A.size(); + const auto [M, N] = shape(A); // l is lead Col<> l = {0}; for (ptrdiff_t m = 0; m < M; ++m) { diff --git a/test/simplex_test.cpp b/test/simplex_test.cpp index 58f1d80..5a998e6 100644 --- a/test/simplex_test.cpp +++ b/test/simplex_test.cpp @@ -14,6 +14,7 @@ TEST(SimplexTest, BasicAssertions) { // 15 >= 2x + 5y + 3z IntMatrix<> A{"[10 3 2 1; 15 2 5 3]"_mat}; IntMatrix<> B{DenseDims<>{{0}, {4}}}; + IntMatrix<> D{"[0 0 0 -2 -3 -4; 10 1 0 3 2 1; 15 0 1 2 5 3 ]"_mat}; OwningArena<> alloc; Optional optS0{Simplex::positiveVariables(&alloc, A)}; EXPECT_TRUE(optS0.hasValue()); @@ -32,6 +33,7 @@ TEST(SimplexTest, BasicAssertions) { C[4] = -3; C[5] = -4; std::cout << "S.tableau =" << S->getTableau() << "\n"; + EXPECT_EQ(S->getTableau(), D); EXPECT_EQ(S->run(), 20); } } @@ -116,7 +118,14 @@ auto simplexFromTableau(Arena<> *alloc, IntMatrix<> &tableau) ptrdiff_t numCon = ptrdiff_t(tableau.numRow()) - 1; ptrdiff_t numVar = ptrdiff_t(tableau.numCol()) - 1; Simplex *simp{Simplex::create(alloc, numCon, numVar)}; + for (ptrdiff_t r = 0, R = ptrdiff_t(numRows(tableau)); r < R; ++r) + for (ptrdiff_t c = 0, N = ptrdiff_t(numCols(tableau)); c < N; ++c) + invariant(tableau[r, c] != std::numeric_limits::min()); simp->getTableau() << tableau; + auto C{simp->getConstraints()}; + for (ptrdiff_t r = 0, R = ptrdiff_t(numRows(C)); r < R; ++r) + for (ptrdiff_t c = 0, N = ptrdiff_t(numCols(C)); c < N; ++c) + invariant(C[r, c] != std::numeric_limits::min()); return simp; } @@ -1344,7 +1353,7 @@ TEST(LexMinSimplexTest2, BasicAssertions) { } } -TEST(Infesaible, BasicAssertions) { +TEST(Infeasible, BasicAssertions) { IntMatrix<> C{DenseDims<>{{220}, {383}}, 0}; C[0, 0] = -1; C[0, 1] = 1; diff --git a/test/tuple_test.cpp b/test/tuple_test.cpp new file mode 100644 index 0000000..de6d5c9 --- /dev/null +++ b/test/tuple_test.cpp @@ -0,0 +1,56 @@ + +#include "Containers/Tuple.hpp" +#include +#include +#include + +using poly::containers::Tuple, poly::containers::tie; + +// NOLINTNEXTLINE(modernize-use-trailing-return-type) +TEST(TupleTest, BasicAssertions) { + double x = 2.3; + double y = 4.5; + long z = -5; + ulong w = 15; + Tuple t{w, x, y, z}; + { + auto [a, b, c, d] = t; + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + EXPECT_EQ(a, w); + EXPECT_EQ(b, x); + EXPECT_EQ(c, y); + EXPECT_EQ(d, z); + } + Tuple t1 = t.map([](auto arg) { return 3 * arg; }); + { + auto [a, b, c, d] = t1; + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + EXPECT_EQ(a, 3 * w); + EXPECT_EQ(b, 3 * x); + EXPECT_EQ(c, 3 * y); + EXPECT_EQ(d, 3 * z); + } + t1.apply([](auto &arg) { arg *= 2; }); + { + auto [a, b, c, d] = t1; + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + static_assert(std::same_as); + EXPECT_EQ(a, 6 * w); + EXPECT_EQ(b, 6 * x); + EXPECT_EQ(c, 6 * y); + EXPECT_EQ(d, 6 * z); + tie(w, x, y, z) = t1; + EXPECT_EQ(a, w); + EXPECT_EQ(b, x); + EXPECT_EQ(c, y); + EXPECT_EQ(d, z); + } +}