From 126e170804fc2986dbe1b4ea3b31e2b442b1fa44 Mon Sep 17 00:00:00 2001 From: Sylvain Joube Date: Sun, 15 Sep 2024 17:52:48 +0200 Subject: [PATCH] Algorithms : reduce --- include/kwk/algorithm/algos/reduce.hpp | 38 ++- test/algorithm/algos/context/cpu/reduce.cpp | 84 ++++++ .../algos/context/generic/reduce.hpp | 276 ++++++++++++++++++ test/algorithm/algos/reduce.cpp | 259 ---------------- test/algorithm/algos/reduce/1d.cpp | 53 ++++ test/algorithm/algos/reduce/2d.cpp | 55 ++++ test/algorithm/algos/reduce/4d.cpp | 59 ++++ 7 files changed, 558 insertions(+), 266 deletions(-) create mode 100644 test/algorithm/algos/context/cpu/reduce.cpp create mode 100644 test/algorithm/algos/context/generic/reduce.hpp delete mode 100644 test/algorithm/algos/reduce.cpp create mode 100644 test/algorithm/algos/reduce/1d.cpp create mode 100644 test/algorithm/algos/reduce/2d.cpp create mode 100644 test/algorithm/algos/reduce/4d.cpp diff --git a/include/kwk/algorithm/algos/reduce.hpp b/include/kwk/algorithm/algos/reduce.hpp index 1d77e5a8..8c502b43 100644 --- a/include/kwk/algorithm/algos/reduce.hpp +++ b/include/kwk/algorithm/algos/reduce.hpp @@ -1,13 +1,14 @@ -//================================================================================================== +//====================================================================================================================== /** KIWAKU - Containers Well Made Copyright : KIWAKU Project Contributors SPDX-License-Identifier: BSL-1.0 **/ -//================================================================================================== +//====================================================================================================================== #pragma once #include +#include #include #include #include @@ -22,22 +23,45 @@ min, max, minmax -> valeurs namespace kwk { + + // Reduce is not a required part of Contexts (unlike map) + // A custom overloaded reduce(my_context, ...) is required to use a custom context. + template + constexpr auto reduce(Context& ctx, In const& in, Func f, auto init) + { + ctx.map( [&](auto const& i) { init = f(init, i); } + , ctx.in(in) + ); + return init; + } + template constexpr auto reduce(In const& in, Func f, auto init) { - kwk::for_each([&](auto... is) { init = f(init, in(is...)); }, in.shape() ); - return init; + return kwk::reduce(cpu, in, f, init); + } + + template + constexpr auto reduce(Context& ctx, In const& in, Func f) + { + return kwk::reduce(ctx, in, f, typename In::value_type{}); } template constexpr auto reduce(In const& in, Func f) { - return kwk::reduce(in, f, typename In::value_type{}); + return kwk::reduce(cpu, in, f); + } + + template + constexpr auto reduce(Context& ctx, In const& in) + { + return kwk::reduce(ctx, in, [](auto a, auto e) { return a+e; }); } template constexpr auto reduce(In const& in) { - return kwk::reduce(in, [](auto a, auto e) { return a+e; }); + return kwk::reduce(cpu, in); } -} +} // namespace kwk diff --git a/test/algorithm/algos/context/cpu/reduce.cpp b/test/algorithm/algos/context/cpu/reduce.cpp new file mode 100644 index 00000000..af3c70cc --- /dev/null +++ b/test/algorithm/algos/context/cpu/reduce.cpp @@ -0,0 +1,84 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" +#include "../generic/reduce.hpp" + +// TODO: update these tests + +TTS_CASE("Check for kwk::reduce(in) 1D") +{ + kwk::test::reduce_in_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in) 1D - larger") +{ + kwk::test::reduce_in_1D_larger(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in) 2D") +{ + kwk::test::reduce_in_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in) 3D") +{ + kwk::test::reduce_in_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in) 4D") +{ + kwk::test::reduce_in_4D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func) 1D") +{ + kwk::test::reduce_in_func_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func) 2D") +{ + kwk::test::reduce_in_func_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func) 3D") +{ + kwk::test::reduce_in_func_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func) 4D") +{ + kwk::test::reduce_in_func_4D(kwk::cpu); +}; + +TTS_CASE("Check for float kwk::reduce(in, func)") +{ + kwk::test::reduce_in_func_float(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func, init) 1D") +{ + kwk::test::reduce_in_func_init_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func, init) 2D") +{ + kwk::test::reduce_in_func_init_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func, init) 3D") +{ + kwk::test::reduce_in_func_init_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::reduce(in, func, init) 4D") +{ + kwk::test::reduce_in_func_init_4D(kwk::cpu); +}; \ No newline at end of file diff --git a/test/algorithm/algos/context/generic/reduce.hpp b/test/algorithm/algos/context/generic/reduce.hpp new file mode 100644 index 00000000..77161f7e --- /dev/null +++ b/test/algorithm/algos/context/generic/reduce.hpp @@ -0,0 +1,276 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#pragma once + +#include +#include +#include +#include "test.hpp" + +// TODO: update these tests + +namespace kwk::test +{ + + template + void reduce_in_1D_larger(Context&& ctx) + { + const std::size_t size = 1600000; + // double* data = new double[size]; + std::vector data(size); + + auto global_fct = [](auto init, auto x) { return init + x; }; + + double sum = 0; + for (std::size_t i = 0; i < size; ++i) { data[i] = i; sum = global_fct(sum, i); } + + auto d = kwk::view{kwk::source = data, kwk::of_size(size)}; + + auto res = kwk::reduce(ctx, d, global_fct); + + std::cout << res << "\n"; + // delete[] data; + + TTS_EQUAL(res, sum); + }; + + template + void reduce_in_1D(Context&& ctx) + { + int data[2]; + int vdata = 1; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + + auto res = kwk::reduce(ctx, d); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_2D(Context&& ctx) + { + int data[2*3]; + int vdata = 36; + + fill_data(data, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + auto res = kwk::reduce(ctx, d); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_3D(Context&& ctx) + { + int data[2*3*4]; + int vdata = 1476; + + fill_data(data, kwk::of_size(2,3,4), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + auto res = kwk::reduce(ctx, d); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_4D(Context&& ctx) + { + int data[2*3*4*5]; + int vdata = 74040; + + fill_data(data, kwk::of_size(2,3,4,5), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + + auto res = kwk::reduce(ctx, d); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_func_1D(Context&& ctx) + { + int data[2]; + int vdata = 10; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+10*e); + }); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_func_2D(Context&& ctx) + { + int data[2*3]; + int vdata = 360; + + fill_data(data, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+10*e); + }); + + TTS_EQUAL(res, vdata); + }; + + + template + void reduce_in_func_3D(Context&& ctx) + { + int data[2*3*4]; + int vdata = 14760; + + fill_data(data, kwk::of_size(2,3,4), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+10*e); + }); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_func_4D(Context&& ctx) + { + int data[2*3*4*5]; + int vdata = 740400; + + fill_data(data, kwk::of_size(2,3,4,5), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+10*e); + }); + + TTS_EQUAL(res, vdata); + }; + + + template + void reduce_in_func_float(Context&& ctx) + { + float data[2*2] = { 1.f,2.2f + , 3.3f,4.4f + }; + + float vdata = 10.9f; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+e); + }); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_func_init_1D(Context&& ctx) + { + int data[2]; + int vdata = 11; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+e); + }, 10); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_func_init_2D(Context&& ctx) + { + int data[2*3]; + int vdata = 136; + + fill_data(data, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+e); + }, 100); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_func_init_3D(Context&& ctx) + { + int data[2*3*4]; + int vdata = 2476; + + fill_data(data, kwk::of_size(2,3,4), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+e); + }, 1000); + + TTS_EQUAL(res, vdata); + }; + + template + void reduce_in_func_init_4D(Context&& ctx) + { + int data[2*3*4*5]; + int vdata = 84040; + + fill_data(data, kwk::of_size(2,3,4,5), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + + auto res = reduce(ctx, d, + [](auto a, auto e) + { + return (a+e); + }, 10000); + + TTS_EQUAL(res, vdata); + }; + +} \ No newline at end of file diff --git a/test/algorithm/algos/reduce.cpp b/test/algorithm/algos/reduce.cpp deleted file mode 100644 index e992975d..00000000 --- a/test/algorithm/algos/reduce.cpp +++ /dev/null @@ -1,259 +0,0 @@ -//================================================================================================== -/* - KIWAKU - Containers Well Made - Copyright : KIWAKU Contributors & Maintainers - SPDX-License-Identifier: BSL-1.0 -*/ -//================================================================================================== -#include -#include -#include -#include "test.hpp" - -TTS_CASE("Check for kwk::reduce(in) 1D") -{ - int data[2]; - int vdata = 1; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - auto res = kwk::reduce(d); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::reduce(in) 2D") -{ - int data[2*3]; - int vdata = 36; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - auto res = kwk::reduce(d); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::reduce(in) 3D") -{ - int data[2*3*4]; - int vdata = 1476; - - fill_data(data, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - auto res = kwk::reduce(d); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::reduce(in) 4D") -{ - int data[2*3*4*5]; - int vdata = 74040; - - fill_data(data, kwk::of_size(2,3,4,5), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - auto res = kwk::reduce(d); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::reduce(in, func) 1D") -{ - int data[2]; - int vdata = 10; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+10*e); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::reduce(in, func) 2D") -{ - int data[2*3]; - int vdata = 360; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+10*e); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::reduce(in, func) 3D") -{ - int data[2*3*4]; - int vdata = 14760; - - fill_data(data, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+10*e); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::reduce(in, func) 4D") -{ - int data[2*3*4*5]; - int vdata = 740400; - - fill_data(data, kwk::of_size(2,3,4,5), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+10*e); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for float kwk::reduce(in, func)") -{ - float data[2*2] = { 1.f,2.2f - , 3.3f,4.4f - }; - - float vdata = 10.9f; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; - - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+e); - }); - - TTS_EQUAL(res, vdata); - - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::reduce(in, func, init) 1D") -{ - int data[2]; - int vdata = 11; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+e); - }, 10); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::reduce(in, func, init) 2D") -{ - int data[2*3]; - int vdata = 136; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+e); - }, 100); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::reduce(in, func, init) 3D") -{ - int data[2*3*4]; - int vdata = 2476; - - fill_data(data, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+e); - }, 1000); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::reduce(in, func, init) 4D") -{ - int data[2*3*4*5]; - int vdata = 84040; - - fill_data(data, kwk::of_size(2,3,4,5), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - int count = 0; - auto res = reduce(d, - [&count](auto a, auto e) - { - count++; - return (a+e); - }, 10000); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; \ No newline at end of file diff --git a/test/algorithm/algos/reduce/1d.cpp b/test/algorithm/algos/reduce/1d.cpp new file mode 100644 index 00000000..89e15edb --- /dev/null +++ b/test/algorithm/algos/reduce/1d.cpp @@ -0,0 +1,53 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include +#include +#include +#include "test.hpp" +#include + +TTS_CASE("Check for kwk::reduce(in) 1D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t input_size = d0; + std::array input; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + auto res = kwk::reduce(view_in); + auto res_std = std::reduce(input.begin(), input.end()); + + // TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(res, res_std); +}; + + +TTS_CASE("Check for kwk::reduce(in, func) and kwk::reduce(in, func, init) 1D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t input_size = d0; + std::array input; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + std::size_t count = 0; + auto res = kwk::reduce(view_in, [&](auto e1, auto e2) { ++count; return e1 + e2 + 1; }); + auto res2 = kwk::reduce(view_in, [&](auto e1, auto e2) { return e1 + e2 + 1; }, 87); + auto res_std = std::reduce(input.begin(), input.end(), 0, [&](auto e1, auto e2) { return e1 + e2 + 1; }); + + // TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(res, res_std); + TTS_EQUAL(static_cast(res2), res_std + 87); + TTS_EQUAL(count, input_size); +}; diff --git a/test/algorithm/algos/reduce/2d.cpp b/test/algorithm/algos/reduce/2d.cpp new file mode 100644 index 00000000..fdcc0675 --- /dev/null +++ b/test/algorithm/algos/reduce/2d.cpp @@ -0,0 +1,55 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include +#include +#include +#include "test.hpp" +#include + +TTS_CASE("Check for kwk::reduce(in) 2D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t d1 = 11; + const std::size_t input_size = d0 * d1; + std::array input; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + auto res = kwk::reduce(view_in); + auto res_std = std::reduce(input.begin(), input.end()); + + // TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(res, res_std); +}; + + +TTS_CASE("Check for kwk::reduce(in, func) and kwk::reduce(in, func, init) 2D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t d1 = 11; + const std::size_t input_size = d0 * d1; + std::array input; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + std::size_t count = 0; + auto res = kwk::reduce(view_in, [&](auto e1, auto e2) { ++count; return e1 + e2 + 1; }); + auto res2 = kwk::reduce(view_in, [&](auto e1, auto e2) { return e1 + e2 + 1; }, 87); + auto res_std = std::reduce(input.begin(), input.end(), 0, [&](auto e1, auto e2) { return e1 + e2 + 1; }); + + // TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(res, res_std); + TTS_EQUAL(static_cast(res2), res_std + 87); + TTS_EQUAL(count, input_size); +}; diff --git a/test/algorithm/algos/reduce/4d.cpp b/test/algorithm/algos/reduce/4d.cpp new file mode 100644 index 00000000..1b7a72e6 --- /dev/null +++ b/test/algorithm/algos/reduce/4d.cpp @@ -0,0 +1,59 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include +#include +#include +#include "test.hpp" +#include + +TTS_CASE("Check for kwk::reduce(in) 4D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t d1 = 11; + const std::size_t d2 = 13; + const std::size_t d3 = 5; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + auto res = kwk::reduce(view_in); + auto res_std = std::reduce(input.begin(), input.end()); + + // TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(res, res_std); +}; + + +TTS_CASE("Check for kwk::reduce(in, func) and kwk::reduce(in, func, init) 4D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t d1 = 11; + const std::size_t d2 = 13; + const std::size_t d3 = 5; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; + auto res = kwk::reduce(view_in, [&](auto e1, auto e2) { ++count; return e1 + e2 + 1; }); + auto res2 = kwk::reduce(view_in, [&](auto e1, auto e2) { return e1 + e2 + 1; }, 87); + auto res_std = std::reduce(input.begin(), input.end(), 0, [&](auto e1, auto e2) { return e1 + e2 + 1; }); + + // TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(res, res_std); + TTS_EQUAL(static_cast(res2), res_std + 87); + TTS_EQUAL(count, input_size); +};