Skip to content

Commit

Permalink
Add integrate() function to T-SIMD library
Browse files Browse the repository at this point in the history
Moved out of experimental.H to ext.H and added tests
  • Loading branch information
jonicho committed Oct 24, 2024
1 parent 8953c1e commit 7f9bd18
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 49 deletions.
52 changes: 3 additions & 49 deletions src/lib/tsimd/experimental.H
Original file line number Diff line number Diff line change
Expand Up @@ -36,57 +36,11 @@
#include <cstddef>

namespace simd {
namespace experimental {

// ========================================================================
// integration of values in simd::Vec
// ========================================================================

// example:
// 0 1 2 3 4 5 6 7
// + - 0 1 2 3 4 5 6 slle(1)
// --------------------------------------
// 0 0-1 1-2 2-3 3-4 4-5 5-6 6-7
// + - - 0 0-1 1-2 2-3 3-4 4-5 slle(2)
// --------------------------------------
// 0 0-1 0-2 0-3 1-4 2-5 3-6 4-7
// + - - - - 0 0-1 0-2 0-3 slle(4)
// --------------------------------------
// 0 0-1 0-2 0-3 0-4 0-5 0-6 0-7
//
// problem: slle has immediate argument, T-SIMD: template parameter

// primary template
template <typename T, size_t SIMD_WIDTH, int SHIFT, int END_SHIFT>
struct HInt
{
public:
static SIMD_INLINE simd::Vec<T, SIMD_WIDTH> integrate(
const simd::Vec<T, SIMD_WIDTH> &v)
{
return HInt<T, SIMD_WIDTH, 2 * SHIFT, END_SHIFT>::integrate(
simd::add(v, simd::slle<SHIFT>(v)));
}
};

// termination template
template <typename T, size_t SIMD_WIDTH, int END_SHIFT>
struct HInt<T, SIMD_WIDTH, END_SHIFT, END_SHIFT>
{
public:
static SIMD_INLINE simd::Vec<T, SIMD_WIDTH> integrate(
const simd::Vec<T, SIMD_WIDTH> &v)
{
return v;
}
};

template <typename T, size_t SIMD_WIDTH>
static SIMD_INLINE simd::Vec<T, SIMD_WIDTH> integrate(
const simd::Vec<T, SIMD_WIDTH> &v)
{
return HInt<T, SIMD_WIDTH, 1, simd::Vec<T, SIMD_WIDTH>::elems>::integrate(v);
}
// put experimental code here

} // namespace experimental
} // namespace simd

#endif
66 changes: 66 additions & 0 deletions src/lib/tsimd/ext.H
Original file line number Diff line number Diff line change
Expand Up @@ -3268,6 +3268,72 @@ static SIMD_INLINE void transpose(
// internal::ext::transpose2inplcLane(rows);
}

// ========================================================================
// integration of values in simd::Vec
// ========================================================================

// example:
// 0 1 2 3 4 5 6 7
// + - 0 1 2 3 4 5 6 slle(1)
// --------------------------------------
// 0 0-1 1-2 2-3 3-4 4-5 5-6 6-7
// + - - 0 0-1 1-2 2-3 3-4 4-5 slle(2)
// --------------------------------------
// 0 0-1 0-2 0-3 1-4 2-5 3-6 4-7
// + - - - - 0 0-1 0-2 0-3 slle(4)
// --------------------------------------
// 0 0-1 0-2 0-3 0-4 0-5 0-6 0-7
//
// problem: slle has immediate argument, T-SIMD: template parameter

namespace internal {
namespace ext {
// primary template
template <typename T, size_t SIMD_WIDTH, int SHIFT, int END_SHIFT>
struct HInt
{
public:
static SIMD_INLINE simd::Vec<T, SIMD_WIDTH> integrate(
const simd::Vec<T, SIMD_WIDTH> &v)
{
return HInt<T, SIMD_WIDTH, 2 * SHIFT, END_SHIFT>::integrate(
simd::add(v, simd::slle<SHIFT>(v)));
}
};

// termination template
template <typename T, size_t SIMD_WIDTH, int END_SHIFT>
struct HInt<T, SIMD_WIDTH, END_SHIFT, END_SHIFT>
{
public:
static SIMD_INLINE simd::Vec<T, SIMD_WIDTH> integrate(
const simd::Vec<T, SIMD_WIDTH> &v)
{
return v;
}
};
} // namespace ext
} // namespace internal

/**
* @ingroup group_horizontal
* @brief Integrates the values of a Vec.
*
* This function integrates the values of a Vec, i.e. it computes the
* prefix sum of the elements.
*
* @param[in] v Vec to integrate
*
* @return Vec with integrated values
*/
template <typename T, size_t SIMD_WIDTH>
static SIMD_INLINE simd::Vec<T, SIMD_WIDTH> integrate(
const simd::Vec<T, SIMD_WIDTH> &v)
{
return internal::ext::HInt<T, SIMD_WIDTH, 1,
simd::Vec<T, SIMD_WIDTH>::elems>::integrate(v);
}

// ===========================================================================
// setones: set all bits to 1
// ===========================================================================
Expand Down
15 changes: 15 additions & 0 deletions src/test/autotest/serial.H
Original file line number Diff line number Diff line change
Expand Up @@ -2599,6 +2599,21 @@ static SIMD_INLINE uint64_t msb2int(const SerialVec<Double, SIMD_WIDTH> &a)
return msb2int(reinterpret<uint64_t>(a));
}

// ---------------------------------------------------------------------------
// integrate
// ---------------------------------------------------------------------------
template <typename T, size_t SIMD_WIDTH>
static SIMD_INLINE SerialVec<T, SIMD_WIDTH> integrate(const SerialVec<T, SIMD_WIDTH> &a)
{
SerialVec<T, SIMD_WIDTH> c;
T sum = 0;
for (size_t i = 0; i < c.elements; i++) {
sum += a[i];
c[i] = sum;
}
return c;
}

} // namespace auto_test
} // namespace simd

Expand Down
6 changes: 6 additions & 0 deletions src/test/autotest/test1.C
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ int main(int argc, char *argv[])
TestAll<Unary, SW, Div2rd>::test(repeats1, pattern);
TestFloat<Binary, SW, Sign>::test(repeats1, pattern);
TestAll<Binary, SW, AbsDiff>::test(repeats1, pattern);
TestInt<Unary, SW, Integrate>::test(repeats1, pattern);

// TODO: integrate produces errors for floating point types because of
// different summation orders. How to fix this?
// TestFloat<Unary, SW, Integrate>::test(repeats1, pattern);

// TODO: operators
// TODO: Vecs
printf("simdvecautotest1 complete\n");
Expand Down
20 changes: 20 additions & 0 deletions src/test/autotest/wrappers.H
Original file line number Diff line number Diff line change
Expand Up @@ -2572,6 +2572,26 @@ struct Iota
}
};

template <typename T, size_t SIMD_WIDTH>
struct Integrate
{
static SIMD_INLINE std::string name()
{
return t2s<T, SIMD_WIDTH>("integrate");
}

static SIMD_INLINE void randomizeInput(SerialVec<T, SIMD_WIDTH> &vec)
{
vec.randomize();
}

template <template <typename, size_t> class VEC>
static SIMD_INLINE VEC<T, SIMD_WIDTH> apply(const VEC<T, SIMD_WIDTH> &a)
{
return integrate(a);
}
};

} // namespace auto_test
} // namespace simd

Expand Down

0 comments on commit 7f9bd18

Please sign in to comment.