Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
petiaccja committed Apr 12, 2021
1 parent f456da2 commit c7ceff7
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 121 deletions.
133 changes: 13 additions & 120 deletions include/dspbb/Math/Arithmetic.hpp
Original file line number Diff line number Diff line change
@@ -1,143 +1,36 @@
#pragma once

#include <xsimd/xsimd.hpp>
#include <dspbb/Vectorization/Kernels.hpp>


namespace dspbb {


template <class T>
struct is_vectorized {
static constexpr bool value = xsimd::simd_traits<T>::size > 1;
};


//------------------------------------------------------------------------------
// Generic calculation helpers.
//------------------------------------------------------------------------------

//--------------------------------------
// Vector-vector
//--------------------------------------
template <class R, class T, class U, class Op>
void Calculate(R* out, const T* a, const U* b, size_t length, Op op) {
const R* last = out + length;
for (; out != last; ++out, ++a, ++b) {
*out = R(op(*a, *b));
}
}


template <class T, class Op, std::enable_if_t<is_vectorized<T>::value, int> = 0>
void Calculate(T* out, const T* a, const T* b, size_t length, Op op) {
using V = xsimd::simd_type<T>;
constexpr size_t vsize = xsimd::simd_traits<T>::size;

const size_t vlength = (length / vsize) * vsize;

const T* vlast = out + vlength;
for (; out < vlast; out += vsize, a += vsize, b += vsize) {
V va, vb;
va.load_unaligned(a);
vb.load_unaligned(b);
auto vr = op(va, vb);
vr.store_unaligned(out);
}

Calculate<T, T, T>(out, a, b, length - vlength, op);
}


//--------------------------------------
// Scalar-vector
//--------------------------------------
template <class R, class T, class U, class Op, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void Calculate(R* out, const T& a, const U* b, size_t length, Op op) {
const R* last = out + length;
for (; out != last; ++out, ++b) {
*out = R(op(a, *b));
}
}


template <class T, class Op, std::enable_if_t<!std::is_pointer<T>::value && is_vectorized<T>::value, int> = 0>
void Calculate(T* out, const T& a, const T* b, size_t length, Op op) {
using V = xsimd::simd_type<T>;
constexpr size_t vsize = xsimd::simd_traits<T>::size;

const size_t vlength = (length / vsize) * vsize;

const T* vlast = out + vlength;
V va{ a };
for (; out < vlast; out += vsize, b += vsize) {
V vb;
vb.load_unaligned(b);
auto vr = op(va, vb);
vr.store_unaligned(out);
}

Calculate<T, T, T>(out, a, b, length - vlength, op);
}


//--------------------------------------
// Vector-scalar
//--------------------------------------

template <class R, class T, class U, class Op, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void Calculate(R* out, const T* a, const U& b, size_t length, Op op) {
const R* last = out + length;
for (; out != last; ++out, ++a) {
*out = R(op(*a, b));
}
}


template <class T, class Op, std::enable_if_t<!std::is_pointer<T>::value && is_vectorized<T>::value, int> = 0>
void Calculate(T* out, const T* a, const T& b, size_t length, Op op) {
using V = xsimd::simd_type<T>;
constexpr size_t vsize = xsimd::simd_traits<T>::size;

const size_t vlength = (length / vsize) * vsize;

const T* vlast = out + vlength;
V vb{ b };
for (; out < vlast; out += vsize, a += vsize) {
V va;
va.load_unaligned(a);
auto vr = op(va, vb);
vr.store_unaligned(out);
}

Calculate<T, T, T>(out, a, b, length - vlength, op);
}


//------------------------------------------------------------------------------
// Vector-vector operations.
//------------------------------------------------------------------------------

template <class R, class T, class U>
void Multiply(R* out, const T* a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a * b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a * b; });
}


template <class R, class T, class U>
void Divide(R* out, const T* a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a / b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a / b; });
}


template <class R, class T, class U>
void Add(R* out, const T* a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a + b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a + b; });
}


template <class R, class T, class U>
void Subtract(R* out, const T* a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a - b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a - b; });
}

//------------------------------------------------------------------------------
Expand All @@ -146,49 +39,49 @@ void Subtract(R* out, const T* a, const U* b, size_t length) {

template <class R, class T, class U, std::enable_if_t<!std::is_pointer<U>::value, int> = 0>
void Multiply(R* out, const T* a, const U& b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a * b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a * b; });
}


template <class R, class T, class U, std::enable_if_t<!std::is_pointer<U>::value, int> = 0>
void Divide(R* out, const T* a, const U& b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a / b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a / b; });
}


template <class R, class T, class U, std::enable_if_t<!std::is_pointer<U>::value, int> = 0>
void Add(R* out, const T* a, const U& b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a + b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a + b; });
}


template <class R, class T, class U, std::enable_if_t<!std::is_pointer<U>::value, int> = 0>
void Subtract(R* out, const T* a, const U& b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a - b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a - b; });
}


template <class R, class T, class U, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void Multiply(R* out, const T& a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a * b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a * b; });
}


template <class R, class T, class U, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void Divide(R* out, const T& a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a / b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a / b; });
}


template <class R, class T, class U, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void Add(R* out, const T& a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a + b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a + b; });
}


template <class R, class T, class U, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void Subtract(R* out, const T& a, const U* b, size_t length) {
Calculate(out, a, b, length, [](const auto& a, const auto& b) { return a - b; });
BinaryOperationVectorized(out, a, b, length, [](const auto& a, const auto& b) { return a - b; });
}

} // namespace dspbb
2 changes: 1 addition & 1 deletion include/dspbb/Math/Convolution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void Convolution(R* out, const U* u, const V* v, size_t lenU, size_t lenV, size_
const intptr_t uoffset = std::max(intptr_t(0), intptr_t(first) - intptr_t(i));
const intptr_t ooffset = std::max(intptr_t(0), intptr_t(i) - intptr_t(first));
const intptr_t ccount = std::max(intptr_t(0), std::min(intptr_t(count), intptr_t(lenU) - uoffset));
Calculate(out + ooffset, out + ooffset, u + uoffset, ccount, [scale](const auto& a, const auto& b) { return a + b * scale; });
BinaryOperationVectorized(out + ooffset, out + ooffset, u + uoffset, ccount, [scale](const auto& a, const auto& b) { return a + b * scale; });
}
}

Expand Down
1 change: 1 addition & 0 deletions include/dspbb/Math/Functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <complex>
#include <type_traits>
#include <dspbb/Vectorization/MathFunctions.hpp>


namespace dspbb {
Expand Down
152 changes: 152 additions & 0 deletions include/dspbb/Vectorization/Kernels.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
#pragma once

#include <xsimd/xsimd.hpp>


namespace dspbb {


template <class T>
struct is_vectorized {
static constexpr bool value = xsimd::simd_traits<T>::size > 1;
};


//------------------------------------------------------------------------------
// Binary operations.
//------------------------------------------------------------------------------

template <class R, class T, class U, class Op>
void BinaryOperation(R* out, const T* a, const U* b, size_t length, Op op) {
const R* last = out + length;
for (; out != last; ++out, ++a, ++b) {
*out = R(op(*a, *b));
}
}

template <class R, class T, class U, class Op, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void BinaryOperation(R* out, const T& a, const U* b, size_t length, Op op) {
const R* last = out + length;
for (; out != last; ++out, ++b) {
*out = R(op(a, *b));
}
}

template <class R, class T, class U, class Op, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void BinaryOperation(R* out, const T* a, const U& b, size_t length, Op op) {
const R* last = out + length;
for (; out != last; ++out, ++a) {
*out = R(op(*a, b));
}
}

template <class T, class Op, std::enable_if_t<is_vectorized<T>::value, int> = 0>
void BinaryOperationVectorized(T* out, const T* a, const T* b, size_t length, Op op) {
using V = xsimd::simd_type<T>;
constexpr size_t vsize = xsimd::simd_traits<T>::size;

const size_t vlength = (length / vsize) * vsize;

const T* vlast = out + vlength;
for (; out < vlast; out += vsize, a += vsize, b += vsize) {
V va, vb;
va.load_unaligned(a);
vb.load_unaligned(b);
auto vr = op(va, vb);
vr.store_unaligned(out);
}

BinaryOperation(out, a, b, length - vlength, op);
}

template <class T, class Op, std::enable_if_t<!std::is_pointer<T>::value && is_vectorized<T>::value, int> = 0>
void BinaryOperationVectorized(T* out, const T& a, const T* b, size_t length, Op op) {
using V = xsimd::simd_type<T>;
constexpr size_t vsize = xsimd::simd_traits<T>::size;

const size_t vlength = (length / vsize) * vsize;

const T* vlast = out + vlength;
V va{ a };
for (; out < vlast; out += vsize, b += vsize) {
V vb;
vb.load_unaligned(b);
auto vr = op(va, vb);
vr.store_unaligned(out);
}

BinaryOperation(out, a, b, length - vlength, op);
}

template <class T, class Op, std::enable_if_t<!std::is_pointer<T>::value && is_vectorized<T>::value, int> = 0>
void BinaryOperationVectorized(T* out, const T* a, const T& b, size_t length, Op op) {
using V = xsimd::simd_type<T>;
constexpr size_t vsize = xsimd::simd_traits<T>::size;

const size_t vlength = (length / vsize) * vsize;

const T* vlast = out + vlength;
V vb{ b };
for (; out < vlast; out += vsize, a += vsize) {
V va;
va.load_unaligned(a);
auto vr = op(va, vb);
vr.store_unaligned(out);
}

BinaryOperation(out, a, b, length - vlength, op);
}


template <class R, class T, class U, class Op>
void BinaryOperationVectorized(R* out, const T* a, const U* b, size_t length, Op op) {
BinaryOperation(out, a, b, length, op);
}

template <class R, class T, class U, class Op, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void BinaryOperationVectorized(R* out, const T& a, const U* b, size_t length, Op op) {
BinaryOperation(out, a, b, length, op);
}

template <class R, class T, class U, class Op, std::enable_if_t<!std::is_pointer<T>::value, int> = 0>
void BinaryOperationVectorized(R* out, const T* a, const U& b, size_t length, Op op) {
BinaryOperation(out, a, b, length, op);
}

//------------------------------------------------------------------------------
// Unary operations.
//------------------------------------------------------------------------------

template <class R, class T, class Op>
void UnaryOperation(R* out, const T* in, size_t length, Op op) {
const R* last = out + length;
for (; out != last; ++out, ++in) {
*out = R(op(*in));
}
}

template <class R, class T, class Op>
void UnaryOperationVectorized(R* out, const T* in, size_t length, Op op) {
return UnaryOperation(out, in, length, op);
}

template <class T, class Op, std::enable_if_t<!is_vectorized<T>::value, int> = 0>
void UnaryOperationVectorized(T* out, T* in, size_t length, Op op) {
using V = xsimd::simd_type<T>;
constexpr size_t vsize = xsimd::simd_traits<T>::size;

const size_t vlength = (length / vsize) * vsize;

const T* vlast = out + vlength;
for (; out < vlast; out += vsize, in += vsize) {
V vin;
vin.load_unaligned(in);
auto vr = op(vin);
vr.store_unaligned(out);
}

UnaryOperation(out, in, length - vlength, op);
}


} // namespace dspbb
Loading

0 comments on commit c7ceff7

Please sign in to comment.