1 /*************************************************************************** 2 * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * 3 * Copyright (c) QuantStack * 4 * * 5 * Distributed under the terms of the BSD 3-Clause License. * 6 * * 7 * The full license is in the file LICENSE, distributed with this software. * 8 ****************************************************************************/ 9 10 #include "test_common_macros.hpp" 11 #include "test_common_macros.hpp" 12 #if (defined(__GNUC__) && !defined(__clang__)) 13 #pragma GCC diagnostic push 14 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" 15 #pragma GCC diagnostic ignored "-Wconversion" 16 #pragma GCC diagnostic ignored "-Wfloat-conversion" 17 #include "xtensor/xmath.hpp" 18 #pragma GCC diagnostic pop 19 #else 20 #include "xtensor/xmath.hpp" 21 #endif 22 #include "xtensor/xutils.hpp" 23 #include "xtensor/xfixed.hpp" 24 #include "xtensor/xbuilder.hpp" 25 #include "xtensor/xreducer.hpp" 26 #include "xtensor/xview.hpp" 27 #include "xtensor/xmanipulation.hpp" 28 #include "xtensor/xarray.hpp" 29 #include "xtensor/xtensor.hpp" 30 #include "xtensor/xrandom.hpp" 31 #include "xtensor/xoptional.hpp" 32 #include "xtensor/xoptional_assembly.hpp" 33 #include "xtensor/xio.hpp" 34 35 namespace xt 36 { 37 38 #define CHECK_RESULT_TYPE(EXPRESSION, EXPECTED_TYPE) \ 39 { \ 40 using result_type = typename std::decay_t<decltype(EXPRESSION)>::value_type; \ 41 EXPECT_TRUE((std::is_same<result_type, EXPECTED_TYPE>::value)); \ 42 } 43 44 #define CHECK_TAG_TYPE(EXPRESSION, EXPECTED_TYPE) \ 45 { \ 46 using result_type = typename std::decay_t<decltype(EXPRESSION)>::expression_tag; \ 47 EXPECT_TRUE((std::is_same<result_type, EXPECTED_TYPE>::value)); \ 48 } 49 50 #define CHECK_TYPE(VALUE, EXPECTED_TYPE) \ 51 { \ 52 using result_type = typename std::decay_t<decltype(VALUE)>; \ 53 EXPECT_TRUE((std::is_same<result_type, EXPECTED_TYPE>::value)); \ 54 } 55 56 struct xreducer_features 57 { 58 using axes_type = std::array<std::size_t, 2>; 59 using shape_type = xarray<double>::shape_type; 60 using xarray_type = xarray<double>; 61 using func = xreducer_functors<std::plus<double>>; 62 63 axes_type m_axes; 64 65 xarray_type m_a; 66 67 xreducer<func, const xarray_type&, axes_type, xt::reducer_options<double, std::tuple<xt::evaluation_strategy::lazy_type>>> m_red; 68 69 xreducer_features(); 70 }; 71 xreducer_features()72 xreducer_features::xreducer_features() 73 : m_axes({1, 3}), m_a(ones<double>({3, 2, 4, 6, 5})), 74 m_red(func(), m_a, m_axes, xt::evaluation_strategy::lazy) 75 { 76 for (std::size_t i = 0; i < 2; ++i) 77 { 78 for (std::size_t j = 0; j < 6; ++j) 79 { 80 m_a(1, i, 1, j, 1) = 2; 81 } 82 } 83 } 84 85 struct xreducer_opt_features 86 { 87 using axes_type = std::array<std::size_t, 2>; 88 using shape_type = typename xarray_optional<double>::shape_type; 89 90 using xarray_of_optional_type = xarray<xtl::xoptional<double>>; 91 using xarray_optional_type = xarray_optional<double>; 92 using optional_assembly_type = xoptional_assembly<xarray<double>, xarray<bool>>; 93 94 axes_type m_axes; 95 96 xarray_of_optional_type m_array_of_optional, m_simple_array_of_optional; 97 98 xarray_optional_type m_array_optional, m_simple_array_optional; 99 100 optional_assembly_type m_optional_assembly, m_simple_optional_assembly; 101 xreducer_opt_featuresxt::xreducer_opt_features102 xreducer_opt_features(): 103 m_axes({1, 3}), 104 m_array_of_optional(ones<xtl::xoptional<double>>({3, 2, 4, 6, 5})), 105 m_array_optional(ones<xtl::xoptional<double>>({3, 2, 4, 6, 5})), 106 m_optional_assembly(ones<xtl::xoptional<double>>({3, 2, 4, 6, 5})) 107 { 108 for (std::size_t i = 0; i < 2; ++i) 109 { 110 for (std::size_t j = 0; j < 6; ++j) 111 { 112 m_array_of_optional(1, i, 1, j, 1) = 2; 113 m_array_optional(1, i, 1, j, 1) = 2; 114 m_optional_assembly(1, i, 1, j, 1) = 2; 115 } 116 } 117 m_array_of_optional(0, 0, 0, 0, 0) = xtl::missing<double>(); 118 m_array_optional(0, 0, 0, 0, 0) = xtl::missing<double>(); 119 m_optional_assembly(0, 0, 0, 0, 0) = xtl::missing<double>(); 120 121 m_simple_array_of_optional = xarray_of_optional_type({{1, 2, 0}, {4, 8, xtl::missing<double>()}}); 122 m_simple_array_optional = xarray_optional_type({{1, 2, 0}, {4, 8, xtl::missing<double>()}}); 123 m_simple_optional_assembly = optional_assembly_type({{1, 2, 0}, {4, 8, xtl::missing<double>()}}); 124 } 125 }; 126 127 #define TEST_EXPRESSION_TAG(INPUT, EXPECTED) \ 128 auto res = xt::sum(INPUT, feats.m_axes); \ 129 CHECK_TAG_TYPE(res, EXPECTED); 130 TEST(xreducer,expression_tag)131 TEST(xreducer, expression_tag) 132 { 133 xreducer_features feats; 134 TEST_EXPRESSION_TAG(feats.m_a, xtensor_expression_tag); 135 } 136 TEST(xreducer_array_of_optional,expression_tag)137 TEST(xreducer_array_of_optional, expression_tag) 138 { 139 xreducer_opt_features feats; 140 TEST_EXPRESSION_TAG(feats.m_array_of_optional, xtensor_expression_tag); 141 } 142 TEST(xreducer_array_optional,expression_tag)143 TEST(xreducer_array_optional, expression_tag) 144 { 145 xreducer_opt_features feats; 146 TEST_EXPRESSION_TAG(feats.m_array_optional, xoptional_expression_tag); 147 } 148 TEST(xreducer_optional_assembly,expression_tag)149 TEST(xreducer_optional_assembly, expression_tag) 150 { 151 xreducer_opt_features feats; 152 TEST_EXPRESSION_TAG(feats.m_optional_assembly, xoptional_expression_tag); 153 } 154 #undef TEST_EXPRESSION_TAG 155 156 #define TEST_VALUE_HAS_VALUE(INPUT, V_TYPE, OPTIONAL) \ 157 using result_type = std::conditional_t<OPTIONAL, xtl::xoptional<double>, double>; \ 158 \ 159 auto res = xt::sum(INPUT, feats.m_axes); \ 160 CHECK_RESULT_TYPE(res, result_type); \ 161 CHECK_TYPE(xt::value(res)(1, 1, 1), V_TYPE); \ 162 EXPECT_EQ(!OPTIONAL, xt::has_value(res)(0, 0, 0)); \ 163 EXPECT_TRUE(xt::has_value(res)(1, 1, 1)); 164 TEST(xreducer,value_has_value)165 TEST(xreducer, value_has_value) 166 { 167 xreducer_features feats; 168 TEST_VALUE_HAS_VALUE(feats.m_a, double, false); 169 } 170 /* 171 TEST(xreducer_array_of_optional, value_has_value) 172 { 173 xreducer_opt_features feats; 174 TEST_VALUE_HAS_VALUE(feats.m_array_of_optional, xtl::xoptional<double>, true); // TODO: fail, the mask is not reflecting the missing values 175 } 176 */ TEST(xreducer_array_optional,value_has_value)177 TEST(xreducer_array_optional, value_has_value) 178 { 179 xreducer_opt_features feats; 180 TEST_VALUE_HAS_VALUE(feats.m_array_optional, double, true); 181 } 182 TEST(xreducer_optional_assembly,value_has_value)183 TEST(xreducer_optional_assembly, value_has_value) 184 { 185 xreducer_opt_features feats; 186 TEST_VALUE_HAS_VALUE(feats.m_optional_assembly, double, true); 187 } 188 189 #undef TEST_VALUE_HAS_VALUE 190 TEST(xreducer,functor_type)191 TEST(xreducer, functor_type) 192 { 193 auto sum = [](auto const& left, auto const& right) { return left + right; }; 194 auto sum_functor = xt::make_xreducer_functor(sum); 195 xt::xarray<int> a = {{1, 2, 3}, {4, 5, 6}}; 196 xt::xarray<int> a_sums = xt::reduce(std::move(sum_functor), a, {1}); 197 xt::xarray<int> a_sums2 = xt::reduce(sum_functor, a, {1}); 198 xt::xarray<int> expect = {6, 15}; 199 EXPECT_EQ(a_sums, expect); 200 EXPECT_EQ(a_sums2, expect); 201 202 xt::xarray<int> a_sums3 = xt::reduce(sum, a, {1}); 203 EXPECT_EQ(a_sums3, expect); 204 205 } 206 TEST(xreducer,errors)207 TEST(xreducer, errors) 208 { 209 xt::xarray<int> a = {{1, 2, 3}, {4, 5, 6}}; 210 XT_EXPECT_THROW(xt::sum(a, {1, 0}), std::runtime_error); 211 XT_EXPECT_THROW(xt::sum(a, {0, 2}), std::runtime_error); 212 XT_EXPECT_THROW(xt::sum(a, {1, 0}, evaluation_strategy::immediate), std::runtime_error); 213 XT_EXPECT_THROW(xt::sum(a, {0, 2}, evaluation_strategy::immediate), std::runtime_error); 214 } 215 TEST(xreducer,shape)216 TEST(xreducer, shape) 217 { 218 xreducer_features features; 219 xreducer_features::shape_type s = {3, 4, 5}; 220 EXPECT_EQ(s, features.m_red.shape()); 221 EXPECT_EQ(features.m_red.layout(), layout_type::dynamic); 222 } 223 TEST(xreducer,access)224 TEST(xreducer, access) 225 { 226 xreducer_features features; 227 EXPECT_EQ(12, features.m_red(0, 0, 0)); 228 EXPECT_EQ(24, features.m_red(1, 1, 1)); 229 EXPECT_EQ(features.m_red(0, 1), features.m_red(0, 0, 1)); 230 EXPECT_EQ(features.m_red(1, 2, 1, 0, 1), features.m_red(1, 0, 1)); 231 232 EXPECT_EQ(12, features.m_red(2, 0, 0, 0)); 233 EXPECT_EQ(12, features.m_red()); 234 } 235 TEST(xreducer,unchecked)236 TEST(xreducer, unchecked) 237 { 238 xreducer_features features; 239 EXPECT_EQ(12, features.m_red.unchecked(0, 0, 0)); 240 EXPECT_EQ(24, features.m_red.unchecked(1, 1, 1)); 241 } 242 TEST(xreducer,indexed_access)243 TEST(xreducer, indexed_access) 244 { 245 xreducer_features features; 246 EXPECT_EQ(12, (features.m_red[{0, 0, 0}])); 247 EXPECT_EQ(24, (features.m_red[{1, 1, 1}])); 248 } 249 TEST(xreducer,at)250 TEST(xreducer, at) 251 { 252 xreducer_features features; 253 EXPECT_EQ(12, features.m_red.at(0, 0, 0)); 254 EXPECT_EQ(24, features.m_red.at(1, 1, 1)); 255 XT_EXPECT_ANY_THROW(features.m_red.at(10, 10, 10)); 256 XT_EXPECT_ANY_THROW(features.m_red.at(0, 0, 0, 0)); 257 } 258 TEST(xreducer,iterator)259 TEST(xreducer, iterator) 260 { 261 xreducer_features features; 262 auto iter = features.m_red.cbegin(); 263 auto iter_end = features.m_red.cend(); 264 const xreducer_features::shape_type& s = features.m_red.shape(); 265 std::size_t nb_iter = 1; 266 nb_iter = std::accumulate(s.cbegin(), s.cend(), nb_iter, std::multiplies<std::size_t>()); 267 std::advance(iter, static_cast<std::ptrdiff_t>(nb_iter)); 268 EXPECT_EQ(iter_end, iter); 269 } 270 TEST(xreducer,assign)271 TEST(xreducer, assign) 272 { 273 xreducer_features features; 274 xarray<double> res = features.m_red; 275 xarray<double> expected = 12 * ones<double>({3, 4, 5}); 276 expected(1, 1, 1) = 24; 277 EXPECT_EQ(expected, res); 278 279 xarray_optional<double> opt_expected = 12 * ones<double>({3, 4, 5}); 280 opt_expected(1, 1, 1) = 24; 281 282 // TODO: fix the reducer assignment issue in multithreaded env and enable 283 // these tests again. 284 #if !defined(XTENSOR_USE_TBB) && !defined(XTENSOR_USE_OPENMP) 285 xreducer_opt_features::xarray_of_optional_type opt_res1 = res; 286 CHECK_RESULT_TYPE(opt_res1, xtl::xoptional<double>); 287 CHECK_TYPE(xt::value(opt_res1)(1, 1, 1), xtl::xoptional<double>); 288 EXPECT_EQ(xt::has_value(opt_res1), xt::full_like(res, true)); 289 EXPECT_EQ(opt_expected, opt_res1); 290 291 xreducer_opt_features::xarray_optional_type opt_res2 = res; 292 CHECK_RESULT_TYPE(opt_res2, xtl::xoptional<double>); 293 CHECK_TYPE(xt::value(opt_res2)(1, 1, 1), double); 294 EXPECT_EQ(xt::has_value(opt_res2), xt::full_like(res, true)); 295 EXPECT_EQ(opt_expected, opt_res2); 296 297 xreducer_opt_features::optional_assembly_type opt_res3 = res; 298 CHECK_RESULT_TYPE(opt_res3, xtl::xoptional<double>); 299 CHECK_TYPE(xt::value(opt_res3)(1, 1, 1), double); 300 EXPECT_EQ(xt::has_value(opt_res3), xt::full_like(res, true)); 301 EXPECT_EQ(opt_expected, opt_res3); 302 #endif 303 } 304 305 #define TEST_OPT_ASSIGNMENT(INPUT) \ 306 auto res = xt::sum(INPUT, feats.m_axes); \ 307 \ 308 xreducer_opt_features::xarray_of_optional_type res1 = res; \ 309 CHECK_RESULT_TYPE(res1, xtl::xoptional<double>); \ 310 CHECK_TYPE(xt::value(res1)(1, 1, 1), xtl::xoptional<double>);\ 311 EXPECT_EQ(res1(1, 1, 1), 24.); \ 312 /* EXPECT_FALSE(xt::has_value(res1)(0, 0, 0)); */ \ 313 EXPECT_TRUE(xt::has_value(res1)(1, 1, 1)); \ 314 \ 315 xreducer_opt_features::xarray_optional_type res2 = res; \ 316 CHECK_RESULT_TYPE(res2, xtl::xoptional<double>); \ 317 CHECK_TYPE(xt::value(res2)(1, 1, 1), double); \ 318 EXPECT_EQ(res2(1, 1, 1), 24.); \ 319 EXPECT_FALSE(xt::has_value(res2)(0, 0, 0)); \ 320 EXPECT_TRUE(xt::has_value(res2)(1, 1, 1)); \ 321 \ 322 xreducer_opt_features::optional_assembly_type res3 = res; \ 323 CHECK_RESULT_TYPE(res3, xtl::xoptional<double>); \ 324 CHECK_TYPE(xt::value(res3)(1, 1, 1), double); \ 325 EXPECT_EQ(res3(1, 1, 1), 24.); \ 326 EXPECT_FALSE(xt::has_value(res3)(0, 0, 0)); \ 327 EXPECT_TRUE(xt::has_value(res3)(1, 1, 1)); 328 TEST(xreducer_array_of_optional,assign)329 TEST(xreducer_array_of_optional, assign) 330 { 331 xreducer_opt_features feats; 332 TEST_OPT_ASSIGNMENT(feats.m_array_of_optional) 333 } 334 TEST(xreducer_array_optional,assign)335 TEST(xreducer_array_optional, assign) 336 { 337 xreducer_opt_features feats; 338 TEST_OPT_ASSIGNMENT(feats.m_array_optional) 339 } 340 TEST(xreducer_optional_assembly,assign)341 TEST(xreducer_optional_assembly, assign) 342 { 343 xreducer_opt_features feats; 344 TEST_OPT_ASSIGNMENT(feats.m_optional_assembly) 345 } 346 #undef TEST_OPT_ASSIGNMENT 347 TEST(xreducer,sum)348 TEST(xreducer, sum) 349 { 350 xreducer_features features; 351 xarray<double> res = sum(features.m_a, features.m_axes); 352 xarray<double> expected = 12 * ones<double>({3, 4, 5}); 353 expected(1, 1, 1) = 24; 354 EXPECT_EQ(expected, res); 355 } 356 357 #define TEST_OPT_SUM(INPUT) \ 358 auto res = xt::sum(INPUT, feats.m_axes); \ 359 EXPECT_EQ(res.dimension(), std::size_t(3)); \ 360 EXPECT_EQ(res(0, 0, 0), xtl::missing<double>()); \ 361 EXPECT_EQ(res(1, 1, 1), 24.); 362 TEST(xreducer_array_of_optional,sum)363 TEST(xreducer_array_of_optional, sum) 364 { 365 xreducer_opt_features feats; 366 TEST_OPT_SUM(feats.m_array_of_optional); 367 } 368 TEST(xreducer_array_optional,sum)369 TEST(xreducer_array_optional, sum) 370 { 371 xreducer_opt_features feats; 372 TEST_OPT_SUM(feats.m_array_optional); 373 } 374 TEST(xreducer_optional_assembly,sum)375 TEST(xreducer_optional_assembly, sum) 376 { 377 xreducer_opt_features feats; 378 TEST_OPT_SUM(feats.m_optional_assembly); 379 } 380 #undef TEST_OPT_SUM 381 TEST(xreducer,sum_tensor)382 TEST(xreducer, sum_tensor) 383 { 384 xtensor<double, 2> m = {{1, 2}, {3, 4}}; 385 xarray<double> res = xt::sum(m, {0}); 386 EXPECT_EQ(res.dimension(), std::size_t(1)); 387 EXPECT_EQ(res(0), 4.0); 388 EXPECT_EQ(res(1), 6.0); 389 } 390 TEST(xreducer,single_axis_sugar)391 TEST(xreducer, single_axis_sugar) 392 { 393 xarray<double> m = {{1, 0}, {3, 4}}; 394 395 xarray<std::size_t> res1 = xt::count_nonzero(m, {1}); 396 xarray<std::size_t> res2 = xt::count_nonzero(m, 1); 397 EXPECT_EQ(res1, res2); 398 399 xarray<double> res3 = xt::sum(m, {1}); 400 xarray<double> res4 = xt::sum(m, 1); 401 EXPECT_EQ(res3, res4); 402 } 403 404 #define TEST_OPT_SINGLE_AXIS(INPUT) \ 405 auto res = xt::sum(INPUT, feats.m_axes); \ 406 xarray_optional<std::size_t> res1 = xt::count_nonzero(INPUT, {1}); \ 407 xarray_optional<std::size_t> res2 = xt::count_nonzero(INPUT, 1); \ 408 EXPECT_EQ(res1, res2); \ 409 \ 410 xarray_optional<double> res3 = xt::sum(INPUT, {1}); \ 411 xarray_optional<double> res4 = xt::sum(INPUT, 1); \ 412 EXPECT_EQ(res3, res4); 413 TEST(xreducer_array_of_optional,single_axis_sugar)414 TEST(xreducer_array_of_optional, single_axis_sugar) 415 { 416 xreducer_opt_features feats; 417 TEST_OPT_SINGLE_AXIS(feats.m_array_of_optional); 418 } 419 TEST(xreducer_array_optional,single_axis_sugar)420 TEST(xreducer_array_optional, single_axis_sugar) 421 { 422 xreducer_opt_features feats; 423 TEST_OPT_SINGLE_AXIS(feats.m_array_optional); 424 } 425 TEST(xreducer_optional_assembly,single_axis_sugar)426 TEST(xreducer_optional_assembly, single_axis_sugar) 427 { 428 xreducer_opt_features feats; 429 TEST_OPT_SINGLE_AXIS(feats.m_optional_assembly); 430 } 431 #undef TEST_OPT_SINGLE_AXIS 432 TEST(xreducer,sum2)433 TEST(xreducer, sum2) 434 { 435 xarray<double> u = ones<double>({2, 4}); 436 xarray<double> expectedu0 = 2 * ones<double>({4}); 437 xarray<double> resu0 = sum(u, {0}); 438 EXPECT_EQ(expectedu0, resu0); 439 xarray<double> expectedu1 = 4 * ones<double>({2}); 440 xarray<double> resu1 = sum(u, {std::size_t(1)}); 441 xarray<double> resm1 = sum(u, {-1}); 442 443 std::array<std::size_t, 1> a_us = {1}; 444 std::array<std::ptrdiff_t, 1> a_ss = {-1}; 445 xarray<double> res_refu1 = sum(u, a_us); 446 xarray<double> res_refm1 = sum(u, a_ss); 447 448 EXPECT_EQ(expectedu1, resm1); 449 EXPECT_EQ(expectedu1, resu1); 450 EXPECT_EQ(expectedu1, res_refm1); 451 EXPECT_EQ(expectedu1, res_refu1); 452 453 xarray<double> v = ones<double>({4, 2}); 454 xarray<double> expectedv0 = 4 * ones<double>({2}); 455 xarray<double> resv0 = sum(v, {0}); 456 EXPECT_EQ(expectedv0, resv0); 457 xarray<double> expectedv1 = 2 * ones<double>({4}); 458 xarray<double> resv1 = sum(v, {1}); 459 EXPECT_EQ(expectedv1, resv1); 460 461 // check that there is no overflow 462 xarray<uint8_t> c = ones<uint8_t>({1000}); 463 EXPECT_EQ(1000u, sum(c)()); 464 } 465 TEST(xreducer,sum_all)466 TEST(xreducer, sum_all) 467 { 468 xreducer_features features; 469 auto res = sum(features.m_a); 470 double expected = 732; 471 EXPECT_EQ(res(), expected); 472 } 473 474 #define TEST_OPT_SUM_ALL(INPUT) \ 475 auto res = xt::sum(INPUT); \ 476 EXPECT_EQ(res(), xtl::missing<double>()); 477 TEST(xreducer_array_of_optional,sum_all)478 TEST(xreducer_array_of_optional, sum_all) 479 { 480 xreducer_opt_features feats; 481 TEST_OPT_SUM_ALL(feats.m_array_of_optional); 482 } 483 TEST(xreducer_array_optional,sum_all)484 TEST(xreducer_array_optional, sum_all) 485 { 486 xreducer_opt_features feats; 487 TEST_OPT_SUM_ALL(feats.m_array_optional); 488 } 489 TEST(xreducer_optional_assembly,sum_all)490 TEST(xreducer_optional_assembly, sum_all) 491 { 492 xreducer_opt_features feats; 493 TEST_OPT_SUM_ALL(feats.m_optional_assembly); 494 } 495 #undef TEST_OPT_SUM_ALL 496 TEST(xreducer,prod)497 TEST(xreducer, prod) 498 { 499 // check that there is no overflow 500 xarray<uint8_t> c = 2 * ones<uint8_t>({34}); 501 EXPECT_EQ(1ULL << 34, prod<long long>(c)()); 502 } 503 504 #define TEST_OPT_PROD(INPUT) \ 505 auto res1 = xt::prod(INPUT); \ 506 EXPECT_EQ(res1(), xtl::missing<double>()); \ 507 \ 508 auto res2 = xt::prod(INPUT, feats.m_axes); \ 509 EXPECT_EQ(res2(), xtl::missing<double>()); \ 510 EXPECT_EQ(res2(1, 1, 1), 4096.); 511 TEST(xreducer_array_of_optional,prod)512 TEST(xreducer_array_of_optional, prod) 513 { 514 xreducer_opt_features feats; 515 TEST_OPT_PROD(feats.m_array_of_optional); 516 } 517 TEST(xreducer_array_optional,prod)518 TEST(xreducer_array_optional, prod) 519 { 520 xreducer_opt_features feats; 521 TEST_OPT_PROD(feats.m_array_optional); 522 } 523 TEST(xreducer_optional_assembly,prod)524 TEST(xreducer_optional_assembly, prod) 525 { 526 xreducer_opt_features feats; 527 TEST_OPT_PROD(feats.m_optional_assembly); 528 } 529 #undef TEST_OPT_PROD 530 TEST(xreducer,mean)531 TEST(xreducer, mean) 532 { 533 xtensor<double, 2> input 534 {{-1.0, 0.0}, {1.0, 0.0}}; 535 auto mean_all = mean(input); 536 auto mean0 = mean(input, {0}); 537 auto mean1 = mean(input, {1}); 538 539 xtensor<double, 0> expect_all = 0.0; 540 xtensor<double, 1> expect0 = {0.0, 0.0}; 541 xtensor<double, 1> expect1 = {-0.5, 0.5}; 542 543 EXPECT_EQ(mean_all(), expect_all()); 544 EXPECT_TRUE(all(equal(mean0, expect0))); 545 EXPECT_TRUE(all(equal(mean1, expect1))); 546 547 #ifndef SKIP_ON_WERROR 548 // may loose precision because uint8_t is casted to long for intermediate 549 // computations and then divided by a double for mean 550 xarray<uint8_t> c = {1, 2}; 551 EXPECT_EQ(mean(c)(), 1.5); 552 #endif 553 554 const auto rvalue_xarray = [] () { return xtensor<double, 1>({1, 2}); }; 555 EXPECT_EQ(mean(rvalue_xarray(), {0})(), 1.5); 556 } 557 558 #define TEST_OPT_MEAN(INPUT) \ 559 auto res1 = xt::mean(INPUT); \ 560 EXPECT_EQ(res1(), xtl::missing<double>()); \ 561 \ 562 auto res2 = xt::mean(INPUT, feats.m_axes); \ 563 EXPECT_EQ(res2(), xtl::missing<double>()); \ 564 EXPECT_EQ(res2(1, 1, 1), 2.); 565 TEST(xreducer_array_of_optional,mean)566 TEST(xreducer_array_of_optional, mean) 567 { 568 xreducer_opt_features feats; 569 TEST_OPT_MEAN(feats.m_array_of_optional); 570 } 571 TEST(xreducer_array_optional,mean)572 TEST(xreducer_array_optional, mean) 573 { 574 xreducer_opt_features feats; 575 TEST_OPT_MEAN(feats.m_array_optional); 576 } 577 TEST(xreducer_optional_assembly,mean)578 TEST(xreducer_optional_assembly, mean) 579 { 580 xreducer_opt_features feats; 581 TEST_OPT_MEAN(feats.m_optional_assembly); 582 } 583 #undef TEST_OPT_MEAN 584 TEST(xreducer,average)585 TEST(xreducer, average) 586 { 587 xt::xtensor<float, 2> a = {{ 3, 4, 2, 1}, { 1, 1, 3, 2}}; 588 xt::xarray<double> all_weights = {{1, 2, 3, 4}, { 5, 6, 7, 8}}; 589 auto avg_all = xt::average(a, all_weights); 590 auto avg_all_2 = xt::average(a, all_weights, {0ul, 1ul}); 591 592 auto avg0 = xt::average(a, xt::xarray<double>{3, 9}, {0}); 593 auto avg1 = xt::average(a, xt::xarray<double>{1,2,3,4}, {1}); 594 auto avg_m1 = xt::average(a, xt::xarray<double>{1,2,3,4}, {-1}); 595 auto avg_d1 = xt::average(a, xt::xarray<double>{1,2,3,4}, {-1}, evaluation_strategy::immediate); 596 597 xtensor<double, 0> expect_all = 1.9166666666666667; 598 xtensor<double, 1> expect0 = {1.5, 1.75, 2.75, 1.75}; 599 xtensor<double, 1> expect1 = {2.1, 2.0}; 600 601 EXPECT_TRUE(allclose(avg_all, expect_all)); 602 EXPECT_TRUE(allclose(avg_all_2, expect_all)); 603 EXPECT_TRUE(all(equal(avg0, expect0))); 604 EXPECT_TRUE(all(equal(avg1, expect1))); 605 EXPECT_TRUE(all(equal(avg_m1, expect1))); 606 EXPECT_TRUE(all(equal(avg_d1, expect1))); 607 } 608 609 #define TEST_OPT_AVERAGE(INPUT) \ 610 xt::xarray<double> all_weights = {{3, 3, 3}, \ 611 {1, 1, 1}}; \ 612 auto res1 = xt::average(INPUT, all_weights); \ 613 EXPECT_EQ(res1(), xtl::missing<double>()); \ 614 \ 615 xtensor_optional<double, 1> expect = {1., 2., xtl::missing<double>()}; \ 616 xt::xarray<double> weights = {2, 0}; \ 617 auto res2 = xt::average(INPUT, weights, {0}); \ 618 EXPECT_TRUE(all(equal(res2, expect))); 619 TEST(xreducer_array_of_optional,average)620 TEST(xreducer_array_of_optional, average) 621 { 622 xreducer_opt_features feats; 623 TEST_OPT_AVERAGE(feats.m_simple_array_of_optional); 624 } 625 TEST(xreducer_array_optional,average)626 TEST(xreducer_array_optional, average) 627 { 628 xreducer_opt_features feats; 629 TEST_OPT_AVERAGE(feats.m_simple_array_optional); 630 } 631 TEST(xreducer_optional_assembly,average)632 TEST(xreducer_optional_assembly, average) 633 { 634 xreducer_opt_features feats; 635 TEST_OPT_AVERAGE(feats.m_simple_optional_assembly); 636 } 637 #undef TEST_OPT_AVERAGE 638 TEST(xreducer,count_nonzero)639 TEST(xreducer, count_nonzero) 640 { 641 xarray<double> m = {{1, 0}, {3, 4}}; 642 643 xarray<std::size_t> res0 = xt::count_nonzero(m, {0}); 644 xtensor<std::size_t, 1> expect0 = {2, 1}; 645 EXPECT_TRUE(all(equal(res0, expect0))); 646 647 xarray<std::size_t> res1 = xt::count_nonzero(m, {1}); 648 xtensor<std::size_t, 1> expect1 = {1, 2}; 649 EXPECT_TRUE(all(equal(res1, expect1))); 650 } 651 652 #define TEST_OPT_COUNT_NONZEROS(INPUT) \ 653 auto res0 = xt::count_nonzero(INPUT, {0}); \ 654 xtensor_optional<std::size_t, 1> expect0 = \ 655 {2, 2, xtl::missing<std::size_t>()}; \ 656 EXPECT_TRUE(all(equal(res0, expect0))); \ 657 \ 658 auto res1 = xt::count_nonzero(INPUT, {1}); \ 659 xtensor_optional<std::size_t, 1> expect1 = \ 660 {2, xtl::missing<std::size_t>()}; \ 661 EXPECT_TRUE(all(equal(res1, expect1))); 662 663 /* TODO: fix policy, missing values should lead to a missing value result 664 TEST(xreducer_array_of_optional, count_nonzero) 665 { 666 xreducer_opt_features feats; 667 TEST_OPT_COUNT_NONZEROS(feats.m_simple_array_of_optional); 668 } 669 670 TEST(xreducer_array_optional, count_nonzero) 671 { 672 xreducer_opt_features feats; 673 TEST_OPT_COUNT_NONZEROS(feats.m_simple_array_optional); 674 } 675 676 TEST(xreducer_optional_assembly, count_nonzero) 677 { 678 xreducer_opt_features feats; 679 TEST_OPT_COUNT_NONZEROS(feats.m_simple_optional_assembly); 680 } 681 */ 682 #undef TEST_OPT_COUNT_NONZEROS 683 TEST(xreducer,minmax)684 TEST(xreducer, minmax) 685 { 686 using A = std::array<double, 2>; 687 688 xtensor<double, 2> input 689 {{-1.0, 0.0}, {1.0, 0.0}}; 690 EXPECT_EQ(minmax(input)(), (A{-1.0, 1.0})); 691 } 692 TEST(xreducer,immediate)693 TEST(xreducer, immediate) 694 { 695 xarray<double> a = xt::arange(27); 696 a.resize({3, 3, 3}); 697 698 xarray<double> a_lz = sum(a); 699 auto a_gd = sum(a, evaluation_strategy::immediate); 700 EXPECT_EQ(a_lz, a_gd); 701 702 a_lz = sum(a, {1}); 703 a_gd = sum(a, {1}, evaluation_strategy::immediate); 704 EXPECT_EQ(a_lz, a_gd); 705 706 a_lz = sum(a, {0, 2}); 707 a_gd = sum(a, {0, 2}, evaluation_strategy::immediate); 708 EXPECT_EQ(a_lz, a_gd); 709 710 a_lz = sum(a, {1, 2}); 711 a_gd = sum(a, {1, 2}, evaluation_strategy::immediate); 712 EXPECT_EQ(a_lz, a_gd); 713 714 a = xt::arange(4 * 3 * 6 * 2 * 7); 715 a.resize({4, 3, 6, 2, 7}); 716 717 a_lz = sum(a); 718 a_gd = sum(a, evaluation_strategy::immediate); 719 EXPECT_EQ(a_lz, a_gd); 720 721 a_lz = sum(a, {1}); 722 a_gd = sum(a, {1}, evaluation_strategy::immediate); 723 EXPECT_EQ(a_lz, a_gd); 724 725 a_lz = sum(a, {0, 2}); 726 a_gd = sum(a, {0, 2}, evaluation_strategy::immediate); 727 EXPECT_EQ(a_lz, a_gd); 728 729 a_lz = sum(a, {1, 2}); 730 a_gd = sum(a, {1, 2}, evaluation_strategy::immediate); 731 EXPECT_EQ(a_lz, a_gd); 732 733 a_lz = sum(a, {1, 3, 4}); 734 a_gd = sum(a, {1, 3, 4}, evaluation_strategy::immediate); 735 EXPECT_EQ(a_lz, a_gd); 736 737 a_lz = sum(a, {0, 1, 4}); 738 a_gd = sum(a, {0, 1, 4}, evaluation_strategy::immediate); 739 EXPECT_EQ(a_lz, a_gd); 740 741 a_lz = sum(a, {0, 1, 3}); 742 a_gd = sum(a, {0, 1, 3}, evaluation_strategy::immediate); 743 EXPECT_EQ(a_lz, a_gd); 744 745 a_lz = sum(a, {0, 2, 3}); 746 a_gd = sum(a, {0, 2, 3}, evaluation_strategy::immediate); 747 EXPECT_EQ(a_lz, a_gd); 748 749 a_lz = sum(a, {1, 2, 3}); 750 a_gd = sum(a, {1, 2, 3}, evaluation_strategy::immediate); 751 EXPECT_EQ(a_lz, a_gd); 752 753 xtensor<short, 3, layout_type::column_major> ct = xt::random::randint<short>({1, 5, 3}); 754 EXPECT_EQ(sum(ct, {0, 2}), sum(ct, {0, 2}, evaluation_strategy::immediate)); 755 756 xtensor<short, 5, layout_type::column_major> ct2 = xt::random::randint<short>({1, 5, 1, 2, 3}); 757 EXPECT_EQ(sum(ct2, {0, 1, 2}), sum(ct2, {0, 1, 2}, evaluation_strategy::immediate)); 758 EXPECT_EQ(sum(ct2, {2, 3}), sum(ct2, {2, 3}, evaluation_strategy::immediate)); 759 EXPECT_EQ(sum(ct2, {1, 3}), sum(ct2, {1, 3}, evaluation_strategy::immediate)); 760 } 761 TEST(xreducer,chaining_reducers)762 TEST(xreducer, chaining_reducers) 763 { 764 xt::xarray<double> a = {{ 1., 2. }, 765 { 3., 4. }}; 766 767 auto b = a - xt::sum(a, { 0 }); 768 auto c = xt::sum(b, { 0 }); 769 EXPECT_EQ(c(0), -4.); 770 EXPECT_EQ(c(1), -6.); 771 } 772 TEST(xreducer,immediate_shape)773 TEST(xreducer, immediate_shape) 774 { 775 xtensor<double, 2> c = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; 776 auto xa = xt::sum(c, {0}, evaluation_strategy::immediate); 777 auto is_arr = [](const auto& c) 778 { 779 bool istrue = detail::is_array<std::decay_t<decltype(c)>>::value; 780 return istrue; 781 }; 782 783 EXPECT_TRUE(is_arr(xa.shape())); 784 785 xtensor<double, 3> a; 786 a.resize({3, 3, 3}); 787 std::iota(a.storage().begin(), a.storage().end(), 0); 788 789 xarray<double> a_lz = sum(a); 790 auto a_gd = sum(a, evaluation_strategy::immediate); 791 EXPECT_EQ(a_lz, a_gd); 792 EXPECT_TRUE(is_arr(a_gd.shape())); 793 794 a_lz = sum(a, {1}); 795 auto a_gd_1 = sum(a, {1}, evaluation_strategy::immediate); 796 EXPECT_EQ(a_lz, a_gd_1); 797 798 a_lz = sum(a, {0, 2}); 799 auto a_gd_2 = sum(a, {0, 2}, evaluation_strategy::immediate); 800 EXPECT_EQ(a_lz, a_gd_2); 801 802 EXPECT_TRUE(is_arr(a_gd_1.shape())); 803 EXPECT_TRUE(is_arr(a_gd_2.shape())); 804 805 a_lz = sum(a, {1, 2}); 806 a_gd_2 = sum(a, {1, 2}, evaluation_strategy::immediate); 807 EXPECT_EQ(a_lz, a_gd_2); 808 } 809 TEST(xreducer,xfixed_reduction)810 TEST(xreducer, xfixed_reduction) 811 { 812 xtensor_fixed<double, xshape<3, 3, 3>> a; 813 std::iota(a.storage().begin(), a.storage().end(), 0); 814 815 xtensor<double, 3> b; 816 b.resize({3, 3, 3}); 817 std::iota(b.storage().begin(), b.storage().end(), 0); 818 819 auto is_arr = [](const auto& c) 820 { 821 bool istrue = detail::is_array<std::decay_t<decltype(c)>>::value; 822 return istrue; 823 }; 824 825 xarray<double> a_lz = sum(a); 826 auto a_gd = sum(a, evaluation_strategy::immediate); 827 EXPECT_EQ(a_lz, a_gd); 828 829 // EXPECT_TRUE(is_fixed(a_gd.shape())); // this actually evaluates to const_array 830 831 a_lz = sum(a, xt::dynamic_shape<std::size_t>{1}); 832 auto a_gd_1 = sum(a, xt::dynamic_shape<std::size_t>{1}, evaluation_strategy::immediate); 833 auto b_gd_1 = sum(b, {1}, evaluation_strategy::immediate); 834 EXPECT_EQ(a_lz, a_gd_1); 835 EXPECT_EQ(a_lz, b_gd_1); 836 837 a_lz = sum(a, {0, 2}); 838 auto a_gd_2 = sum(a, {0, 2}, evaluation_strategy::immediate); 839 auto b_gd_2 = sum(b, {0, 2}, evaluation_strategy::immediate); 840 EXPECT_EQ(a_lz, a_gd_2); 841 EXPECT_EQ(b_gd_2, a_gd_2); 842 EXPECT_EQ(a_gd_2.dimension(), std::size_t(1)); 843 844 // EXPECT_TRUE(is_arr(a_gd_1.shape())); 845 EXPECT_TRUE(is_arr(a_gd_2.shape())); 846 847 a_lz = sum(a, {1, 2}); 848 a_gd_2 = sum(a, {1, 2}, evaluation_strategy::immediate); 849 EXPECT_EQ(a_lz, a_gd_2); 850 851 auto a_lx_3 = sum(a, {1, 2}); 852 auto a_lz_3 = sum(a, xshape<1, 2>()); 853 auto a_gd_3 = sum(a, xshape<1, 2>(), evaluation_strategy::immediate); 854 xarray<double> xevd = a_lz_3; 855 EXPECT_EQ(a_lz_3, a_gd_2); 856 EXPECT_TRUE(a_gd_3 == a_gd_2); 857 bool truth = std::is_same<decltype(a_gd_3), xtensor_fixed<double, xshape<3>>>::value; 858 EXPECT_TRUE(truth); 859 860 xtensor<short, 3> ct = xt::random::randint<short>({1, 5, 3}); 861 xtensor_fixed<short, xshape<1, 5, 3>> c = ct; 862 auto b_fx_1 = sum(c, xshape<0, 2>(), evaluation_strategy::immediate); 863 auto b_fx_2 = sum(c, xshape<0, 1>(), evaluation_strategy::immediate); 864 auto b_fx_3 = sum(c, xshape<0, 1, 2>(), evaluation_strategy::immediate); 865 866 EXPECT_EQ(sum(ct, {0, 2}, evaluation_strategy::immediate), sum(c, {0, 2})); 867 EXPECT_TRUE(b_fx_1 == sum(c, {0, 2})); 868 EXPECT_TRUE(b_fx_2 == sum(c, {0, 1})); 869 EXPECT_EQ(b_fx_3, sum(c, {0, 1, 2})); 870 871 truth = std::is_same<std::decay_t<decltype(b_fx_1)>, xtensor_fixed<int, xshape<5>>>::value; 872 EXPECT_TRUE(truth); 873 truth = std::is_same<std::decay_t<decltype(b_fx_3)>, xtensor_fixed<int, xshape<>>>::value; 874 EXPECT_TRUE(truth); 875 876 truth = std::is_same<xshape<1, 3>, typename fixed_xreducer_shape_type<xshape<1, 5, 3>, xshape<1>>::type>(); 877 EXPECT_TRUE(truth); 878 truth = std::is_same<xshape<5>, typename fixed_xreducer_shape_type<xshape<1, 5, 3>, xshape<0, 2>>::type>(); 879 EXPECT_TRUE(truth); 880 truth = std::is_same<xshape<>, typename fixed_xreducer_shape_type<xshape<1, 5, 3>, xshape<0, 1, 2>>::type>(); 881 EXPECT_TRUE(truth); 882 truth = std::is_same<xshape<1, 5>, typename fixed_xreducer_shape_type<xshape<1, 5>, xshape<2>>::type>(); 883 EXPECT_TRUE(truth); 884 } 885 TEST(xreducer,view_steppers)886 TEST(xreducer, view_steppers) 887 { 888 xt::xtensor<double, 2> X({10, 20}); 889 xt::xtensor<double, 2> Y(X.shape()); 890 891 X = xt::random::randn<double>(X.shape()); 892 893 xt::xtensor<double, 2> vx0 = xt::view(xt::sum(X, {1}), xt::all(), xt::newaxis()); 894 xt::xtensor<double, 2> vx1 = xt::expand_dims(xt::sum(X, {1}), 1); 895 896 EXPECT_EQ(vx0, vx1); 897 } 898 TEST(xreducer,wrong_number_of_indices)899 TEST(xreducer, wrong_number_of_indices) 900 { 901 xt::xtensor<double, 4> a = xt::random::rand<double>({5, 5, 5, 5}); 902 double e = xt::sum(a)(); 903 double s1 = xt::sum(a)(0); 904 EXPECT_EQ(s1, e); 905 double s2 = xt::sum(a)(0, 1, 2, 3, 4, 5, 0); 906 EXPECT_EQ(s2, e); 907 908 auto red = xt::sum(a, {0}); 909 EXPECT_EQ(red(2), red(0, 0, 2)); 910 EXPECT_EQ(red(1, 2), red(0, 1, 2)); 911 EXPECT_EQ(red(1, 2), red(1, 1, 1, 1, 1, 0, 1, 2)); 912 } 913 TEST(xreducer,normalize_axes)914 TEST(xreducer, normalize_axes) 915 { 916 xt::xtensor<double, 4> x{}; 917 std::vector<std::size_t> sva {0, 1, 2, 3}; 918 std::vector<std::ptrdiff_t> svb = {-4, 1, -2, -1}; 919 std::initializer_list<std::ptrdiff_t> initlist = {-4, 1, -2, -1}; 920 std::array<std::size_t, 4> saa = {0, 1, 2, 3}; 921 std::array<std::ptrdiff_t, 4> sab = {-4, 1, -2, -1}; 922 923 auto resa = forward_normalize<std::vector<std::size_t>>(x, svb); 924 EXPECT_EQ(forward_normalize<std::vector<std::size_t>>(x, svb), sva); 925 EXPECT_EQ(forward_normalize<std::vector<std::size_t>>(x, initlist), sva); 926 auto resaa = forward_normalize<std::array<std::size_t, 4>>(x, saa); 927 EXPECT_EQ(resaa, saa); 928 auto resab = forward_normalize<std::array<std::size_t, 4>>(x, sab); 929 EXPECT_EQ(resab, saa); 930 } 931 TEST(xreducer,input_0d)932 TEST(xreducer, input_0d) 933 { 934 xt::xarray<double> a; 935 EXPECT_EQ(0., xt::amin(a)[0]); 936 937 using A = std::array<double, 2>; 938 xt::xarray<double> b(1.2); 939 EXPECT_EQ(b.dimension(), 0u); 940 EXPECT_EQ(minmax(b)(), (A{1.2, 1.2})); 941 } 942 943 template <std::size_t... I, std::size_t... J> operator ==(fixed_shape<I...>,fixed_shape<J...>)944 bool operator==(fixed_shape<I...>, fixed_shape<J...>) 945 { 946 std::array<std::size_t, sizeof...(I)> ix = {I...}; 947 std::array<std::size_t, sizeof...(J)> jx = {J...}; 948 return sizeof...(J) == sizeof...(I) && std::equal(ix.begin(), ix.end(), jx.begin()); 949 } 950 TEST(xreducer,keep_dims)951 TEST(xreducer, keep_dims) 952 { 953 xt::xtensor<double, 4> a = xt::reshape_view(xt::arange<double>(5 * 5 * 5 * 5), {5, 5, 5, 5}); 954 955 auto res = xt::sum(a, {0, 1}, xt::keep_dims | xt::evaluation_strategy::immediate); 956 EXPECT_EQ(res.shape(), (std::array<std::size_t, 4>{1, 1, 5, 5})); 957 auto res2 = xt::sum(a, {0, 1}, xt::keep_dims); 958 EXPECT_EQ(res2.shape(), (std::array<std::size_t, 4>{1, 1, 5, 5})); 959 960 xt::xarray<double> b = a; 961 auto res3 = xt::sum(b, {0, 1}, xt::keep_dims | xt::evaluation_strategy::immediate); 962 EXPECT_EQ(res3.shape(), (xt::dynamic_shape<std::size_t>{1, 1, 5, 5})); 963 auto res4 = xt::sum(b, {0, 1}, xt::keep_dims | xt::evaluation_strategy::lazy); 964 EXPECT_EQ(res4.shape(), (xt::dynamic_shape<std::size_t>{1, 1, 5, 5})); 965 966 xt::xarray<double> resx3 = xt::sum(a, {0, 1}); 967 auto exp1 = xt::sum(a, {0, 1}); 968 969 EXPECT_EQ(res, res2); 970 EXPECT_EQ(res, res3); 971 EXPECT_EQ(res, res4); 972 973 EXPECT_TRUE(xt::allclose(res, res2)); 974 EXPECT_TRUE(xt::allclose(res, res3)); 975 EXPECT_TRUE(xt::allclose(res, res4)); 976 977 auto res5 = xt::sum(a, xt::keep_dims); 978 EXPECT_EQ(res5.shape(), (xt::static_shape<size_t, 4>{1, 1, 1, 1})); 979 auto res6 = xt::sum(a); 980 EXPECT_EQ(res6.shape(), (xt::static_shape<size_t, 0>{})); 981 xt::xtensor_fixed<double, xshape<5, 5, 5, 5>> c = a; 982 auto res7 = xt::sum(c); 983 EXPECT_EQ(res7.shape(), (xt::xshape<>{})); 984 auto res8 = xt::sum(c, xt::keep_dims); 985 EXPECT_EQ(res8.shape(), (xt::xshape<1, 1, 1, 1>{})); 986 } 987 TEST(xreducer,initial_value)988 TEST(xreducer, initial_value) 989 { 990 xt::xtensor<double, 4> a = xt::reshape_view(xt::arange<double>(5 * 5 * 5 * 5), {5, 5, 5, 5}); 991 992 auto res = xt::sum(a, {0, 2}, xt::keep_dims | xt::evaluation_strategy::immediate | initial(5)); 993 auto reso = xt::sum(a, {0, 2}, xt::keep_dims | xt::evaluation_strategy::immediate); 994 EXPECT_EQ(res, reso + 5); 995 996 xt::xarray<double> res2 = xt::sum(a, {0, 2}, xt::keep_dims | initial(5)); 997 auto reso2 = xt::sum(a, {0, 2}, xt::keep_dims); 998 EXPECT_EQ(res2, reso2 + 5); 999 1000 auto re0 = xt::prod(a, {1, 2}, xt::keep_dims | xt::evaluation_strategy::immediate | initial(0)); 1001 EXPECT_TRUE(xt::all(equal(re0, 0.))); 1002 1003 auto rex0 = xt::prod(a, {1, 2}, initial(0)); 1004 EXPECT_TRUE(xt::all(equal(rex0, 0.))); 1005 } 1006 TEST(xreducer,ones_first)1007 TEST(xreducer, ones_first) 1008 { 1009 auto a = xt::ones<int>(std::vector<int>({ 1,1,2,4 })); 1010 std::vector<int> arraxis = { 1 }; 1011 auto result = xt::sum(a, arraxis, xt::keep_dims | xt::evaluation_strategy::immediate); 1012 EXPECT_EQ(a, result); 1013 1014 std::vector<int> arraxis2 = { 1, 2 }; 1015 auto res2 = xt::sum(a, arraxis2, xt::keep_dims | xt::evaluation_strategy::immediate); 1016 xt::xarray<int> expected = { {{{2, 2, 2, 2}}} }; 1017 EXPECT_EQ(expected, res2); 1018 } 1019 TEST(xreducer,empty_axes)1020 TEST(xreducer, empty_axes) 1021 { 1022 xarray<int> a = { {1, 2, 3}, {4, 5, 6} }; 1023 std::vector<std::size_t> axes = {}; 1024 auto res0 = xt::sum(a, axes); 1025 auto res1 = xt::sum(a, axes, xt::keep_dims | xt::evaluation_strategy::immediate); 1026 1027 EXPECT_EQ(res0, a); 1028 EXPECT_EQ(res1, a); 1029 } 1030 TEST(xreducer,zero_shape)1031 TEST(xreducer, zero_shape) 1032 { 1033 xt::xarray<int> x = xt::zeros<int>({ 0, 1 }); 1034 1035 auto res0 = xt::sum(x, { 0 }, xt::keep_dims); 1036 EXPECT_EQ(res0.shape()[0], size_t(1)); 1037 EXPECT_EQ(res0.shape()[1], size_t(1)); 1038 EXPECT_EQ(res0(0, 0), 0); 1039 1040 auto res1 = xt::sum(x, { 1 }, xt::keep_dims); 1041 EXPECT_EQ(res1.shape()[0], size_t(0)); 1042 EXPECT_EQ(res1.shape()[1], size_t(1)); 1043 EXPECT_EQ(res1.size(), size_t(0)); 1044 1045 auto res2 = xt::sum(x, xt::keep_dims); 1046 EXPECT_EQ(res2.shape()[0], size_t(1)); 1047 EXPECT_EQ(res2.shape()[1], size_t(1)); 1048 EXPECT_EQ(res2(0, 0), 0); 1049 } 1050 TEST(xreducer,empty_array)1051 TEST(xreducer, empty_array) 1052 { 1053 xt::xarray<double> a = xt::ones<double>({ 1, 2, 0, 1 }); 1054 double result0 = xt::mean(a)(); 1055 EXPECT_TRUE(std::isnan(result0)); 1056 1057 auto result1 = xt::mean(a, { 1 }); 1058 auto expected1 = xt::xarray<double>::from_shape({1, 0, 1}); 1059 EXPECT_EQ(result1, expected1); 1060 1061 auto result2 = xt::mean(a, { 2 }); 1062 auto expected2 = xt::xarray<double>::from_shape({1, 2, 1}); 1063 EXPECT_EQ(result2.shape(), expected2.shape()); 1064 EXPECT_TRUE(std::isnan(result2(0, 0, 0))); 1065 EXPECT_TRUE(std::isnan(result2(0, 1, 0))); 1066 } 1067 TEST(xreducer,double_axis)1068 TEST(xreducer, double_axis) 1069 { 1070 xt::xarray<int> a = xt::ones<int>({ 3, 2}); 1071 XT_EXPECT_ANY_THROW(xt::sum(a, {1, 1})); 1072 } 1073 TEST(xreducer,sum_xtensor_of_fixed)1074 TEST(xreducer, sum_xtensor_of_fixed) 1075 { 1076 xt::xtensor_fixed<float, xt::xshape<3>> a = {1, 2, 3}, b = {1, 2, 3}; 1077 xt::xtensor<xt::xtensor_fixed<float, xt::xshape<3>>, 1> c = {a, b}; 1078 1079 auto res = xt::sum(c)(); 1080 EXPECT_EQ(res, a * 2.); 1081 1082 xt::xtensor_fixed<float, xt::xshape<3>> res1 = res; 1083 EXPECT_EQ(res1, a * 2.); 1084 } 1085 } 1086