1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
//@HEADER
// ************************************************************************
//
// Kokkos v. 4.0
// Copyright (2022) National Technology & Engineering
// Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
// See https://kokkos.org/LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//@HEADER
#include <TestStdAlgorithmsCommon.hpp>
#include <iterator>
#include <algorithm>
#include <numeric>
namespace Test {
namespace stdalgos {
namespace Mismatch {
namespace KE = Kokkos::Experimental;
std::string value_type_to_string(int) { return "int"; }
std::string value_type_to_string(double) { return "double"; }
template <class Tag, class ValueType>
void print_scenario_details(std::size_t ext1, std::size_t ext2,
const std::string& flag) {
std::cout << "mismatch: "
<< "ext1 = " << ext1 << ", "
<< "ext2 = " << ext2 << ", " << flag << ", "
<< view_tag_to_string(Tag{}) << ", "
<< value_type_to_string(ValueType()) << std::endl;
}
template <class Tag, class ViewType, class... Args>
void run_single_scenario(ViewType view1, ViewType view2,
const std::string& flag, Args... args) {
using value_type = typename ViewType::value_type;
using exe_space = typename ViewType::execution_space;
using aux_view_t = Kokkos::View<value_type*, exe_space>;
const std::size_t ext1 = view1.extent(0);
const std::size_t ext2 = view2.extent(0);
// print_scenario_details<Tag, value_type>(ext1, ext2, flag);
aux_view_t aux_view1("aux_view1", ext1);
auto v1_h = create_mirror_view(Kokkos::HostSpace(), aux_view1);
aux_view_t aux_view2("aux_view2", ext2);
auto v2_h = create_mirror_view(Kokkos::HostSpace(), aux_view2);
// note that the checks ext1>0 and ext2>0 are there
// otherwise we get an error for CUDA NVCC DEBUG CI
// view is is always filled with 8's
if (ext1 > 0) {
for (std::size_t i = 0; i < ext1; ++i) {
v1_h(i) = static_cast<value_type>(8);
}
}
if (flag == "fill-to-match") {
if (ext2 > 0) {
for (std::size_t i = 0; i < ext2; ++i) {
v2_h(i) = static_cast<value_type>(8);
}
}
}
else if (flag == "fill-to-mismatch") {
// need to make them mismatch, so we fill
// with same value and only modifify the
// second view arbitrarily at middle point
if (ext2 > 0) {
for (std::size_t i = 0; i < ext2; ++i) {
v2_h(i) = static_cast<value_type>(8);
}
// make them mismatch at middle
v2_h(ext2 / 2) = -5;
}
} else {
FAIL() << "Kokkos: stdalgo: test: mismatch: Invalid string";
}
Kokkos::deep_copy(aux_view1, v1_h);
CopyFunctor<aux_view_t, ViewType> F1(aux_view1, view1);
Kokkos::parallel_for("copy1", view1.extent(0), F1);
Kokkos::deep_copy(aux_view2, v2_h);
CopyFunctor<aux_view_t, ViewType> F2(aux_view2, view2);
Kokkos::parallel_for("copy2", view2.extent(0), F2);
// run the std::mismatch on a host copy of the data
auto view1_h = create_host_space_copy(view1);
auto view2_h = create_host_space_copy(view2);
auto f1_h = KE::cbegin(view1_h);
auto l1_h = KE::cend(view1_h);
auto f2_h = KE::cbegin(view2_h);
auto l2_h = KE::cend(view2_h);
auto std_res = std::mismatch(f1_h, l1_h, f2_h, l2_h, args...);
const auto std_diff1 = std_res.first - f1_h;
const auto std_diff2 = std_res.second - f2_h;
{
// check our overloads with iterators
auto f1 = KE::cbegin(view1);
auto l1 = KE::cend(view1);
auto f2 = KE::cbegin(view2);
auto l2 = KE::cend(view2);
auto my_res1 = KE::mismatch(exespace(), f1, l1, f2, l2, args...);
auto my_res2 = KE::mismatch("label", exespace(), f1, l1, f2, l2, args...);
const auto my_diff11 = my_res1.first - f1;
const auto my_diff12 = my_res1.second - f2;
const auto my_diff21 = my_res2.first - f1;
const auto my_diff22 = my_res2.second - f2;
ASSERT_EQ(my_diff11, std_diff1);
ASSERT_EQ(my_diff12, std_diff2);
ASSERT_EQ(my_diff21, std_diff1);
ASSERT_EQ(my_diff22, std_diff2);
}
{
// check our overloads with views
auto my_res1 = KE::mismatch(exespace(), view1, view2, args...);
auto my_res2 = KE::mismatch("label", exespace(), view1, view2, args...);
const auto my_diff11 = my_res1.first - KE::begin(view1);
const auto my_diff12 = my_res1.second - KE::begin(view2);
const auto my_diff21 = my_res2.first - KE::begin(view1);
const auto my_diff22 = my_res2.second - KE::begin(view2);
ASSERT_EQ(my_diff11, std_diff1);
ASSERT_EQ(my_diff12, std_diff2);
ASSERT_EQ(my_diff21, std_diff1);
ASSERT_EQ(my_diff22, std_diff2);
}
}
template <class Tag, class ValueType>
void run_all_scenarios() {
using vecs_t = std::vector<std::string>;
const std::map<std::string, std::size_t> scenarios = {
{"empty", 0}, {"one-element", 1}, {"two-elements", 2},
{"small", 11}, {"medium", 21103}, {"large", 101513}};
for (const auto& scenario : scenarios) {
{
const std::size_t view1_ext = scenario.second;
auto view1 = create_view<ValueType>(Tag{}, view1_ext, "mismatch_view_1");
// for each view1 scenario, I want to test the case of a
// second view that is smaller, equal size and greater than the view1
const vecs_t view2cases = (scenario.first != "empty")
? vecs_t({"smaller", "equalsize", "larger"})
: vecs_t({"equalsize", "larger"});
for (auto it2 : view2cases) {
std::size_t view2_ext = view1_ext;
// modify extent of view2 based on what we want
if (std::string(it2) == "smaller") {
view2_ext -= 1;
} else if (std::string(it2) == "larger") {
view2_ext += 3;
}
auto view2 =
create_view<ValueType>(Tag{}, view2_ext, "mismatch_view_2");
// and now we want to test both the case view1 and view2 match,
// as well as the case where they don't match
for (const auto& it3 : {"fill-to-match", "fill-to-mismatch"}) {
// run to use default predicate
run_single_scenario<Tag>(view1, view2, it3);
// run using an arbitrary predicate
using predicate_type = IsEqualFunctor<ValueType>;
run_single_scenario<Tag>(view1, view2, it3, predicate_type());
}
}
}
}
}
TEST(std_algorithms_mismatch_test, test) {
run_all_scenarios<DynamicTag, double>();
run_all_scenarios<StridedThreeTag, int>();
}
} // namespace Mismatch
} // namespace stdalgos
} // namespace Test
|