#include <catch.hpp>

#include <PastisAssert.hpp>
#include <Array.hpp>
#include <ArrayUtils.hpp>

// Instantiate to ensure full coverage is performed
template class Array<int>;

TEST_CASE("ArrayUtils", "[utils]") {

  SECTION("checking for reductions") {
    using ArrayType = Array<int>;
    using data_type = ArrayType::data_type;

    Array<int> a(10);
    a[0] =13;
    a[1] = 1;
    a[2] = 8;
    a[3] =-3;
    a[4] =23;
    a[5] =-1;
    a[6] =13;
    a[7] = 0;
    a[8] =12;
    a[9] = 9;

    SECTION("ReduceMin") {
      ReduceMin r_min(a);
      data_type data;

      r_min.init(data);
      REQUIRE(data == std::numeric_limits<data_type>::max());

      r_min(2,data);
      REQUIRE(data == 8);

      r_min(9,data);
      REQUIRE(data == 8);

      r_min(5,data);
      REQUIRE(data == -1);

      {
        data = 0;
        data_type r_value{3};
        r_min.join(data, r_value);
        REQUIRE(data == 0);
      }

      {
        data = 0;
        data_type r_value{-5};
        r_min.join(data, r_value);
        REQUIRE(data == -5);
      }

      REQUIRE((r_min == -3));

      REQUIRE((ReduceMin(a) == -3));
    }

    SECTION("ReduceMax") {
      ReduceMax r_max(a);
      data_type data;

      r_max.init(data);
      REQUIRE(data == -std::numeric_limits<data_type>::max());

      r_max(3,data);
      REQUIRE(data == -3);
      r_max(5,data);
      REQUIRE(data == -1);
      r_max(8,data);
      REQUIRE(data == 12);

      {
        data = 0;
        data_type r_value{3};
        r_max.join(data, r_value);
        REQUIRE(data == 3);
      }

      {
        data = 0;
        data_type r_value{-5};
        r_max.join(data, r_value);
        REQUIRE(data == 0);
      }

      REQUIRE((r_max == 23));

      REQUIRE((ReduceMax(a) == 23));
    }
  }
}