SimpleLayoutTemplate

Macros

Line Code
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
#include <memory>
#include <tuple>

#define CATCH_CONFIG_MAIN
#include <catch.hpp>

#include "DataFormats/SoATemplate/interface/SoALayout.h"

// clang-format off
GENERATE_SOA_LAYOUT(SimpleLayoutTemplate,
  SOA_COLUMN(float, x),
  SOA_COLUMN(float, y),
  SOA_COLUMN(float, z),
  SOA_COLUMN(float, t))
// clang-format on

using SimpleLayout = SimpleLayoutTemplate<>;

TEST_CASE("SoATemplate") {
  // number of elements
  const std::size_t slSize = 10;
  // size in bytes
  const std::size_t slBufferSize = SimpleLayout::computeDataSize(slSize);
  // memory buffer aligned according to the layout requirements
  std::unique_ptr<std::byte, decltype(std::free) *> slBuffer{
      reinterpret_cast<std::byte *>(aligned_alloc(SimpleLayout::alignment, slBufferSize)), std::free};
  // SoA layout
  SimpleLayout sl{slBuffer.get(), slSize};

  SECTION("Row wide copies, row") {
    SimpleLayout::View slv{sl};
    SimpleLayout::ConstView slcv{sl};
    auto slv0 = slv[0];
    slv0.x() = 1;
    slv0.y() = 2;
    slv0.z() = 3;
    slv0.t() = 5;
    // Fill up
    for (SimpleLayout::View::size_type i = 1; i < slv.metadata().size(); ++i) {
      auto slvi = slv[i];
      slvi = slv[i - 1];
      auto slvix = slvi.x();
      slvi.x() += slvi.y();
      slvi.y() += slvi.z();
      slvi.z() += slvi.t();
      slvi.t() += slvix;
    }
    // Verification and const view access
    float x = 1, y = 2, z = 3, t = 5;
    for (SimpleLayout::View::size_type i = 0; i < slv.metadata().size(); ++i) {
      auto slvi = slv[i];
      auto slcvi = slcv[i];
      REQUIRE(slvi.x() == x);
      REQUIRE(slvi.y() == y);
      REQUIRE(slvi.z() == z);
      REQUIRE(slvi.t() == t);
      REQUIRE(slcvi.x() == x);
      REQUIRE(slcvi.y() == y);
      REQUIRE(slcvi.z() == z);
      REQUIRE(slcvi.t() == t);
      auto tx = x;
      x += y;
      y += z;
      z += t;
      t += tx;
    }
  }

  SECTION("Row initializer, const view access, restrict disabling") {
    // With two views, we are creating (artificially) aliasing and should warn the compiler by turning restrict qualifiers off.
    using View = SimpleLayout::ViewTemplate<cms::soa::RestrictQualify::disabled, cms::soa::RangeChecking::Default>;
    using ConstView =
        SimpleLayout::ConstViewTemplate<cms::soa::RestrictQualify::disabled, cms::soa::RangeChecking::Default>;
    View slv{sl};
    ConstView slcv{sl};
    auto slv0 = slv[0];
    slv0 = {7, 11, 13, 17};
    // Fill up
    for (SimpleLayout::View::size_type i = 1; i < slv.metadata().size(); ++i) {
      auto slvi = slv[i];
      // Copy the const view
      slvi = slcv[i - 1];
      auto slvix = slvi.x();
      slvi.x() += slvi.y();
      slvi.y() += slvi.z();
      slvi.z() += slvi.t();
      slvi.t() += slvix;
    }
    // Verification and const view access
    auto [x, y, z, t] = std::make_tuple(7.0, 11.0, 13.0, 17.0);
    for (SimpleLayout::View::size_type i = 0; i < slv.metadata().size(); ++i) {
      auto slvi = slv[i];
      auto slcvi = slcv[i];
      REQUIRE(slvi.x() == x);
      REQUIRE(slvi.y() == y);
      REQUIRE(slvi.z() == z);
      REQUIRE(slvi.t() == t);
      REQUIRE(slcvi.x() == x);
      REQUIRE(slcvi.y() == y);
      REQUIRE(slcvi.z() == z);
      REQUIRE(slcvi.t() == t);
      auto tx = x;
      x += y;
      y += z;
      z += t;
      t += tx;
    }
  }

  SECTION("Range checking View") {
    // Enable range checking
    using View = SimpleLayout::ViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::enabled>;
    View slv{sl};
    int underflow = -1;
    int overflow = slv.metadata().size();
    // Check for under-and overflow in the row accessor
    REQUIRE_THROWS_AS(slv[underflow], std::out_of_range);
    REQUIRE_THROWS_AS(slv[overflow], std::out_of_range);
    // Check for under-and overflow in the element accessors
    REQUIRE_THROWS_AS(slv.x(underflow), std::out_of_range);
    REQUIRE_THROWS_AS(slv.x(overflow), std::out_of_range);
  }

  SECTION("Range checking ConstView") {
    // Enable range checking
    using ConstView =
        SimpleLayout::ConstViewTemplate<cms::soa::RestrictQualify::Default, cms::soa::RangeChecking::enabled>;
    ConstView slcv{sl};
    int underflow = -1;
    int overflow = slcv.metadata().size();
    // Check for under-and overflow in the row accessor
    REQUIRE_THROWS_AS(slcv[underflow], std::out_of_range);
    REQUIRE_THROWS_AS(slcv[overflow], std::out_of_range);
    // Check for under-and overflow in the element accessors
    REQUIRE_THROWS_AS(slcv.x(underflow), std::out_of_range);
    REQUIRE_THROWS_AS(slcv.x(overflow), std::out_of_range);
  }
}