diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 144d7e1b..99f7d576 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -18,7 +18,7 @@ jobs: fail-fast: false steps: - name: Fetch current branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Prepare KIWAKU run: | mkdir build && cd build @@ -30,7 +30,7 @@ jobs: ninja doxygen - name: Deploy to gh-pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./build/docs diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 6484c898..629e8f89 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -25,7 +25,7 @@ jobs: - {test: CPM , mode: 2 } steps: - name: Fetch current branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Check KIWAKU works with ${{ matrix.cfg.test }} uses: ./.github/actions/integration with: diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index 6a0221d4..ff386c14 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -17,7 +17,7 @@ jobs: gcc-linux: runs-on: [ubuntu-latest] container: - image: ghcr.io/jfalcou/compilers:v6 + image: ghcr.io/jfalcou/compilers:v7 strategy: fail-fast: false matrix: @@ -26,7 +26,7 @@ jobs: - { opts: -Ofast -flto=auto -DNDEBUG } steps: - name: Fetch current branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Kiwaku using g++-12 with ${{ matrix.cfg.opts }} run: | mkdir build @@ -40,7 +40,7 @@ jobs: clang-linux: runs-on: [ubuntu-latest] container: - image: ghcr.io/jfalcou/compilers:v6 + image: ghcr.io/jfalcou/compilers:v7 strategy: fail-fast: false matrix: @@ -51,7 +51,7 @@ jobs: - { opts: "-O0 -stdlib=libc++" , linker: -stdlib=libc++ } steps: - name: Fetch current branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Running CMake for clang++ with ${{ matrix.cfg.opts }} run: | mkdir build && cd build @@ -62,7 +62,7 @@ jobs: run: cd build && ctest --output-on-failure -j 2 clang-macosx: - runs-on: [macos-12] + runs-on: [macos-14] strategy: fail-fast: false matrix: @@ -73,7 +73,7 @@ jobs: - { opts: "-Ofast -flto -DNDEBUG -stdlib=libc++", linker: -stdlib=libc++ } steps: - name: Fetch current branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Running CMake for clang++ with ${{ matrix.cfg.opts }} run: | mkdir build && cd build @@ -84,7 +84,7 @@ jobs: run: cd build && ctest --output-on-failure -j 2 gcc-macosx: - runs-on: [macos-11] + runs-on: [macos-14] strategy: fail-fast: false matrix: @@ -93,18 +93,18 @@ jobs: - { opts: -Ofast -flto -DNDEBUG } steps: - name: Fetch current branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Running CMake for g++ with ${{ matrix.cfg.opts }} run: | mkdir build && cd build - cmake .. -DCMAKE_CXX_COMPILER=g++-11 -DCMAKE_CXX_FLAGS="${{ matrix.cfg.opts }}" + cmake .. -DCMAKE_CXX_COMPILER=g++-14 -DCMAKE_CXX_FLAGS="${{ matrix.cfg.opts }}" - name: Compiling Unit Tests run: cd build && make unit -j 2 - name: Running Unit Tests run: cd build && ctest --output-on-failure -j 2 android: - runs-on: [macos-12] + runs-on: [macos-14] strategy: fail-fast: false matrix: @@ -113,7 +113,7 @@ jobs: - { opts: -Ofast -flto -DNDEBUG } steps: - name: Fetch current branch - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Running CMake for g++ with ${{ matrix.cfg.opts }} run: | mkdir build && cd build @@ -131,7 +131,7 @@ jobs: # - { mode: Release} # steps: # - name: Fetch current branch - # uses: actions/checkout@v3 + # uses: actions/checkout@v4 # - name: Running CMake for MSVC ${{ matrix.cfg.mode }} # run: | # mkdir build && cd build diff --git a/.gitignore b/.gitignore index f122bea7..6165ee46 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,15 @@ doc/conf.py .vscode/* .cache/* .ideas/* + + +test/sycl_sandbox/obsolete +test/sycl_sandbox/test_templates_include.hpp +test/sycl_sandbox/test_templates.cpp +exec.sh +*.save +*.txt +*.save* + +*.inactive +*.ignore diff --git a/include/kwk/algorithm/algos/binary_search.hpp b/include/kwk/algorithm/algos/binary_search.hpp index bd3c2138..a45ba924 100644 --- a/include/kwk/algorithm/algos/binary_search.hpp +++ b/include/kwk/algorithm/algos/binary_search.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 @@ -15,18 +16,22 @@ #include #include -// ALGO: -/* -equal_range // view entre les deux boundss -*/ // trouver un moyen malin de calculer la position // échanger de place func et non func et appeler func namespace kwk { - template - constexpr auto lower_bound(Out const& out, auto value, Func func) + + // Unused context + // Function overloaded, even if Context is not used: for overloading with other contexts. + // eg.: + // constexpr auto lower_bound(sycl::context& c, Out const& out, auto value, Func func) + template + constexpr std::optional> + lower_bound(Context&, Out const& out, auto value, Func func) { + if (out.numel() == 0) return std::nullopt; + auto count = out.numel(); auto first = 0; auto it = 0; @@ -48,18 +53,29 @@ namespace kwk else count = step; } - return (first < out.numel()) ? std::optional>{kwk::coordinates(it, out.shape())} + return (first < out.numel()) ? std::optional>{kwk::coordinates(it, out.shape())} : std::nullopt; } + template + constexpr auto lower_bound(Out const& out, auto value, Func func) + { + return lower_bound(cpu, out, value, func); // Unused context + } + template + constexpr auto lower_bound(Context& ctx, Out const& out, auto value) + { + return lower_bound(ctx, out, value, [](auto e, auto i){return e constexpr auto lower_bound(Out const& out, auto value) { - return lower_bound(out, value, [](auto e, auto i){return e - constexpr auto upper_bound(Out const& out, auto value, Func func) + // Unused context + template + constexpr auto upper_bound(Context&, Out const& out, auto value, Func func) { auto count = out.numel(); auto first = 0; @@ -82,38 +98,59 @@ namespace kwk else count = step; } - return (first < out.numel()) ? std::optional>{kwk::coordinates(it, out.shape())} + return (first < out.numel()) ? std::optional>{kwk::coordinates(it, out.shape())} : std::nullopt; } + template + constexpr auto upper_bound(Out const& out, auto value, Func func) + { + return upper_bound(cpu, out, value, func); + } + + template + constexpr auto upper_bound(Context& ctx, Out const& out, auto value) + { + return upper_bound(ctx, out, value, [](auto e, auto i){return e constexpr auto upper_bound(Out const& out, auto value) { - return upper_bound( out, value, [](auto e, auto i){return e - constexpr bool binary_search(Out const& out, auto value, Func func) + + template + constexpr bool binary_search(Context& ctx, Out const& out, auto value, Func func) { - auto first = kwk::coordinates(0, out.shape()); - auto f = std::apply([](auto... i) { return kumi::tuple{i...}; }, first); + // Finds the index of the first element before (or equal to) value + // returns an std::array + auto first = lower_bound(ctx, out, value, func); - if (func(value, out(f))) return false; + // Element not found + if (first == std::nullopt) return false; - auto p = kwk::lower_bound(out, value, func); - bool outbound; + // transforms the array into a kumi::tuple + auto kumi_findex = std::apply([](auto... i) { return kumi::tuple{i...}; }, *first); - if(p) - outbound = false; - else - outbound = true; + // return (out(kumi_findex) == value); + return !(func(value, out(kumi_findex))); - return (!outbound); + } + template + constexpr bool binary_search(Out const& out, auto value, Func func) + { + return binary_search(cpu, out, value, func); } + template + constexpr bool binary_search(Context& ctx, Out const& out, auto value) + { + return binary_search(ctx, out, value, [](auto e, auto i){return e constexpr bool binary_search(Out const& out, auto value) { - return binary_search(out, value, [](auto e, auto i){return e +#include #include +#include #include #include #include namespace kwk { + + template + constexpr auto copy(Context& ctx, Out& out, In const& in) + { + kwk::transform(ctx, [](auto in) { return in; }, out, KWK_FWD(in) ); + } + template - constexpr auto copy(Out& out, In&& in) + constexpr auto copy(Out& out, In const& in) + { + kwk::copy(cpu, out, in); + } + + + template + constexpr auto copy_if(Context& ctx, Func f, Out& out, In const& in) { - kwk::transform([](auto in) { return in; }, out, KWK_FWD(in) ); + // kwk::for_each(ctx, [&](auto... is) { if(f(in(is...))) out(is...) = KWK_FWD(in)(is...); }, out.shape() ); + ctx.map([f](auto& o, auto const& i) { if(f(i)) o = i; }, ctx.out(out), ctx.in(in)); } template - constexpr auto copy_if(Func f, Out& out, In&& in) + constexpr auto copy_if(Func f, Out& out, In const& in) { - kwk::for_each([&](auto... is) { if(f(in(is...))) out(is...) = KWK_FWD(in)(is...); }, out.shape() ); + kwk::copy_if(cpu, f, out, in); } } diff --git a/include/kwk/algorithm/algos/find.hpp b/include/kwk/algorithm/algos/find.hpp index 1d05e07b..60f151fb 100644 --- a/include/kwk/algorithm/algos/find.hpp +++ b/include/kwk/algorithm/algos/find.hpp @@ -1,21 +1,25 @@ -//================================================================================================== +//====================================================================================================================== /** KIWAKU - Containers Well Made Copyright : KIWAKU Project Contributors SPDX-License-Identifier: BSL-1.0 **/ -//================================================================================================== +//====================================================================================================================== #pragma once #include +#include #include #include #include #include #include +#include #include #include +#include +#include // ALGO: /* adjacent_find -> PB ND @@ -26,69 +30,171 @@ find_end -> search_last // For_each interruptible + renvoi optional namespace kwk { - template - auto find_if(Container const& c, Check f) + + // Unused context + template + std::optional> + find_if(Context&, Container const& c, Check f) { - auto pos = kumi::generate(-1); + // TODO: if no element found, return a kumi tuple containing the size of each dimension + // and NOT -1 for each dimension. + kwk::position pos; - kwk::__::for_until( [&](auto... is) + // TODO: replace kwk::__::for_until with kwk::for_until? + bool valid_position = kwk::__::for_until( [&](auto... is) { if(f(c(is...))) { - pos = kumi::tuple{is...}; + unsigned long poss[Container::static_order] = {is...}; + for (std::size_t i = 0; i < Container::static_order; ++i) + { + pos[i] = static_cast::position_type>(poss[i]); + } return true; } return false; } , c.shape() ); + + if (valid_position) return std::optional>{pos}; + else return std::nullopt; + + } + + template + std::optional> + find_if(Container const& c, Check f) + { + return kwk::find_if(cpu, c, f); + } - return pos; + template + constexpr std::optional> + find(Context& ctx, Out const& out, auto value) + { + return find_if(ctx, out, [&](auto e){return e == value;}); } template - constexpr auto find(Out const& out, auto value) + constexpr std::optional> + find(Out const& out, auto value) { - return find_if(out, [&](auto e){return e == value;}); + return find(cpu, out, value); + } + + template + constexpr std::optional> + find_if_not(Context& ctx, Out const& out, Func f) + { + return find_if(ctx, out, [f](auto x){return !f(x);}); } template - constexpr auto find_if_not(Out const& out, Func f) + constexpr std::optional> + find_if_not(Out const& out, Func f) { - return kwk::find_if(out, [f](auto x){return !f(x);}); + return kwk::find_if_not(cpu, out, f); } - template - constexpr auto find_first_of(Out const& out, Values const& in) + template + constexpr std::optional> + find_first_of(Context& ctx, Out const& out, Values const& in) { - return kwk::find_if(out, [&](auto e) + // TODO: possible performance issue with contexts + // (any_of will call a new proxy each time it is called) + return find_if(ctx, out, [&](auto e) { - return kwk::any_of(in, [&](auto x){return (x==e);}); + return any_of(ctx, in, [&](auto x){return (x==e);}); }); } - template - constexpr auto find_last_if(Out const& out, Func f) + template + constexpr std::optional> + find_first_of(Out const& out, Values const& in) + { + return kwk::find_first_of(cpu, out, in); + } + + // TODO?: add find_first_of(Out const& out, Values const& in, Func f)? + + template + constexpr std::optional> + find_last_if(Context& ctx, Out const& out, Func f) { - auto res = kwk::find_if(kwk::reverse(out), f); + auto res = find_if(ctx, kwk::reverse(out), f); - kumi::for_each([](auto s, auto& r) + // std::cout << static_cast(out.shape()(0).numel()) << "\n"; + // std::cout << kwk::get<0>(out.shape()) << "\n"; + + // kwk::for_each([](auto s) + // { + // // r = s-1-r; + // std::cout << s << "\n"; + // }, Out::static_order); + + if (res.has_value()) { - r = s-1-r; - }, out.shape(), res); + // // + // for (auto i : Out::static_order) + // { + // // res[i] = + // // std::integral_constant ii; + // // constexpr int ii = 8; + // // std::cout << kwk::get(out.shape()) << "\n"; + // std::cout << i << "\n"; + // } + + // kumi::for_each_index( [&](auto i, auto) { std::cout << " " << +kwk::get(out.shape()) << typeid(i).name(); }, out.shape()); + + // Reverse positions + kumi::for_each_index( [&](auto i, auto) { res.value()[i] = kwk::get(out.shape()) - 1 - res.value()[i]; } + , out.shape() + ); + // kumi::for_each( [&](auto e) { std::cout << e << "\n"; }, out.shape()); + } + + // // TODO: replace kumi::for_each with kwk::for_each? + // kumi::for_each([](auto s, auto& r) + // { + // r = s-1-r; + // }, out.shape(), res); return res; } + template + constexpr std::optional> + find_last_if(Out const& out, Func f) + { + return find_last_if(cpu, out, f); + } + + template + constexpr std::optional> + find_last(Context& ctx, Out const& out, auto value) + { + return find_last_if(ctx, out, [&](auto e){return e == value;}); + } + template - constexpr auto find_last(Out const& out, auto value) + constexpr std::optional> + find_last(Out const& out, auto value) + { + return kwk::find_last(cpu, out, value); + } + + template + constexpr std::optional> + find_last_if_not(Context& ctx, Out const& out, Func f) { - return find_last_if(out, [&](auto e){return e == value;}); + return find_last_if(ctx, out, [f](auto x){return !f(x);}); } template - constexpr auto find_last_if_not(Out const& out, Func f) + constexpr std::optional> + find_last_if_not(Out const& out, Func f) { - return kwk::find_last_if(out, [f](auto x){return !f(x);}); + return kwk::find_last_if_not(cpu, out, f); } } diff --git a/include/kwk/algorithm/algos/for_each.hpp b/include/kwk/algorithm/algos/for_each.hpp index e399c9e1..d4a79360 100644 --- a/include/kwk/algorithm/algos/for_each.hpp +++ b/include/kwk/algorithm/algos/for_each.hpp @@ -1,26 +1,34 @@ -//================================================================================================== +//====================================================================================================================== /** KIWAKU - Containers Well Made Copyright : KIWAKU Project Contributors SPDX-License-Identifier: BSL-1.0 **/ -//================================================================================================== +//====================================================================================================================== #pragma once #include +#include #include #include #include #include +// #include namespace kwk { - //================================================================================================ + //==================================================================================================================== //! @addtogroup algorithms //! @{ - //================================================================================================ + //==================================================================================================================== - //================================================================================================ + template + constexpr auto for_each(Context& ctx, Func&& f, shape const& shp) + { + return ctx.map(KWK_FWD(f), shp); + } + + //==================================================================================================================== //! @brief Simple walkthrough over all possible indexes //! //! Applies the given function object `f` to every coordinates that are valid inside the given @@ -37,17 +45,21 @@ namespace kwk //! //! @groupheader{Example} //! @include docs/algorithms/for_each_shape.cpp - //================================================================================================ + //==================================================================================================================== template - constexpr auto for_each(Func f, shape const& shp) + constexpr auto for_each(Func&& f, shape const& shp) + { + kwk::for_each(cpu, KWK_FWD(f), shp); + } + + template + constexpr auto for_each(Context& ctx, Func&& f, C0&& c0, Cs&&... cs) { - return [&](std::index_sequence const&) - { - return __::for_each(f, shp ); - }( std::make_index_sequence::static_order>{} ); + ctx.map([&](auto... is) { return KWK_FWD(f)(KWK_FWD(c0)(is...), KWK_FWD(cs)(is...)...); }, c0.shape() ); + return f; } - //================================================================================================ + //==================================================================================================================== //! @brief Simple walkthrough over all elements of a container //! //! Applies the given function object `f` to every elements of a given kwk::container. @@ -64,15 +76,14 @@ namespace kwk //! //! @groupheader{Example} //! @include docs/algorithms/for_each.cpp - //================================================================================================ + //==================================================================================================================== template - constexpr auto for_each(Func f, C0&& c0, Cs&&... cs) + constexpr auto for_each(Func&& f, C0&& c0, Cs&&... cs) { - kwk::for_each([&](auto... is) { return f(KWK_FWD(c0)(is...), KWK_FWD(cs)(is...)...); }, c0.shape() ); - return f; + return kwk::for_each(cpu, KWK_FWD(f), KWK_FWD(c0), KWK_FWD(cs)...); } - //================================================================================================ + //==================================================================================================================== //! @brief Simple walkthrough over all elements of a container and their coordinates //! //! Applies the given function object `f` to every elements of a given kwk::container and @@ -89,20 +100,26 @@ namespace kwk //! //! @groupheader{Example} //! @include docs/algorithms/for_each_index.cpp - //================================================================================================ - template - constexpr auto for_each_index(Func f, Container&& c) + //==================================================================================================================== + template + constexpr auto for_each_index(Context& ctx, Func&& f, Container&& c) { - kwk::for_each ( [&](auto... is) { return f(KWK_FWD(c)(is...), is...); } + kwk::for_each ( ctx + , [&](auto... is) { return KWK_FWD(f)(KWK_FWD(c)(is...), is...); } , c.shape() ); return f; } + template + constexpr auto for_each_index(Func f, Container&& c) + { + return for_each_index(cpu, f, c); + } + - - //================================================================================================ + //==================================================================================================================== //! @} - //================================================================================================ + //==================================================================================================================== } diff --git a/include/kwk/algorithm/algos/generator.hpp b/include/kwk/algorithm/algos/generator.hpp index 2c8e876e..4ea301f2 100644 --- a/include/kwk/algorithm/algos/generator.hpp +++ b/include/kwk/algorithm/algos/generator.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 @@ -15,34 +16,73 @@ namespace kwk { + template + constexpr auto fill(Context& ctx, Out& out, auto value) + { + ctx.map([&](auto& o) { o = value; }, ctx.out(out) ); + } template constexpr auto fill(Out& out, auto value) { - kwk::for_each([&](auto... is) { out(is...) = value; }, out.shape() ); + // TODO: put back kwk:: namespace before function call + fill(cpu, out, value); } + + template + constexpr auto generate(Context& ctx, Func f, Out& out) + { + // TODO: put back kwk:: namespace before function call + ctx.map_index([f](auto& o, auto... is) { o = f(is...); }, ctx.out(out)); + } template constexpr auto generate(Func f, Out& out) { - kwk::for_each([&](auto... is) { out(is...) = f(is...); }, out.shape() ); + // TODO: put back kwk:: namespace before function call + generate(cpu, f, out); } + + template + constexpr auto iota(Context& ctx, Out& out, auto value) + { + // TODO: put back kwk:: namespace before function call + // TODO?: maybe call iota(ctx, out, value, step = 1) ? + ctx.map([&](auto& o) { o = value++; }, ctx.out(out)); + } template constexpr auto iota(Out& out, auto value) { - kwk::for_each([&](auto... is) { out(is...) = value++; }, out.shape() ); + // TODO: put back kwk:: namespace before function call + iota(cpu, out, value); } + + template + constexpr auto iota(Context& ctx, Out& out) + { + // TODO: put back kwk:: namespace before function call + using type = typename Out::value_type; + iota(ctx, out, type{}); + } template constexpr auto iota(Out& out) { - using type = typename Out::value_type; - kwk::iota(out,type{}); + // TODO: put back kwk:: namespace before function call + iota(cpu, out); } + + template + constexpr auto iota(Context& ctx, Out& out, auto value, auto step) + { + // TODO: put back kwk:: namespace before function call + ctx.map([&](auto& o) { o = value; value += step; }, ctx.out(out)); + } template constexpr auto iota(Out& out, auto value, auto step) { - kwk::for_each([&](auto... is) { out(is...) = value; value+=step; }, out.shape() ); + // TODO: put back kwk:: namespace before function call + iota(cpu, out, value, step); } } diff --git a/include/kwk/algorithm/algos/numeric.hpp b/include/kwk/algorithm/algos/numeric.hpp index 3d1058d4..c39d8c6d 100644 --- a/include/kwk/algorithm/algos/numeric.hpp +++ b/include/kwk/algorithm/algos/numeric.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 @@ -20,105 +21,198 @@ partial_sum -> à voir si duplicata inclusive scan adjacent_difference -> à voir à part */ +// TODO: put back kwk:: namespace before every function call + namespace kwk { - template - constexpr auto transform_reduce(In const& in1, In const& in2, auto init, Func_R R, Func_T T) + template + constexpr auto transform_reduce(Context& ctx, In1 const& in1, In2 const& in2, auto init, Func_R R, Func_T T) { // return error for in1.shape() != in2.shape() - kwk::for_each([&](auto... is) { init = R(init, T(in1(is...), in2(is...))); }, in1.shape() ); + ctx.map([&](auto const& i1, auto const& i2) { init = R(init, T(i1, i2)); }, ctx.in(in1), ctx.in(in2)); return init; } + template + constexpr auto transform_reduce(In1 const& in1, In2 const& in2, auto init, Func_R R, Func_T T) + { + return transform_reduce(cpu, in1, in2, init, R, T); + } + // voir pour avoir version func_T et init sans func_R ? - template - constexpr auto transform_reduce(In const& in1, In const& in2, auto init, Func_T T) + template + constexpr auto transform_reduce(Context& ctx, In1 const& in1, In2 const& in2, auto init, Func_T T) { // return error for in1.shape() != in2.shape() - return kwk::transform_reduce(in1, in2, init, [](auto r, auto d){ return (r+d); }, T); + return transform_reduce(ctx, in1, in2, init, [](auto r, auto d){ return (r+d); }, T); + } + + template + constexpr auto transform_reduce(In1 const& in1, In2 const& in2, auto init, Func_T T) + { + return transform_reduce(cpu, in1, in2, init, T); } - template - constexpr auto transform_reduce(In const& in1, In const& in2, auto init) + template + constexpr auto transform_reduce(Context& ctx, In1 const& in1, In2 const& in2, auto init) { // return error for in1.shape() != in2.shape() - return kwk::transform_reduce(in1, in2, init, [](auto i1, auto i2){ return (i1+i2); }); + //By default, the transform function of the standard is (*) multiply + return transform_reduce(ctx, in1, in2, init, [](auto i1, auto i2){ return (i1 * i2); }); + } + + template + constexpr auto transform_reduce(In1 const& in1, In2 const& in2, auto init) + { + return transform_reduce(cpu, in1, in2, init); } - template - constexpr auto transform_reduce(In const& in1, In const& in2) + // Not present in the standard library + template + constexpr auto transform_reduce(Context& ctx, In1 const& in1, In2 const& in2) { + // According to cppreference + using t1 = typename In1::value_type; + using t2 = typename In2::value_type; + auto R = [](auto const& e1, auto const& e2) { return e1 + e2; }; + auto T = [](auto const& e1, auto const& e2) { return e1 * e2; }; + using return_type = decltype(R(t1{}, T(t1{}, t2{}))); + // return error for in1.shape() != in2.shape() - return kwk::transform_reduce(in1, in2, typename In::value_type{}); + return transform_reduce(ctx, in1, in2, return_type{}); } - template - constexpr auto inner_product(In const& in1, In const& in2, auto init, Func_1 f1, Func_2 f2) + template + constexpr auto transform_reduce(In1 const& in1, In2 const& in2) { - if(in1.shape() != in2.shape()) return -1; - //pareil que for each element in in1, in2 ? - kwk::for_each([&](auto... is) { init = f1(init, f2(in1(is...), in2(is...))); }, in1.shape() ); + return transform_reduce(cpu, in1, in2); + } + + template + constexpr auto inner_product(Context& ctx, In1 const& in1, In2 const& in2, auto init, Func_1 f1, Func_2 f2) + { + KIWAKU_ASSERT( in1.shape() == in2.shape() + , "[KWK] - Inner product dimensions do not match, container one dimensions are " + << in1.shape() << ", container two dimensions are " + << in2.shape() << "." + ); + ctx.map([&](auto const& i1, auto const& i2) { init = f1(init, f2(i1, i2)); }, ctx.in(in1), ctx.in(in2)); return init; } - template - constexpr auto inner_product(In const& in1, In const& in2, auto init) + template + constexpr auto inner_product(In1 const& in1, In2 const& in2, auto init, Func_1 f1, Func_2 f2) + { + return inner_product(cpu, in1, in2, init, f1, f2); + } + + template + constexpr auto inner_product(Context& ctx, In1 const& in1, In2 const& in2, auto init) { - return kwk::inner_product(in1, in2, init, + return inner_product(ctx, in1, in2, init, [](auto r, auto d){ return (r+d); }, [](auto i1, auto i2){ return (i1*i2); }); } - template - constexpr auto inner_product(In const& in1, In const& in2) + template + constexpr auto inner_product(In1 const& in1, In2 const& in2, auto init) { - return kwk::inner_product(in1, in2, typename In::value_type{}); + return inner_product(cpu, in1, in2, init); } - template< typename Func1, typename Func2, concepts::container In, concepts::container Out > - constexpr auto transform_exclusive_scan(const In in, Out& out, auto init, Func1 f1, Func2 f2) + template + constexpr auto inner_product(Context& ctx, In1 const& in1, In2 const& in2) + { + // According to cppreference + using t1 = typename In1::value_type; + using t2 = typename In2::value_type; + auto sum = [](auto const& e1, auto const& e2) { return e1 + e2; }; + auto product = [](auto const& e1, auto const& e2) { return e1 * e2; }; + using return_type = decltype(sum(t1{}, product(t1{}, t2{}))); + + return inner_product(ctx, in1, in2, return_type{}); + } + + template + constexpr auto inner_product(In1 const& in1, In2 const& in2) + { + return inner_product(cpu, in1, in2); + } + + template + constexpr auto transform_exclusive_scan(Context& ctx, In const& in, Out& out, auto init, Func1 f1, Func2 f2) { auto sum = init; - kwk::for_each([&](auto... is) - { - out(is...) = sum; - sum = f1(sum, f2(in(is...))); - }, in.shape() ); + ctx.map([&](auto const& i, auto& o) { o = sum; sum = f1(sum, f2(i)); }, ctx.in(in), ctx.out(out)); + } + + template< typename Func1, typename Func2, concepts::container In, concepts::container Out > + constexpr auto transform_exclusive_scan(In const& in, Out& out, auto init, Func1 f1, Func2 f2) + { + transform_exclusive_scan(cpu, in, out, init, f1, f2); + } + + template + constexpr auto exclusive_scan(Context& ctx, In const& in, Out& out, auto init, Func f) + { + transform_exclusive_scan(ctx, in, out, init, f, [](auto e){return e;}); } template< typename Func, concepts::container In, concepts::container Out > - constexpr auto exclusive_scan(const In in, Out& out, auto init, Func f) + constexpr auto exclusive_scan(In const& in, Out& out, auto init, Func f) + { + exclusive_scan(cpu, in, out, init, f); + } + + template + constexpr auto exclusive_scan(Context& ctx, In const& in, Out& out, auto init) { - kwk::transform_exclusive_scan(in, out, init, f, [](auto e){return e;}); + exclusive_scan(ctx, in, out, init, [](auto e, auto i){return (e + i);}); } template< concepts::container In, concepts::container Out > - constexpr auto exclusive_scan(const In in, Out& out, auto init) + constexpr auto exclusive_scan(In const& in, Out& out, auto init) { - kwk::exclusive_scan(in, out, init, [](auto e, auto i){return (e + i);}); + exclusive_scan(cpu, in, out, init); } - // a corriger - template< typename Func1, typename Func2, concepts::container In, concepts::container Out > - constexpr auto transform_inclusive_scan(const In in, Out& out, auto init, Func1 f1, Func2 f2) + // (Sasa?): "a corriger" + template + constexpr auto transform_inclusive_scan(Context& ctx, In const& in, Out& out, auto init, Func1 f1, Func2 f2) { + // Will not work with sycl_context auto sum = init; - kwk::for_each([&](auto... is) - { - sum = f1(sum, f2(in(is...))); - out(is...) = sum; - }, in.shape() ); + ctx.map([&](auto const& i, auto& o) { sum = f1(sum, f2(i)); o = sum; }, ctx.in(in), ctx.out(out)); + } + + template< typename Func1, typename Func2, concepts::container In, concepts::container Out > + constexpr auto transform_inclusive_scan(In const& in, Out& out, auto init, Func1 f1, Func2 f2) + { + transform_inclusive_scan(cpu, in, out, init, f1, f2); + } + + template + constexpr auto inclusive_scan(Context& ctx, In const& in, Out& out, auto init, Func f) + { + transform_inclusive_scan(ctx, in, out, init, f, [](auto e){return e;}); } template< typename Func, concepts::container In, concepts::container Out > - constexpr auto inclusive_scan(const In in, Out& out, auto init, Func f) + constexpr auto inclusive_scan(In const& in, Out& out, auto init, Func f) { - kwk::transform_inclusive_scan(in, out, init, f, [](auto e){return e;}); + inclusive_scan(cpu, in, out, init, f); + } + + template + constexpr auto inclusive_scan(Context& ctx, In const& in, Out& out, auto init) + { + inclusive_scan(ctx, in, out, init, [](auto e, auto i){return (e + i);}); } template< concepts::container In, concepts::container Out > - constexpr auto inclusive_scan(const In in, Out& out, auto init) + constexpr auto inclusive_scan(In const& in, Out& out, auto init) { - kwk::inclusive_scan(in, out, init, [](auto e, auto i){return (e + i);}); + inclusive_scan(cpu, in, out, init); } -} + +} // namespace kwk diff --git a/include/kwk/algorithm/algos/predicates.hpp b/include/kwk/algorithm/algos/predicates.hpp index d64bbcb2..d6f39c03 100644 --- a/include/kwk/algorithm/algos/predicates.hpp +++ b/include/kwk/algorithm/algos/predicates.hpp @@ -1,14 +1,15 @@ -//================================================================================================== +//====================================================================================================================== /** KIWAKU - Containers Well Made Copyright : KIWAKU Project Contributors SPDX-License-Identifier: BSL-1.0 **/ -//================================================================================================== +//====================================================================================================================== #pragma once #include #include +#include #include #include #include @@ -22,33 +23,64 @@ starts_with -> sous vue de k depuis le début (interprété 1D ?) namespace kwk { + + template + constexpr auto all_of(Context& ctx, In const& in, Func f) + { + return reduce(ctx, in, [f](auto a, auto e) { return a && f(e); }, true ); + } + template constexpr auto all_of(In const& in, Func f) { - return reduce(in, [f](auto a, auto e) { return a && f(e); }, true ); + return all_of(cpu, in, f); + } + + template + constexpr auto any_of(Context& ctx, In const& in, Func f) + { + return reduce(ctx, in, [f](auto a, auto e) { return a || f(e); }, false ); } template constexpr auto any_of(In const& in, Func f) { - return reduce(in, [f](auto a, auto e) { return a || f(e); }, false ); + return any_of(cpu, in, f); + } + + template + constexpr auto none_of(Context& ctx, In const& in, Func f) + { + return !any_of(ctx, in, f); } template constexpr auto none_of(In const& in, Func f) { - return !any_of(in, f); + return none_of(cpu, in, f); + } + + template + constexpr auto count(Context& ctx, In const& in, auto value) + { + return reduce(ctx, in, [value](auto a, auto e) { return a + ((e==value) ? 1 : 0); }, std::size_t{} ); } - template< concepts::container In> + template constexpr auto count(In const& in, auto value) { - return reduce(in, [value](auto a, auto e) { return a + ((e==value) ? 1 : 0); }, std::size_t{} ); + return count(cpu, in, value); + } + + template + constexpr auto count_if(Context& ctx, In const& in, Func f) + { + return reduce(ctx, in, [f](auto a, auto e) { return a + (f(e) ? 1 : 0); }, std::size_t{} ); } template constexpr auto count_if(In const& in, Func f) { - return reduce(in, [f](auto a, auto e) { return a + (f(e) ? 1 : 0); }, std::size_t{} ); + return count_if(cpu, in, f); } } 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/include/kwk/algorithm/algos/replace.hpp b/include/kwk/algorithm/algos/replace.hpp index 5a6a0b5d..300b7714 100644 --- a/include/kwk/algorithm/algos/replace.hpp +++ b/include/kwk/algorithm/algos/replace.hpp @@ -1,29 +1,39 @@ -//================================================================================================== +//====================================================================================================================== /** KIWAKU - Containers Well Made Copyright : KIWAKU Project Contributors SPDX-License-Identifier: BSL-1.0 **/ -//================================================================================================== +//====================================================================================================================== #pragma once #include +#include #include -#include -#include -#include namespace kwk { - template - constexpr auto replace(Out& out, auto old_value, auto new_value) + template + constexpr void replace_if(Context& ctx, Out& out, Func f, auto new_value) { - kwk::for_each([&](auto... is) { if(out(is...) == old_value) KWK_FWD(out)(is...) = new_value; }, out.shape() ); + ctx.map([=](auto& o) { if(f(o)) o = new_value; }, Context::inout(out)); } template - constexpr auto replace_if(Out& out, Func f, auto new_value) + constexpr void replace_if(Out& out, Func f, auto new_value) + { + replace_if(cpu, out, f, new_value); + } + + template + constexpr void replace(Context& ctx, Out& out, auto old_value, auto new_value) + { + replace_if(ctx, out, [old_value](auto const& x) { return x == old_value; }, new_value); + } + + template + constexpr void replace(Out& out, auto old_value, auto new_value) { - kwk::for_each([&](auto... is) { if(f(out(is...))) KWK_FWD(out)(is...) = new_value; }, out.shape() ); + replace(cpu, out, old_value, new_value); } } diff --git a/include/kwk/algorithm/algos/transform.hpp b/include/kwk/algorithm/algos/transform.hpp index 406d3a9f..937353ac 100644 --- a/include/kwk/algorithm/algos/transform.hpp +++ b/include/kwk/algorithm/algos/transform.hpp @@ -1,25 +1,33 @@ -//================================================================================================== +//====================================================================================================================== /** KIWAKU - Containers Well Made Copyright : KIWAKU Project Contributors SPDX-License-Identifier: BSL-1.0 **/ -//================================================================================================== +//====================================================================================================================== #pragma once #include -#include -#include -#include -#include +#include namespace kwk { + // Transform is not a required part of contexts anymore + template< typename Context, typename Func, concepts::container Out + , concepts::container C0, concepts::container... Cs + > + constexpr void transform(Context& ctx,Func&& f, Out& out, C0 const& c0, Cs const&... cs) + { + ctx.map ( [&](auto& o, auto const& i0, auto const&... in) { o = KWK_FWD(f)(i0, in...); } + , ctx.out(out), ctx.in(c0), ctx.in(cs)... + ); + } + template< typename Func, concepts::container Out , concepts::container C0, concepts::container... Cs > - constexpr auto transform(Func f, Out& out, C0&& c0, Cs&&... cs) + constexpr void transform(Func&& f, Out& out, C0&& c0, Cs&&... cs) { - kwk::for_each([&](auto... is) { out(is...) = f(KWK_FWD(c0)(is...), KWK_FWD(cs)(is...)...); }, out.shape() ); + kwk::transform(cpu, KWK_FWD(f), out, KWK_FWD(c0), KWK_FWD(cs)...); } } diff --git a/include/kwk/context/base.hpp b/include/kwk/context/base.hpp new file mode 100644 index 00000000..cf8bb88c --- /dev/null +++ b/include/kwk/context/base.hpp @@ -0,0 +1,38 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Project Contributors + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#pragma once + +#include +#include + +namespace kwk +{ + template + struct base_context + { + protected: + Context& self() { return static_cast(*this); } + Context const& self() const { return static_cast(*this); } + + public: + + static auto const& in (kwk::concepts::container auto const& c) { return c; } + static auto& out (kwk::concepts::container auto& c) { return c; } + static auto& inout(kwk::concepts::container auto& c) { return c; } + + // reduce is not part of base_context anymore. + // template + // constexpr auto reduce(In const& in, Func f, auto init) const + // { + // self().map ( [&](auto const& i) { init = f(init, i); } + // , Context::in(in) + // ); + // return init; + // } + }; +} diff --git a/include/kwk/context/context.hpp b/include/kwk/context/context.hpp new file mode 100644 index 00000000..7cc462c6 --- /dev/null +++ b/include/kwk/context/context.hpp @@ -0,0 +1,20 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Project Contributors + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#pragma once + +namespace kwk +{ + //==================================================================================================================== + //! @defgroup contexts Contexts + //! @brief Hardware-specific evaluation contexts for algorithms + //! + //==================================================================================================================== +} + +#include +#include \ No newline at end of file diff --git a/include/kwk/context/cpu/context.hpp b/include/kwk/context/cpu/context.hpp new file mode 100644 index 00000000..50435c59 --- /dev/null +++ b/include/kwk/context/cpu/context.hpp @@ -0,0 +1,41 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Project Contributors + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#pragma once + +#include +#include +#include + +namespace kwk +{ + struct cpu_context : base_context + { + template + constexpr auto map(Func f, shape const& shp) const + { + return __::for_each(f, shp ); + } + + template + constexpr auto map(Func f, C0&& c0, Cs&&... cs) const + { + this->map([&](auto... is) { return f(KWK_FWD(c0)(is...), KWK_FWD(cs)(is...)...); }, c0.shape() ); + return f; + } + + template + constexpr auto map_index(Func f, Container&& c) const + { + this->map([&](auto... is) { return f(KWK_FWD(c)(is...), is...); }, c.shape()); + return f; + } + }; + + inline constexpr cpu_context cpu = {}; + +} diff --git a/include/kwk/detail/algorithm/for_until.hpp b/include/kwk/detail/algorithm/for_until.hpp index 01238464..440b6d4d 100644 --- a/include/kwk/detail/algorithm/for_until.hpp +++ b/include/kwk/detail/algorithm/for_until.hpp @@ -32,7 +32,7 @@ namespace kwk , [&](auto... is) { found = f(is...); } ); loops(); - return f; + return found; } } } \ No newline at end of file diff --git a/include/kwk/utility/container/shape.hpp b/include/kwk/utility/container/shape.hpp index f40c7e3d..cb077fac 100644 --- a/include/kwk/utility/container/shape.hpp +++ b/include/kwk/utility/container/shape.hpp @@ -241,7 +241,7 @@ namespace kwk KWK_PURE constexpr bool contains(Coords... p) const noexcept requires(static_order == sizeof...(Coords)) { - return kumi::apply( [&](auto... m) { return ((p < m) && ... && true); }, *this); + return kumi::apply( [&](auto... m) { return ((p < static_cast(m)) && ... && true); }, *this); } //============================================================================================== diff --git a/include/kwk/utility/container/stride.hpp b/include/kwk/utility/container/stride.hpp index c22387e4..776e1ab9 100644 --- a/include/kwk/utility/container/stride.hpp +++ b/include/kwk/utility/container/stride.hpp @@ -81,10 +81,12 @@ namespace kwk //============================================================================================== // stride is its self option keyword //============================================================================================== - using stored_value_type = stride; + using stored_value_type = stride const&; using keyword_type = __::strides_; - constexpr auto operator()(keyword_type const&) const noexcept { return *this; } + // constexpr auto operator()(keyword_type const&) const noexcept { return *this; } + constexpr stored_value_type operator()(keyword_type const&) const noexcept { return *this; } + //============================================================================================== //! @brief Constructs a default @ref kwk::stride equals to [1 1 ... 1] diff --git a/include/kwk/utility/position.hpp b/include/kwk/utility/position.hpp new file mode 100644 index 00000000..803ef759 --- /dev/null +++ b/include/kwk/utility/position.hpp @@ -0,0 +1,74 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Project Contributors + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include + +namespace kwk +{ + template + struct position + { + using position_type = int; + position_type pos[Size]; + + constexpr position_type& operator[](std::size_t index) + { + return pos[index]; + } + + constexpr position_type const& operator[](std::size_t index) const + { + return pos[index]; + } + + constexpr bool operator==(position const& other) const + { + for (std::size_t i = 0; i < Size; ++i) + { + if (this->operator[](i) != other[i]) + return false; + } + return true; + } + + template + friend std::ostream& operator<<(std::ostream& os, position const& p) + { + os << "position<" << Size_ << ">("; + for (std::size_t i = 0; i < Size_; ++i) + { + os << p.pos[i]; + if (i + 1 != Size_) os << ", "; + } + return os << ")"; + } + + // === Kumi interface === + using is_product_type = void; + + template + friend constexpr auto const& get(position const& p) noexcept + { + return p.pos[I]; + } + + template + friend constexpr auto& get(position& p) noexcept + { + return p.pos[I]; + } + // ^^^ Kumi interface ^^^ + }; +} + +template struct std::tuple_size> : std::integral_constant {}; +template struct std::tuple_element> { using type = typename kwk::position::position_type; }; \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2f73610a..3c10e0a2 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -7,6 +7,31 @@ include(make_unit) set(unit_root "${CMAKE_SOURCE_DIR}/test") glob_unit(${unit_root} "algorithm/algos/*.cpp") + +glob_unit(${unit_root} "algorithm/algos/reduce/*.cpp") +glob_unit(${unit_root} "algorithm/algos/context/cpu/reduce.cpp") + +glob_unit(${unit_root} "algorithm/algos/copy/*.cpp") +glob_unit(${unit_root} "algorithm/algos/context/cpu/copy.cpp") + +glob_unit(${unit_root} "algorithm/algos/numeric/*.cpp") +# glob_unit(${unit_root} "algorithm/algos/context/cpu/numeric.cpp") WIP + +glob_unit(${unit_root} "algorithm/algos/replace/*.cpp") +# glob_unit(${unit_root} "algorithm/algos/context/cpu/replace.cpp") WIP + +glob_unit(${unit_root} "algorithm/algos/binary_search/*.cpp") +# glob_unit(${unit_root} "algorithm/algos/context/cpu/binary_search.cpp") WIP + +glob_unit(${unit_root} "algorithm/algos/find/*.cpp") +# glob_unit(${unit_root} "algorithm/algos/context/cpu/find.cpp") WIP + +glob_unit(${unit_root} "algorithm/algos/predicates/*.cpp") +# glob_unit(${unit_root} "algorithm/algos/context/cpu/predicates.cpp") WIP + +glob_unit(${unit_root} "algorithm/algos/generator/*.cpp") +# glob_unit(${unit_root} "algorithm/algos/context/cpu/generator.cpp") WIP + glob_unit(${unit_root} "algorithm/views/*.cpp") glob_unit(${unit_root} "concepts/*.cpp") glob_unit(${unit_root} "container/table/*.cpp") diff --git a/test/algorithm/algos/binary_search.cpp b/test/algorithm/algos/binary_search.cpp deleted file mode 100644 index b21ae695..00000000 --- a/test/algorithm/algos/binary_search.cpp +++ /dev/null @@ -1,495 +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::lower_bound(In, value) 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::lower_bound(d, 1); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - - -TTS_CASE("Check for kwk::lower_bound(In, value) 2D") -{ - int data[2*3]; - int vdata[] = {1,1}; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - auto res = kwk::lower_bound(d, 21); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::lower_bound(In, value) 3D") -{ - int data[2*3*4]; - int vdata[] = {1,0,0}; - - 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::lower_bound(d, 100); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::lower_bound(In, value) 4D") -{ - int data[2*3*4*5]; - int vdata[] = {1,0,0,0}; - - 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::lower_bound(d, 1000); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::lower_bound(In, value, func) 1D") -{ - int data[2]; - int vdata[] = {0}; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - auto res = kwk::lower_bound(d, 1, [](auto e, auto s) - { - return e < (s-1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - - -TTS_CASE("Check for kwk::lower_bound(In, value, func) 2D") -{ - int data[2*3]; - int vdata[] = {1,0}; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - auto res = kwk::lower_bound(d, 21, [](auto e, auto s) - { - return e < (s-1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::lower_bound(In, value, func) 3D") -{ - int data[2*3*4]; - int vdata[] = {1,0,0}; - - 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::lower_bound(d, 101, [](auto e, auto s) - { - return e < (s-1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::lower_bound(In, value, func) 4D") -{ - int data[2*3*4*5]; - int vdata[] = {1,0,0,0}; - - 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::lower_bound(d, 1001, [](auto e, auto s) - { - return e < (s-1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - - -TTS_CASE("Check for kwk::upper_bound(In, value) 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::upper_bound(d, 0); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - - -TTS_CASE("Check for kwk::upper_bound(In, value) 2D") -{ - int data[2*3]; - int vdata[] = {1,1}; - - const std::vector rdata {0, 1, 2, 10, 11, 12}; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - auto res = kwk::upper_bound(d, 10); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::upper_bound(In, value) 3D") -{ - int data[2*3*4]; - int vdata[] = {1,0,0}; - - 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::upper_bound(d, 23); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::upper_bound(In, value) 4D") -{ - int data[2*3*4*5]; - int vdata[] = {1,0,0,0}; - - 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::upper_bound(d, 234); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::upper_bound(In, value, func) 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::upper_bound(d, 0, [](auto e, auto s) - { - return e > (s+1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - - -TTS_CASE("Check for kwk::upper_bound(In, value, func) 2D") -{ - int data[2*3]; - int vdata[] = {1,1}; - - const std::vector rdata {0, 1, 2, 10, 11, 12}; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - auto res = kwk::upper_bound(d, 9, [](auto e, auto s) - { - return e > (s+1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::upper_bound(In, value, func) 3D") -{ - int data[2*3*4]; - int vdata[] = {1,0,0}; - - 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::upper_bound(d, 22, [](auto e, auto s) - { - return e > (s+1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - -TTS_CASE("Check for kwk::upper_bound(In, value, func) 4D") -{ - int data[2*3*4*5]; - int vdata[] = {1,0,0,0}; - - 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::upper_bound(d, 233, [](auto e, auto s) - { - return e > (s+1); - }); - - if(res) - TTS_ALL_EQUAL(*res, vdata); - else - TTS_EXPECT(res == std::nullopt); -}; - - -TTS_CASE("Check for kwk::binary_search(In, value) 1D") -{ - int data[2]; - int needles[] = {0,1,2}; - - std::array res; - std::array vres {true, true, false}; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle)) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; - - -TTS_CASE("Check for kwk::binary_search(In, value) 2D") -{ - int data[2*3]; - int needles[] = {0,11,21}; - - std::array res; - std::array vres {true, true, false}; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle)) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; - -TTS_CASE("Check for kwk::binary_search(In, value) 3D") -{ - int data[2*3*4]; - int needles[] = {0,111,211}; - - std::array res; - std::array vres {true, true, false}; - - fill_data(data, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle)) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; - -TTS_CASE("Check for kwk::binary_search(In, value) 4D") -{ - int data[2*3*4*5]; - int needles[] = {0,1111,2111}; - - std::array res; - std::array vres {true, true, false}; - - 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)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle)) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; - -TTS_CASE("Check for kwk::binary_search(In, value, func) 1D") -{ - int data[2]; - int needles[] = {0,1,2}; - - std::array res; - std::array vres {true, true, false}; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle, [](auto e, auto s){return e < s;})) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; - - -TTS_CASE("Check for kwk::binary_search(In, value, func) 2D") -{ - int data[2*3]; - int needles[] = {0,11,21}; - - std::array res; - std::array vres {true, true, false}; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle, [](auto e, auto s){return e < s;})) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; - -TTS_CASE("Check for kwk::binary_search(In, value, func) 3D") -{ - int data[2*3*4]; - int needles[] = {0,111,211}; - - std::array res; - std::array vres {true, true, false}; - - fill_data(data, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle, [](auto e, auto s){return e < s;})) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; - -TTS_CASE("Check for kwk::binary_search(In, value, func) 4D") -{ - int data[2*3*4*5]; - int needles[] = {0,1111,2111}; - - std::array res; - std::array vres {true, true, false}; - - 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)}; - - size_t i = 0; - for (auto needle : needles) - if(kwk::binary_search(d, needle, [](auto e, auto s){return e < s;})) - res[i++] = true; - else - res[i++] = false; - - TTS_ALL_EQUAL(res, vres); -}; \ No newline at end of file diff --git a/test/algorithm/algos/binary_search/1d.cpp b/test/algorithm/algos/binary_search/1d.cpp new file mode 100644 index 00000000..4618f8bd --- /dev/null +++ b/test/algorithm/algos/binary_search/1d.cpp @@ -0,0 +1,637 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" +#include +#include + +// binary_search + +// Only tests 1D tables/views +// TODO: at some point, make algorithms work for nD + +TTS_CASE("Check for kwk::lower_bound(In, value) 1D") +{ + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // Valid values + { + int search = -2984612; + std::size_t expected = 0; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), (std::array{expected})); + TTS_EQUAL ((*kwk::lower_bound(view, search))[0] + , std::distance(std::lower_bound(input.begin(), input.end(), search), input.begin()) + ); + } + { + int search = 0; + std::size_t expected = 0; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), (std::array{expected})); + TTS_EQUAL ((*kwk::lower_bound(view, search))[0] + , std::distance(std::lower_bound(input.begin(), input.end(), search), input.begin()) + ); + } + { + int search = -1; + std::size_t expected = 0; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), (std::array{expected})); + TTS_EQUAL ((*kwk::lower_bound(view, search))[0] + , std::distance(std::lower_bound(input.begin(), input.end(), search), input.begin()) + ); + } + { + int search = 10; + std::size_t expected = 10; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), (std::array{expected})); + TTS_EQUAL ((*kwk::lower_bound(view, search))[0] + , std::distance(input.begin(), std::lower_bound(input.begin(), input.end(), search)) + ); + } + { + int search = 19; + std::size_t expected = 19; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), (std::array{expected})); + TTS_EQUAL ((*kwk::lower_bound(view, search))[0] + , std::distance(input.begin(), std::lower_bound(input.begin(), input.end(), search)) + ); + } + // Invalid values + { + int search = 20; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } +}; + +TTS_CASE("Check for kwk::lower_bound(In, value, func) 1D with function") +{ + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = (i - 10) * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto func = [](auto const& input_, auto const& element_) { return input_ < (element_ - 10) * 2; }; + + // Valid values + { + /*Compare values*/ + int search = -2984612; + std::size_t expected = 0; + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), r); + /*Compare with std implementation: compare found indexes*/ + TTS_EQUAL ( (*kwk::lower_bound(view, search, func))[0] + , (std::lower_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + { + /*Compare values*/ + int search = -1; + std::size_t expected = 0; + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), r); + /*Compare with std implementation: compare found indexes*/ + TTS_EQUAL ( (*kwk::lower_bound(view, search, func))[0] + , (std::lower_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + { + /*Compare values*/ + int search = 0; + std::size_t expected = 0; + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), r); + /*Compare with std implementation: compare found indexes*/ + TTS_EQUAL ( (*kwk::lower_bound(view, search, func))[0] + , (std::lower_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + { + /*Compare values*/ + int search = 9; + std::size_t expected = 9; + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), r); + /*Compare with std implementation: compare found indexes*/ + TTS_EQUAL ( (*kwk::lower_bound(view, search, func))[0] + , (std::lower_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + { + /*Compare values*/ + int search = 19; + std::size_t expected = 19; + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), r); + /*Compare with std implementation: compare found indexes*/ + TTS_EQUAL ( (*kwk::lower_bound(view, search, func))[0] + , (std::lower_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + + // Erroneous values + { + int search = 20; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + +TTS_CASE("Check for kwk::lower_bound 1D: size 0") +{ + std::vector input; // will not work for an std::array of size 0 + const std::size_t input_size = 0; + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto func = [](auto const& input_, auto const& element_) { return input_ < (element_ - 10) * 2; }; + + // Every value should lead to an invalid result + { + int search = -2984612; + // Checks that kwk::lower_bound returns an erroneous value + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + // Checks whether we shound really expect an erroneous value (std:: being our source of truth) + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = -1; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 0; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 19; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 20; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + + // With function + { + int search = -2984612; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = -1; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 0; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 19; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 20; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + + +TTS_CASE("Check for kwk::upper_bound(In, value) 1D") +{ + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // upper_bound returns the index of the first element above the specified value + { + int search = -78495; + std::size_t expected = 0; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search))[0] + , (std::upper_bound(input.begin(), input.end(), search) - input.begin()) + ); + } + { + int search = -1; + std::size_t expected = 0; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search))[0] + , (std::upper_bound(input.begin(), input.end(), search) - input.begin()) + ); + } + { + int search = 0; + std::size_t expected = 1; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search))[0] + , (std::upper_bound(input.begin(), input.end(), search) - input.begin()) + ); + } + { + int search = 18; + std::size_t expected = 19; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search))[0] + , (std::upper_bound(input.begin(), input.end(), search) - input.begin()) + ); + } + + // Erroneous values + { + int search = 19; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 20; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } +}; + + +TTS_CASE("Check for kwk::upper_bound(In, value) 1D with function") +{ + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3 - 20; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto func = [](auto const& search_, auto const& element_) { return search_ * 3 - 20 < element_; }; + + // upper_bound returns the index of the first element above the specified value + { + int search = -78495; + std::size_t expected = 0; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search, func))[0] + , (std::upper_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + { + int search = -1; + std::size_t expected = 0; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search, func))[0] + , (std::upper_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + { + int search = 0; + std::size_t expected = 1; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search, func))[0] + , (std::upper_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + { + int search = 18; + std::size_t expected = 19; + /*Compare values*/ + std::array r{expected}; + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), r); + /*Compare with std implementation*/ + TTS_EQUAL ( (*kwk::upper_bound(view, search, func))[0] + , (std::upper_bound(input.begin(), input.end(), search, func) - input.begin()) + ); + } + + // Erroneous values + { + int search = 19; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 20; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + +TTS_CASE("Check for kwk::upper_bound 1D: size = 0") +{ + const std::size_t input_size = 0; + std::vector input; // will not work for an std::array of size 0 + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3 - 20; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto func = [](auto const& search_, auto const& element_) { return search_ * 3 - 20 < element_; }; + + // Erroneous values + { + int search = -78495; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = -1; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 0; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 18; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 19; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 20; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + + // Erroneous values, with function + { + int search = -78495; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = -1; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 0; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 18; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 19; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 20; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = 78456465; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + +TTS_CASE("Check for kwk::binary_search(In, value) 1D") +{ + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // Ensures that the return value is expected + { + bool expected = false; + int search = -895; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = -1; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = 0; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18*3-1; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = 18*3; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18*3+1; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18*3+2; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = 19*3; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 20*3; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 2000*3; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 2000*3+1; + bool truth = kwk::binary_search(view, search); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search)); + } +}; + +TTS_CASE("Check for kwk::binary_search(In, value) 1D with function v1") +{ + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 3; } // * 3 - 20 + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + auto func = [](auto const& search_, auto const& element_) { return search_ < element_; }; + + + + // Ensures that the return value is expected + { + bool expected = false; + int search = -895; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = -1; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = 0; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18*3-1; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = 18*3; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18*3+1; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18*3+2; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = 19*3; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 20*3; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 2000*3; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 2000*3+1; + bool truth = kwk::binary_search(view, search, func); + TTS_EQUAL(truth, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(truth, std::binary_search(input.begin(), input.end(), search, func)); + } +}; diff --git a/test/algorithm/algos/binary_search/2d.cpp b/test/algorithm/algos/binary_search/2d.cpp new file mode 100644 index 00000000..923086b1 --- /dev/null +++ b/test/algorithm/algos/binary_search/2d.cpp @@ -0,0 +1,479 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" +#include +#include + +// binary_search + +// Only tests 2D tables/views +// TODO: at some point, make algorithms work for nD + +TTS_CASE("Check for kwk::lower_bound(In, value) 2D") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + // Valid values + { + int search = -2984612; + std::array expected{0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = 0; + std::array expected{0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = -1; + std::array expected{0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = 10; + std::array expected = lindex_to_pos_arr(d1, 10); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = input_size-1; + // {d0-1, d1-1} = lindex_to_pos_arr(d1, input_size-1); + std::array expected{d0-1, d1-1}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + // Invalid values + { + int search = input_size; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } +}; + +TTS_CASE("Check for kwk::lower_bound(In, value, func) 2D with function") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = (i - 10) * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto func = [](auto const& input_, auto const& element_) { return input_ < (element_ - 10) * 2; }; + + // Valid values + { + /*Compare values*/ + int search = -2984612; + std::array expected{0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = -1; + std::array expected{0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = 0; + std::array expected{0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = 9; + std::array expected = lindex_to_pos_arr(d1, 9); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = input_size-1; + std::array expected{d0-1, d1-1}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + + // Erroneous values + { + int search = input_size; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + + +TTS_CASE("Check for kwk::upper_bound(In, value) 2D") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + // upper_bound returns the index of the first element above the specified value + { + int search = -78495; + std::array expected{0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + { + int search = -1; + std::array expected{0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + { + int search = 0; + std::array expected{0, 1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + { + int search = input_size-2; + std::array expected{d0-1, d1-1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + + // Erroneous values + { + int search = input_size-1; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = input_size; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } +}; + + +TTS_CASE("Check for kwk::upper_bound(In, value) 2D with function") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + 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 - 20; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto func = [](auto const& search_, auto const& element_) { return search_ * 3 - 20 < element_; }; + + // upper_bound returns the index of the first element above the specified value + { + int search = -78495; + std::array expected{0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + { + int search = -1; + std::array expected{0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + { + int search = 0; + std::array expected{0, 1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + { + int search = input_size-2; + std::array expected{d0-1, d1-1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + + // Erroneous values + { + int search = input_size-1; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = input_size; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + + +TTS_CASE("Check for kwk::binary_search(In, value) 2D") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + 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 = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + // Ensures that the return value is expected + { + bool expected = false; + int search = -895; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = -1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = 0; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18 * 3 - 1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = 18 * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18 * 3 + 1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18 * 3 + 2; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = (input_size-1) * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = (input_size) * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3 + 1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } +}; + +TTS_CASE("Check for kwk::binary_search(In, value) 2D with function") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + 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; } // * 3 - 20 + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + auto func = [](auto const& search_, auto const& element_) { return search_ < element_; }; + + // Ensures that the return value is expected + { + bool expected = false; + int search = -895; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = -1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = 0; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18 * 3 - 1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = 18 * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18 * 3 + 1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18 * 3 + 2; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = (input_size-1) * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = (input_size) * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3 + 1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } +}; diff --git a/test/algorithm/algos/binary_search/4d.cpp b/test/algorithm/algos/binary_search/4d.cpp new file mode 100644 index 00000000..c4410fd6 --- /dev/null +++ b/test/algorithm/algos/binary_search/4d.cpp @@ -0,0 +1,491 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" +#include +#include + +// binary_search + +// Only tests 4D tables/views +// TODO: at some point, make algorithms work for nD + +TTS_CASE("Check for kwk::lower_bound(In, value) 4D") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t d2 = 6; + const std::size_t d3 = 14; + 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; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + // Valid values + { + int search = -2984612; + std::array expected{0, 0, 0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = 0; + std::array expected{0, 0, 0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = -1; + std::array expected{0, 0, 0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = 10; + std::array expected = lindex_to_pos_arr(d1, d2, d3, 10); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + { + int search = input_size-1; + // {d0-1, d1-1, d2-1, d3-1} = lindex_to_pos_arr(d1, d2, d3, input_size-1); + std::array expected{d0-1, d1-1, d2-1, d3-1}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), expected); + auto std_res = std::lower_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search), std_pos); + } + // Invalid values + { + int search = input_size; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::lower_bound(view, search), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search), input.end()); + } +}; + +TTS_CASE("Check for kwk::lower_bound(In, value, func) 4D with function") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t d2 = 6; + const std::size_t d3 = 14; + 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 - 10) * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto func = [](auto const& input_, auto const& element_) { return input_ < (element_ - 10) * 2; }; + + // Valid values + { + /*Compare values*/ + int search = -2984612; + std::array expected{0, 0, 0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = -1; + std::array expected{0, 0, 0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = 0; + std::array expected{0, 0, 0, 0}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = 9; + std::array expected = lindex_to_pos_arr(d1, d2, d3, 9); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + { + /*Compare values*/ + int search = input_size-1; + std::array expected{d0-1, d1-1, d2-1, d3-1}; + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), expected); + /*Compare with std implementation: compare found indexes*/ + auto std_res = std::lower_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::lower_bound(view, search, func), std_pos); + } + + // Erroneous values + { + int search = input_size; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::lower_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::lower_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + + +TTS_CASE("Check for kwk::upper_bound(In, value) 4D") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t d2 = 6; + const std::size_t d3 = 14; + 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; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + // upper_bound returns the index of the first element above the specified value + { + int search = -78495; + std::array expected{0, 0, 0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + { + int search = -1; + std::array expected{0, 0, 0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + { + int search = 0; + std::array expected{0, 0, 0, 1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + { + int search = input_size-2; + std::array expected{d0-1, d1-1, d2-1, d3-1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search), std_pos); + } + + // Erroneous values + { + int search = input_size-1; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = input_size; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::upper_bound(view, search), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search), input.end()); + } +}; + + +TTS_CASE("Check for kwk::upper_bound(In, value) 4D with function") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t d2 = 6; + const std::size_t d3 = 14; + 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 - 20; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto func = [](auto const& search_, auto const& element_) { return search_ * 3 - 20 < element_; }; + + // upper_bound returns the index of the first element above the specified value + { + int search = -78495; + std::array expected{0, 0, 0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + { + int search = -1; + std::array expected{0, 0, 0, 0}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + { + int search = 0; + std::array expected{0, 0, 0, 1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + { + int search = input_size-2; + std::array expected{d0-1, d1-1, d2-1, d3-1}; + /*Compare values*/ + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), expected); + /*Compare with std implementation*/ + auto std_res = std::upper_bound(input.begin(), input.end(), search, func); + auto std_pos = std_res_to_pos(std_res, input.begin(), d1, d2, d3); + TTS_ALL_EQUAL(*kwk::upper_bound(view, search, func), std_pos); + } + + // Erroneous values + { + int search = input_size-1; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = input_size; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } + { + int search = input_size + 784565; + TTS_EQUAL(kwk::upper_bound(view, search, func), std::nullopt); + TTS_EQUAL(std::upper_bound(input.begin(), input.end(), search, func), input.end()); + } +}; + + +TTS_CASE("Check for kwk::binary_search(In, value) 4D") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t d2 = 6; + const std::size_t d3 = 14; + 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 = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + // Ensures that the return value is expected + { + bool expected = false; + int search = -895; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = -1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = 0; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18 * 3 - 1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = 18 * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18 * 3 + 1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = 18 * 3 + 2; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = true; + int search = (input_size-1) * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = (input_size) * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3 + 1; + bool found = kwk::binary_search(view, search); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search)); + } +}; + +TTS_CASE("Check for kwk::binary_search(In, value) 4D with function") +{ + const std::size_t d0 = 8; + const std::size_t d1 = 12; + const std::size_t d2 = 6; + const std::size_t d3 = 14; + 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; } // * 3 - 20 + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + auto func = [](auto const& search_, auto const& element_) { return search_ < element_; }; + + // Ensures that the return value is expected + { + bool expected = false; + int search = -895; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = -1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = 0; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18 * 3 - 1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = 18 * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18 * 3 + 1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = 18 * 3 + 2; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = true; + int search = (input_size-1) * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = (input_size) * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } + { + bool expected = false; + int search = (input_size + 2000) * 3 + 1; + bool found = kwk::binary_search(view, search, func); + TTS_EQUAL(found, expected); // Ensures that we did not make a mistake with the expected value + TTS_EQUAL(found, std::binary_search(input.begin(), input.end(), search, func)); + } +}; diff --git a/test/algorithm/algos/context/cpu/copy.cpp b/test/algorithm/algos/context/cpu/copy.cpp new file mode 100644 index 00000000..2ca27fec --- /dev/null +++ b/test/algorithm/algos/context/cpu/copy.cpp @@ -0,0 +1,60 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" +#include "../generic/copy.hpp" + +// TODO: update these tests + +TTS_CASE("Check for kwk::copy(out, in) 1D") +{ + kwk::test::copy_out_in_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::copy(out, in) 2D") +{ + kwk::test::copy_out_in_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::copy(out, in) 3D") +{ + kwk::test::copy_out_in_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::copy(out, in) 4D") +{ + kwk::test::copy_out_in_4D(kwk::cpu); +}; + +TTS_CASE("Check for double kwk::copy(out, in) 2D") +{ + kwk::test::copy_out_in_2D_double(kwk::cpu); +}; + +TTS_CASE("Check for kwk::copy_if(func, out, in) 1D") +{ + kwk::test::copy_if_func_out_in_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::copy_if(func, out, in) 2D") +{ + kwk::test::copy_if_func_out_in_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::copy_if(func, out, in) 3D") +{ + kwk::test::copy_if_func_out_in_3D(kwk::cpu); +}; + + +TTS_CASE("Check for kwk::copy_if(func, out, in) 4D") +{ + kwk::test::copy_if_func_out_in_4D(kwk::cpu); +}; \ No newline at end of file diff --git a/test/algorithm/algos/context/cpu/predicates.cpp b/test/algorithm/algos/context/cpu/predicates.cpp new file mode 100644 index 00000000..d9485234 --- /dev/null +++ b/test/algorithm/algos/context/cpu/predicates.cpp @@ -0,0 +1,130 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" +#include "../generic/predicates.hpp" + +// TODO: update these tests + +TTS_CASE("Check for kwk::all_of(in, func) 1D") +{ + kwk::test::all_of_in_func_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::all_of(in, func) 2D") +{ + kwk::test::all_of_in_func_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::all_of(in, func) 3D") +{ + kwk::test::all_of_in_func_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::all_of(in, func) 4D") +{ + kwk::test::all_of_in_func_4D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::all_of(in, func) False") +{ + kwk::test::all_of_in_func_false(kwk::cpu); +}; + + +TTS_CASE("Check for kwk::any_of(in, func) 1D") +{ + kwk::test::any_of_in_func_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::any_of(in, func) 2D") +{ + kwk::test::any_of_in_func_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::any_of(in, func) 3D") +{ + kwk::test::any_of_in_func_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::any_of(in, func) 4D") +{ + kwk::test::any_of_in_func_4D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::any_of(in, func) False") +{ + kwk::test::any_of_in_func_false(kwk::cpu); +}; + +TTS_CASE("Check for kwk::none_of(in, func) 1D") +{ + kwk::test::none_of_in_func_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::none_of(in, func) 2D") +{ + kwk::test::none_of_in_func_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::none_of(in, func) 3D") +{ + kwk::test::none_of_in_func_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::none_of(in, func) 4D") +{ + kwk::test::none_of_in_func_4D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::none_of(in, func) False") +{ + kwk::test::none_of_in_func_false(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count(in, value) 1D") +{ + kwk::test::count_in_value_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count(in, value) 2D") +{ + kwk::test::count_in_value_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count(in, value) 3D") +{ + kwk::test::count_in_value_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count(in, value) 4D") +{ + kwk::test::count_in_value_4D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count_if(in, func) 1D") +{ + kwk::test::count_if_in_func_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count_if(in, func) 2D") +{ + kwk::test::count_if_in_func_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count_if(in, func) 3D") +{ + kwk::test::count_if_in_func_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::count_if(in, func) 4D") +{ + kwk::test::count_if_in_func_4D(kwk::cpu); +}; \ No newline at end of file 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/cpu/replace.cpp b/test/algorithm/algos/context/cpu/replace.cpp new file mode 100644 index 00000000..0c96b4d4 --- /dev/null +++ b/test/algorithm/algos/context/cpu/replace.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 "../generic/replace.hpp" + +// TODO: update these tests + +TTS_CASE("Check for kwk::replace(value, new_value) 1D") +{ + kwk::test::replace_value_new_value_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace(value, new_value) 2D") +{ + kwk::test::replace_value_new_value_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace(value, new_value) 3D") +{ + kwk::test::replace_value_new_value_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace(value, new_value) 4D") +{ + kwk::test::replace_value_new_value_4D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace_if(func, new_value) 1D") +{ + kwk::test::replace_if_func_new_value_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace_if(func, new_value) 2D") +{ + kwk::test::replace_if_func_new_value_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace_if(func, new_value) 3D") +{ + kwk::test::replace_if_func_new_value_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace_if(func, new_value) 4D") +{ + kwk::test::replace_if_func_new_value_4D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::replace_if(func, new_value) 4D smaller view - with CPU context") +{ + kwk::test::replace_if_func_new_value_4D_smaller_view(kwk::cpu); +}; diff --git a/test/algorithm/algos/context/cpu/transform.cpp b/test/algorithm/algos/context/cpu/transform.cpp new file mode 100644 index 00000000..d612dbf7 --- /dev/null +++ b/test/algorithm/algos/context/cpu/transform.cpp @@ -0,0 +1,34 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" +#include "../generic/transform.hpp" + +// TODO: update these tests + +TTS_CASE("Check for kwk::transform(value, new_value) 1D - CPU context") +{ + kwk::test::transform_value_new_value_1D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::transform(value, new_value) 2D - CPU context") +{ + kwk::test::transform_value_new_value_2D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::transform(value, new_value) 3D - CPU context") +{ + kwk::test::transform_value_new_value_3D(kwk::cpu); +}; + +TTS_CASE("Check for kwk::transform(value, new_value) 4D - CPU context") +{ + kwk::test::transform_value_new_value_4D(kwk::cpu); +}; diff --git a/test/algorithm/algos/context/generic/copy.hpp b/test/algorithm/algos/context/generic/copy.hpp new file mode 100644 index 00000000..e9e26b33 --- /dev/null +++ b/test/algorithm/algos/context/generic/copy.hpp @@ -0,0 +1,214 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" + +// TODO: update these tests + +namespace kwk::test +{ + // TTS_CASE("Check for kwk::copy(out, in) 1D") + template + void copy_out_in_1D(Context&& ctx) + { + int data[2]; + + fill_data(data, kwk::of_size(2), true); + + int vdata[2]; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + auto v = kwk::view{kwk::source = vdata, kwk::of_size(2)}; + + kwk::copy(ctx, v, d); + + TTS_ALL_EQUAL(data, vdata); + }; + + // TTS_CASE("Check for kwk::copy(out, in) 2D") + template + void copy_out_in_2D(Context&& ctx) + { + int data[2*3]; + + fill_data(data, kwk::of_size(2,3), true); + + int vdata[2*3]; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3)}; + + kwk::copy(ctx, v, d); + + TTS_ALL_EQUAL(data, vdata); + }; + + // TTS_CASE("Check for kwk::copy(out, in) 3D") + template + void copy_out_in_3D(Context&& ctx) + { + int data[2*3*4]; + + fill_data(data, kwk::of_size(2,3,4), true); + + int vdata[2*3*4]; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3,4)}; + + kwk::copy(ctx, v, d); + + TTS_ALL_EQUAL(data, vdata); + }; + + // TTS_CASE("Check for kwk::copy(out, in) 4D") + template + void copy_out_in_4D(Context&& ctx) + { + int data[2*3*4*5]; + + fill_data(data, kwk::of_size(2,3,4,5), true); + + int vdata[2*3*4*5]; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3,4,5)}; + + kwk::copy(ctx, v, d); + + TTS_ALL_EQUAL(data, vdata); + }; + + // TTS_CASE("Check for double kwk::copy(out, in) 2D") + template + void copy_out_in_2D_double(Context&& ctx) + { + double data[2*3]; + + fill_data(data, kwk::of_size(2,3), true); + + double vdata[2*3]; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3)}; + + kwk::copy(ctx, v, d); + + TTS_ALL_EQUAL(data, vdata); + }; + + // TTS_CASE("Check for kwk::copy_if(func, out, in) 1D") + template + void copy_if_func_out_in_1D(Context&& ctx) + { + int data[2]; + + fill_data(data, kwk::of_size(2), true); + + int rdata[2]; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + auto r = kwk::view{kwk::source = rdata, kwk::of_size(2)}; + + kwk::copy_if(ctx, [](auto e) + { + return (e<1); + } + ,r, d); + + TTS_EQUAL(rdata[0], 0); + }; + + // TTS_CASE("Check for kwk::copy_if(func, out, in) 2D") + template + void copy_if_func_out_in_2D(Context&& ctx) + { + int data[2*3]; + fill_data(data, kwk::of_size(2,3), true); + + int rdata[2*3]; + fill_data(rdata, kwk::of_size(2,3), false); + + int vdata[2*3]; + fill_data(vdata, kwk::of_size(2,3), false); + + vdata[1*3+0] = 10; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + auto r = kwk::view{kwk::source = rdata, kwk::of_size(2,3)}; + + kwk::copy_if(ctx, [](auto e) + { + return (e==10); + } + ,r, d); + + TTS_ALL_EQUAL(rdata, vdata); + }; + + // TTS_CASE("Check for kwk::copy_if(func, out, in) 3D") + template + void copy_if_func_out_in_3D(Context&& ctx) + { + int data[2*3*4]; + fill_data(data, kwk::of_size(2,3,4), true); + + int rdata[2*3*4]; + fill_data(rdata, kwk::of_size(2,3,4), false); + + int vdata[2*3*4]; + fill_data(vdata, kwk::of_size(2,3,4), false); + + vdata[1*4*3+0+3] = 103; + vdata[0+1*4+3] = 13; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + auto r = kwk::view{kwk::source = rdata, kwk::of_size(2,3,4)}; + + kwk::copy_if(ctx, [](auto e) + { + return (e==103 || e==13); + } + ,r, d); + + TTS_ALL_EQUAL(rdata, vdata); + }; + + + // TTS_CASE("Check for kwk::copy_if(func, out, in) 4D") + template + void copy_if_func_out_in_4D(Context&& ctx) + { + int data[2*3*4*5]; + fill_data(data, kwk::of_size(2,3,4,5), true); + + int rdata[2*3*4*5]; + fill_data(rdata, kwk::of_size(2,3,4,5), false); + + int vdata[2*3*4*5]; + fill_data(vdata, kwk::of_size(2,3,4,5), false); + + vdata[0+0+0+1] = 1; + vdata[0+0+0+2] = 2; + vdata[0+0+0+3] = 3; + vdata[0+0+0+4] = 4; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + auto r = kwk::view{kwk::source = rdata, kwk::of_size(2,3,4,5)}; + + kwk::copy_if(ctx, [](auto e) + { + return (e<10); + } + ,r, d); + + TTS_ALL_EQUAL(rdata, vdata); + }; +} \ No newline at end of file diff --git a/test/algorithm/algos/context/generic/predicates.hpp b/test/algorithm/algos/context/generic/predicates.hpp new file mode 100644 index 00000000..338d5a48 --- /dev/null +++ b/test/algorithm/algos/context/generic/predicates.hpp @@ -0,0 +1,436 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" + +// TODO: update these tests + +namespace kwk::test +{ + // void reduce_in_1D_larger(Context&& ctx) + template + void all_of_in_func_1D(Context&& ctx) + { + int data[2]; + bool vdata = true; + + fill_data(data, kwk::of_size(2), false); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + auto res = kwk::all_of(ctx, d, [&](auto e) + { + return (e == 0); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::all_of(in, func) 2D") + template + void all_of_in_func_2D(Context&& ctx) + { + int data[2*3]; + bool vdata = true; + + fill_data(data, kwk::of_size(2,3), false); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + auto res = kwk::all_of(ctx, d, [&](auto e) + { + return (e == 0); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::all_of(in, func) 3D") + template + void all_of_in_func_3D(Context&& ctx) + { + int data[2*3*4]; + bool vdata = true; + + fill_data(data, kwk::of_size(2,3,4), false); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + auto res = kwk::all_of(ctx, d, [&](auto e) + { + return (e == 0); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::all_of(in, func) 4D") + template + void all_of_in_func_4D(Context&& ctx) + { + int data[2*3*4*5]; + bool vdata = true; + + fill_data(data, kwk::of_size(2,3,4,5), false); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + + auto res = kwk::all_of(ctx, d, [&](auto e) + { + return (e == 0); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::all_of(in, func) False") + template + void all_of_in_func_false(Context&& ctx) + { + int data[2*2] = { 2,2 + , 2,3 + }; + + bool vdata = false; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; + + auto res = kwk::all_of(ctx, d, [&](auto e) + { + return (e == 2); + }); + + TTS_EQUAL(res, vdata); + }; + + + // TTS_CASE("Check for kwk::any_of(in, func) 1D") + template + void any_of_in_func_1D(Context&& ctx) + { + int data[2]; + bool vdata = true; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + + auto res = kwk::any_of(ctx, d, [&](auto e) + { + return (e == 1); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::any_of(in, func) 2D") + template + void any_of_in_func_2D(Context&& ctx) + { + int data[2*3]; + bool vdata = true; + + fill_data(data, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + auto res = kwk::any_of(ctx, d, [&](auto e) + { + return (e == 12); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::any_of(in, func) 3D") + template + void any_of_in_func_3D(Context&& ctx) + { + int data[2*3*4]; + bool vdata = true; + + 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::any_of(ctx, d, [&](auto e) + { + return (e == 123); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::any_of(in, func) 4D") + template + void any_of_in_func_4D(Context&& ctx) + { + int data[2*3*4*5]; + bool vdata = true; + + 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::any_of(ctx, d, [&](auto e) + { + return (e == 1234); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::any_of(in, func) False") + template + void any_of_in_func_false(Context&& ctx) + { + int data[2*2] = { 2,2 + , 2,2 + }; + + bool vdata = false; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; + + auto res = kwk::any_of(ctx, d, [&](auto e) + { + return (e == 3); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::none_of(in, func) 1D") + template + void none_of_in_func_1D(Context&& ctx) + { + int data[2]; + bool vdata = true; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + + auto res = kwk::none_of(ctx, d, [&](auto e) + { + return (e == 2); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::none_of(in, func) 2D") + template + void none_of_in_func_2D(Context&& ctx) + { + int data[2*3]; + bool vdata = true; + + fill_data(data, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + auto res = kwk::none_of(ctx, d, [&](auto e) + { + return (e == 23); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::none_of(in, func) 3D") + template + void none_of_in_func_3D(Context&& ctx) + { + int data[2*3*4]; + bool vdata = true; + + 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::none_of(ctx, d, [&](auto e) + { + return (e == 234); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::none_of(in, func) 4D") + template + void none_of_in_func_4D(Context&& ctx) + { + int data[2*3*4*5]; + bool vdata = true; + + 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::none_of(ctx, d, [&](auto e) + { + return (e == 2345); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::none_of(in, func) False") + template + void none_of_in_func_false(Context&& ctx) + { + int data[2*2] = { 3,2 + , 2,2 + }; + + bool vdata = false; + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; + + auto res = kwk::none_of(ctx, d, [&](auto e) + { + return (e == 3); + }); + + TTS_EQUAL(res, vdata); + }; + + // TTS_CASE("Check for kwk::count(in, value) 1D") + template + void count_in_value_1D(Context&& ctx) + { + int data[2]; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + + unsigned long res = kwk::count(ctx, d, 1); + + TTS_EQUAL(res, 1UL); + }; + + // TTS_CASE("Check for kwk::count(in, value) 2D") + template + void count_in_value_2D(Context&& ctx) + { + int data[2*3]; + + fill_data(data, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + unsigned long res = kwk::count(ctx, d, 12); + + TTS_EQUAL(res, 1UL); + }; + + // TTS_CASE("Check for kwk::count(in, value) 3D") + template + void count_in_value_3D(Context&& ctx) + { + int data[2*3*4]; + + fill_data(data, kwk::of_size(2,3,4), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + unsigned long res = kwk::count(ctx, d, 123); + + TTS_EQUAL(res, 1UL); + }; + + // TTS_CASE("Check for kwk::count(in, value) 4D") + template + void count_in_value_4D(Context&& ctx) + { + int data[2*3*4*5]; + + 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)}; + + unsigned long res = kwk::count(ctx, d, 1234); + + TTS_EQUAL(res, 1UL); + }; + + // TTS_CASE("Check for kwk::count_if(in, func) 1D") + template + void count_if_in_func_1D(Context&& ctx) + { + int data[2]; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + + unsigned long res = kwk::count_if(ctx, d, [&](auto e) + { + return (e >= 0); + }); + + TTS_EQUAL(res, 2UL); + }; + + // TTS_CASE("Check for kwk::count_if(in, func) 2D") + template + void count_if_in_func_2D(Context&& ctx) + { + int data[2*3]; + + fill_data(data, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + unsigned long res = kwk::count_if(ctx, d, [&](auto e) + { + return (e >= 10); + }); + + TTS_EQUAL(res, 3UL); + }; + + // TTS_CASE("Check for kwk::count_if(in, func) 3D") + template + void count_if_in_func_3D(Context&& ctx) + { + int data[2*3*4]; + + fill_data(data, kwk::of_size(2,3,4), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + unsigned long res = kwk::count_if(ctx, d, [&](auto e) + { + return (e >= 120); + }); + + TTS_EQUAL(res, 4UL); + }; + + // TTS_CASE("Check for kwk::count_if(in, func) 4D") + template + void count_if_in_func_4D(Context&& ctx) + { + int data[2*3*4*5]; + + 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)}; + + unsigned long res = kwk::count_if(ctx, d, [&](auto e) + { + return (e >= 1230); + }); + + TTS_EQUAL(res, 5UL); + }; +} \ 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/context/generic/replace.hpp b/test/algorithm/algos/context/generic/replace.hpp new file mode 100644 index 00000000..c997624c --- /dev/null +++ b/test/algorithm/algos/context/generic/replace.hpp @@ -0,0 +1,176 @@ +//====================================================================================================================== +/* + 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 replace_value_new_value_1D(Context&& ctx) + { + int data[2]; + int vdata[2]; + + fill_data(data, kwk::of_size(2), true); + fill_data(vdata, kwk::of_size(2), true); + + vdata[1] = 10; + + auto v = kwk::view{kwk::source = data, kwk::of_size(2)}; + + ::kwk::replace(ctx, v, 1, 10); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_value_new_value_2D(Context&& ctx) + { + int data[2*3]; + int vdata[2*3]; + + fill_data(data, kwk::of_size(2,3), true); + fill_data(vdata, kwk::of_size(2,3), true); + + vdata[1*3+2] = 120; + + auto v = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + ::kwk::replace(ctx, v, 12, 120); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_value_new_value_3D(Context&& ctx) + { + int data[2*3*4]; + int vdata[2*3*4]; + + fill_data(data, kwk::of_size(2,3,4), true); + fill_data(vdata, kwk::of_size(2,3,4), true); + + vdata[1*4*3+2*4+3] = 1230; + + auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + ::kwk::replace(ctx, v, 123, 1230); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_value_new_value_4D(Context&& ctx) + { + int data[2*3*4*5]; + int vdata[2*3*4*5]; + + fill_data(data, kwk::of_size(2,3,4,5), true); + fill_data(vdata, kwk::of_size(2,3,4,5), true); + + vdata[1*5*4*3+2*5*4+3*5+4] = 12340; + + auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + + ::kwk::replace(ctx, v, 1234, 12340); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_if_func_new_value_1D(Context&& ctx) + { + int data[2]; + int vdata[2]; + + fill_data(data, kwk::of_size(2), true); + fill_data(vdata, kwk::of_size(2), false); + + auto v = kwk::view{kwk::source = data, kwk::of_size(2)}; + + ::kwk::replace_if(ctx, v, [&](auto e) { return (e>=0); }, 0); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_if_func_new_value_2D(Context&& ctx) + { + int data[2*3]; + int vdata[2*3]; + + fill_data(data, kwk::of_size(2,3), true); + fill_data(vdata, kwk::of_size(2,3), false); + + auto v = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + + ::kwk::replace_if(ctx, v, [&](auto e) { return (e>=0); }, 0); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_if_func_new_value_3D(Context&& ctx) + { + int data[2*3*4]; + int vdata[2*3*4]; + + fill_data(data, kwk::of_size(2,3,4), true); + fill_data(vdata, kwk::of_size(2,3,4), false); + + auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + + ::kwk::replace_if(ctx, v, [&](auto e) { return (e>=0); }, 0); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_if_func_new_value_4D(Context&& ctx) + { + int data[2*3*4*5]; + int vdata[2*3*4*5]; + + fill_data(data, kwk::of_size(2,3,4,5), true); + fill_data(vdata, kwk::of_size(2,3,4,5), false); + + auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + + ::kwk::replace_if(ctx, v, [&](auto e) { return (e>=0); }, 0); + + TTS_ALL_EQUAL(data, vdata); + }; + + template + void replace_if_func_new_value_4D_smaller_view(Context&& ctx) + { + int data[2*3*4*5]; + int vdata[2*3*4*5]; + + fill_data(data, kwk::of_size(2,3,4,5), true); + fill_data(vdata, kwk::of_size(2,3,4,5), false); + + for(int j = 0; j<3; j++) + for(int k = 0; k<4; k++) + for(int l = 0; l<5; l++) + vdata[1*5*4*3+j*5*4+k*5+l] = 1000+100*j+10*k+l; + + auto v = kwk::view{kwk::source = data, kwk::of_size(1,3,4,5)}; + + ::kwk::replace_if(ctx, v, [&](auto e) { return (e>=0); }, 0); + + TTS_ALL_EQUAL(data, vdata); + }; +} \ No newline at end of file diff --git a/test/algorithm/algos/context/generic/transform.hpp b/test/algorithm/algos/context/generic/transform.hpp new file mode 100644 index 00000000..cf81a852 --- /dev/null +++ b/test/algorithm/algos/context/generic/transform.hpp @@ -0,0 +1,104 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#pragma once + +#include +#include +#include "test.hpp" + +// TODO: update these tests + +namespace kwk::test +{ + template + void transform_value_new_value_1D(Context&& ctx) + { + int data[2]; + double res[2]; + double vdata[2] = {1, 0.5}; + + fill_data(data, kwk::of_size(2), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + auto v = kwk::view{kwk::source = res, kwk::of_size(2)}; + + ::kwk::transform(ctx, [&](auto e) { return 1.0/(1.0+e); }, v, d); + + TTS_ALL_EQUAL(res, vdata); + } + + template + void transform_value_new_value_2D(Context&& ctx) + { + int data[2*3]; + double res[2*3]; + double vdata[2*3]; + + fill_data(data, kwk::of_size(2,3), true); + fill_data(vdata, kwk::of_size(2,3), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + auto v = kwk::view{kwk::source = res, kwk::of_size(2,3)}; + + for(int i = 0; i<2; i++) + for(int j = 0; j<3; j++) + vdata[i*3+j] = 1.0/(1.0+vdata[i*3+j]); + + ::kwk::transform(ctx, [&](auto e) { return 1.0/(1.0+e); }, v, d); + + TTS_ALL_EQUAL(res, vdata); + }; + + template + void transform_value_new_value_3D(Context&& ctx) + { + int data[2*3*4]; + double res[2*3*4]; + double vdata[2*3*4]; + + fill_data(data, kwk::of_size(2,3,4), true); + fill_data(vdata, kwk::of_size(2,3,4), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + auto v = kwk::view{kwk::source = res, kwk::of_size(2,3,4)}; + + for(int i = 0; i<2; i++) + for(int j = 0; j<3; j++) + for(int k = 0; k<4; k++) + vdata[i*4*3+j*4+k] = 1.0/(1.0+vdata[i*4*3+j*4+k]); + + ::kwk::transform(ctx, [&](auto e) { return 1.0/(1.0+e); }, v, d); + + TTS_ALL_EQUAL(res, vdata); + }; + + template + void transform_value_new_value_4D(Context&& ctx) + { + int data[2*3*4*5]; + double res[2*3*4*5]; + double vdata[2*3*4*5]; + + fill_data(data, kwk::of_size(2,3,4,5), true); + fill_data(vdata, kwk::of_size(2,3,4,5), true); + + auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + auto v = kwk::view{kwk::source = res, kwk::of_size(2,3,4,5)}; + + for(int i = 0; i<2; i++) + for(int j = 0; j<3; j++) + for(int k = 0; k<4; k++) + for(int l = 0; l<5; l++) + vdata[i*5*4*3+j*5*4+k*5+l] = 1.0/(1.0+vdata[i*5*4*3+j*5*4+k*5+l]); + + ::kwk::transform(ctx, [&](auto e) { return 1.0/(1.0+e); }, v, d); + + TTS_ALL_EQUAL(res, vdata); + }; + +} \ No newline at end of file diff --git a/test/algorithm/algos/copy.cpp b/test/algorithm/algos/copy.cpp deleted file mode 100644 index 6b36b68a..00000000 --- a/test/algorithm/algos/copy.cpp +++ /dev/null @@ -1,203 +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::copy(out, in) 1D") -{ - int data[2]; - - fill_data(data, kwk::of_size(2), true); - - int vdata[2]; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - auto v = kwk::view{kwk::source = vdata, kwk::of_size(2)}; - - kwk::copy(v, d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::copy(out, in) 2D") -{ - int data[2*3]; - - fill_data(data, kwk::of_size(2,3), true); - - int vdata[2*3]; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3)}; - - kwk::copy(v, d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::copy(out, in) 3D") -{ - int data[2*3*4]; - - fill_data(data, kwk::of_size(2,3,4), true); - - int vdata[2*3*4]; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3,4)}; - - kwk::copy(v, d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::copy(out, in) 4D") -{ - int data[2*3*4*5]; - - fill_data(data, kwk::of_size(2,3,4,5), true); - - int vdata[2*3*4*5]; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3,4,5)}; - - kwk::copy(v, d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for double kwk::copy(out, in) 2D") -{ - double data[2*3]; - - fill_data(data, kwk::of_size(2,3), true); - - double vdata[2*3]; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - auto v = kwk::view{kwk::source = vdata, kwk::of_size(2,3)}; - - kwk::copy(v, d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::copy_if(func, out, in) 1D") -{ - int data[2]; - - fill_data(data, kwk::of_size(2), true); - - int rdata[2]; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - auto r = kwk::view{kwk::source = rdata, kwk::of_size(2)}; - - int count = 0; - kwk::copy_if([&](auto e) - { - count++; - return (e<1); - } - ,r, d); - - TTS_EQUAL(rdata[0], 0); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::copy_if(func, out, in) 2D") -{ - int data[2*3]; - fill_data(data, kwk::of_size(2,3), true); - - int rdata[2*3]; - fill_data(rdata, kwk::of_size(2,3), false); - - int vdata[2*3]; - fill_data(vdata, kwk::of_size(2,3), false); - - vdata[1*3+0] = 10; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - auto r = kwk::view{kwk::source = rdata, kwk::of_size(2,3)}; - - int count = 0; - kwk::copy_if([&](auto e) - { - count++; - return (e==10); - } - ,r, d); - - TTS_ALL_EQUAL(rdata, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::copy_if(func, out, in) 3D") -{ - int data[2*3*4]; - fill_data(data, kwk::of_size(2,3,4), true); - - int rdata[2*3*4]; - fill_data(rdata, kwk::of_size(2,3,4), false); - - int vdata[2*3*4]; - fill_data(vdata, kwk::of_size(2,3,4), false); - - vdata[1*4*3+0+3] = 103; - vdata[0+1*4+3] = 13; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - auto r = kwk::view{kwk::source = rdata, kwk::of_size(2,3,4)}; - - int count = 0; - kwk::copy_if([&](auto e) - { - count++; - return (e==103 || e==13); - } - ,r, d); - - TTS_ALL_EQUAL(rdata, vdata); - TTS_EQUAL(count, d.numel()); -}; - - -TTS_CASE("Check for kwk::copy_if(func, out, in) 4D") -{ - int data[2*3*4*5]; - fill_data(data, kwk::of_size(2,3,4,5), true); - - int rdata[2*3*4*5]; - fill_data(rdata, kwk::of_size(2,3,4,5), false); - - int vdata[2*3*4*5]; - fill_data(vdata, kwk::of_size(2,3,4,5), false); - - vdata[0+0+0+1] = 1; - vdata[0+0+0+2] = 2; - vdata[0+0+0+3] = 3; - vdata[0+0+0+4] = 4; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - auto r = kwk::view{kwk::source = rdata, kwk::of_size(2,3,4,5)}; - - int count = 0; - kwk::copy_if([&](auto e) - { - count++; - return (e<10); - } - ,r, d); - - TTS_ALL_EQUAL(rdata, vdata); - TTS_EQUAL(count, d.numel()); -}; \ No newline at end of file diff --git a/test/algorithm/algos/copy/1d.cpp b/test/algorithm/algos/copy/1d.cpp new file mode 100644 index 00000000..b7041135 --- /dev/null +++ b/test/algorithm/algos/copy/1d.cpp @@ -0,0 +1,138 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" + +// copy 1D + +TTS_CASE("Check for kwk::copy(out, in) 1D") +{ + const std::size_t input_size = 200; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(output_size)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + +TTS_CASE("Check for kwk::copy(out, in) 1D with double") +{ + const std::size_t input_size = 200; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(output_size)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + +TTS_CASE("Check for kwk::copy(out, in) 1D size 1000000") +{ + const std::size_t input_size = 1000000; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(output_size)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + +TTS_CASE("Check for kwk::copy(out, in) 1D size 1") +{ + const std::size_t input_size = 1; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(output_size)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + +TTS_CASE("Check for kwk::copy(out, in) 1D size 0") +{ + std::vector input; + std::vector output; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(0)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(0)}; + + kwk::copy(view_output, view_input); + + TTS_EQUAL(output.size(), 0UL); +}; + + +TTS_CASE("Check for kwk::copy_if(func, out, in) 1D") +{ + const std::size_t input_size = 200; + const std::size_t output_size = input_size; + std::array input; + std::array output; + std::array expected; + input.fill(0); + output.fill(0); + expected.fill(0); + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(output_size)}; + + std::size_t count = 0; // Only compatible with sequential CPU code... + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + auto func = [&](auto e) { ++count; return (e < 101); }; + + for (std::size_t i = 0; i < output_size; ++i) + { + expected[i] = func(input[i]) ? input[i] : 0; + }; + TTS_EQUAL(count, output_size); + + count = 0; + kwk::copy_if(func, view_output, view_input); + TTS_EQUAL(count, output_size); + + TTS_ALL_EQUAL(output, expected); +}; + + + +TTS_CASE("Check for kwk::copy(out, in, func) 1D size 0") +{ + std::vector input; + std::vector output; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(0)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(0)}; + auto func = [&](auto e) { return (e < 101); }; + + kwk::copy_if(func, view_output, view_input); + + TTS_EQUAL(output.size(), 0UL); +}; \ No newline at end of file diff --git a/test/algorithm/algos/copy/2d.cpp b/test/algorithm/algos/copy/2d.cpp new file mode 100644 index 00000000..69efddd7 --- /dev/null +++ b/test/algorithm/algos/copy/2d.cpp @@ -0,0 +1,85 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" + +// copy 4D + +TTS_CASE("Check for kwk::copy(out, in) 4D") +{ + const std::size_t d0 = 12; + const std::size_t d1 = 70; + const std::size_t input_size = d0 * d1; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + + +TTS_CASE("Check for kwk::copy(out, in) 4D with double") +{ + + const std::size_t d0 = 12; + const std::size_t d1 = 70; + const std::size_t input_size = d0 * d1; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + + +TTS_CASE("Check for kwk::copy_if(func, out, in) 4D") +{ + const std::size_t d0 = 12; + const std::size_t d1 = 70; + const std::size_t input_size = d0 * d1; + const std::size_t output_size = input_size; + std::array input; + std::array output; + std::array expected; + input.fill(0); + output.fill(0); + expected.fill(0); + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + std::size_t count = 0; // Only compatible with sequential CPU code... + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + auto func = [&](auto e) { ++count; return (e < 101); }; + + for (std::size_t i = 0; i < output_size; ++i) + { + expected[i] = func(input[i]) ? input[i] : 0; + }; + TTS_EQUAL(count, output_size); + + count = 0; + kwk::copy_if(func, view_output, view_input); + TTS_EQUAL(count, output_size); + + TTS_ALL_EQUAL(output, expected); +}; diff --git a/test/algorithm/algos/copy/4d.cpp b/test/algorithm/algos/copy/4d.cpp new file mode 100644 index 00000000..c9239066 --- /dev/null +++ b/test/algorithm/algos/copy/4d.cpp @@ -0,0 +1,91 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" + +// copy 4D + +TTS_CASE("Check for kwk::copy(out, in) 4D") +{ + const std::size_t d0 = 12; + const std::size_t d1 = 70; + const std::size_t d2 = 8; + const std::size_t d3 = 18; + const std::size_t input_size = d0 * d1 * d2 * d3; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + + +TTS_CASE("Check for kwk::copy(out, in) 4D with double") +{ + + const std::size_t d0 = 12; + const std::size_t d1 = 70; + const std::size_t d2 = 8; + const std::size_t d3 = 18; + const std::size_t input_size = d0 * d1 * d2 * d3; + const std::size_t output_size = input_size; + std::array input; + std::array output; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::copy(view_output, view_input); + + TTS_ALL_EQUAL(input, output); +}; + + +TTS_CASE("Check for kwk::copy_if(func, out, in) 4D") +{ + const std::size_t d0 = 12; + const std::size_t d1 = 70; + const std::size_t d2 = 8; + const std::size_t d3 = 18; + const std::size_t input_size = d0 * d1 * d2 * d3; + const std::size_t output_size = input_size; + std::array input; + std::array output; + std::array expected; + input.fill(0); + output.fill(0); + expected.fill(0); + + auto view_input = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto view_output = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; // Only compatible with sequential CPU code... + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; }; + auto func = [&](auto e) { ++count; return (e < 101); }; + + for (std::size_t i = 0; i < output_size; ++i) + { + expected[i] = func(input[i]) ? input[i] : 0; + }; + TTS_EQUAL(count, output_size); + + count = 0; + kwk::copy_if(func, view_output, view_input); + TTS_EQUAL(count, output_size); + + TTS_ALL_EQUAL(output, expected); +}; diff --git a/test/algorithm/algos/find.cpp b/test/algorithm/algos/find.cpp deleted file mode 100644 index 78bfbc5d..00000000 --- a/test/algorithm/algos/find.cpp +++ /dev/null @@ -1,455 +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::find(In, value) 1D") -{ - int data[2]; - auto vdata = kumi::iota<1>(1); - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - auto res = kwk::find(d, 1); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find(In, value) 2D") -{ - int data[2*3]; - auto vdata = kumi::iota<2>(1); - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - auto res = kwk::find(d, 12); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find(In, value) 3D") -{ - int data[2*3*4]; - auto vdata = kumi::iota<3>(1); - - 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::find(d, 123); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find(In, value) 4D") -{ - int data[2*3*4*5]; - auto vdata = kumi::iota<4>(1); - - 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::find(d, 1234); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_if(In, func) 1D") -{ - int data[2]; - auto vdata = kumi::iota<1>(1); - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = kwk::find_if(d, [&](auto e){ count++; return (e==1); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::find_if(In, func) 2D") -{ - int data[2*3]; - auto vdata = kumi::iota<2>(1); - - 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 = kwk::find_if(d, [&](auto e){ count++; return (e==12); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::find_if(In, func) 3D") -{ - int data[2*3*4]; - auto vdata = kumi::iota<3>(1); - - 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 = kwk::find_if(d, [&](auto e){ count++; return (e==123); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::find_if(In, func) 4D") -{ - int data[2*3*4*5]; - auto vdata = kumi::iota<4>(1); - - 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 = kwk::find_if(d, [&](auto e){ count++; return (e==1234); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - - -TTS_CASE("Check for kwk::find_if_not(In, func) 1D") -{ - int data[2]; - auto vdata = kumi::iota<1>(1); - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = kwk::find_if_not(d, [&](auto e){ count++; return (e<1); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::find_if_not(In, func) 2D") -{ - int data[2*3]; - auto vdata = kumi::iota<2>(1); - - 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 = kwk::find_if_not(d, [&](auto e){ count++; return (e<12); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::find_if_not(In, func) 3D") -{ - int data[2*3*4]; - auto vdata = kumi::iota<3>(1); - - 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 = kwk::find_if_not(d, [&](auto e){ count++; return (e<123); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::find_if_not(In, func) 4D") -{ - int data[2*3*4*5]; - auto vdata = kumi::iota<4>(1); - - 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 = kwk::find_if_not(d, [&](auto e){ count++; return (e<1234); }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - - -TTS_CASE("Check for kwk::find_first_of(In, func) 1D") -{ - int data[2]; - int value[] = {1111, 11111, 30, 1, 12}; - auto vdata = kumi::generate<1,int>(1); - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - auto v = kwk::view{kwk::source = value}; - - auto res = kwk::find_first_of(d, v); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_first_of(In, func) 2D") -{ - int data[2*3]; - int value[] = {11, 12}; - auto vdata = kumi::generate<2, int>(1); - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - auto v = kwk::view{kwk::source = value}; - - auto res = kwk::find_first_of(d, v); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_first_of(In, func) 3D") -{ - int data[2*3*4]; - int value[] = {111, 122}; - auto vdata = kumi::generate<3, int>(1); - - fill_data(data, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - auto v = kwk::view{kwk::source = value}; - - auto res = kwk::find_first_of(d, v); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_first_of(In, func) 4D") -{ - int data[2*3*4*5]; - int value[] = {1111, 1222}; - auto vdata = kumi::generate<4, int>(1); - - 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 v = kwk::view{kwk::source = value}; - - auto res = kwk::find_first_of(d, v); - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_last(In, value) 1D") -{ - int data[2]; - auto vdata = kumi::iota<1>(1); - - fill_data(data, kwk::of_size(2), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - auto res = kwk::find_last(d, 0); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -// Wait for merge V2 -// TTS_CASE("Check for kwk::find_last(In, value) 2D") -// { -// int data[2*3]; -// auto vdata = kumi::iota<2>(1); - -// fill_data(data, kwk::of_size(2,3), false); - -// auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - -// auto res = kwk::find_last(d, 0); - -// std::cout << res << std::endl; - -// TTS_EQUAL(res, vdata); -// }; - -TTS_CASE("Check for kwk::find_last(In, value) 3D") -{ - int data[2*3*4]; - auto vdata = kumi::iota<3>(1); - - fill_data(data, kwk::of_size(2,3,4), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - auto res = kwk::find_last(d, 0); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_last(In, value) 4D") -{ - int data[2*3*4*5]; - auto vdata = kumi::iota<4>(1); - - fill_data(data, kwk::of_size(2,3,4,5), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - auto res = kwk::find_last(d, 0); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_last_if(In, value) 1D") -{ - int data[2]; - auto vdata = kumi::iota<1>(1); - - fill_data(data, kwk::of_size(2), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - auto res = kwk::find_last_if(d, [](auto e){return e==0;}); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -// Wait merge shape V2 -// TTS_CASE("Check for kwk::find_last_if(In, value) 2D") -// { -// int data[2*3]; -// auto vdata = kumi::iota<2>(1); - -// fill_data(data, kwk::of_size(2,3), false); - -// auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - -// auto res = kwk::find_last_if(d, [](auto e){return e==0;}); - -// std::cout << res << std::endl; - -// TTS_EQUAL(res, vdata); -// }; - -TTS_CASE("Check for kwk::find_last_if(In, value) 3D") -{ - int data[2*3*4]; - auto vdata = kumi::iota<3>(1); - - fill_data(data, kwk::of_size(2,3,4), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - auto res = kwk::find_last_if(d, [](auto e){return e==0;}); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_last_if(In, value) 4D") -{ - int data[2*3*4*5]; - auto vdata = kumi::iota<4>(1); - - fill_data(data, kwk::of_size(2,3,4,5), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - auto res = kwk::find_last_if(d, [](auto e){return e==0;}); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_last_if_not(In, value) 1D") -{ - int data[2]; - auto vdata = kumi::iota<1>(1); - - fill_data(data, kwk::of_size(2), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - auto res = kwk::find_last_if_not(d, [](auto e){return e!=0;}); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -// TTS_CASE("Check for kwk::find_last_if_not(In, value) 2D") -// { -// int data[2*3]; -// auto vdata = kumi::iota<2>(1); - -// fill_data(data, kwk::of_size(2,3), false); - -// auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - -// auto res = kwk::find_last_if_not(d, [](auto e){return e!=0;}); - -// std::cout << res << std::endl; - -// TTS_EQUAL(res, vdata); -// }; - -TTS_CASE("Check for kwk::find_last_if_not(In, value) 3D") -{ - int data[2*3*4]; - auto vdata = kumi::iota<3>(1); - - fill_data(data, kwk::of_size(2,3,4), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - auto res = kwk::find_last_if_not(d, [](auto e){return e!=0;}); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; - -TTS_CASE("Check for kwk::find_last_if_not(In, value) 4D") -{ - int data[2*3*4*5]; - auto vdata = kumi::iota<4>(1); - - fill_data(data, kwk::of_size(2,3,4,5), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - auto res = kwk::find_last_if_not(d, [](auto e){return e!=0;}); - - std::cout << res << std::endl; - - TTS_EQUAL(res, vdata); -}; \ No newline at end of file diff --git a/test/algorithm/algos/find/1d.cpp b/test/algorithm/algos/find/1d.cpp new file mode 100644 index 00000000..6c165abf --- /dev/null +++ b/test/algorithm/algos/find/1d.cpp @@ -0,0 +1,392 @@ +//====================================================================================================================== +/* + 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::find(In, value) 1D") +{ + // Empty array + { + const std::size_t input_size = 0; + std::vector input(input_size); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto res = kwk::find(view, 0); + TTS_EQUAL(res.has_value(), false); + } + + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2 - 10; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // Not found + { + auto res = kwk::find(view, 11); + TTS_EQUAL(res.has_value(), false); + } + + // First position + { + auto res = kwk::find(view, -10); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find returned std::nullopt and not the expected valid value."); + } + + // Random position + { + auto res = kwk::find(view, 12); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{11}); + else TTS_FAIL("find returned std::nullopt and not the expected valid value."); + } + + // Last position + { + auto res = kwk::find(view, (static_cast(input_size) - 1) * 2 - 10); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{input_size-1}); + else TTS_FAIL("find returned std::nullopt and not the expected valid value."); + } +}; + + +TTS_CASE("Check for kwk::find_if(In, func) 1D") +{ + // Empty array + { + const std::size_t input_size = 0; + std::vector input(input_size); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto func = [&](auto item) { return (item % 2) == 0; }; + auto res = kwk::find_if(view, func); + TTS_EQUAL(res.has_value(), false); + } + + // Array of size 20 + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + auto func_even = [&](auto item) { return (item % 2) == 0; }; + auto func_odd = [&](auto item) { return (item % 2) == 1; }; + + // First element should be valid + { + auto res = kwk::find_if(view, func_even); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_if returned std::nullopt and not the expected valid value."); + } + + // Odd item not found + { + auto res = kwk::find_if(view, func_odd); + TTS_EQUAL(res.has_value(), false); + } + + // Added matching item (odd number) at random position : 12 + input[12] = 7; + { + auto res = kwk::find_if(view, func_odd); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{12}); + else TTS_FAIL("find_if returned std::nullopt and not the expected valid value."); + } + + // Test first position + input[12] = 24; + input[0] = 7; + { + auto res = kwk::find_if(view, func_odd); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_if returned std::nullopt and not the expected valid value."); + } + + // Test last position + input[0] = 0; + input[input_size-1] = 7; + { + auto res = kwk::find_if(view, func_odd); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{input_size-1}); + else TTS_FAIL("find_if returned std::nullopt and not the expected valid value."); + } +}; + +TTS_CASE("Check for kwk::find_if_not(In, func) 1D") +{ + // Empty array + { + const std::size_t input_size = 0; + std::vector input(input_size); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + auto func = [&](auto item) { return (item % 2) == 0; }; + auto res = kwk::find_if_not(view, func); + + TTS_EQUAL(res.has_value(), false); + } + + // Non-empty array + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // Looking for the first item that is not odd + { + auto func_odd = [&](auto item) { return (item % 2) == 1; }; + auto res = kwk::find_if_not(view, func_odd); + + // To avoid a nasty compiler error + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_if_not returned std::nullopt and not the expected valid value."); + } + + // Not found case: looking for the first item that is not even + auto func_even = [&](auto item) { return (item % 2) == 0; }; + { + // "not even" item not found + auto res = kwk::find_if_not(view, func_even); + TTS_EQUAL(res.has_value(), false); + } + + // Added matching item (odd number) at a random position + input[12] = 7; + { + auto res = kwk::find_if_not(view, func_even); + // To avoid a nasty compiler error + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{12}); + else TTS_FAIL("find_if_not returned std::nullopt and not the expected valid value."); + } + + // Test first position + input[12] = 24; + input[0] = 3; + { + auto res = kwk::find_if_not(view, func_even); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_if_not returned std::nullopt and not the expected valid value."); + } + + // Test last position + input[0] = 0; + input[input_size-1] = 3; + { + auto res = kwk::find_if_not(view, func_even); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{input_size-1}); + else TTS_FAIL("find_if_not returned std::nullopt and not the expected valid value."); + } +}; + + +// TODO?: Implement find_last_of? +TTS_CASE("Check for kwk::find_first_of(In, In) 1D") +{ + // Empty array + { + const std::size_t input_size = 0; + std::vector input(input_size); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + std::vector search{-10, -5, 0, 8, 11}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + auto res = kwk::find_first_of(view, sv); + TTS_EQUAL(res.has_value(), false); + } + + const std::size_t input_size = 40; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // No element found + { + std::vector search{-10, -5, 1, 7, 11}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + auto res = kwk::find_first_of(view, sv); + TTS_EQUAL(res.has_value(), false); + } + + // Element "0" found at position 0 + { + std::vector search{-10, -5, 0, 8, 11}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + auto res = kwk::find_first_of(view, sv); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_first_of returned std::nullopt and not the expected valid value."); + } + + // Element "8" found at position 4 + { + std::vector search{-10, -5, 1, 16, 8}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + auto res = kwk::find_first_of(view, sv); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{4}); + else TTS_FAIL("find_first_of returned std::nullopt and not the expected valid value."); + } + + // Element "input_size*2-2" found at last position: input_size-1 + { + std::vector search{input_size*2-2, -5, 1, 7, 11}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + auto res = kwk::find_first_of(view, sv); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{input_size-1}); + else TTS_FAIL("find_first_of returned std::nullopt and not the expected valid value."); + } +}; + + +TTS_CASE("Check for kwk::find_last(In, value) 1D") +{ + // // Empty array + { + const std::size_t input_size = 0; + std::vector input(input_size); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + int search{6}; + auto res = kwk::find_last(view, search); + TTS_EQUAL(res.has_value(), false); + } + + const std::size_t input_size = 40; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = 6; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // Not found + { + auto res = kwk::find_last(view, 8); + TTS_EQUAL(res.has_value(), false); + } + + // Last position + { + auto res = kwk::find_last(view, 6); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{input_size-1}); + else TTS_FAIL("find_last returned std::nullopt and not the expected valid value."); + } + + // Random position + input[4] = 8; + { + auto res = kwk::find_last(view, 8); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{4}); + else TTS_FAIL("find_last returned std::nullopt and not the expected valid value."); + } + input[4] = 6; + + // First position + input[0] = 8; + { + auto res = kwk::find_last(view, 8); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_last returned std::nullopt and not the expected valid value."); + } +}; + +TTS_CASE("Check for kwk::find_last_if(In, func) 1D") +{ + auto func = [](auto const& e) { return (e % 2) == 0; }; + + // Empty array + { + const std::size_t input_size = 0; + std::vector input(input_size); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto res = kwk::find_last_if(view, func); + TTS_EQUAL(res.has_value(), false); + } + + const std::size_t input_size = 40; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = 5; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // Not found + { + auto res = kwk::find_last_if(view, func); + TTS_EQUAL(res.has_value(), false); + } + + // Last position + input[input_size-1] = 8; + { + auto res = kwk::find_last_if(view, func); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{input_size-1}); + else TTS_FAIL("find_last_if returned std::nullopt and not the expected valid value."); + } + input[input_size-1] = 5; + + // Random position + input[4] = 16; + { + auto res = kwk::find_last_if(view, func); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{4}); + else TTS_FAIL("find_last_if returned std::nullopt and not the expected valid value."); + } + input[4] = 5; + + // First position + input[0] = 6; + { + auto res = kwk::find_last_if(view, func); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_last_if returned std::nullopt and not the expected valid value."); + } +}; + +TTS_CASE("Check for kwk::find_last_if_not(In, func) 1D") +{ + + auto func = [](auto const& e) { return (e % 2) != 0; }; + + // Empty array + { + const std::size_t input_size = 0; + std::vector input(input_size); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + auto res = kwk::find_last_if_not(view, func); + TTS_EQUAL(res.has_value(), false); + } + + const std::size_t input_size = 40; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = 5; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + // Not found + { + auto res = kwk::find_last_if_not(view, func); + TTS_EQUAL(res.has_value(), false); + } + + // Last position + input[input_size-1] = 8; + { + auto res = kwk::find_last_if_not(view, func); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{input_size-1}); + else TTS_FAIL("find_last_if_not returned std::nullopt and not the expected valid value."); + } + input[input_size-1] = 5; + + // Random position + input[4] = 16; + { + auto res = kwk::find_last_if_not(view, func); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{4}); + else TTS_FAIL("find_last_if_not returned std::nullopt and not the expected valid value."); + } + input[4] = 5; + + // First position + input[0] = 6; + { + auto res = kwk::find_last_if_not(view, func); + if (res.has_value()) TTS_EQUAL(res.value(), kwk::position<1>{0}); + else TTS_FAIL("find_last_if_not returned std::nullopt and not the expected valid value."); + } +}; diff --git a/test/algorithm/algos/find/2d.cpp.disabled b/test/algorithm/algos/find/2d.cpp.disabled new file mode 100644 index 00000000..87cecc58 --- /dev/null +++ b/test/algorithm/algos/find/2d.cpp.disabled @@ -0,0 +1,429 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" + +// TODO: if no element were found, return a kumi tuple containing the size of each dimension +// and NOT -1 for each dimension. + + +TTS_CASE("Check for kwk::find(In, value) 2D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t input_size = d0 * d1; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + { + int search = -10; + kumi::tuple expected{-1, -1}; + // kumi::tuple expected = kumi::make_tuple(-1); + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = -1; + kumi::tuple expected{-1, -1}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = 0; + kumi::tuple expected{0, 0}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = 10; + kumi::tuple expected = lindex_to_pos(d1, 5); + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = 11; + kumi::tuple expected{-1, -1}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = (input_size-1)*2; + kumi::tuple expected{d0-1, d1-1}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = input_size*2; + kumi::tuple expected{-1, -1}; + TTS_EQUAL(kwk::find(view, search), expected); + } +}; + + +TTS_CASE("Check for kwk::find_if(In, func) 2D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t input_size = d0 * d1; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + { + int search = -10; + kumi::tuple expected{-1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = -1; + kumi::tuple expected{-1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = 0; + kumi::tuple expected{0, 0}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, 1UL); + } + { + int search = 1; + kumi::tuple expected{0, 1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, 2U); + } + { + int search = input_size-1; + kumi::tuple expected{d0-1, d1-1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = input_size; + kumi::tuple expected{-1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = 478123; + kumi::tuple expected{-1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } +}; + + +TTS_CASE("Check for kwk::find_if_not(In, func) 2D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + 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 = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + { + int search = -10; + kumi::tuple expected{0, 0}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 1UL); // 0, 1, 2 + } + { + int search = -1; + kumi::tuple expected{0, 0}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 1UL); // 0, 1, 2 + } + { + int search = 0; + kumi::tuple expected{0, 0}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 1UL); // 0, 1, 2 + } + { + int search = 1; + kumi::tuple expected{0, 1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 2UL); + } + { + int search = input_size-1; + kumi::tuple expected{d0-1, d1-1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = input_size; + kumi::tuple expected{-1, -1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = input_size + 20000; + kumi::tuple expected{-1, -1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, input_size); + } +}; + + +// TODO?: Implement find_last_of? +TTS_CASE("Check for kwk::find_first_of(In, In) 2D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + 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; } + + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + { + std::vector search{-10}; + kumi::tuple expected{-1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, 2, 8, 11}; + kumi::tuple expected{-1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, 0, 8, 11}; + kumi::tuple expected{0, 0}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, (input_size/2 - 1)*3, 8, 11}; + kumi::tuple expected = lindex_to_pos(d1, input_size/2 - 1); + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, (input_size/2)*3, -5, 8, 11}; + kumi::tuple expected{-1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, (input_size+87845)*3, 8, 11}; + kumi::tuple expected{-1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } +}; + + +TTS_CASE("Check for kwk::find_last(In, value) 2D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t input_size = d0 * d1; + // e.g.: 0 3 6 9 12 12 9 6 3 0 + std::array input; + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kumi::tuple expect_not_found{d0, d1}; + + { + int search{-10}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + // TTS_EQUAL(kwk::find_last_if(view, [&](auto e){return e == search;}), expected); + } + { + int search{-1}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + } + { + int search{0}; + kumi::tuple expected{d0-1, d1-1}; + TTS_EQUAL(kwk::find_last(view, search), expected); + } + { + int search{1}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + } + { + int search{3}; + kumi::tuple expected{d0-1, d1-2}; + TTS_EQUAL(kwk::find_last(view, search), expected); + } + { + int search{(input_size/2 - 1) * 3}; + kumi::tuple expected = lindex_to_pos(d1, input_size/2); + TTS_EQUAL(kwk::find_last(view, search), expected); + } + { + int search{input_size + 1000}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + } +}; + + +TTS_CASE("Check for kwk::find_last_if(In, func) 2D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t input_size = d0 * d1; + // e.g.: 0 3 6 9 12 12 9 6 3 0 + std::array input; + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kumi::tuple expect_not_found{d0, d1}; + + { + int search{-10}; + auto func = [=](auto const& e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } + { + int search{-1}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } + { + int search{0}; + kumi::tuple expected{d0-1, d1-1}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expected); + } + { + int search{1}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } + { + int search{3}; + kumi::tuple expected{d0-1, d1-2}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expected); + } + { + int search{(input_size/2 - 1) * 3}; + kumi::tuple expected = lindex_to_pos(d1, input_size/2); + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expected); + } + { + int search{input_size + 1000}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } +}; + + +TTS_CASE("Check for kwk::find_last_if_not(In, func) 2D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t input_size = d0 * d1; + // e.g.: 0 3 6 9 12 12 9 6 3 0 + std::array input; + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kumi::tuple expect_not_found{d0, d1}; + + { + int search{-10}; + auto func = [=](auto const& e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } + { + int search{-1}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } + { + int search{0}; + kumi::tuple expected{d0-1, d1-1}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expected); + } + { + int search{1}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } + { + int search{3}; + kumi::tuple expected{d0-1, d1-2}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expected); + } + { + int search{(input_size/2 - 1) * 3}; + kumi::tuple expected = lindex_to_pos(d1, input_size/2); + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expected); + } + { + int search{input_size + 1000}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } +}; diff --git a/test/algorithm/algos/find/4d.cpp.disabled b/test/algorithm/algos/find/4d.cpp.disabled new file mode 100644 index 00000000..e4e01bdf --- /dev/null +++ b/test/algorithm/algos/find/4d.cpp.disabled @@ -0,0 +1,442 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include +#include "test.hpp" + +// TODO: if no element were found, return a kumi tuple containing the size of each dimension +// and NOT -1 for each dimension. + +TTS_CASE("Check for kwk::find(In, value) 4D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 12; + const std::size_t d3 = 2; + 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 * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + { + int search = -10; + kumi::tuple expected{-1, -1, -1, -1}; + // kumi::tuple expected = kumi::make_tuple(-1); + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = -1; + kumi::tuple expected{-1, -1, -1, -1}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = 0; + kumi::tuple expected{0, 0, 0, 0}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = 10; + kumi::tuple expected = lindex_to_pos(d1, d2, d3, 5); + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = 11; + kumi::tuple expected{-1, -1, -1, -1}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = (input_size-1)*2; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-1}; + TTS_EQUAL(kwk::find(view, search), expected); + } + { + int search = input_size*2; + kumi::tuple expected{-1, -1, -1, -1}; + TTS_EQUAL(kwk::find(view, search), expected); + } +}; + + +TTS_CASE("Check for kwk::find_if(In, func) 4D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 12; + const std::size_t d3 = 2; + 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 * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + { + int search = -10; + kumi::tuple expected{-1, -1, -1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = -1; + kumi::tuple expected{-1, -1, -1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = 0; + kumi::tuple expected{0, 0, 0, 0}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, 1UL); + } + { + int search = 1; + kumi::tuple expected{0, 0, 0, 1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, 2U); + } + { + int search = input_size-1; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = input_size; + kumi::tuple expected{-1, -1, -1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = 478123; + kumi::tuple expected{-1, -1, -1, -1}; + std::size_t count = 0; + auto func = [&](auto item){ ++count; return (item/2 == search); }; + TTS_EQUAL(kwk::find_if(view, func), expected); + TTS_EQUAL(count, input_size); + } +}; + + +TTS_CASE("Check for kwk::find_if_not(In, func) 4D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 12; + const std::size_t d3 = 2; + 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 = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + { + int search = -10; + kumi::tuple expected{0, 0, 0, 0}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 1UL); // 0, 1, 2 + } + { + int search = -1; + kumi::tuple expected{0, 0, 0, 0}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 1UL); // 0, 1, 2 + } + { + int search = 0; + kumi::tuple expected{0, 0, 0, 0}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 1UL); // 0, 1, 2 + } + { + int search = 1; + kumi::tuple expected{0, 0, 0, 1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, 2UL); + } + { + int search = input_size-1; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = input_size; + kumi::tuple expected{-1, -1, -1, -1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, input_size); + } + { + int search = input_size + 20000; + kumi::tuple expected{-1, -1, -1, -1}; + std::size_t count = 0; + // First element that has (item/3 >= search) i.e. index >= search + auto func = [&](auto item){ ++count; return (item/3 < search); }; + TTS_EQUAL(kwk::find_if_not(view, func), expected); + TTS_EQUAL(count, input_size); + } +}; + + +// TODO?: Implement find_last_of? +TTS_CASE("Check for kwk::find_first_of(In, In) 4D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 12; + const std::size_t d3 = 2; + 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; } + + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + { + std::vector search{-10}; + kumi::tuple expected{-1, -1, -1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, 2, 8, 11}; + kumi::tuple expected{-1, -1, -1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, 0, 8, 11}; + kumi::tuple expected{0, 0, 0, 0}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, (input_size/2 - 1)*3, 8, 11}; + kumi::tuple expected = lindex_to_pos(d1, d2, d3, input_size/2 - 1); + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, (input_size/2)*3, -5, 8, 11}; + kumi::tuple expected{-1, -1, -1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } + { + std::vector search{-10, -5, (input_size+87845)*3, 8, 11}; + kumi::tuple expected{-1, -1, -1, -1}; + auto sv = kwk::view{kwk::source = search, kwk::of_size(search.size())}; + TTS_EQUAL(kwk::find_first_of(view, sv), expected); + } +}; + + +TTS_CASE("Check for kwk::find_last(In, value) 4D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 12; + const std::size_t d3 = 2; + const std::size_t input_size = d0 * d1 * d2 * d3; + // e.g.: 0 3 6 9 12 12 9 6 3 0 + std::array input; + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kumi::tuple expect_not_found{d0, d1, d2, d3}; + + { + int search{-10}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + // TTS_EQUAL(kwk::find_last_if(view, [&](auto e){return e == search;}), expected); + } + { + int search{-1}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + } + { + int search{0}; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-1}; + TTS_EQUAL(kwk::find_last(view, search), expected); + } + { + int search{1}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + } + { + int search{3}; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-2}; + TTS_EQUAL(kwk::find_last(view, search), expected); + } + { + int search{(input_size/2 - 1) * 3}; + kumi::tuple expected = lindex_to_pos(d1, d2, d3, input_size/2); + TTS_EQUAL(kwk::find_last(view, search), expected); + } + { + int search{input_size + 1000}; + TTS_EQUAL(kwk::find_last(view, search), expect_not_found); + } +}; + + +TTS_CASE("Check for kwk::find_last_if(In, func) 4D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 12; + const std::size_t d3 = 2; + const std::size_t input_size = d0 * d1 * d2 * d3; + // e.g.: 0 3 6 9 12 12 9 6 3 0 + std::array input; + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kumi::tuple expect_not_found{d0, d1, d2, d3}; + + { + int search{-10}; + auto func = [=](auto const& e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } + { + int search{-1}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } + { + int search{0}; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-1}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expected); + } + { + int search{1}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } + { + int search{3}; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-2}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expected); + } + { + int search{(input_size/2 - 1) * 3}; + kumi::tuple expected = lindex_to_pos(d1, d2, d3, input_size/2); + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expected); + } + { + int search{input_size + 1000}; + auto func = [&](auto e){ return e == search; }; + TTS_EQUAL(kwk::find_last_if(view, func), expect_not_found); + } +}; + + +TTS_CASE("Check for kwk::find_last_if_not(In, func) 4D") +{ + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 12; + const std::size_t d3 = 2; + const std::size_t input_size = d0 * d1 * d2 * d3; + // e.g.: 0 3 6 9 12 12 9 6 3 0 + std::array input; + for (std::size_t i = 0; i < input_size/2; ++i) { input[i] = i * 3; } + for (std::size_t i = 0; i < input_size/2; ++i) + { + input[i + input_size/2] = (input_size/2 - i - 1) * 3; + } + + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kumi::tuple expect_not_found{d0, d1, d2, d3}; + + { + int search{-10}; + auto func = [=](auto const& e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } + { + int search{-1}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } + { + int search{0}; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-1}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expected); + } + { + int search{1}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } + { + int search{3}; + kumi::tuple expected{d0-1, d1-1, d2-1, d3-2}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expected); + } + { + int search{(input_size/2 - 1) * 3}; + kumi::tuple expected = lindex_to_pos(d1, d2, d3, input_size/2); + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expected); + } + { + int search{input_size + 1000}; + auto func = [&](auto e){ return e != search; }; + TTS_EQUAL(kwk::find_last_if_not(view, func), expect_not_found); + } +}; diff --git a/test/algorithm/algos/for_each.cpp b/test/algorithm/algos/for_each.cpp index 5bd51fb7..6a64bea3 100644 --- a/test/algorithm/algos/for_each.cpp +++ b/test/algorithm/algos/for_each.cpp @@ -1,148 +1,392 @@ -//================================================================================================== +//====================================================================================================================== /* KIWAKU - Containers Well Made Copyright : KIWAKU Contributors & Maintainers SPDX-License-Identifier: BSL-1.0 */ -//================================================================================================== +//====================================================================================================================== #include #include #include "test.hpp" +// for_each 1D - 4D + TTS_CASE("Check for kwk::for_each(func, shape)") { auto shp = kwk::of_size(4,kwk::fixed<6>,3ULL); - int count = 0; - kwk::for_each( [&](auto...) { count++; }, shp); + std::int32_t count = 0; + kwk::for_each( [&](auto...) { ++count; }, shp); TTS_EQUAL(count, shp.numel()); }; + TTS_CASE("Check for kwk::for_each(func, container) 1D") { - float data[2]; + using data_type = int; + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + + std::size_t count{0}; + data_type total{0}; + + kwk::for_each( [&](auto e) { ++count; total += e; }, view); + + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); + // TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); +}; + +TTS_CASE("Check for kwk::for_each(func, container) 1D with float") +{ + using data_type = float; + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + + std::size_t count{0}; + data_type total{0}; + + kwk::for_each( [&](auto e) { ++count; total += e; }, view); + + TTS_EQUAL(count, input_size); + // TTS_EQUAL(total, chk_total); + TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); +}; + +TTS_CASE("Check for kwk::for_each(func, container) 1D with std::uint64_t") +{ + using data_type = std::uint64_t; + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + + std::size_t count{0}; + data_type total{0}; + + kwk::for_each( [&](auto e) { ++count; total += e; }, view); + + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); + // TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); +}; + +TTS_CASE("Check for kwk::for_each(func, container) 1D size 0") +{ + using data_type = int; + std::vector input; + input.resize(0); - fill_data(data, kwk::of_size(2), true); + auto view = kwk::view{kwk::source = input, kwk::of_size(0)}; - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + std::size_t count{0}; + data_type total{0}; - float sum = 0.f; - int count = 0; - kwk::for_each( [&](auto e) { count++; sum +=e; }, d); + kwk::for_each( [&](auto e) { ++count; total += e; }, view); - TTS_EQUAL(sum, 1.f); - TTS_EQUAL(count, d.numel()); + TTS_EQUAL(count, 0UL); + TTS_EQUAL(total, 0); }; TTS_CASE("Check for kwk::for_each(func, container) 2D") { - float data[2*3]; + using data_type = int; + const std::size_t d0 = 20; + const std::size_t d1 = 41; + const std::size_t input_size = d0 * d1; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; - fill_data(data, kwk::of_size(2,3), true); + data_type chk_total = 0; + for (data_type e : input) { chk_total += e; } - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + std::size_t count = 0; + data_type total = 0; - float sum = 0.f; - int count = 0; - kwk::for_each( [&](auto e) { count++; sum +=e; }, d); + kwk::for_each( [&](auto e) { ++count; total += e; }, view); - TTS_EQUAL(sum, 36.f); - TTS_EQUAL(count, d.numel()); + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); }; -TTS_CASE("Check for kwk::for_each(func, container) 3D") +TTS_CASE("Check for kwk::for_each(func, container) 3D with float") { - float data[2*3*4]; + using data_type = float; + const std::size_t d0 = 20; + const std::size_t d1 = 41; + const std::size_t d2 = 14; + const std::size_t input_size = d0 * d1 * d2; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2)}; - fill_data(data, kwk::of_size(2,3,4), true); + data_type chk_total = 0; + for (data_type e : input) { chk_total += e; } - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + std::size_t count = 0; + data_type total = 0; - float sum = 0.f; - int count = 0; - kwk::for_each( [&](auto e) { count++; sum +=e; }, d); + kwk::for_each( [&](auto e) { ++count; total += e; }, view); - TTS_EQUAL(sum, 1476.f); - TTS_EQUAL(count, d.numel()); + TTS_EQUAL(count, input_size); + TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); }; TTS_CASE("Check for kwk::for_each(func, container) 4D") { - float data[2*3*4*5]; + using data_type = int; + const std::size_t d0 = 20; + const std::size_t d1 = 41; + const std::size_t d2 = 14; + const std::size_t d3 = 11; + 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 * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + data_type chk_total = 0; + for (data_type e : input) { chk_total += e; } + + std::size_t count = 0; + data_type total = 0; + + kwk::for_each( [&](auto e) { ++count; total += e; }, view); + + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); + // TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); +}; + + +TTS_CASE("Check for kwk::for_each_index(func, container) 1D") +{ + using data_type = int; + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; - fill_data(data, kwk::of_size(2,3,4,5), true); + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; + std::size_t count{0}; + data_type total{0}; - float sum = 0.f; - int count = 0; - kwk::for_each( [&](auto e) { count++; sum +=e; }, d); + kwk::for_each_index( [&](auto& e, auto i0) { ++count; total += e; e = i0 + 1; }, view); - TTS_EQUAL(sum, 74040.f); - TTS_EQUAL(count, d.numel()); + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); + // TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); + + std::array expected_result; + for (std::size_t i = 0; i < input_size; ++i) { expected_result[i] = i + 1; } + + TTS_ALL_EQUAL(input, expected_result); }; -TTS_CASE("Check for kwk::for_each_index(func, container) 1D") +TTS_CASE("Check for kwk::for_each_index(func, container) 1D with float") { - int data[2]; - int vdata[2]; + using data_type = float; + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + + std::size_t count{0}; + data_type total{0}; - fill_data(vdata, kwk::of_size(2), true); + kwk::for_each_index( [&](auto& e, auto i0) { ++count; total += e; e = i0 + 1; }, view); - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; + TTS_EQUAL(count, input_size); + // TTS_EQUAL(total, chk_total); + TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); - int count = 0; - kwk::for_each_index( [&](auto& e, auto i0) { count++; e = i0; }, d); + std::array expected_result; + for (std::size_t i = 0; i < input_size; ++i) { expected_result[i] = i + 1; } - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); + TTS_ALL_EQUAL(input, expected_result); }; -TTS_CASE("Check for kwk::for_each_index(func, container) 2D") +TTS_CASE("Check for kwk::for_each_index(func, container) 1D with std::uint64_t") { - int data[2*3]; - int vdata[2*3]; + using data_type = std::uint64_t; + const std::size_t input_size = 20; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + + std::size_t count{0}; + data_type total{0}; - fill_data(vdata, kwk::of_size(2,3), true); + kwk::for_each_index( [&](auto& e, auto i0) { ++count; total += e; e = i0 + 1; }, view); - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); + // TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); - int count = 0; - kwk::for_each_index( [&](auto& e, auto i1, auto i0) { count++; e = i0 + i1*10; }, d); + std::array expected_result; + for (std::size_t i = 0; i < input_size; ++i) { expected_result[i] = i + 1; } - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); + TTS_ALL_EQUAL(input, expected_result); }; -TTS_CASE("Check for kwk::for_each_index(func, container) 3D") +TTS_CASE("Check for kwk::for_each_index(func, container) 1D size 0") { - int data[2*3*4]; - int vdata[2*3*4]; + using data_type = int; + std::vector input; + input.resize(0); - fill_data(vdata, kwk::of_size(2,3,4), true); + auto view = kwk::view{kwk::source = input, kwk::of_size(0)}; - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; + std::size_t count = 0; + data_type total = 0; - int count = 0; - kwk::for_each_index( [&](auto& e, auto i2, auto i1, auto i0) { count++; e = i0 + i1*10 + i2*100; }, d); + kwk::for_each_index( [&](auto& e, auto i0) { ++count; total += e; e = i0 + 1; }, view); - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); + TTS_EQUAL(count, 0UL); + TTS_EQUAL(total, 0); }; -TTS_CASE("Check for kwk::for_each_index(func, container) 4D") + +TTS_CASE("Check for kwk::for_each_index(func, container) 2D") { - int data[2*3*4*5]; - int vdata[2*3*4*5]; + using data_type = int; + const std::size_t d0 = 4; + const std::size_t d1 = 10; + const std::size_t input_size = d0 * d1; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + std::size_t count{0}; + data_type total{0}; + + auto pos_to_value = [](std::size_t i0, std::size_t i1) { return i0*100 + i1; }; + + kwk::for_each_index( [&](auto& e, auto i0, auto i1) { ++count; total += e; e = pos_to_value(i0, i1); }, view); + + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); + // TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); + + std::array expected_result; + std::size_t cpt{0}; + for (std::size_t i0 = 0; i0 < d0; ++i0) + for (std::size_t i1 = 0; i1 < d1; ++i1) + { + expected_result[cpt++] = pos_to_value(i0, i1); + } + + TTS_ALL_EQUAL(input, expected_result); +}; - fill_data(vdata, kwk::of_size(2,3,4,5), true); - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; +TTS_CASE("Check for kwk::for_each_index(func, container) 3D with float") +{ + using data_type = float; + const std::size_t d0 = 2; + const std::size_t d1 = 10; + const std::size_t d2 = 6; + const std::size_t input_size = d0 * d1 * d2; + std::array input; + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + std::size_t count{0}; + data_type total{0}; + + auto pos_to_value = [](std::size_t i0, std::size_t i1, std::size_t i2) { + return i0 * 10000 + i1 * 100 + i2; + }; + + kwk::for_each_index ( + [&](auto& e, auto i0, auto i1, auto i2) { + ++count; total += e; e = pos_to_value(i0, i1, i2); + } + , view); + + TTS_EQUAL(count, input_size); + // TTS_EQUAL(total, chk_total); + TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); + + std::array expected_result; + std::size_t cpt{0}; + for (std::size_t i0 = 0; i0 < d0; ++i0) + for (std::size_t i1 = 0; i1 < d1; ++i1) + for (std::size_t i2 = 0; i2 < d2; ++i2) + { + expected_result[cpt++] = pos_to_value(i0, i1, i2); + } + + TTS_ALL_EQUAL(input, expected_result); +}; - int count = 0; - kwk::for_each_index( [&](auto& e, auto i3, auto i2, auto i1, auto i0) { count++; e = i0 + i1*10 + i2*100 + i3*1000; }, d); - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); +TTS_CASE("Check for kwk::for_each_index(func, container) 4D") +{ + using data_type = int; + const std::size_t d0 = 2; + const std::size_t d1 = 10; + const std::size_t d2 = 6; + const std::size_t d3 = 3; + 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 * 2; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + data_type chk_total{0}; + for (data_type e : input) { chk_total += e; } + std::size_t count{0}; + data_type total{0}; + + auto pos_to_value = [](std::size_t i0, std::size_t i1, std::size_t i2, std::size_t i3) { + return i0 * 1000000 + i1 * 10000 + i2 * 100 + i3; + }; + + kwk::for_each_index ( + [&](auto& e, auto i0, auto i1, auto i2, auto i3) { + ++count; total += e; e = pos_to_value(i0, i1, i2, i3); + } + , view); + + TTS_EQUAL(count, input_size); + TTS_EQUAL(total, chk_total); + // TTS_RELATIVE_EQUAL(total, chk_total, FLOAT_TOLERANCE_PERCENT); + + std::array expected_result; + std::size_t cpt{0}; + for (std::size_t i0 = 0; i0 < d0; ++i0) + for (std::size_t i1 = 0; i1 < d1; ++i1) + for (std::size_t i2 = 0; i2 < d2; ++i2) + for (std::size_t i3 = 0; i3 < d3; ++i3) + { + expected_result[cpt++] = pos_to_value(i0, i1, i2, i3); + } + + TTS_ALL_EQUAL(input, expected_result); }; diff --git a/test/algorithm/algos/generator.cpp b/test/algorithm/algos/generator.cpp deleted file mode 100644 index b407cd05..00000000 --- a/test/algorithm/algos/generator.cpp +++ /dev/null @@ -1,411 +0,0 @@ -//================================================================================================== -/* - KIWAKU - Containers Well Made - Copyright : KIWAKU Contributors & Maintainers - SPDX-License-Identifier: BSL-1.0 -*/ -//================================================================================================== -#include -#include -#include "test.hpp" - - -TTS_CASE("Check for kwk::fill(out, value) 1D") -{ - int data[2]; - - int vdata[2] = { 1, 1 }; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - kwk::fill(d, 1); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::fill(out, value) 2D") -{ - int data[2*3]; - - int vdata[2*3]; - - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - vdata[i*3+j] = 2; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - kwk::fill(d, 2); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::fill(out, value) 3D") -{ - int data[2*3*4]; - - int vdata[2*3*4]; - - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - vdata[i*4*3+j*4+k] = 3; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - kwk::fill(d, 3); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::fill(out, value) 4D") -{ - int data[2*3*4*5]; - - int vdata[2*3*4*5]; - - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - for(int l = 0; l<5; l++) - vdata[i*5*4*3+j*5*4+k*5+l] = 4; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - kwk::fill(d, 4); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::generate(out, func) 1D") -{ - int data[2]; - int vdata[2]; - - fill_data(vdata, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - kwk::generate([&](auto p1) - { - count++; - return p1; - } - , d); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::generate(out, func) 2D") -{ - int data[2*3]; - int vdata[2*3]; - - fill_data(vdata, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - int count = 0; - kwk::generate([&](auto p1, auto p2) - { - count++; - return 10*p1+p2; - } - , d); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::generate(out, func) 3D") -{ - int data[2*3*4]; - int vdata[2*3*4]; - - fill_data(vdata, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - int count = 0; - kwk::generate([&](auto p1, auto p2, auto p3) - { - count++; - return 100*p1+10*p2+p3; - } - , d); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::generate(out, func) 4D") -{ - int data[2*3*4*5]; - int vdata[2*3*4*5]; - - fill_data(vdata, 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; - kwk::generate([&](auto p1, auto p2, auto p3, auto p4) - { - count++; - return 1000*p1+100*p2+10*p3+p4; - } - , d); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::iota(out) 1D") -{ - int data[2]; - int vdata[2] = { 0, 1}; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - kwk::iota(d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out) 2D") -{ - int data[2*3]; - int vdata[2*3]; - - int iot = 0; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - { - vdata[i*3+j] = iot; - iot++; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - kwk::iota(d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out) 3D") -{ - int data[2*3*4]; - int vdata[2*3*4]; - - int iot = 0; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - { - vdata[i*4*3+j*4+k] = iot; - iot++; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - kwk::iota(d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out) 4D") -{ - int data[2*3*4*5]; - int vdata[2*3*4*5]; - - int iot = 0; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - for(int l = 0; l<5; l++) - { - vdata[i*5*4*3+j*5*4+k*5+l] = iot; - iot++; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - kwk::iota(d); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out, value) 1D") -{ - int data[2]; - int vdata[2] = {1,2}; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - kwk::iota(d, 1); - - TTS_ALL_EQUAL(data, vdata); -}; - - -TTS_CASE("Check for kwk::iota(out, value) 2D") -{ - int data[2*3]; - int vdata[2*3]; - - int iot = 2; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - { - vdata[i*3+j] = iot; - iot++; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - kwk::iota(d,2); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out, value) 3D") -{ - int data[2*3*4]; - int vdata[2*3*4]; - - int iot = 3; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - { - vdata[i*4*3+j*4+k] = iot; - iot++; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - kwk::iota(d,3); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out, value) 4D") -{ - int data[2*3*4*5]; - int vdata[2*3*4*5]; - - int iot = 4; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - for(int l = 0; l<5; l++) - { - vdata[i*5*4*3+j*5*4+k*5+l] = iot; - iot++; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - kwk::iota(d,4); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out, value, step) 1D") -{ - int data[2]; - int vdata[2] = {0,10}; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - kwk::iota(d, 0, 10); - - TTS_ALL_EQUAL(data, vdata); -}; - - -TTS_CASE("Check for kwk::iota(out, value, step) 2D") -{ - int data[2*3]; - int vdata[2*3]; - - int iot = 0; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - { - vdata[i*3+j] = iot; - iot+=20; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - kwk::iota(d,0,20); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out, value, step) 3D") -{ - int data[2*3*4]; - int vdata[2*3*4]; - - int iot = 0; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - { - vdata[i*4*3+j*4+k] = iot; - iot+=30; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - kwk::iota(d,0,30); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::iota(out, value, step) 4D") -{ - int data[2*3*4*5]; - int vdata[2*3*4*5]; - - int iot = 0; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - for(int l = 0; l<5; l++) - { - vdata[i*5*4*3+j*5*4+k*5+l] = iot; - iot+=40; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - kwk::iota(d,0,40); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for float kwk::iota(out, value, step) 4D") -{ - float data[2*3*4*5]; - float vdata[2*3*4*5]; - - float iot = 0.f; - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - for(int l = 0; l<5; l++) - { - vdata[i*5*4*3+j*5*4+k*5+l] = iot; - iot+=40.5f; - } - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - kwk::iota(d,0.f,40.5f); - - TTS_ALL_EQUAL(data, vdata); -}; \ No newline at end of file diff --git a/test/algorithm/algos/generator/1d.cpp b/test/algorithm/algos/generator/1d.cpp new file mode 100644 index 00000000..47ece837 --- /dev/null +++ b/test/algorithm/algos/generator/1d.cpp @@ -0,0 +1,118 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include +#include +#include "test.hpp" + +// generator 1D + +TTS_CASE("Check for kwk::fill(container, value) 1D") +{ + using data_type = int; + const std::size_t input_size = 20; + std::array input; + for (data_type& e : input) { e = 0; } + // std::fill(input.begin(), input.end(), 0); + auto view = kwk::view{kwk::source = input, kwk::of_size(input_size)}; + + kwk::fill(view, 8); + std::array expected; + std::fill(expected.begin(), expected.end(), 8); + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::generate(func, container) 1D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t input_size = d0; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0)}; + + std::size_t count = 0; + kwk::generate ([&](auto i0) { + count++; + return i0 * 3; + } + , view + ); + + std::array expected; + for (std::size_t i0 = 0; i0 < d0; ++i0) + { + expected[i0] = i0 * 3; + } + + TTS_ALL_EQUAL(input, expected); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::iota(out) 1D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t input_size = d0; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0)}; + + kwk::iota(view); + + std::array expected; + for (std::size_t i0 = 0; i0 < d0; ++i0) + { + expected[i0] = i0; + } + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value) 1D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t input_size = d0; + data_type initial_value = 87; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0)}; + + kwk::iota(view, initial_value); + + std::array expected; + for (std::size_t i0 = 0; i0 < d0; ++i0) + { + expected[i0] = i0 + initial_value; + } + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value, step) 1D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t input_size = d0; + data_type initial_value = 87; + std::size_t step = 5; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0)}; + + kwk::iota(view, initial_value, step); + + std::array expected; + for (std::size_t i0 = 0; i0 < d0; ++i0) + { + expected[i0] = i0 * step + initial_value; + } + + TTS_ALL_EQUAL(input, expected); +}; diff --git a/test/algorithm/algos/generator/2d.cpp b/test/algorithm/algos/generator/2d.cpp new file mode 100644 index 00000000..4975f363 --- /dev/null +++ b/test/algorithm/algos/generator/2d.cpp @@ -0,0 +1,144 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include "test.hpp" + +// generator 2D + +TTS_CASE("Check for kwk::fill(container, value) 2D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t d1 = 10; + const std::size_t input_size = d0 * d1; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kwk::fill(view, 8); + std::array expected; + std::fill(expected.begin(), expected.end(), 8); + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::generate(func, container) 2D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t d1 = 7; + const std::size_t input_size = d0 * d1; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + std::size_t count = 0; + kwk::generate ([&](auto i0, auto i1) { + count++; + return i0 * 100 + i1; + } + , view + ); + + std::array expected; + std::size_t cpt{0}; + for (std::size_t i0 = 0; i0 < d0; ++i0) + for (std::size_t i1 = 0; i1 < d1; ++i1) + { + expected[cpt++] = i0 * 100 + i1; + } + + TTS_ALL_EQUAL(input, expected); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::iota(out) 2D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t input_size = d0 * d1; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kwk::iota(view); + + std::array expected; + std::iota(expected.begin(), expected.end(), 0); + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value) 2D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + int initial_value = 87; + const std::size_t input_size = d0 * d1; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kwk::iota(view, initial_value); + + std::array expected; + std::iota(expected.begin(), expected.end(), initial_value); + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value, step) 2D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + data_type initial_value = 87; + std::size_t step = 5; + const std::size_t input_size = d0 * d1; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kwk::iota(view, initial_value, step); + + std::array expected; + // std::iota(expected.begin(), expected.end(), initial_value, step); + for (std::size_t i = 0; i < input_size; ++i) + { + expected[i] = i * step + initial_value; + } + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value, step) 2D") +{ + using data_type = int; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + data_type initial_value = 87; + std::size_t step = 5; + const std::size_t input_size = d0 * d1; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + + kwk::iota(view, initial_value, step); + + std::array expected; + // std::iota(expected.begin(), expected.end(), initial_value, step); + for (std::size_t i = 0; i < input_size; ++i) + { + expected[i] = i * step + initial_value; + } + + TTS_ALL_EQUAL(input, expected); +}; diff --git a/test/algorithm/algos/generator/4d.cpp b/test/algorithm/algos/generator/4d.cpp new file mode 100644 index 00000000..041feebc --- /dev/null +++ b/test/algorithm/algos/generator/4d.cpp @@ -0,0 +1,158 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include +#include "test.hpp" + +// generator 4D + +TTS_CASE("Check for kwk::fill(container, value) 4D with float") +{ + using data_type = float; + const std::size_t d0 = 6; + const std::size_t d1 = 10; + const std::size_t d2 = 4; + const std::size_t d3 = 12; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kwk::fill(view, 8); + std::array expected; + std::fill(expected.begin(), expected.end(), 8); + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::generate(func, container) 4D with float") +{ + using data_type = float; + const std::size_t d0 = 6; + const std::size_t d1 = 7; + const std::size_t d2 = 9; + const std::size_t d3 = 4; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; + kwk::generate ([&](auto i0, auto i1, auto i2, auto i3) { + count++; + return i0 * 1000000 + i1 * 10000 + i2 * 100 + i3; + } + , view + ); + + std::array expected; + std::size_t cpt{0}; + for (std::size_t i0 = 0; i0 < d0; ++i0) + for (std::size_t i1 = 0; i1 < d1; ++i1) + for (std::size_t i2 = 0; i2 < d2; ++i2) + for (std::size_t i3 = 0; i3 < d3; ++i3) + { + expected[cpt++] = i0 * 1000000 + i1 * 10000 + i2 * 100 + i3; + } + + TTS_ALL_EQUAL(input, expected); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::iota(out) 4D with float") +{ + using data_type = float; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 11; + const std::size_t d3 = 3; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kwk::iota(view); + + std::array expected; + std::iota(expected.begin(), expected.end(), 0); + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value) 4D with float") +{ + using data_type = float; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 11; + const std::size_t d3 = 3; + data_type initial_value = 87; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kwk::iota(view, initial_value); + + std::array expected; + std::iota(expected.begin(), expected.end(), initial_value); + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value, step) 4D with float") +{ + using data_type = float; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 11; + const std::size_t d3 = 3; + data_type initial_value = 87; + std::size_t step = 5; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kwk::iota(view, initial_value, step); + + std::array expected; + + for (std::size_t i = 0; i < input_size; ++i) + { + expected[i] = i * step + initial_value; + } + + TTS_ALL_EQUAL(input, expected); +}; + +TTS_CASE("Check for kwk::iota(out, value, step), with float 4D with float") +{ + using data_type = float; + const std::size_t d0 = 6; + const std::size_t d1 = 8; + const std::size_t d2 = 11; + const std::size_t d3 = 3; + data_type initial_value = 87; + std::size_t step = 5; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + for (data_type& e : input) { e = 0; } + auto view = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + + kwk::iota(view, initial_value, step); + + std::array expected; + + for (std::size_t i = 0; i < input_size; ++i) + { + expected[i] = i * step + initial_value; + } + + TTS_ALL_EQUAL(input, expected); +}; diff --git a/test/algorithm/algos/numeric.cpp b/test/algorithm/algos/numeric.cpp deleted file mode 100644 index dc06b854..00000000 --- a/test/algorithm/algos/numeric.cpp +++ /dev/null @@ -1,662 +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::transform_reduce(In1, In2, Reduce, Transform, init) 1D") -{ - int data1[2]; - int data2[2]; - - fill_data(data1, kwk::of_size(2), true); - fill_data(data2, kwk::of_size(2), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - auto res = kwk::transform_reduce(d1, d2, 10, - [](auto r, auto d){ return (r+d); }, - [](auto i1, auto i2){ return (i1*i2); } - ); - - TTS_EQUAL(res, 11); -}; - -TTS_CASE("Check for kwk::transform_reduce(In1, In2, Transform) 2D") -{ - int data1[2*3]; - int data2[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - fill_data(data2, kwk::of_size(2,3), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - auto res = kwk::transform_reduce(d1, d2, 0, - [](auto i1, auto i2){ return (i1*i2); } - ); - - TTS_EQUAL(res, 370); -}; - -TTS_CASE("Check for kwk::transform_reduce(In1, In2, Reduce, Transform, init) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - fill_data(data2, kwk::of_size(2,3,4), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - auto res = kwk::transform_reduce(d1, d2, 0, - [](auto r, auto d){ return (r+d); }, - [](auto i1, auto i2){ return (i1*i2); } - ); - - TTS_EQUAL(res, 152404); -}; - -TTS_CASE("Check for kwk::transform_reduce(In1, In2, Reduce, Transform, init) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - fill_data(data2, kwk::of_size(2,3,4,5), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - auto res = kwk::transform_reduce(d1, d2, 0, - [](auto r, auto d){ return (r+d); }, - [](auto i1, auto i2){ return (i1*i2); } - ); - - TTS_EQUAL(res, 76497920); -}; - -TTS_CASE("Check for kwk::inner_product(In1, In2, value, sum, product) 1D") -{ - int data1[2]; - int data2[2]; - - fill_data(data1, kwk::of_size(2), true); - fill_data(data2, kwk::of_size(2), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - auto res = kwk::inner_product(d1, d2, 0, - [](auto r, auto d){ return (r+d); }, - [](auto i1, auto i2){ return (i1==i2); } - ); - - TTS_EQUAL(res, 2); -}; - - -TTS_CASE("Check for kwk::inner_product(In1, In2, value, sum, product) 2D") -{ - int data1[2*3]; - int data2[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - fill_data(data2, kwk::of_size(2,3), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - auto res = kwk::inner_product(d1, d2, 0, - [](auto r, auto d){ return (r+d); }, - [](auto i1, auto i2){ return (i1==i2); } - ); - - TTS_EQUAL(res, 6); -}; - -TTS_CASE("Check for kwk::inner_product(In1, In2) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - fill_data(data2, kwk::of_size(2,3,4), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - auto res = kwk::inner_product(d1, d2); - - TTS_EQUAL(res, 152404); -}; - -TTS_CASE("Check for kwk::inner_product(In1, In2) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - fill_data(data2, kwk::of_size(2,3,4,5), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - auto res = kwk::inner_product(d1, d2); - - TTS_EQUAL(res, 76497920); -}; - -TTS_CASE("Check for kwk::transform_exclusive_scan(In, Out, init, f1, f2) 1D") -{ - int data1[2]; - int data2[2]; - int data3[2]; - - fill_data(data1, kwk::of_size(2), true); - fill_data(data2, kwk::of_size(2), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - kwk::transform_exclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_exclusive_scan(data1, &data1[2], - data3, - 0, std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::transform_exclusive_scan(In, Out, init, f1, f2) 2D") -{ - int data1[2*3]; - int data2[2*3]; - int data3[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - fill_data(data2, kwk::of_size(2,3), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - kwk::transform_exclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_exclusive_scan(data1, &data1[2*3], - data3, - 0, std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::transform_exclusive_scan(In, Out, init, f1, f2) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - int data3[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - fill_data(data2, kwk::of_size(2,3,4), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - kwk::transform_exclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_exclusive_scan(data1, &data1[2*3*4], - data3, - 0, std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::transform_exclusive_scan(In, Out, init, f1, f2) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - int data3[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - fill_data(data2, kwk::of_size(2,3,4,5), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - kwk::transform_exclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_exclusive_scan(data1, &data1[2*3*4*5], - data3, - 0, std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::transform_inclusive_scan(In, Out, init, f1, f2) 1D") -{ - int data1[2]; - int data2[2]; - int data3[2]; - - fill_data(data1, kwk::of_size(2), true); - fill_data(data2, kwk::of_size(2), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - kwk::transform_inclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_inclusive_scan(data1, &data1[2], - data3, - std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::transform_inclusive_scan(In, Out, init, f1, f2) 2D") -{ - int data1[2*3]; - int data2[2*3]; - int data3[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - fill_data(data2, kwk::of_size(2,3), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - kwk::transform_inclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_inclusive_scan(data1, &data1[2*3], - data3, - std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::transform_inclusive_scan(In, Out, init, f1, f2) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - int data3[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - fill_data(data2, kwk::of_size(2,3,4), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - kwk::transform_inclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_inclusive_scan(data1, &data1[2*3*4], - data3, - std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::transform_inclusive_scan(In, Out, init, f1, f2) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - int data3[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - fill_data(data2, kwk::of_size(2,3,4,5), true); - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - kwk::transform_inclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }, - [](auto i1){ return (i1); }); - - std::transform_inclusive_scan(data1, &data1[2*3*4*5], - data3, - std::plus{}, [](auto i1){ return (i1); }); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init, func) 1D") -{ - int data1[2]; - int data2[2]; - int data3[2]; - - fill_data(data1, kwk::of_size(2), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - kwk::exclusive_scan(d1, d2, 1, [](auto r, auto d){ return (r*d); }); - - std::exclusive_scan(data1, &data1[2], - data3, 1, - std::multiplies{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init, func) 2D") -{ - int data1[2*3]; - int data2[2*3]; - int data3[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - kwk::exclusive_scan(d1, d2, 1, [](auto r, auto d){ return (r*d); }); - - std::exclusive_scan(data1, &data1[2*3], - data3, 1, - std::multiplies{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init, func) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - int data3[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - kwk::exclusive_scan(d1, d2, 1, [](auto r, auto d){ return (r*d); }); - - std::exclusive_scan(data1, &data1[2*3*4], - data3, 1, - std::multiplies{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init, func) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - int data3[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - kwk::exclusive_scan(d1, d2, 1, [](auto r, auto d){ return (r*d); }); - - std::exclusive_scan(data1, &data1[2*3*4*5], - data3, 1, - std::multiplies{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init) 1D") -{ - int data1[2]; - int data2[2]; - int data3[2]; - - fill_data(data1, kwk::of_size(2), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - kwk::exclusive_scan(d1, d2, 0); - - std::exclusive_scan(data1, &data1[2], - data3, 0); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init) 2D") -{ - int data1[2*3]; - int data2[2*3]; - int data3[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - kwk::exclusive_scan(d1, d2, 0); - - std::exclusive_scan(data1, &data1[2*3], - data3, 0); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - int data3[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - kwk::exclusive_scan(d1, d2, 0); - - std::exclusive_scan(data1, &data1[2*3*4], - data3, 0); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::exclusive_scan(In, Out, init) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - int data3[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - kwk::exclusive_scan(d1, d2, 0); - - std::exclusive_scan(data1, &data1[2*3*4*5], - data3, 0); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init, func) 1D") -{ - int data1[2]; - int data2[2]; - int data3[2]; - - fill_data(data1, kwk::of_size(2), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - kwk::inclusive_scan(d1, d2, 1, [](auto r, auto d){ return (r*d); }); - - std::inclusive_scan(data1, &data1[2], - data3, - std::multiplies{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init, func) 2D") -{ - int data1[2*3]; - int data2[2*3]; - int data3[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - kwk::inclusive_scan(d1, d2, 1, [](auto r, auto d){ return (r*d); }); - - std::inclusive_scan(data1, &data1[2*3], - data3, - std::multiplies{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init, func) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - int data3[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - kwk::inclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }); - - std::inclusive_scan(data1, &data1[2*3*4], - data3, - std::plus{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init, func) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - int data3[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - kwk::inclusive_scan(d1, d2, 0, [](auto r, auto d){ return (r+d); }); - - std::inclusive_scan(data1, &data1[2*3*4*5], - data3, - std::plus{}); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init) 1D") -{ - int data1[2]; - int data2[2]; - int data3[2]; - - fill_data(data1, kwk::of_size(2), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2)}; - - kwk::inclusive_scan(d1, d2, 0); - - std::inclusive_scan(data1, &data1[2], - data3); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init) 2D") -{ - int data1[2*3]; - int data2[2*3]; - int data3[2*3]; - - fill_data(data1, kwk::of_size(2,3), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3)}; - - kwk::inclusive_scan(d1, d2, 0); - - std::inclusive_scan(data1, &data1[2*3], - data3); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init) 3D") -{ - int data1[2*3*4]; - int data2[2*3*4]; - int data3[2*3*4]; - - fill_data(data1, kwk::of_size(2,3,4), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4)}; - - kwk::inclusive_scan(d1, d2, 0); - - std::inclusive_scan(data1, &data1[2*3*4], - data3); - - TTS_ALL_EQUAL(data2, data3); -}; - -TTS_CASE("Check for kwk::inclusive_scan(In, Out, init) 4D") -{ - int data1[2*3*4*5]; - int data2[2*3*4*5]; - int data3[2*3*4*5]; - - fill_data(data1, kwk::of_size(2,3,4,5), true); - data1[0] = 1; - - auto d1 = kwk::view{kwk::source = data1, kwk::of_size(2,3,4,5)}; - auto d2 = kwk::view{kwk::source = data2, kwk::of_size(2,3,4,5)}; - - kwk::inclusive_scan(d1, d2, 0); - - std::inclusive_scan(data1, &data1[2*3*4*5], - data3); - - TTS_ALL_EQUAL(data2, data3); -}; \ No newline at end of file diff --git a/test/algorithm/algos/numeric/1d.cpp b/test/algorithm/algos/numeric/1d.cpp new file mode 100644 index 00000000..9047a156 --- /dev/null +++ b/test/algorithm/algos/numeric/1d.cpp @@ -0,0 +1,365 @@ +//================================================================================================== +/* + 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::transform_reduce(In1, In2, init, Reduce, Transform) 1D") +{ + float init_value = 11; + const std::size_t input_size = 200; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(input_size)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(input_size)}; + + std::size_t reduce_count = 0; + std::size_t transform_count = 0; + + auto res = kwk::transform_reduce( view1, view2, init_value + // Reduce function + , [&](auto r, auto d) { ++reduce_count; return (r + d); } + // Transform function + , [&](auto i1, auto i2) { ++transform_count; return (i1 * i2); } + ); + + auto chk = std::transform_reduce ( input1.begin(), input1.end(), input2.begin(), init_value + // Reduce function + , [](auto r, auto d) { return (r + d); } + // Transform function + , [](auto i1, auto i2) { return (i1 * i2); }); + + TTS_EQUAL(typeid(res), typeid(float)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); + // TTS_EXPECT(floats_are_same(res, chk)); + TTS_EQUAL(reduce_count, input_size); + TTS_EQUAL(transform_count, input_size); +}; + + +TTS_CASE("Check for kwk::transform_reduce(In1, In2, init, Transform) 1D") +{ + double init_value = 11; + const std::size_t input_size = 200; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3 + 10.875; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(input_size)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(input_size)}; + + std::size_t transform_count = 0; + + auto res = kwk::transform_reduce( view1, view2, init_value + // Transform function + , [&](auto i1, auto i2) { ++transform_count; return (i1 * i2); } + ); + + auto chk = std::transform_reduce(input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_EQUAL(typeid(res), typeid(double)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(transform_count, input_size); +}; + + +TTS_CASE("Check for kwk::transform_reduce(In1, In2) 1D") +{ + double init_value = 11; + const std::size_t input_size = 84521; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3 + 10.875; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(input_size)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(input_size)}; + + auto res = kwk::transform_reduce(view1, view2, init_value); + auto chk = std::transform_reduce(input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_EQUAL(typeid(res), typeid(double)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2, value, sum, product) 1D") +{ + float init_value = 87; + const std::size_t d0 = 2784; + const std::size_t input_size = d0; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0)}; + + auto res = kwk::inner_product(view1, view2, init_value, + [](auto r, auto d) { return (r + d); }, + [](auto i1, auto i2) { return (i1 * i2); } + ); + + auto res_std = std::inner_product (input1.begin(), input1.end(), input2.begin(), init_value + , [](auto r, auto d) { return (r + d); } + , [](auto i1, auto i2) { return (i1 * i2); } + ); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2, init) 1D") +{ + float init_value = 87.7f; + const std::size_t d0 = 2784; + const std::size_t input_size = d0; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0)}; + + auto res = kwk::inner_product(view1, view2, init_value); + auto res_std = std::inner_product (input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); + TTS_EQUAL(typeid(res_std), typeid(float)); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2) 1D") +{ + const std::size_t d0 = 2784; + const std::size_t input_size = d0; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0)}; + + auto res = kwk::inner_product(view1, view2); + auto res_std = std::inner_product(input1.begin(), input1.end(), input2.begin(), float{}); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); + TTS_EQUAL(typeid(res_std), typeid(float)); +}; + + +TTS_CASE("Check for kwk::transform_exclusive_scan(In, Out, init, f1, f2) 1D") +{ + double init_value = 87; + const std::size_t d0 = 4651; + const std::size_t input_size = d0; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0)}; + + kwk::transform_exclusive_scan ( view_in, view_out + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + std::transform_exclusive_scan ( input.begin(), input.end() + , output_std.begin() + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::transform_inclusive_scan(In, Out, init, f1, f2) 1D") +{ + double init_value = 0; + const std::size_t d0 = 4816; + const std::size_t input_size = d0; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0)}; + + kwk::transform_inclusive_scan ( view_in, view_out + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + std::transform_inclusive_scan ( input.begin(), input.end() + , output_std.begin() + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + , init_value + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::exclusive_scan(In, Out, init, func) 1D") +{ + float initial_value = 0; + const std::size_t d0 = 8716; + const std::size_t input_size = d0; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0)}; + + kwk::exclusive_scan ( view_in, view_out + , initial_value + , [](auto r, auto d){ return (r / d); } + ); + + std::exclusive_scan ( input.begin(), input.end() + , output_std.begin() + , initial_value + , [](auto r, auto d){ return (r / d); } + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::exclusive_scan(In, Out, init) 1D") +{ + int initial_value = 0; + const std::size_t d0 = 471; + const std::size_t input_size = d0; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0)}; + + kwk::exclusive_scan(view_in, view_out, initial_value); + std::exclusive_scan(input.begin(), input.end(), output_std.begin(), initial_value); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::inclusive_scan(In, Out, init, func) 1D") +{ + const std::size_t d0 = 485; + const std::size_t input_size = d0; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0)}; + + kwk::inclusive_scan(view_in, view_out, float{0}, [](auto r, auto d){ return r + d * 0.2452f; }); + std::inclusive_scan ( input.begin(), input.end(), output_std.begin() + , [](auto r, auto d){ return r + d * 0.2452f; } + , float{0} + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::inclusive_scan(In, Out, init) 1D") +{ + const std::size_t d0 = 471; + const std::size_t input_size = d0; + std::array input, output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0)}; + + kwk::inclusive_scan(view_in, view_out, int{0}); + std::inclusive_scan(input.begin(), input.end(), output_std.begin()); + + TTS_ALL_EQUAL(output, output_std); +}; diff --git a/test/algorithm/algos/numeric/2d.cpp b/test/algorithm/algos/numeric/2d.cpp new file mode 100644 index 00000000..d3785229 --- /dev/null +++ b/test/algorithm/algos/numeric/2d.cpp @@ -0,0 +1,380 @@ +//================================================================================================== +/* + 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::transform_reduce(In1, In2, init, Reduce, Transform) 2D") +{ + float init_value = 11; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1)}; + + std::size_t reduce_count = 0; + std::size_t transform_count = 0; + + auto res = kwk::transform_reduce( view1, view2, init_value + // Reduce function + , [&](auto r, auto d) { ++reduce_count; return (r + d); } + // Transform function + , [&](auto i1, auto i2) { ++transform_count; return (i1 * i2); } + ); + + auto chk = std::transform_reduce ( input1.begin(), input1.end(), input2.begin(), init_value + // Reduce function + , [](auto r, auto d) { return (r + d); } + // Transform function + , [](auto i1, auto i2) { return (i1 * i2); }); + + TTS_EQUAL(typeid(res), typeid(float)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); + // TTS_EXPECT(floats_are_same(res, chk)); + TTS_EQUAL(reduce_count, input_size); + TTS_EQUAL(transform_count, input_size); +}; + + +TTS_CASE("Check for kwk::transform_reduce(In1, In2, init, Transform) 2D") +{ + double init_value = 11; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3 + 10.875; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1)}; + + std::size_t transform_count = 0; + + auto res = kwk::transform_reduce( view1, view2, init_value + // Transform function + , [&](auto i1, auto i2) { ++transform_count; return (i1 * i2); } + ); + + auto chk = std::transform_reduce(input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_EQUAL(typeid(res), typeid(double)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(transform_count, input_size); +}; + + +TTS_CASE("Check for kwk::transform_reduce(In1, In2) 2D") +{ + double init_value = 11; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3 + 10.875; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1)}; + + auto res = kwk::transform_reduce(view1, view2, init_value); + auto chk = std::transform_reduce(input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_EQUAL(typeid(res), typeid(double)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2, value, sum, product) 2D") +{ + float init_value = 87; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1)}; + + auto res = kwk::inner_product(view1, view2, init_value, + [](auto r, auto d) { return (r + d); }, + [](auto i1, auto i2) { return (i1 * i2); } + ); + + auto res_std = std::inner_product (input1.begin(), input1.end(), input2.begin(), init_value + , [](auto r, auto d) { return (r + d); } + , [](auto i1, auto i2) { return (i1 * i2); } + ); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2, init) 2D") +{ + float init_value = 87.7f; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1)}; + + auto res = kwk::inner_product(view1, view2, init_value); + auto res_std = std::inner_product (input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); + TTS_EQUAL(typeid(res_std), typeid(float)); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2) 2D") +{ + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1)}; + + auto res = kwk::inner_product(view1, view2); + auto res_std = std::inner_product(input1.begin(), input1.end(), input2.begin(), float{}); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); + TTS_EQUAL(typeid(res_std), typeid(float)); +}; + + +TTS_CASE("Check for kwk::transform_exclusive_scan(In, Out, init, f1, f2) 2D") +{ + double init_value = 87; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::transform_exclusive_scan ( view_in, view_out + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + std::transform_exclusive_scan ( input.begin(), input.end() + , output_std.begin() + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::transform_inclusive_scan(In, Out, init, f1, f2) 2D") +{ + double init_value = 0; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::transform_inclusive_scan ( view_in, view_out + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + std::transform_inclusive_scan ( input.begin(), input.end() + , output_std.begin() + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + , init_value + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::exclusive_scan(In, Out, init, func) 2D") +{ + float initial_value = 0; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0, d1)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::exclusive_scan ( view_in, view_out + , initial_value + , [](auto r, auto d){ return (r / d); } + ); + + std::exclusive_scan ( input.begin(), input.end() + , output_std.begin() + , initial_value + , [](auto r, auto d){ return (r / d); } + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::exclusive_scan(In, Out, init) 2D") +{ + int initial_value = 0; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::exclusive_scan(view_in, view_out, initial_value); + std::exclusive_scan(input.begin(), input.end(), output_std.begin(), initial_value); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::inclusive_scan(In, Out, init, func) 2D") +{ + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::inclusive_scan(view_in, view_out, float{0}, [](auto r, auto d){ return r + d * 0.2452f; }); + std::inclusive_scan ( input.begin(), input.end(), output_std.begin() + , [](auto r, auto d){ return r + d * 0.2452f; } + , float{0} + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::inclusive_scan(In, Out, init) 2D") +{ + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t input_size = d0 * d1; + std::array input, output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1)}; + + kwk::inclusive_scan(view_in, view_out, int{0}); + std::inclusive_scan(input.begin(), input.end(), output_std.begin()); + + TTS_ALL_EQUAL(output, output_std); +}; diff --git a/test/algorithm/algos/numeric/4d.cpp b/test/algorithm/algos/numeric/4d.cpp new file mode 100644 index 00000000..bd70f4db --- /dev/null +++ b/test/algorithm/algos/numeric/4d.cpp @@ -0,0 +1,404 @@ +//================================================================================================== +/* + 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::transform_reduce(In1, In2, init, Reduce, Transform) 4D") +{ + float init_value = 11; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1, d2, d3)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1, d2, d3)}; + + std::size_t reduce_count = 0; + std::size_t transform_count = 0; + + auto res = kwk::transform_reduce( view1, view2, init_value + // Reduce function + , [&](auto r, auto d) { ++reduce_count; return (r + d); } + // Transform function + , [&](auto i1, auto i2) { ++transform_count; return (i1 * i2); } + ); + + auto chk = std::transform_reduce ( input1.begin(), input1.end(), input2.begin(), init_value + // Reduce function + , [](auto r, auto d) { return (r + d); } + // Transform function + , [](auto i1, auto i2) { return (i1 * i2); }); + + TTS_EQUAL(typeid(res), typeid(float)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); + // TTS_EXPECT(floats_are_same(res, chk)); + TTS_EQUAL(reduce_count, input_size); + TTS_EQUAL(transform_count, input_size); +}; + + +TTS_CASE("Check for kwk::transform_reduce(In1, In2, init, Transform) 4D") +{ + double init_value = 11; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3 + 10.875; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1, d2, d3)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1, d2, d3)}; + + std::size_t transform_count = 0; + + auto res = kwk::transform_reduce( view1, view2, init_value + // Transform function + , [&](auto i1, auto i2) { ++transform_count; return (i1 * i2); } + ); + + auto chk = std::transform_reduce(input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_EQUAL(typeid(res), typeid(double)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(transform_count, input_size); +}; + + +TTS_CASE("Check for kwk::transform_reduce(In1, In2) 4D") +{ + double init_value = 11; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input1; + std::array input2; + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3 + 10.875; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1, d2, d3)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1, d2, d3)}; + + auto res = kwk::transform_reduce(view1, view2, init_value); + auto chk = std::transform_reduce(input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_EQUAL(typeid(res), typeid(double)); + TTS_RELATIVE_EQUAL(res, chk, FLOAT_TOLERANCE_PERCENT); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2, value, sum, product) 4D") +{ + float init_value = 87; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1, d2, d3)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1, d2, d3)}; + + auto res = kwk::inner_product(view1, view2, init_value, + [](auto r, auto d) { return (r + d); }, + [](auto i1, auto i2) { return (i1 * i2); } + ); + + auto res_std = std::inner_product (input1.begin(), input1.end(), input2.begin(), init_value + , [](auto r, auto d) { return (r + d); } + , [](auto i1, auto i2) { return (i1 * i2); } + ); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2, init) 4D") +{ + float init_value = 87.7f; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1, d2, d3)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1, d2, d3)}; + + auto res = kwk::inner_product(view1, view2, init_value); + auto res_std = std::inner_product (input1.begin(), input1.end(), input2.begin(), init_value); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); + TTS_EQUAL(typeid(res_std), typeid(float)); +}; + + +TTS_CASE("Check for kwk::inner_product(In1, In2) 4D") +{ + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input1; + std::array input2; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i; + input2[i] = i * 0.3f + 10.875f; + } + + auto view1 = kwk::view{kwk::source = input1, kwk::of_size(d0, d1, d2, d3)}; + auto view2 = kwk::view{kwk::source = input2, kwk::of_size(d0, d1, d2, d3)}; + + auto res = kwk::inner_product(view1, view2); + auto res_std = std::inner_product(input1.begin(), input1.end(), input2.begin(), float{}); + + TTS_RELATIVE_EQUAL(res, res_std, FLOAT_TOLERANCE_PERCENT); + TTS_EQUAL(typeid(res), typeid(float)); + TTS_EQUAL(typeid(res_std), typeid(float)); +}; + + +TTS_CASE("Check for kwk::transform_exclusive_scan(In, Out, init, f1, f2) 4D") +{ + double init_value = 87; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::transform_exclusive_scan ( view_in, view_out + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + std::transform_exclusive_scan ( input.begin(), input.end() + , output_std.begin() + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::transform_inclusive_scan(In, Out, init, f1, f2) 4D") +{ + double init_value = 0; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::transform_inclusive_scan ( view_in, view_out + , init_value + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + ); + + std::transform_inclusive_scan ( input.begin(), input.end() + , output_std.begin() + , [](auto r, auto d){ return (r / d); } + , [](auto i1){ return (i1 * 2); } + , init_value + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::exclusive_scan(In, Out, init, func) 4D") +{ + float initial_value = 0; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input, kwk::of_size(d0, d1, d2, d3)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::exclusive_scan ( view_in, view_out + , initial_value + , [](auto r, auto d){ return (r / d); } + ); + + std::exclusive_scan ( input.begin(), input.end() + , output_std.begin() + , initial_value + , [](auto r, auto d){ return (r / d); } + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::exclusive_scan(In, Out, init) 4D") +{ + int initial_value = 0; + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::exclusive_scan(view_in, view_out, initial_value); + std::exclusive_scan(input.begin(), input.end(), output_std.begin(), initial_value); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::inclusive_scan(In, Out, init, func) 4D") +{ + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input; + std::array output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::inclusive_scan(view_in, view_out, float{0}, [](auto r, auto d){ return r + d * 0.2452f; }); + std::inclusive_scan ( input.begin(), input.end(), output_std.begin() + , [](auto r, auto d){ return r + d * 0.2452f; } + , float{0} + ); + + TTS_ALL_EQUAL(output, output_std); +}; + + +TTS_CASE("Check for kwk::inclusive_scan(In, Out, init) 4D") +{ + const std::size_t d0 = 50; + const std::size_t d1 = 12; + const std::size_t d2 = 8; + const std::size_t d3 = 7; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input, output, output_std; + + for (std::size_t i = 0; i < input_size; ++i) + { + input[i] = i * 3 + 10; + output[i] = 0; + output_std[i] = 0; + } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + auto view_out = kwk::view{kwk::source = output, kwk::of_size(d0, d1, d2, d3)}; + + kwk::inclusive_scan(view_in, view_out, int{0}); + std::inclusive_scan(input.begin(), input.end(), output_std.begin()); + + TTS_ALL_EQUAL(output, output_std); +}; diff --git a/test/algorithm/algos/position.cpp b/test/algorithm/algos/position.cpp new file mode 100644 index 00000000..d354537f --- /dev/null +++ b/test/algorithm/algos/position.cpp @@ -0,0 +1,84 @@ +//====================================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//====================================================================================================================== +#include +#include "test.hpp" +#include + +// for_each 1D - 4D + +TTS_CASE("Check for kwk::position(std::array)") +{ + kwk::position<3> p1{{0, 1, 2}}; + + TTS_EQUAL(p1[0], 0); + TTS_EQUAL(p1[1], 1); + TTS_EQUAL(p1[2], 2); + + kwk::position<3> p2; + p2 = {0, 1, 2}; + + TTS_EQUAL(p2[0], 0); + TTS_EQUAL(p2[1], 1); + TTS_EQUAL(p2[2], 2); + + // TTS_EQUAL(p1, p2); + TTS_EQUAL(p1 == p2, true); + + std::stringstream ss; + ss << p1; + TTS_EQUAL(ss.str(), std::string{"position<3>(0, 1, 2)"}); +}; + + +// === Kumi interface === +// Every test fails or raise a compile-time error +// TTS_CASE("Check adapted types model kumi::product_type concept") +// { +// TTS_EXPECT ( kumi::product_type> ); +// TTS_EXPECT ( (kumi::product_type> )); +// TTS_EXPECT_NOT( (kumi::product_type>)); +// }; + +// TTS_CASE("Check adapted type behave like a product_type") +// { +// auto r = kumi::apply( [](auto... x) { return (x + ...); }, kwk::position<4>{{2, 4, 7, 12}}); +// TTS_EQUAL(r, 25); + +// auto zz = kumi::zip( kwk::position<4>{{11, 12, 13, 14}}, kwk::position<4>{{21, 22, 23, 24}}); +// TTS_EQUAL ( zz, ( kumi::tuple { kumi::tuple{11, 21} +// , kumi::tuple{12, 22} +// , kumi::tuple{13, 23} +// , kumi::tuple{14, 24} +// }) +// ); + +// auto cc = kumi::cat( kwk::position<2>{{11, 12}}, kwk::position<2>{{13, 14}}); +// TTS_EQUAL ( cc, ( kumi::tuple {11, 12, 13, 14}) ); +// }; + + +// ======= + +// Generic Kumi tests, unrelated with kwk::position (these tests are passing) +// TTS_CASE("Check adapted external type behave like a product_type") +// { +// auto r = kumi::apply( [](auto... x) { return (x + ...); }, std::array{1,2,5,4}); +// TTS_EQUAL(r, 12); + +// auto zz = kumi::zip( std::array{1,2,5}, std::array{0.1,2.3,4.5}); +// TTS_EQUAL ( zz, ( kumi::tuple { kumi::tuple{1 , 0.1 } +// , kumi::tuple{2 , 2.3 } +// , kumi::tuple{5 , 4.5 } +// }) +// ); + +// auto cc = kumi::cat( std::array{1,2,5}, std::array{0.1,2.3,4.5} ); +// TTS_EQUAL ( cc, ( kumi::tuple {1, 2, 5, 0.1, 2.3, 4.5}) ); +// }; + + diff --git a/test/algorithm/algos/predicates.cpp b/test/algorithm/algos/predicates.cpp deleted file mode 100644 index 342ed78b..00000000 --- a/test/algorithm/algos/predicates.cpp +++ /dev/null @@ -1,443 +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::all_of(in, func) 1D") -{ - int data[2]; - bool vdata = true; - - fill_data(data, kwk::of_size(2), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = kwk::all_of(d, [&](auto e) - { - count++; - return (e == 0); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::all_of(in, func) 2D") -{ - int data[2*3]; - bool vdata = true; - - fill_data(data, kwk::of_size(2,3), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - int count = 0; - auto res = kwk::all_of(d, [&](auto e) - { - count++; - return (e == 0); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::all_of(in, func) 3D") -{ - int data[2*3*4]; - bool vdata = true; - - fill_data(data, kwk::of_size(2,3,4), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - int count = 0; - auto res = kwk::all_of(d, [&](auto e) - { - count++; - return (e == 0); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::all_of(in, func) 4D") -{ - int data[2*3*4*5]; - bool vdata = true; - - fill_data(data, kwk::of_size(2,3,4,5), false); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - int count = 0; - auto res = kwk::all_of(d, [&](auto e) - { - count++; - return (e == 0); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::all_of(in, func) False") -{ - int data[2*2] = { 2,2 - , 2,3 - }; - - bool vdata = false; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; - - int count = 0; - auto res = kwk::all_of(d, [&](auto e) - { - count++; - return (e == 2); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - - -TTS_CASE("Check for kwk::any_of(in, func) 1D") -{ - int data[2]; - bool vdata = true; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = kwk::any_of(d, [&](auto e) - { - count++; - return (e == 1); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::any_of(in, func) 2D") -{ - int data[2*3]; - bool vdata = true; - - 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 = kwk::any_of(d, [&](auto e) - { - count++; - return (e == 12); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::any_of(in, func) 3D") -{ - int data[2*3*4]; - bool vdata = true; - - 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 = kwk::any_of(d, [&](auto e) - { - count++; - return (e == 123); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::any_of(in, func) 4D") -{ - int data[2*3*4*5]; - bool vdata = true; - - 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 = kwk::any_of(d, [&](auto e) - { - count++; - return (e == 1234); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::any_of(in, func) False") -{ - int data[2*2] = { 2,2 - , 2,2 - }; - - bool vdata = false; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; - - int count = 0; - auto res = kwk::any_of(d, [&](auto e) - { - count++; - return (e == 3); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::none_of(in, func) 1D") -{ - int data[2]; - bool vdata = true; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = kwk::none_of(d, [&](auto e) - { - count++; - return (e == 2); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::none_of(in, func) 2D") -{ - int data[2*3]; - bool vdata = true; - - 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 = kwk::none_of(d, [&](auto e) - { - count++; - return (e == 23); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::none_of(in, func) 3D") -{ - int data[2*3*4]; - bool vdata = true; - - 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 = kwk::none_of(d, [&](auto e) - { - count++; - return (e == 234); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::none_of(in, func) 4D") -{ - int data[2*3*4*5]; - bool vdata = true; - - 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 = kwk::none_of(d, [&](auto e) - { - count++; - return (e == 2345); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::none_of(in, func) False") -{ - int data[2*2] = { 3,2 - , 2,2 - }; - - bool vdata = false; - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,2)}; - - int count = 0; - auto res = kwk::none_of(d, [&](auto e) - { - count++; - return (e == 3); - }); - - TTS_EQUAL(res, vdata); - TTS_EQUAL(count, 1); -}; - -TTS_CASE("Check for kwk::count(in, value) 1D") -{ - int data[2]; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - auto res = kwk::count(d, 1); - - TTS_EQUAL(res, 1UL); -}; - -TTS_CASE("Check for kwk::count(in, value) 2D") -{ - int data[2*3]; - - fill_data(data, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - auto res = kwk::count(d, 12); - - TTS_EQUAL(res, 1UL); -}; - -TTS_CASE("Check for kwk::count(in, value) 3D") -{ - int data[2*3*4]; - - 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::count(d, 123); - - TTS_EQUAL(res, 1UL); -}; - -TTS_CASE("Check for kwk::count(in, value) 4D") -{ - int data[2*3*4*5]; - - 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::count(d, 1234); - - TTS_EQUAL(res, 1UL); -}; - -TTS_CASE("Check for kwk::count_if(in, func) 1D") -{ - int data[2]; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - auto res = kwk::count_if(d, [&](auto e) - { - count++; - return (e >= 0); - }); - - TTS_EQUAL(res, 2UL); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::count_if(in, func) 2D") -{ - int data[2*3]; - - 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 = kwk::count_if(d, [&](auto e) - { - count++; - return (e >= 10); - }); - - TTS_EQUAL(res, 3UL); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::count_if(in, func) 3D") -{ - int data[2*3*4]; - - 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 = kwk::count_if(d, [&](auto e) - { - count++; - return (e >= 120); - }); - - TTS_EQUAL(res, 4UL); - TTS_EQUAL(count, d.numel()); -}; - -TTS_CASE("Check for kwk::count_if(in, func) 4D") -{ - int data[2*3*4*5]; - - 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 = kwk::count_if(d, [&](auto e) - { - count++; - return (e >= 1230); - }); - - TTS_EQUAL(res, 5UL); - TTS_EQUAL(count, d.numel()); -}; \ No newline at end of file diff --git a/test/algorithm/algos/predicates/1d.cpp b/test/algorithm/algos/predicates/1d.cpp new file mode 100644 index 00000000..5faa7832 --- /dev/null +++ b/test/algorithm/algos/predicates/1d.cpp @@ -0,0 +1,178 @@ +//================================================================================================== +/* + 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::all_of(in, func) 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::all_of( view_in + , [&](auto e) { ++count; return (e % 3 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::all_of(in, func) 1D false") +{ + 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; } + input[200] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + std::size_t count = 0; + auto res = kwk::all_of( view_in + , [&](auto e) { ++count; return (e % 3 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, 201UL); +}; + + +TTS_CASE("Check for kwk::any_of(in, func) 1D true") +{ + 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 * 2 + 1; } + input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + std::size_t count = 0; + auto res = kwk::any_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, 201UL); +}; + +TTS_CASE("Check for kwk::any_of(in, func) 1D false") +{ + 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 * 2 + 1; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + std::size_t count = 0; + auto res = kwk::any_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, input_size); +}; + + +TTS_CASE("Check for kwk::none_of(in, func) 1D true") +{ + 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 * 2 + 1; } + // input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + std::size_t count = 0; + auto res = kwk::none_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::none_of(in, func) 1D false") +{ + 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 * 2 + 1; } + input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + std::size_t count = 0; + auto res = kwk::none_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, 201UL); +}; + + +TTS_CASE("Check for kwk::count(in, value) 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 * 2; } + input[100] = 8; + input[234] = 8; + input[311] = 8; + input[312] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + auto res = kwk::count(view_in, 8); + + TTS_EQUAL(res, 5UL); +}; + +TTS_CASE("Check for kwk::count_if(in, func) 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 * 2; } + input[234] = 8; + input[311] = 8; + input[312] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + auto res = kwk::count_if(view_in, [](auto e) { return e <= 100; }); + + TTS_EQUAL(res, 54UL); +}; + diff --git a/test/algorithm/algos/predicates/2d.cpp b/test/algorithm/algos/predicates/2d.cpp new file mode 100644 index 00000000..d3844f11 --- /dev/null +++ b/test/algorithm/algos/predicates/2d.cpp @@ -0,0 +1,186 @@ +//================================================================================================== +/* + 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::all_of(in, func) 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::all_of( view_in + , [&](auto e) { ++count; return (e % 3 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::all_of(in, func) 2D false") +{ + 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; } + input[200] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + std::size_t count = 0; + auto res = kwk::all_of( view_in + , [&](auto e) { ++count; return (e % 3 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, 201UL); +}; + + +TTS_CASE("Check for kwk::any_of(in, func) 2D true") +{ + 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 * 2 + 1; } + input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + std::size_t count = 0; + auto res = kwk::any_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, 201UL); +}; + +TTS_CASE("Check for kwk::any_of(in, func) 2D false") +{ + 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 * 2 + 1; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + std::size_t count = 0; + auto res = kwk::any_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, input_size); +}; + + +TTS_CASE("Check for kwk::none_of(in, func) 2D true") +{ + 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 * 2 + 1; } + // input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + std::size_t count = 0; + auto res = kwk::none_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::none_of(in, func) 2D false") +{ + 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 * 2 + 1; } + input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + std::size_t count = 0; + auto res = kwk::none_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, 201UL); +}; + + +TTS_CASE("Check for kwk::count(in, value) 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 * 2; } + input[100] = 8; + input[234] = 8; + input[311] = 8; + input[312] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + auto res = kwk::count(view_in, 8); + + TTS_EQUAL(res, 5UL); +}; + +TTS_CASE("Check for kwk::count_if(in, func) 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 * 2; } + input[234] = 8; + input[311] = 8; + input[312] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + auto res = kwk::count_if(view_in, [](auto e) { return e <= 100; }); + + TTS_EQUAL(res, 54UL); +}; + diff --git a/test/algorithm/algos/predicates/4d.cpp b/test/algorithm/algos/predicates/4d.cpp new file mode 100644 index 00000000..ffd605df --- /dev/null +++ b/test/algorithm/algos/predicates/4d.cpp @@ -0,0 +1,202 @@ +//================================================================================================== +/* + 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::all_of(in, func) 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::all_of( view_in + , [&](auto e) { ++count; return (e % 3 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::all_of(in, func) 4D false") +{ + 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; } + input[200] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; + auto res = kwk::all_of( view_in + , [&](auto e) { ++count; return (e % 3 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, 201UL); +}; + + +TTS_CASE("Check for kwk::any_of(in, func) 4D true") +{ + 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 * 2 + 1; } + input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; + auto res = kwk::any_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, 201UL); +}; + +TTS_CASE("Check for kwk::any_of(in, func) 4D false") +{ + 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 * 2 + 1; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; + auto res = kwk::any_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, input_size); +}; + + +TTS_CASE("Check for kwk::none_of(in, func) 4D true") +{ + 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 * 2 + 1; } + // input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; + auto res = kwk::none_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, true); + TTS_EQUAL(count, input_size); +}; + +TTS_CASE("Check for kwk::none_of(in, func) 4D false") +{ + 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 * 2 + 1; } + input[200] = 222; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + std::size_t count = 0; + auto res = kwk::none_of( view_in + , [&](auto e) { ++count; return (e % 2 == 0); } + ); + + TTS_EQUAL(res, false); + TTS_EQUAL(count, 201UL); +}; + + +TTS_CASE("Check for kwk::count(in, value) 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 * 2; } + input[100] = 8; + input[234] = 8; + input[311] = 8; + input[312] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + auto res = kwk::count(view_in, 8); + + TTS_EQUAL(res, 5UL); +}; + +TTS_CASE("Check for kwk::count_if(in, func) 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 * 2; } + input[234] = 8; + input[311] = 8; + input[312] = 8; + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + auto res = kwk::count_if(view_in, [](auto e) { return e <= 100; }); + + TTS_EQUAL(res, 54UL); +}; + 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); +}; diff --git a/test/algorithm/algos/replace.cpp b/test/algorithm/algos/replace.cpp deleted file mode 100644 index d73f1ca2..00000000 --- a/test/algorithm/algos/replace.cpp +++ /dev/null @@ -1,223 +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::replace(value, new_value) 1D") -{ - int data[2]; - int vdata[2]; - - fill_data(data, kwk::of_size(2), true); - fill_data(vdata, kwk::of_size(2), true); - - vdata[1] = 10; - - auto v = kwk::view{kwk::source = data, kwk::of_size(2)}; - - kwk::replace(v, 1, 10); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::replace(value, new_value) 2D") -{ - int data[2*3]; - int vdata[2*3]; - - fill_data(data, kwk::of_size(2,3), true); - fill_data(vdata, kwk::of_size(2,3), true); - - vdata[1*3+2] = 120; - - auto v = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - kwk::replace(v, 12, 120); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::replace(value, new_value) 3D") -{ - int data[2*3*4]; - int vdata[2*3*4]; - - fill_data(data, kwk::of_size(2,3,4), true); - fill_data(vdata, kwk::of_size(2,3,4), true); - - vdata[1*4*3+2*4+3] = 1230; - - auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - kwk::replace(v, 123, 1230); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::replace(value, new_value) 4D") -{ - int data[2*3*4*5]; - int vdata[2*3*4*5]; - - fill_data(data, kwk::of_size(2,3,4,5), true); - fill_data(vdata, kwk::of_size(2,3,4,5), true); - - vdata[1*5*4*3+2*5*4+3*5+4] = 12340; - - auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - kwk::replace(v, 1234, 12340); - - TTS_ALL_EQUAL(data, vdata); -}; - -TTS_CASE("Check for kwk::replace_if(func, new_value) 1D") -{ - int data[2]; - int vdata[2]; - - fill_data(data, kwk::of_size(2), true); - fill_data(vdata, kwk::of_size(2), false); - - auto v = kwk::view{kwk::source = data, kwk::of_size(2)}; - - int count = 0; - kwk::replace_if(v, [&](auto e) - { - count++; - return (e>=0); - } - , 0); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, v.numel()); -}; - -TTS_CASE("Check for kwk::replace_if(func, new_value) 2D") -{ - int data[2*3]; - int vdata[2*3]; - - fill_data(data, kwk::of_size(2,3), true); - fill_data(vdata, kwk::of_size(2,3), false); - - auto v = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - - int count = 0; - kwk::replace_if(v, [&](auto e) - { - count++; - return (e>=0); - } - , 0); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, v.numel()); -}; - -TTS_CASE("Check for kwk::replace_if(func, new_value) 3D") -{ - int data[2*3*4]; - int vdata[2*3*4]; - - fill_data(data, kwk::of_size(2,3,4), true); - fill_data(vdata, kwk::of_size(2,3,4), false); - - auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - - int count = 0; - kwk::replace_if(v, [&](auto e) - { - count++; - return (e>=0); - } - , 0); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, v.numel()); -}; - -TTS_CASE("Check for kwk::replace_if(func, new_value) 4D") -{ - int data[2*3*4*5]; - int vdata[2*3*4*5]; - - fill_data(data, kwk::of_size(2,3,4,5), true); - fill_data(vdata, kwk::of_size(2,3,4,5), false); - - auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - - int count = 0; - kwk::replace_if(v, [&](auto e) - { - count++; - return (e>=0); - } - , 0); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, v.numel()); -}; - -TTS_CASE("Check for kwk::replace_if(func, new_value) 4D smaller view") -{ - int data[2*3*4*5]; - int vdata[2*3*4*5]; - - fill_data(data, kwk::of_size(2,3,4,5), true); - fill_data(vdata, kwk::of_size(2,3,4,5), false); - - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - for(int l = 0; l<5; l++) - vdata[1*5*4*3+j*5*4+k*5+l] = 1000+100*j+10*k+l; - - auto v = kwk::view{kwk::source = data, kwk::of_size(1,3,4,5)}; - - int count = 0; - kwk::replace_if(v, [&](auto e) - { - count++; - return (e>=0); - } - , 0); - - TTS_ALL_EQUAL(data, vdata); - TTS_EQUAL(count, v.numel()); -}; - -// How to take a view from 2 3 4 5 to 2 3 4 4 ? - -// TTS_CASE("Check for kwk::replace_if(func, new_value) 4D smaller view") -// { -// int data[2*3*4*5]; -// int vdata[2*3*4*5]; - -// fill_data(data, kwk::of_size(2,3,4,5), true); -// fill_data(vdat, kwk::of_size(2,3,4,5), false); - -// for(int i = 0; i<2; i++) -// for(int j = 0; j<3; j++) -// for(int k = 0; k<4; k++) -// vdata[i*j*k*4] = 1000*i+100*j+10*k+4; - -// auto v = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5), kwk::of_size(2,3,4,4)}; - -// int count = 0; -// kwk::replace_if(v, [&](auto e) -// { -// count++; -// return (e>=0); -// } -// , 0); - -// TTS_ALL_EQUAL(data, vdata); -// TTS_EQUAL(count, v.numel()); -// }; \ No newline at end of file diff --git a/test/algorithm/algos/replace/1d.cpp b/test/algorithm/algos/replace/1d.cpp new file mode 100644 index 00000000..f7325532 --- /dev/null +++ b/test/algorithm/algos/replace/1d.cpp @@ -0,0 +1,52 @@ +//================================================================================================== +/* + 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::replace(container, value, new_value) 1D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t input_size = d0; + std::array input, check; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; check[i] = i; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + kwk::replace(view_in, 5, 3); + kwk::replace(view_in, 8, 4); + kwk::replace(view_in, 10, 7825); + + std::replace(check.begin(), check.end(), 5, 3); + std::replace(check.begin(), check.end(), 8, 4); + std::replace(check.begin(), check.end(), 10, 7825); + + TTS_ALL_EQUAL(input, check); +}; + +TTS_CASE("Check for kwk::replace_if(container, func, new_value) 1D") +{ + using data_type = int; + const std::size_t d0 = 471; + const std::size_t input_size = d0; + std::array input, check; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; check[i] = i; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0)}; + + kwk::replace_if(view_in, [](auto const e){ return (e < 50) || (e == 123); }, 3); + std::replace_if(check.begin(), check.end(), [](auto const e){ return (e < 50) || (e == 123); }, 3); + + TTS_ALL_EQUAL(input, check); +}; + diff --git a/test/algorithm/algos/replace/2d.cpp b/test/algorithm/algos/replace/2d.cpp new file mode 100644 index 00000000..67a259e6 --- /dev/null +++ b/test/algorithm/algos/replace/2d.cpp @@ -0,0 +1,54 @@ +//================================================================================================== +/* + 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::replace(container, value, new_value) 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, check; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; check[i] = i; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + kwk::replace(view_in, 5, 3); + kwk::replace(view_in, 8, 4); + kwk::replace(view_in, 10, 7825); + + std::replace(check.begin(), check.end(), 5, 3); + std::replace(check.begin(), check.end(), 8, 4); + std::replace(check.begin(), check.end(), 10, 7825); + + TTS_ALL_EQUAL(input, check); +}; + +TTS_CASE("Check for kwk::replace_if(container, func, new_value) 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, check; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; check[i] = i; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1)}; + + kwk::replace_if(view_in, [](auto const e){ return (e < 50) || (e == 123); }, 3); + std::replace_if(check.begin(), check.end(), [](auto const e){ return (e < 50) || (e == 123); }, 3); + + TTS_ALL_EQUAL(input, check); +}; + diff --git a/test/algorithm/algos/replace/4d.cpp b/test/algorithm/algos/replace/4d.cpp new file mode 100644 index 00000000..0903dcd9 --- /dev/null +++ b/test/algorithm/algos/replace/4d.cpp @@ -0,0 +1,58 @@ +//================================================================================================== +/* + 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::replace(container, value, new_value) 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, check; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; check[i] = i; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + kwk::replace(view_in, 5, 3); + kwk::replace(view_in, 8, 4); + kwk::replace(view_in, 10, 7825); + + std::replace(check.begin(), check.end(), 5, 3); + std::replace(check.begin(), check.end(), 8, 4); + std::replace(check.begin(), check.end(), 10, 7825); + + TTS_ALL_EQUAL(input, check); +}; + +TTS_CASE("Check for kwk::replace_if(container, func, new_value) 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, check; + + for (std::size_t i = 0; i < input_size; ++i) { input[i] = i; check[i] = i; } + + auto view_in = kwk::view{kwk::source = input , kwk::of_size(d0, d1, d2, d3)}; + + kwk::replace_if(view_in, [](auto const e){ return (e < 50) || (e == 123); }, 3); + std::replace_if(check.begin(), check.end(), [](auto const e){ return (e < 50) || (e == 123); }, 3); + + TTS_ALL_EQUAL(input, check); +}; + diff --git a/test/algorithm/algos/temporarily_disabled/context.cpp b/test/algorithm/algos/temporarily_disabled/context.cpp new file mode 100644 index 00000000..e8246276 --- /dev/null +++ b/test/algorithm/algos/temporarily_disabled/context.cpp @@ -0,0 +1,1305 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include +#include +#include +#include +#include +#include +#include +#include +#include "test.hpp" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace test +{ + const std::size_t d0 = 2; + const std::size_t d1 = 3; + int global_data1[d0 * d1]; + int global_data2[d0 * d1]; + + auto make_view_1() + { + for (std::size_t i = 0; i < d0 * d1; ++i) { global_data1[i] = 0; } + global_data1[1] = 6; + global_data1[3] = 6; + return kwk::view{kwk::source = global_data1, kwk::of_size(d0, d1)}; + } + + auto make_view_2() + { + return kwk::view{kwk::source = global_data2, kwk::of_size(d0, d1)}; + } + + struct messaging_context + { + public: + static inline const std::string base_message{"Uninitialized string."}; + // messaging_context() { message = std::make_unique(messaging_context::base_message); } + // std::string get_message() const { return *message; } + // std::string set_message(auto const& msg) const { *message = std::string{msg}; return *message; } + + messaging_context() + { + messages = std::make_unique>(); + } + std::string get_message() const + { + if (messages->size() == 0) return base_message; + return messages->at(messages->size()-1); + } + std::string get_message(std::size_t i) const + { + return messages->at(i); + } + + std::string set_message(auto const& msg) const + { + messages->push_back(std::string{msg}); + return msg; + } + + void print() + { + std::cout << "Messages: "; + std::size_t i = 0; + for (std::string const& s : *messages) + { + std::cout << s; + ++i; + if (i != messages->size()) std::cout << " -> "; + } + std::cout << std::endl; + } + + protected: + // std::unique_ptr message; + std::unique_ptr> messages; + }; +} + +// Functions from context +// for_each : must be reimplemented by every context +// transform : in base_context +// reduce : in base_context + + + +namespace test +{ + struct context_for_each : kwk::base_context, messaging_context + { + using messaging_context::messaging_context; + + template + constexpr auto map(Func f, kwk::shape const& shp) const + { + set_message("map used!"); + return [&](std::index_sequence const&) + { + return kwk::__::for_each(f, shp ); + }( std::make_index_sequence::static_order>{} ); + } + + template + constexpr auto map(Func f, C0&& c0, Cs&&... cs) const + { + this->map([&](auto... is) { return f(KWK_FWD(c0)(is...), KWK_FWD(cs)(is...)...); }, c0.shape() ); + return f; + } + + template + constexpr auto map_index(Func f, Container&& c) const + { + this->map ( [&](auto... is) { return f(KWK_FWD(c)(is...), is...); } + , c.shape() + ); + return f; + } + }; + + struct c_for_each1 : public context_for_each {}; + struct c_for_each2 : public context_for_each {}; + + using c_base = context_for_each; +} +namespace kwk +{ + template + constexpr auto for_each(test::c_for_each2& ctx, Func&& f, shape const& shp) + { + ctx.set_message("for_each(ctx, f, shp) used!"); + kwk::for_each(cpu, KWK_FWD(f), shp); + } + + template + constexpr auto for_each(test::c_for_each1& ctx, Func f, C0&& c0, Cs&&... cs) + { + ctx.set_message("for_each(ctx, f, c0, cs...) used!"); + return kwk::for_each(cpu, f, KWK_FWD(c0), KWK_FWD(cs)...); + } +} +TTS_CASE("Check for context overload - for_each") +{ + auto v = test::make_view_1(); + + // FOR_EACH (for_each) + { + test::context_for_each c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::for_each(c1, [](auto) {}, v); + TTS_EQUAL(c1.get_message(), std::string{"map used!"}); + } + + // kwk::for_each overloads + { + test::c_for_each1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::for_each(c1, [](auto) {}, v); + TTS_EQUAL(c1.get_message(), std::string{"for_each(ctx, f, c0, cs...) used!"}); + + auto shp = kwk::of_size(4,kwk::fixed<6>,3ULL); + test::c_for_each2 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::for_each(c2, [&](auto...) {}, shp); + TTS_EQUAL(c2.get_message(), std::string{"for_each(ctx, f, shp) used!"}); + } +}; + + + + + +namespace test +{ + struct c_transform1 : public context_for_each {}; + + // struct context_transform : kwk::base_context, messaging_context + // { + // using messaging_context::messaging_context; + + // template< typename Func, kwk::concepts::container Out + // , kwk::concepts::container C0, kwk::concepts::container... Cs + // > + // constexpr auto transform(Func f, Out& out, C0&& c0, Cs&&... cs) const + // { + // set_message("transform used!"); + // kwk::for_each(kwk::cpu, [&](auto... is) { out(is...) = f(KWK_FWD(c0)(is...), KWK_FWD(cs)(is...)...); }, out.shape() ); + // } + // }; +} +namespace kwk +{ + template< typename Func, concepts::container Out + , concepts::container C0, concepts::container... Cs + > + constexpr auto transform(test::c_transform1& ctx, Func f, Out& out, C0&& c0, Cs&&... cs) + { + ctx.set_message("transform(ctx, f, out, c0, cs...) used!"); + transform(f, out, KWK_FWD(c0), KWK_FWD(cs)...); + } +} +TTS_CASE("Check for context overload - transform") +{ + auto v = test::make_view_1(); + auto v2 = test::make_view_2(); + + // TRANSFORM (transform -> for_each) + { + // test::context_transform c1; + // TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + // kwk::transform(c1, [](auto e) { return e+1; }, v, v2); + // TTS_EQUAL(c1.get_message(), std::string{"transform used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::transform(c2, [](auto e) { return e+1; }, v, v2); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } + + // kwk::transform specialization + { + test::c_transform1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::transform(c1, [](auto e) { return e+1; }, v, v2); + TTS_EQUAL(c1.get_message(), std::string{"transform(ctx, f, out, c0, cs...) used!"}); + } +}; + + + + + + +namespace test +{ + struct c_reduce1 : public context_for_each {}; + struct c_reduce2 : public context_for_each {}; + struct c_reduce3 : public context_for_each {}; + + // struct context_reduce : kwk::base_context, messaging_context + // { + // using messaging_context::messaging_context; + + // template + // constexpr auto reduce(In const& in, Func f, auto init) const + // { + // set_message("reduce used!"); + // return kwk::reduce(in, f, init); + // } + // }; +} +namespace kwk +{ + + template + constexpr auto reduce(test::c_reduce3& ctx, In const& in, Func f, auto init) + { + ctx.set_message("reduce(ctx, in, f, init) used!"); + return reduce(in, f, init); + } + + template + constexpr auto reduce(test::c_reduce2& ctx, In const& in, Func f) + { + ctx.set_message("reduce(ctx, in, f) used!"); + return reduce(in, f); + } + + template + constexpr auto reduce(test::c_reduce1& ctx, In const& in) + { + ctx.set_message("reduce(ctx, in) used!"); + return reduce(in); + } +} +TTS_CASE("Check for context overload - reduce") +{ + auto v = test::make_view_1(); + + // Reduce context (reduce -> for_each) + { + // test::context_reduce c1; + // TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + // kwk::reduce(c1, v); + // TTS_EQUAL(c1.get_message(), std::string{"reduce used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::reduce(c2, v, [](auto a, auto e){ return (a+e); }); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + + test::context_for_each c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::reduce(c3, v, [](auto a, auto e){ return (a+e); }, 100); + TTS_EQUAL(c3.get_message(), std::string{"map used!"}); + } + + // Reduce overloads + { + test::c_reduce1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::reduce(c1, v); + TTS_EQUAL(c1.get_message(), std::string{"reduce(ctx, in) used!"}); + + test::c_reduce2 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::reduce(c2, v); + TTS_EQUAL(c2.get_message(), std::string{"reduce(ctx, in, f) used!"}); + + test::c_reduce3 c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::reduce(c3, v); + TTS_EQUAL(c3.get_message(), std::string{"reduce(ctx, in, f, init) used!"}); + + test::context_for_each c4; + TTS_EQUAL(c4.get_message(), test::messaging_context::base_message); + kwk::reduce(c4, v); + TTS_EQUAL(c4.get_message(), std::string{"map used!"}); + } + +}; + + + + + + + +namespace test +{ + struct c_upper_bound1 : public context_for_each {}; + struct c_upper_bound2 : public context_for_each {}; + struct c_lower_bound1 : public context_for_each {}; + struct c_lower_bound2 : public context_for_each {}; + struct c_binary_search1 : public context_for_each {}; + struct c_binary_search2 : public context_for_each {}; +} +namespace kwk +{ + template + constexpr auto lower_bound(test::c_lower_bound2& c, Out const& out, auto value, Func func) + { + c.set_message("lower_bound(ctx, out, value, func) used!"); + return lower_bound(out, value, func); + } + template + constexpr auto lower_bound(test::c_lower_bound1& c, Out const& out, auto value) + { + c.set_message("lower_bound(ctx, out, value) used!"); + return lower_bound(out, value); + } + + template + constexpr auto upper_bound(test::c_upper_bound2& c, Out const& out, auto value, Func func) + { + c.set_message("upper_bound(ctx, out, value, func) used!"); + return upper_bound(out, value, func); + } + template + constexpr auto upper_bound(test::c_upper_bound1& c, Out const& out, auto value) + { + c.set_message("upper_bound(ctx, out, value) used!"); + return upper_bound(out, value); + } + + template + constexpr auto binary_search(test::c_binary_search2& c, Out const& out, auto value, Func func) + { + c.set_message("binary_search(ctx, out, value, func) used!"); + return binary_search(out, value, func); + } + template + constexpr auto binary_search(test::c_binary_search1& c, Out const& out, auto value) + { + c.set_message("binary_search(ctx, out, value) used!"); + return binary_search(out, value); + } +} +TTS_CASE("Check for context overload - lower/upper_bound & binary_search") +{ + auto v = test::make_view_1(); + + // LOWER_BOUND (lower_bound -> kwk::coordinates) + { + test::c_lower_bound1 c1; + TTS_EQUAL(c1.get_message(), test::c_base::base_message); + kwk::lower_bound(c1, v, 21); + TTS_EQUAL(c1.get_message(), std::string{"lower_bound(ctx, out, value) used!"}); + + test::c_lower_bound2 c2; + TTS_EQUAL(c2.get_message(), test::c_base::base_message); + kwk::lower_bound(c2, v, 21, [](auto e, auto s) { return e < (s-1); }); + TTS_EQUAL(c2.get_message(), std::string{"lower_bound(ctx, out, value, func) used!"}); + + test::c_lower_bound2 c3; + TTS_EQUAL(c3.get_message(), test::c_base::base_message); + kwk::lower_bound(c3, v, 21); + TTS_EQUAL(c3.get_message(), std::string{"lower_bound(ctx, out, value, func) used!"}); + } + + // UPPER_BOUND (upper_bound -> kwk::coordinates) + { + test::c_upper_bound1 c2; + TTS_EQUAL(c2.get_message(), test::c_base::base_message); + kwk::upper_bound(c2, v, 21); + TTS_EQUAL(c2.get_message(), std::string{"upper_bound(ctx, out, value) used!"}); + + test::c_upper_bound2 c1; + TTS_EQUAL(c1.get_message(), test::c_base::base_message); + kwk::upper_bound(c1, v, 21, [](auto, auto) {return true;}); + TTS_EQUAL(c1.get_message(), std::string{"upper_bound(ctx, out, value, func) used!"}); + + + test::c_upper_bound2 c3; + TTS_EQUAL(c3.get_message(), test::c_base::base_message); + kwk::upper_bound(c3, v, 21); + TTS_EQUAL(c3.get_message(), std::string{"upper_bound(ctx, out, value, func) used!"}); + } + + // BINARY_SEARCH (binary_search -> lower_bound -> kwk::coordinates) + { + test::c_binary_search1 c1; + TTS_EQUAL(c1.get_message(), test::c_base::base_message); + kwk::binary_search(c1, v, 4); + TTS_EQUAL(c1.get_message(), std::string{"binary_search(ctx, out, value) used!"}); + + test::c_binary_search2 c2; + TTS_EQUAL(c2.get_message(), test::c_base::base_message); + kwk::binary_search(c2, v, 4, [](auto e, auto s){return e < s;}); + TTS_EQUAL(c2.get_message(), std::string{"binary_search(ctx, out, value, func) used!"}); + + test::c_lower_bound2 c3; + TTS_EQUAL(c3.get_message(), test::c_base::base_message); + kwk::binary_search(c3, v, 21); + TTS_EQUAL(c3.get_message(), std::string{"lower_bound(ctx, out, value, func) used!"}); // TODO: ERREUR ALÉATOIRE ICI, COMPRENDRE POURQUOI + // TODO: vérifier que l'erreur suivante n'arrive plus, même 1 fois sur 10: + // [context.cpp:341] - ** FAILURE ** : Expression: c3.get_message() == std::string{"lower_bound used!"} is false because: Uninitialized string. != lower_bound used! + } +}; + + + + + + + + +namespace test +{ + struct c_copy : public context_for_each {}; + struct c_copy_if : public context_for_each {}; +} +namespace kwk +{ + template + constexpr auto copy(test::c_copy& ctx, Out& out, In&& in) + { + ctx.set_message("copy used!"); + return copy(out, in); + } + + template + constexpr auto copy_if(test::c_copy_if& ctx, Func f, Out& out, In&& in) + { + ctx.set_message("copy_if used!"); + return copy_if(f, out, in); + } + + // template< typename Func, concepts::container Out + // , concepts::container C0, concepts::container... Cs + // > + // constexpr auto transform(test::c_transform1& ctx, Func f, Out& out, C0&& c0, Cs&&... cs) + // { + // ctx.set_message("transform(ctx, f, out, c0, cs...) used!"); + // transform(f, out, KWK_FWD(c0), KWK_FWD(cs)...); + // } +} +TTS_CASE("Check for context overload - copy & copy_if") +{ + auto v = test::make_view_1(); + auto v2 = test::make_view_2(); + + // COPY (copy -> transform -> for_each) + { + test::c_copy c1; + TTS_EQUAL(c1.get_message(), test::c_base::base_message); + kwk::copy(c1, v, v2); + TTS_EQUAL(c1.get_message(), std::string{"copy used!"}); + + test::c_transform1 c2; + TTS_EQUAL(c2.get_message(), test::c_base::base_message); + kwk::copy(c2, v, v2); + TTS_EQUAL(c2.get_message(), std::string{"transform(ctx, f, out, c0, cs...) used!"}); + + test::context_for_each c3; + TTS_EQUAL(c3.get_message(), test::c_base::base_message); + kwk::copy(c3, v, v2); + TTS_EQUAL(c3.get_message(), std::string{"map used!"}); + } + + // COPY_IF (copy_if -> for_each) + { + test::c_copy_if c1; + TTS_EQUAL(c1.get_message(), test::c_base::base_message); + kwk::copy_if(c1, [](auto) {return true;}, v, v2); + TTS_EQUAL(c1.get_message(), std::string{"copy_if used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::c_base::base_message); + kwk::copy_if(c2, [](auto) {return true;}, v, v2); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } +}; + + + + + + + + +namespace test +{ + struct c_all_of : public context_for_each {}; + struct c_any_of : public context_for_each {}; + struct c_none_of : public context_for_each {}; + struct c_count : public context_for_each {}; + struct c_count_if : public context_for_each {}; +} +namespace kwk +{ + template + constexpr auto all_of(test::c_all_of& ctx, In const& in, Func f) + { + ctx.set_message("all_of used!"); + return kwk::all_of(in, f); + } + + template + constexpr auto any_of(test::c_any_of& ctx, In const& in, Func f) + { + ctx.set_message("any_of used!"); + return kwk::any_of(in, f); + } + + template + constexpr auto none_of(test::c_none_of& ctx, In const& in, Func f) + { + ctx.set_message("none_of used!"); + return kwk::none_of(in, f); + } + + template + constexpr auto count(test::c_count& ctx, In const& in, auto value) + { + ctx.set_message("count used!"); + return kwk::count(in, value); + } + + template + constexpr auto count_if(test::c_count_if& ctx, In const& in, Func f) + { + ctx.set_message("count_if used!"); + return kwk::count_if(in, f); + } +}; +TTS_CASE("Check for context overload - predicates: all_of, any_of, none_of, count, count_if") +{ + auto v = test::make_view_1(); + + // all_of -> reduce -> for_each + { + test::c_all_of c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::all_of(c1, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c1.get_message(), std::string{"all_of used!"}); + + test::c_reduce3 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::all_of(c2, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c2.get_message(), std::string{"reduce(ctx, in, f, init) used!"}); + + test::context_for_each c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::all_of(c3, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c3.get_message(), std::string{"map used!"}); + } + + // COUNT (count -> reduce -> for_each) + { + test::c_count c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::count(c1, v, 6); + TTS_EQUAL(c1.get_message(), std::string{"count used!"}); + + test::c_reduce3 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::count(c2, v, 6); + TTS_EQUAL(c2.get_message(), std::string{"reduce(ctx, in, f, init) used!"}); + + test::context_for_each c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::count(c3, v, 6); + TTS_EQUAL(c3.get_message(), std::string{"map used!"}); + } + + // ANY_OF (any_of -> reduce -> for_each) + { + test::c_any_of c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::any_of(c1, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c1.get_message(), std::string{"any_of used!"}); + + test::c_reduce3 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::any_of(c2, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c2.get_message(), std::string{"reduce(ctx, in, f, init) used!"}); + + test::context_for_each c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::any_of(c3, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c3.get_message(), std::string{"map used!"}); + } + + // NONE_OF (none_of -> !any_of -> reduce -> for_each) + { + test::c_none_of c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::none_of(c1, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c1.get_message(), std::string{"none_of used!"}); + + test::c_any_of c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::none_of(c2, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c2.get_message(), std::string{"any_of used!"}); + + test::c_reduce3 c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::none_of(c3, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c3.get_message(), std::string{"reduce(ctx, in, f, init) used!"}); + + test::context_for_each c4; + TTS_EQUAL(c4.get_message(), test::messaging_context::base_message); + kwk::none_of(c4, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c4.get_message(), std::string{"map used!"}); + } + + // COUNT_IF (count_if -> reduce -> for_each) + { + test::c_count_if c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::count_if(c1, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c1.get_message(), std::string{"count_if used!"}); + + test::c_reduce3 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::count_if(c2, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c2.get_message(), std::string{"reduce(ctx, in, f, init) used!"}); + + test::context_for_each c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::count_if(c3, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c3.get_message(), std::string{"map used!"}); + } +}; + + + + + +// TODO: uncomment "find" tests when kwk::reverse will work again +// TODO: uncomment "find" tests when kwk::reverse will work again + +namespace test +{ + struct c_find : public context_for_each {}; + struct c_find_if : public context_for_each {}; + struct c_find_if_not : public context_for_each {}; + struct c_find_first_of : public context_for_each {}; + struct c_find_last : public context_for_each {}; + struct c_find_last_if : public context_for_each {}; + struct c_find_last_if_not : public context_for_each {}; +} +namespace kwk +{ + template + constexpr auto find_if(test::c_find_if& ctx, Container const& c, Check cc) + { + ctx.set_message("find_if used!"); + return find_if(cpu, c, cc); + } + + template + constexpr auto find(test::c_find& ctx, Out const& o, auto v) + { + ctx.set_message("find used!"); + return find(cpu, o, v); + } + + template + constexpr auto find_if_not(test::c_find_if_not& ctx, Out const& o, Func f) + { + ctx.set_message("find_if_not used!"); + return find_if_not(cpu, o, f); + } + + template + constexpr auto find_first_of(test::c_find_first_of& ctx, Out const& o, Values const& v) + { + ctx.set_message("find_first_of used!"); + return find_first_of(cpu, o, v); + } + + template + constexpr auto find_last_if(test::c_find_last_if& ctx, Out const& o, Func f) + { + ctx.set_message("find_last_if used!"); + return find_last_if(cpu, o, f); + } + + template + constexpr auto find_last(test::c_find_last& ctx, Out const& o, auto v) + { + ctx.set_message("find_last used!"); + return find_last(cpu, o, v); + } + + template + constexpr auto find_last_if_not(test::c_find_last_if_not& ctx, Out const& o, Func f) + { + ctx.set_message("find_last_if_not used!"); + return find_last_if_not(cpu, o, f); + } + + // find_if -> kwk::__::for_until + // find_if_not -> find_if + // find_first_of -> find_if + // find_first_of -> any_of -> reduce -> for_each + // find -> find_if + // find_last_if -> find_if + // find_last -> find_last_if -> find_if + // find_last_if_not -> find_last_if -> find_if +}; + +TTS_CASE("Check for context overload - initially from find.hpp") +{ + auto v = test::make_view_1(); + + // find_if -> kwk::__::for_until + { + test::c_find_if c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::find_if(c1, v, [&](auto){ return true; }); + TTS_EQUAL(c1.get_message(), std::string{"find_if used!"}); + + // kwk::__::for_until + // test::context_for_until c2; + // TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + // kwk::find_if(c2, v, [&](auto e){ return true; }); + // TTS_EQUAL(c2.get_message(), std::string{"for_until used!"}); + } + + // find -> find_if -> kwk::__::for_until + { + test::c_find c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::find(c1, v, 12); + TTS_EQUAL(c1.get_message(), std::string{"find used!"}); + + test::c_find_if c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::find(c2, v, 12); + TTS_EQUAL(c2.get_message(), std::string{"find_if used!"}); + } + + // find_if_not -> find_if -> kwk::__::for_until + { + test::c_find_if_not c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::find_if_not(c1, v, [&](auto){ return true; }); + TTS_EQUAL(c1.get_message(), std::string{"find_if_not used!"}); + + test::c_find_if c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::find_if_not(c2, v, [&](auto){ return true; }); + TTS_EQUAL(c2.get_message(), std::string{"find_if used!"}); + } + + auto v2 = test::make_view_2(); + + // find_first_of -> find_if + // find_first_of -> any_of -> reduce -> for_each + { + // vvv find_first_of -> find_if -> kwk::__::for_until vvv + test::c_find_first_of c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::find_first_of(c1, v, v2); + TTS_EQUAL(c1.get_message(), std::string{"find_first_of used!"}); + + test::c_find_if c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::find_first_of(c2, v, v2); + TTS_EQUAL(c2.get_message(0), std::string{"find_if used!"}); + TTS_EQUAL(c2.get_message(1), std::string{"map used!"}); + + // vvv find_first_of -> any_of -> reduce -> for_each vvv + test::c_any_of c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::find_first_of(c3, v, v2); + TTS_EQUAL(c3.get_message(), std::string{"any_of used!"}); + + test::c_reduce3 c4; + TTS_EQUAL(c4.get_message(), test::messaging_context::base_message); + kwk::find_first_of(c4, v, v2); + TTS_EQUAL(c4.get_message(), std::string{"reduce(ctx, in, f, init) used!"}); + + test::context_for_each c5; + TTS_EQUAL(c5.get_message(), test::messaging_context::base_message); + kwk::find_first_of(c5, v, v2); + TTS_EQUAL(c5.get_message(), std::string{"map used!"}); + } + + // TODO: finir cette partie lorsque les predicates seront finis eux aussi + + // find_last_if -> find_if -> kwk::__::for_until + { + test::c_find_last_if c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::find_last_if(c1, v, [&](auto){ return true; }); + TTS_EQUAL(c1.get_message(), std::string{"find_last_if used!"}); + + test::c_find_if c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::find_last_if(c2, v, [&](auto){ return true; }); + TTS_EQUAL(c2.get_message(), std::string{"find_if used!"}); + } + + // find_last -> find_last_if -> find_if -> kwk::__::for_until + { + test::c_find_last c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::find_last(c1, v, 4); + TTS_EQUAL(c1.get_message(), std::string{"find_last used!"}); + + test::c_find_last_if c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::find_last(c2, v, 4); + TTS_EQUAL(c2.get_message(), std::string{"find_last_if used!"}); + + test::c_find_if c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::find_last(c3, v, 4); + TTS_EQUAL(c3.get_message(), std::string{"find_if used!"}); + } + + // find_last_if_not -> find_last_if -> find_if -> kwk::__::for_until + { + test::c_find_last_if_not c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::find_last_if_not(c1, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c1.get_message(), std::string{"find_last_if_not used!"}); + + test::c_find_last_if c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::find_last_if_not(c2, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c2.get_message(), std::string{"find_last_if used!"}); + + test::c_find_if c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::find_last_if_not(c3, v, [](auto e) { return (e == 0); }); + TTS_EQUAL(c3.get_message(), std::string{"find_if used!"}); + } +}; + + + + + + +namespace test +{ + struct c_fill : public context_for_each {}; + struct c_generate : public context_for_each {}; + struct c_iota1 : public context_for_each {}; + struct c_iota2 : public context_for_each {}; + struct c_iota3 : public context_for_each {}; +} +namespace kwk +{ + template + constexpr auto fill(test::c_fill& ctx, Out& out, auto value) + { + ctx.set_message("fill used!"); + kwk::fill(cpu, out, value); + } + + template + constexpr auto generate(test::c_generate& ctx, Func f, Out& out) + { + ctx.set_message("generate used!"); + kwk::generate(cpu, f, out); + } + + template + constexpr auto iota(test::c_iota2& ctx, Out& out, auto value) + { + ctx.set_message("iota(ctx, out, value) used!"); + kwk::iota(cpu, out, value); + } + + template + constexpr auto iota(test::c_iota1& ctx, Out& out) + { + ctx.set_message("iota(ctx, out) used!"); + kwk::iota(cpu, out); + } + + template + constexpr auto iota(test::c_iota3& ctx, Out& out, auto value, auto step) + { + ctx.set_message("iota(ctx, out, value, step) used!"); + kwk::iota(cpu, out, value, step); + } +}; + +TTS_CASE("Check for context overload - generator: fill, generate, iota") +{ + auto v = test::make_view_1(); + + // fill -> for_each + { + test::c_fill c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::fill(c1, v, 2); + TTS_EQUAL(c1.get_message(), std::string{"fill used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::fill(c2, v, 2); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } + + // generate -> for_each + { + test::c_generate c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::generate(c1, [](auto p1, auto p2) { return p1*10+p2; }, v); + TTS_EQUAL(c1.get_message(), std::string{"generate used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::generate(c2, [](auto p1, auto p2) { return p1*10+p2; }, v); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } + + // iota -> for_each + { + test::c_iota1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::iota(c1, v); + TTS_EQUAL(c1.get_message(), std::string{"iota(ctx, out) used!"}); + + test::c_iota2 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::iota(c2, v); + TTS_EQUAL(c2.get_message(), std::string{"iota(ctx, out, value) used!"}); + + test::c_iota3 c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::iota(c3, v, 0, 20); + TTS_EQUAL(c3.get_message(), std::string{"iota(ctx, out, value, step) used!"}); + + test::context_for_each c4; + TTS_EQUAL(c4.get_message(), test::messaging_context::base_message); + kwk::iota(c4, v); + TTS_EQUAL(c4.get_message(), std::string{"map used!"}); + } + +}; + + + + + + +namespace test +{ + struct c_transform_reduce1 : public context_for_each {}; + struct c_transform_reduce2 : public context_for_each {}; + struct c_transform_reduce3 : public context_for_each {}; + struct c_transform_reduce4 : public context_for_each {}; + struct c_inner_product1 : public context_for_each {}; + struct c_inner_product2 : public context_for_each {}; + struct c_inner_product3 : public context_for_each {}; + struct c_transform_exclusive_scan : public context_for_each {}; + struct c_exclusive_scan1 : public context_for_each {}; + struct c_exclusive_scan2 : public context_for_each {}; + struct c_transform_inclusive_scan : public context_for_each {}; + struct c_inclusive_scan1 : public context_for_each {}; + struct c_inclusive_scan2 : public context_for_each {}; +} +namespace kwk +{ + template + constexpr auto transform_reduce(test::c_transform_reduce4& ctx, In const& in1, In const& in2, auto init, Func_R R, Func_T T) + { + ctx.set_message("transform_reduce(ctx, in1, in2, init, R, T) used!"); + return transform_reduce(cpu, in1, in2, init, R, T); + } + + template + constexpr auto transform_reduce(test::c_transform_reduce3& ctx, In const& in1, In const& in2, auto init, Func_T T) + { + ctx.set_message("transform_reduce(ctx, in1, in2, init, T) used!"); + return transform_reduce(cpu, in1, in2, init, T); + } + + template + constexpr auto transform_reduce(test::c_transform_reduce2& ctx, In const& in1, In const& in2, auto init) + { + ctx.set_message("transform_reduce(ctx, in1, in2, init) used!"); + return transform_reduce(cpu, in1, in2, init); + } + + template + constexpr auto transform_reduce(test::c_transform_reduce1& ctx, In const& in1, In const& in2) + { + ctx.set_message("transform_reduce(ctx, in1, in2) used!"); + return transform_reduce(cpu, in1, in2); + } + + template + constexpr auto inner_product(test::c_inner_product3& ctx, In const& in1, In const& in2, auto init, Func_1 f1, Func_2 f2) + { + ctx.set_message("inner_product(ctx, in1, in2, init, f1, f2) used!"); + return inner_product(cpu, in1, in2, init, f1, f2); + } + + template + constexpr auto inner_product(test::c_inner_product2& ctx, In const& in1, In const& in2, auto init) + { + ctx.set_message("inner_product(ctx, in1, in2, init) used!"); + return inner_product(cpu, in1, in2, init); + } + + template + constexpr auto inner_product(test::c_inner_product1& ctx, In const& in1, In const& in2) + { + ctx.set_message("inner_product(ctx, in1, in2) used!"); + return inner_product(cpu, in1, in2); + } + + template + constexpr auto transform_exclusive_scan(test::c_transform_exclusive_scan& ctx, const In in, Out& out, auto init, Func1 f1, Func2 f2) + { + ctx.set_message("transform_exclusive_scan(ctx, in, out, init, f1, f2) used!"); + transform_exclusive_scan(cpu, in, out, init, f1, f2); + } + + template + constexpr auto exclusive_scan(test::c_exclusive_scan2& ctx, const In in, Out& out, auto init, Func f) + { + ctx.set_message("exclusive_scan(ctx, in, out, init, f) used!"); + exclusive_scan(cpu, in, out, init, f); + } + + template + constexpr auto exclusive_scan(test::c_exclusive_scan1& ctx, const In in, Out& out, auto init) + { + ctx.set_message("exclusive_scan(ctx, in, out, init) used!"); + exclusive_scan(cpu, in, out, init); + } + + // (Sasa?) a corriger + template + constexpr auto transform_inclusive_scan(test::c_transform_inclusive_scan& ctx, const In in, Out& out, auto init, Func1 f1, Func2 f2) + { + ctx.set_message("transform_inclusive_scan(ctx, in, out, init, f1, f2) used!"); + transform_inclusive_scan(cpu, in, out, init, f1, f2); + } + + template + constexpr auto inclusive_scan(test::c_inclusive_scan2& ctx, const In in, Out& out, auto init, Func f) + { + ctx.set_message("inclusive_scan(ctx, in, out, init, f) used!"); + inclusive_scan(cpu, in, out, init, f); + } + + template + constexpr auto inclusive_scan(test::c_inclusive_scan1& ctx, const In in, Out& out, auto init) + { + ctx.set_message("inclusive_scan(ctx, in, out, init) used!"); + inclusive_scan(cpu, in, out, init); + } + +}; + +TTS_CASE("Check for context overload - numeric: transform_reduce, inner_product" + ", transform_exclusive_scan, exclusive_scan, transform_inclusive_scan, inclusive_scan") +{ + auto v = test::make_view_1(); + auto v2 = test::make_view_2(); + + // transform_reduce overloads + { + test::c_transform_reduce1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::transform_reduce(c1, v, v2); + TTS_EQUAL(c1.get_message(), std::string{"transform_reduce(ctx, in1, in2) used!"}); + + test::c_transform_reduce2 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + transform_reduce(c2, v, v2); + TTS_EQUAL(c2.get_message(), std::string{"transform_reduce(ctx, in1, in2, init) used!"}); + + test::c_transform_reduce3 c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::transform_reduce(c3, v, v2); + TTS_EQUAL(c3.get_message(), std::string{"transform_reduce(ctx, in1, in2, init, T) used!"}); + + test::c_transform_reduce4 c4; + TTS_EQUAL(c4.get_message(), test::messaging_context::base_message); + kwk::transform_reduce(c4, v, v2); + TTS_EQUAL(c4.get_message(), std::string{"transform_reduce(ctx, in1, in2, init, R, T) used!"}); + + test::context_for_each c5; + TTS_EQUAL(c5.get_message(), test::messaging_context::base_message); + kwk::transform_reduce(c5, v, v2); + TTS_EQUAL(c5.get_message(), std::string{"map used!"}); + } + + // inner_product overloads + { + test::c_inner_product1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::inner_product(c1, v, v2); + TTS_EQUAL(c1.get_message(), std::string{"inner_product(ctx, in1, in2) used!"}); + + test::c_inner_product2 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + inner_product(c2, v, v2); + TTS_EQUAL(c2.get_message(), std::string{"inner_product(ctx, in1, in2, init) used!"}); + + test::c_inner_product3 c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::inner_product(c3, v, v2); + TTS_EQUAL(c3.get_message(), std::string{"inner_product(ctx, in1, in2, init, f1, f2) used!"}); + + test::context_for_each c4; + TTS_EQUAL(c4.get_message(), test::messaging_context::base_message); + kwk::inner_product(c4, v, v2); + TTS_EQUAL(c4.get_message(), std::string{"map used!"}); + } + + // transform_exclusive_scan -> for_each + { + test::c_transform_exclusive_scan c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::transform_exclusive_scan(c1, v, v2, 0, [](auto r, auto d){ return (r+d); }, + [](auto i1){ return (i1); }); + TTS_EQUAL(c1.get_message(), std::string{"transform_exclusive_scan(ctx, in, out, init, f1, f2) used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::transform_exclusive_scan(c2, v, v2, 0, [](auto r, auto d){ return (r+d); }, + [](auto i1){ return (i1); }); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } + + // exclusive_scan overloads -> for_each + { + test::c_exclusive_scan1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::exclusive_scan(c1, v, v2, 1); + // kwk::exclusive_scan(c1, v, v2, 1, [](auto r, auto d){ return (r*d); }); + TTS_EQUAL(c1.get_message(), std::string{"exclusive_scan(ctx, in, out, init) used!"}); + + test::c_exclusive_scan2 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::exclusive_scan(c2, v, v2, 1); + TTS_EQUAL(c2.get_message(), std::string{"exclusive_scan(ctx, in, out, init, f) used!"}); + + test::context_for_each c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::exclusive_scan(c3, v, v2, 1); + TTS_EQUAL(c3.get_message(), std::string{"map used!"}); + } + + // transform_inclusive_scan -> for_each + { + test::c_transform_inclusive_scan c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::transform_inclusive_scan(c1, v, v2, 0, [](auto r, auto d){ return (r+d); }, [](auto i1){ return (i1); }); + TTS_EQUAL(c1.get_message(), std::string{"transform_inclusive_scan(ctx, in, out, init, f1, f2) used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::transform_inclusive_scan(c2, v, v2, 0, [](auto r, auto d){ return (r+d); }, [](auto i1){ return (i1); }); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } + + // inclusive_scan(ctx, in, out, init) + // -> inclusive_scan(ctx, in, out, init, f) + // -> transform_inclusive_scan + // -> for_each + { + test::c_inclusive_scan1 c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::inclusive_scan(c1, v, v2, 1); + TTS_EQUAL(c1.get_message(), std::string{"inclusive_scan(ctx, in, out, init) used!"}); + + test::c_inclusive_scan2 c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::inclusive_scan(c2, v, v2, 1); + TTS_EQUAL(c2.get_message(), std::string{"inclusive_scan(ctx, in, out, init, f) used!"}); + + test::c_transform_inclusive_scan c3; + TTS_EQUAL(c3.get_message(), test::messaging_context::base_message); + kwk::inclusive_scan(c3, v, v2, 1); + TTS_EQUAL(c3.get_message(), std::string{"transform_inclusive_scan(ctx, in, out, init, f1, f2) used!"}); + + test::context_for_each c4; + TTS_EQUAL(c4.get_message(), test::messaging_context::base_message); + kwk::inclusive_scan(c4, v, v2, 1); + TTS_EQUAL(c4.get_message(), std::string{"map used!"}); + } +}; + + + + + +namespace test +{ + struct c_replace : public context_for_each {}; + struct c_replace_if : public context_for_each {}; +} +namespace kwk +{ + + template + constexpr auto replace(test::c_replace& ctx, Out& out, auto old_value, auto new_value) + { + ctx.set_message("replace(ctx, out, old_value, new_value) used!"); + return replace(cpu, out, old_value, new_value); + } + + template + constexpr auto replace_if(test::c_replace_if& ctx, Out& out, Func f, auto new_value) + { + ctx.set_message("replace_if(ctx, out, f, new_value) used!"); + return replace_if(cpu, out, f, new_value); + } +}; + +TTS_CASE("Check for context overload - replace: replace, replace_if") +{ + auto v = test::make_view_1(); + + { + test::c_replace c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::replace(c1, v, 2, 3); + TTS_EQUAL(c1.get_message(), std::string{"replace(ctx, out, old_value, new_value) used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::replace(c2, v, 2, 3); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } + + { + test::c_replace_if c1; + TTS_EQUAL(c1.get_message(), test::messaging_context::base_message); + kwk::replace_if(c1, v, [&](auto e) { return (e>=0); }, 0); + TTS_EQUAL(c1.get_message(), std::string{"replace_if(ctx, out, f, new_value) used!"}); + + test::context_for_each c2; + TTS_EQUAL(c2.get_message(), test::messaging_context::base_message); + kwk::replace_if(c2, v, [&](auto e) { return (e>=0); }, 0); + TTS_EQUAL(c2.get_message(), std::string{"map used!"}); + } +}; + + +// TODO: Vérifier qu'on passe bien par les bonnes surcharges à chaque fois + diff --git a/test/algorithm/algos/transform.cpp b/test/algorithm/algos/transform.cpp index 66c209b1..f9e219a1 100644 --- a/test/algorithm/algos/transform.cpp +++ b/test/algorithm/algos/transform.cpp @@ -9,117 +9,172 @@ #include #include #include "test.hpp" +#include TTS_CASE("Check for kwk::transform(value, new_value) 1D") { - int data[2]; - double res[2]; - double vdata[2] = {1, 0.5}; - - fill_data(data, kwk::of_size(2), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2)}; - auto v = kwk::view{kwk::source = res, kwk::of_size(2)}; - - int count = 0; - transform( - [&](auto e) - { - count++; - return 1.0/(1.0+e); - }, v, d); - - TTS_ALL_EQUAL(res, vdata); - - TTS_EQUAL(count, d.numel()); + using data_type = int; + const std::size_t d0 = 87; + const std::size_t input_size = d0; + std::array input1, input2, output, check; + + for (std::size_t i = 0; i < input_size; ++i) { input1[i] = i * 3; input2[i] = i * 2; } + + auto view_in1 = kwk::view{kwk::source = input1 , kwk::of_size(d0)}; + auto view_in2 = kwk::view{kwk::source = input2 , kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output , kwk::of_size(d0)}; + + kwk::transform( [&](auto const e1, auto const e2) { + return e1 + e2; + } + , view_out + , view_in1 + , view_in2 + ); + + std::transform( input1.begin(), input1.end() + , input2.begin() + , check.begin() + , [](auto const e1, auto const e2) { + return e1 + e2; + } + ); + + TTS_ALL_EQUAL(output, check); }; -TTS_CASE("Check for kwk::transform(value, new_value) 2D") +TTS_CASE("Check for kwk::transform(value, new_value) 1D with float") { - int data[2*3]; - double res[2*3]; - double vdata[2*3]; - - fill_data(data, kwk::of_size(2,3), true); - fill_data(vdata, kwk::of_size(2,3), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3)}; - auto v = kwk::view{kwk::source = res, kwk::of_size(2,3)}; - - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - vdata[i*3+j] = 1.0/(1.0+vdata[i*3+j]); - - int count = 0; - transform( - [&](auto e) - { - count++; - return 1.0/(1.0+e); - }, v, d); - - TTS_ALL_EQUAL(res, vdata); - - TTS_EQUAL(count, d.numel()); + using data_type = float; + const std::size_t d0 = 87; + const std::size_t input_size = d0; + std::array input1, input2, output, check; + + for (std::size_t i = 0; i < input_size; ++i) + { + input1[i] = i * static_cast(3.88); + input2[i] = i * static_cast(2.87); + } + + auto view_in1 = kwk::view{kwk::source = input1 , kwk::of_size(d0)}; + auto view_in2 = kwk::view{kwk::source = input2 , kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output , kwk::of_size(d0)}; + + kwk::transform( [&](auto const e1, auto const e2) { + return e1 + e2; + } + , view_out + , view_in1 + , view_in2 + ); + + std::transform( input1.begin(), input1.end() + , input2.begin() + , check.begin() + , [](auto const e1, auto const e2) { + return e1 + e2; + } + ); + + TTS_ALL_EQUAL(output, check); }; -TTS_CASE("Check for kwk::transform(value, new_value) 3D") +TTS_CASE("Check for kwk::transform(value, new_value) 1D with std::uint64_t") +{ + using data_type = std::uint64_t; + const std::size_t d0 = 87; + const std::size_t input_size = d0; + std::array input1, input2, output, check; + + for (std::size_t i = 0; i < input_size; ++i) { input1[i] = i * 3; input2[i] = i * 2; } + + auto view_in1 = kwk::view{kwk::source = input1 , kwk::of_size(d0)}; + auto view_in2 = kwk::view{kwk::source = input2 , kwk::of_size(d0)}; + auto view_out = kwk::view{kwk::source = output , kwk::of_size(d0)}; + + kwk::transform( [&](auto const e1, auto const e2) { + return e1 + e2; + } + , view_out + , view_in1 + , view_in2 + ); + + std::transform( input1.begin(), input1.end() + , input2.begin() + , check.begin() + , [](auto const e1, auto const e2) { + return e1 + e2; + } + ); + + TTS_ALL_EQUAL(output, check); +}; + +TTS_CASE("Check for kwk::transform(value, new_value) 2D") { - int data[2*3*4]; - double res[2*3*4]; - double vdata[2*3*4]; - - fill_data(data, kwk::of_size(2,3,4), true); - fill_data(vdata, kwk::of_size(2,3,4), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4)}; - auto v = kwk::view{kwk::source = res, kwk::of_size(2,3,4)}; - - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - vdata[i*4*3+j*4+k] = 1.0/(1.0+vdata[i*4*3+j*4+k]); - - int count = 0; - transform( - [&](auto e) - { - count++; - return 1.0/(1.0+e); - }, v, d); - - TTS_ALL_EQUAL(res, vdata); - - TTS_EQUAL(count, d.numel()); + using data_type = int; + const std::size_t d0 = 87; + const std::size_t d1 = 18; + const std::size_t input_size = d0 * d1; + std::array input1, input2, output, check; + + for (std::size_t i = 0; i < input_size; ++i) { input1[i] = i * 3; input2[i] = i * 2; } + + auto view_in1 = kwk::view{kwk::source = input1 , kwk::of_size(d0, d1)}; + auto view_in2 = kwk::view{kwk::source = input2 , kwk::of_size(d0, d1)}; + auto view_out = kwk::view{kwk::source = output , kwk::of_size(d0, d1)}; + + kwk::transform( [&](auto const e1, auto const e2) { + return e1 + e2; + } + , view_out + , view_in1 + , view_in2 + ); + + std::transform( input1.begin(), input1.end() + , input2.begin() + , check.begin() + , [](auto const e1, auto const e2) { + return e1 + e2; + } + ); + + TTS_ALL_EQUAL(output, check); }; TTS_CASE("Check for kwk::transform(value, new_value) 4D") { - int data[2*3*4*5]; - double res[2*3*4*5]; - double vdata[2*3*4*5]; - - fill_data(data, kwk::of_size(2,3,4,5), true); - fill_data(vdata, kwk::of_size(2,3,4,5), true); - - auto d = kwk::view{kwk::source = data, kwk::of_size(2,3,4,5)}; - auto v = kwk::view{kwk::source = res, kwk::of_size(2,3,4,5)}; - - for(int i = 0; i<2; i++) - for(int j = 0; j<3; j++) - for(int k = 0; k<4; k++) - for(int l = 0; l<5; l++) - vdata[i*5*4*3+j*5*4+k*5+l] = 1.0/(1.0+vdata[i*5*4*3+j*5*4+k*5+l]); - - int count = 0; - transform( - [&](auto e) - { - count++; - return 1.0/(1.0+e); - }, v, d); - - TTS_ALL_EQUAL(res, vdata); - - TTS_EQUAL(count, d.numel()); + using data_type = int; + const std::size_t d0 = 87; + const std::size_t d1 = 18; + const std::size_t d2 = 41; + const std::size_t d3 = 8; + const std::size_t input_size = d0 * d1 * d2 * d3; + std::array input1, input2, output, check; + + for (std::size_t i = 0; i < input_size; ++i) { input1[i] = i * 3; input2[i] = i * 2; } + + auto view_in1 = kwk::view{kwk::source = input1 , kwk::of_size(d0, d1, d2, d3)}; + auto view_in2 = kwk::view{kwk::source = input2 , kwk::of_size(d0, d1, d2, d3)}; + auto view_out = kwk::view{kwk::source = output , kwk::of_size(d0, d1, d2, d3)}; + + kwk::transform( [&](auto const e1, auto const e2) { + return e1 + e2; + } + , view_out + , view_in1 + , view_in2 + ); + + std::transform( input1.begin(), input1.end() + , input2.begin() + , check.begin() + , [](auto const e1, auto const e2) { + return e1 + e2; + } + ); + + TTS_ALL_EQUAL(output, check); }; \ No newline at end of file diff --git a/test/container/view/empty/dynamic_carray.1d.cpp b/test/container/view/empty/dynamic_carray.1d.cpp new file mode 100644 index 00000000..16dc556e --- /dev/null +++ b/test/container/view/empty/dynamic_carray.1d.cpp @@ -0,0 +1,27 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "test.hpp" +#include +#include +#include +#include + +// Tets views of size 0 +TTS_CASE( "Size 0: Build a 1D view with dynamic shape settings from a C array" ) +{ + using namespace kwk::literals; + + // Does not compile if the size of ref is zero. + float ref[1] = {5}; + std::size_t sz = 0; + auto v = kwk::view{ kwk::source = ref, kwk::of_size(sz) }; + TTS_EQUAL ( sizeof(v), sizeof(void*)+sizeof(std::size_t) ); + TTS_EQUAL ( v.size() , 0ULL ); + TTS_EQUAL ( v.shape(), kwk::of_size(sz) ); + TTS_EXPECT_NOT( v.shape().is_fully_static ); +}; diff --git a/test/container/view/empty/dynamic_contiguous_range.1d.cpp b/test/container/view/empty/dynamic_contiguous_range.1d.cpp new file mode 100644 index 00000000..b10a925e --- /dev/null +++ b/test/container/view/empty/dynamic_contiguous_range.1d.cpp @@ -0,0 +1,25 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "test.hpp" +#include +#include +#include +#include + +TTS_CASE( "Size 0: Build a 1D view with dynamic shape settings from a ContiguousRange" ) +{ + using namespace kwk::literals; + + std::vector ref = {}; + std::size_t sz = 0; + auto v = kwk::view{ kwk::source = ref, kwk::of_size(sz) }; + TTS_EQUAL ( sizeof(v), sizeof(void*)+sizeof(std::size_t) ); + TTS_EQUAL ( v.size() , 0ULL ); + TTS_EQUAL ( v.shape(), kwk::of_size(sz) ); + TTS_EXPECT_NOT( v.shape().is_fully_static ); +}; diff --git a/test/container/view/empty/dynamic_ptr.1d.cpp b/test/container/view/empty/dynamic_ptr.1d.cpp new file mode 100644 index 00000000..3b62cbdb --- /dev/null +++ b/test/container/view/empty/dynamic_ptr.1d.cpp @@ -0,0 +1,25 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "test.hpp" +#include +#include +#include +#include + +TTS_CASE( "Size 0: Build a 1D view with dynamic shape settings from a pointer" ) +{ + using namespace kwk::literals; + + std::vector ref = {}; + std::size_t sz = 0; + auto v = kwk::view{ kwk::source = ref.data(), kwk::of_size(sz) }; + TTS_EQUAL ( sizeof(v), sizeof(void*)+sizeof(std::size_t) ); + TTS_EQUAL ( v.size() , 0ULL ); + TTS_EQUAL ( v.shape(), kwk::of_size(sz) ); + TTS_EXPECT_NOT( v.shape().is_fully_static ); +}; diff --git a/test/container/view/empty/dynamic_stdarray.1d.cpp b/test/container/view/empty/dynamic_stdarray.1d.cpp new file mode 100644 index 00000000..3cd37669 --- /dev/null +++ b/test/container/view/empty/dynamic_stdarray.1d.cpp @@ -0,0 +1,25 @@ +//================================================================================================== +/* + KIWAKU - Containers Well Made + Copyright : KIWAKU Contributors & Maintainers + SPDX-License-Identifier: BSL-1.0 +*/ +//================================================================================================== +#include "test.hpp" +#include +#include +#include +#include + +TTS_CASE( "Size 0: Build a 1D view with dynamic shape settings from std::array" ) +{ + using namespace kwk::literals; + + std::array ref = {5}; + std::size_t sz = 0; + auto v = kwk::view{ kwk::source = ref, kwk::of_size(sz) }; + TTS_EQUAL ( sizeof(v), sizeof(void*)+sizeof(std::size_t) ); + TTS_EQUAL ( v.size() , 0ULL ); + TTS_EQUAL ( v.shape(), kwk::of_size(sz) ); + TTS_EXPECT_NOT( v.shape().is_fully_static ); +}; diff --git a/test/test.hpp b/test/test.hpp index fbed5882..71b0c077 100644 --- a/test/test.hpp +++ b/test/test.hpp @@ -1,15 +1,16 @@ -//================================================================================================== +//====================================================================================================================== /** KIWAKU - Containers Well Made Copyright : KIWAKU Project Contributors SPDX-License-Identifier: BSL-1.0 **/ -//================================================================================================== +//====================================================================================================================== #pragma once #include #include #include #include +#include template using int_ = std::integral_constant; template struct nD : std::integral_constant {}; @@ -19,11 +20,105 @@ template using up_to = std::make_index_sequence; #define TTS_CUSTOM_DRIVER_FUNCTION kwk_entry_point #include "tts.hpp" +#define FLOAT_TOLERANCE_PERCENT 0.01 + + +kumi::tuple lindex_to_pos ( std::size_t const d1 + , std::size_t const d2 + , std::size_t const d3 + , int const lindex + ) +{ + int remains = lindex; + std::array p; + std::fill(p.begin(), p.end(), 0); + p[0] = remains / (d1 * d2 * d3); + remains -= p[0] * (d1 * d2 * d3); + p[1] = remains / (d2 * d3); + remains -= p[1] * (d2 * d3); + p[2] = remains / d3; + remains -= p[2] * d3; + p[3] = remains; + + return kumi::tuple{p[0], p[1], p[2], p[3]}; +} + +kumi::tuple lindex_to_pos ( std::size_t const d1 + , int const lindex + ) +{ + int remains = lindex; + std::array p; + std::fill(p.begin(), p.end(), 0); + p[0] = remains / (d1); + remains -= p[0] * (d1); + p[1] = remains; + + return kumi::tuple{p[0], p[1]}; +} + +std::array lindex_to_pos_arr( std::size_t const d1 + , std::size_t const d2 + , std::size_t const d3 + , int const lindex + ) +{ + int remains = lindex; + std::array p; + std::fill(p.begin(), p.end(), 0); + p[0] = remains / (d1 * d2 * d3); + remains -= p[0] * (d1 * d2 * d3); + p[1] = remains / (d2 * d3); + remains -= p[1] * (d2 * d3); + p[2] = remains / d3; + remains -= p[2] * d3; + p[3] = remains; + + return p; +} + +std::array lindex_to_pos_arr( std::size_t const d1 + , int const lindex + ) +{ + int remains = lindex; + std::array p; + std::fill(p.begin(), p.end(), 0); + p[0] = remains / d1; + remains -= p[0] * d1; + p[1] = remains; + + return p; +} + +std::array std_res_to_pos ( int* res + , int* begin + , std::size_t const d1 + , std::size_t const d2 + , std::size_t const d3 + ) +{ + std::size_t dist = static_cast(std::distance(begin, res)); + return lindex_to_pos_arr(d1, d2, d3, dist); +} + +std::array std_res_to_pos ( int* res + , int* begin + , std::size_t const d1 + ) +{ + std::size_t dist = static_cast(std::distance(begin, res)); + return lindex_to_pos_arr(d1, dist); +} + + + template void fill_data(T* data, S shp, bool fill) requires(S::static_order == 1) { - for(int i1 = 0; i1(shp); i1++) + std::cout << get<0>(shp) << "\n"; + for(int i1 = 0; i1 < get<0>(shp); i1++) { if(!fill) data[i1] = 0; else data[i1] = T(i1); diff --git a/test/tts.hpp b/test/tts.hpp index d9a4ce0f..d34bdfc5 100644 --- a/test/tts.hpp +++ b/test/tts.hpp @@ -483,7 +483,7 @@ namespace tts::detail } #define TTS_PROTOTYPE(...) [] __VA_ARGS__ #define TTS_CASE(ID) \ -static bool const TTS_CAT(case_,TTS_FUNCTION) = ::tts::detail::test_capture{ID} + TTS_PROTOTYPE(()) \ +[[maybe_unused]] static bool const TTS_CAT(case_,TTS_FUNCTION) = ::tts::detail::test_capture{ID} + TTS_PROTOTYPE(()) \ #define TTS_CASE_TPL(ID,...) \ static bool const TTS_CAT(case_,TTS_FUNCTION) = ::tts::detail::test_captures<__VA_ARGS__>{ID} \