|
|
|
|
|
|
|
|
|
|
|
#pragma once |
|
|
|
|
|
#include "../geometry.h" |
|
|
|
|
|
|
|
|
struct contiguous_tag{}; |
|
|
|
|
|
struct transpose_tag{}; |
|
|
|
|
|
template<typename layout_t, uint32_t R, uint32_t C> |
|
|
struct Matrix2x2_Offset; |
|
|
|
|
|
template<uint32_t R, uint32_t C> |
|
|
struct Matrix2x2_Offset<contiguous_tag, R, C> |
|
|
{ |
|
|
static const uint32_t OFFSET = R * 2 + C; |
|
|
}; |
|
|
|
|
|
template<uint32_t R, uint32_t C> |
|
|
struct Matrix2x2_Offset<transpose_tag, R, C> |
|
|
{ |
|
|
static const uint32_t OFFSET = C * 2 + R; |
|
|
}; |
|
|
|
|
|
|
|
|
template<typename T, typename layout_t, uint32_t R, uint32_t C> |
|
|
struct Matrix2x2_Indexor |
|
|
{ |
|
|
static const uint32_t OFFSET = Matrix2x2_Offset<layout_t, R, C>::OFFSET; |
|
|
|
|
|
static T &get(T *data) { return data[OFFSET]; } |
|
|
static const T get(const T *data) { return data[OFFSET]; } |
|
|
}; |
|
|
|
|
|
|
|
|
template<typename T> |
|
|
struct Matrix2x2 |
|
|
{ |
|
|
Matrix2x2() = default; |
|
|
Matrix2x2(T r0c0, T r0c1, T r1c0, T r1c1) |
|
|
: m_data{ r0c0, r0c1, r1c0, r1c1 } |
|
|
{ |
|
|
} |
|
|
Matrix2x2(const Point_<T> &r0, const Point_<T> &r1) |
|
|
: m_data{ r0.X, r0.Y, r1.X, r1.Y } |
|
|
{ |
|
|
} |
|
|
Matrix2x2(const Point_<T> &r0, const Point_<T> &r1, transpose_tag) |
|
|
: m_data{ r0.X, r1.X, r0.Y, r1.Y } |
|
|
{ |
|
|
} |
|
|
|
|
|
inline T &operator[](uint32_t i) { return m_data[i]; } |
|
|
inline const T operator[](uint32_t i) const { return m_data[i]; } |
|
|
|
|
|
T m_data[4]; |
|
|
}; |
|
|
|
|
|
template<typename T, typename layout_t> |
|
|
struct Matrix2x2_View |
|
|
{ |
|
|
Matrix2x2_View(const Matrix2x2<T> &m) : m_data(m.m_data) {} |
|
|
|
|
|
const T *m_data; |
|
|
}; |
|
|
|
|
|
template<uint32_t R, uint32_t C, typename T, typename layout_t> |
|
|
const T get(const Matrix2x2_View<T, layout_t> &m) |
|
|
{ |
|
|
return Matrix2x2_Indexor<T, layout_t, R, C>::get(m.m_data); |
|
|
} |
|
|
|
|
|
template<typename T, typename get_pt_t, typename callback_t, typename layout_t = contiguous_tag> |
|
|
inline |
|
|
void matmul_fn(int64_t N, const get_pt_t &get_fn, const Matrix2x2<T> &mat, const callback_t &callback, |
|
|
layout_t lt = layout_t{}) |
|
|
{ |
|
|
Matrix2x2_View<T, layout_t> m{ mat }; |
|
|
|
|
|
#pragma omp simd |
|
|
for (int64_t i = 0; i < N; ++i) { |
|
|
Point_<T> pt = get_fn(i); |
|
|
|
|
|
T x = pt.X * get<0, 0>(m) + pt.Y * get<1, 0>(m); |
|
|
T y = pt.X * get<0, 1>(m) + pt.Y * get<1, 1>(m); |
|
|
|
|
|
callback(i, Point_<T>{ x, y }); |
|
|
} |
|
|
} |
|
|
|