Add basic expressions
This commit is contained in:
parent
e6c191ec2e
commit
4f9e06cb0e
28
src/tenvex/internal/add.h
Normal file
28
src/tenvex/internal/add.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
struct Add : Expr<Add<L, R>>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Add(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_type_storage<L> _l;
|
||||||
|
tnvx_type_storage<R> _r;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Add<L, R> operator+(const Expr<L>& l, const Expr<R>& r) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "add_impl.hpp"
|
||||||
31
src/tenvex/internal/add_impl.hpp
Normal file
31
src/tenvex/internal/add_impl.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "add.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
Add<L, R>::Add(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
|
||||||
|
: _l(l)
|
||||||
|
, _r(r)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Add<L, R>::eval() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_add_ps(_l.eval(), _r.eval());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
Add<L, R> operator+(const Expr<L>& l, const Expr<R>& r) noexcept
|
||||||
|
{
|
||||||
|
return { l.self(), r.self() };
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tnvx
|
||||||
28
src/tenvex/internal/cross.h
Normal file
28
src/tenvex/internal/cross.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
struct Cross : Expr<Cross<L, R>>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Cross(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_type_storage<L> _l;
|
||||||
|
tnvx_type_storage<R> _r;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Cross<L, R> cross(const Expr<L>& l, const Expr<L>& r) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "cross_impl.hpp"
|
||||||
47
src/tenvex/internal/cross_impl.hpp
Normal file
47
src/tenvex/internal/cross_impl.hpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cross.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
Cross<L, R>::Cross(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
|
||||||
|
: _l(l)
|
||||||
|
, _r(r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Cross<L, R>::eval() const noexcept
|
||||||
|
{
|
||||||
|
__m128 a = _l.eval();
|
||||||
|
__m128 b = _r.eval();
|
||||||
|
|
||||||
|
// [ay, az, ax, 0]
|
||||||
|
__m128 a_yzx = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1));
|
||||||
|
// [by, bz, bx, 0]
|
||||||
|
__m128 b_yzx = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1));
|
||||||
|
|
||||||
|
// [ay*bz, az*bx, ax*by, 0]
|
||||||
|
__m128 mul0 = _mm_mul_ps(a, b_yzx);
|
||||||
|
// [az*by, ax*bz, ay*bx, 0]
|
||||||
|
__m128 mul1 = _mm_mul_ps(a_yzx, b);
|
||||||
|
|
||||||
|
// [ay*bz - az*by, az*bx - ax*bz, ax*by - ay*bx, 0]
|
||||||
|
__m128 sub = _mm_sub_ps(mul0, mul1);
|
||||||
|
|
||||||
|
// shuffle обратно в [x, y, z, 0]
|
||||||
|
return _mm_shuffle_ps(sub, sub, _MM_SHUFFLE(3, 0, 2, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
Cross<L, R> cross(const Expr<L>& l, const Expr<L>& r) noexcept
|
||||||
|
{
|
||||||
|
return { l.self(), r.self() };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
12
src/tenvex/internal/defines.h
Normal file
12
src/tenvex/internal/defines.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define TNVX_INLINE __forceinline
|
||||||
|
#define TNVX_RESTRICT __restrict
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define TNVX_INLINE __attribute__((always_inline)) inline
|
||||||
|
#define TNVX_RESTRICT __restrict__
|
||||||
|
#else
|
||||||
|
#define TNVX_INLINE inline
|
||||||
|
#define TNVX_RESTRICT
|
||||||
|
#endif
|
||||||
31
src/tenvex/internal/dot.h
Normal file
31
src/tenvex/internal/dot.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
#include "scalar.h"
|
||||||
|
#include "../vec4.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
requires (!std::same_as<L, Scalar> && !std::same_as<R, Scalar>)
|
||||||
|
struct Dot : Expr<Dot>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Dot(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_type_storage<L> _l;
|
||||||
|
tnvx_type_storage<R> _r;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Dot<L, R> dot(const Expr<L>& l, const Expr<L>& r) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "dot_impl.hpp"
|
||||||
37
src/tenvex/internal/dot_impl.hpp
Normal file
37
src/tenvex/internal/dot_impl.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dot.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
Dot<L, R>::Dot(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
|
||||||
|
: _l(l)
|
||||||
|
, _r(r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Dot<L, R>::eval() const noexcept
|
||||||
|
{
|
||||||
|
__m128 a = _l.eval();
|
||||||
|
__m128 b = _r.eval();
|
||||||
|
|
||||||
|
__m128 mul = _mm_mul_ps(a, b);
|
||||||
|
__m128 shuf = _mm_shuffle_ps(mul, mul, _MM_SHUFFLE(2, 3, 0, 1));
|
||||||
|
__m128 sum = _mm_add_ps(mul, shuf);
|
||||||
|
shuf = _mm_movehl_ps(shuf, sum);
|
||||||
|
sum = _mm_add_ss(sum, shuf);
|
||||||
|
return _mm_shuffle_ps(sum, sum, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
Dot<L, R> dot(const Expr<L>& l, const Expr<L>& r) noexcept
|
||||||
|
{
|
||||||
|
return { l.self(), r.self() };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
47
src/tenvex/internal/expression.h
Normal file
47
src/tenvex/internal/expression.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
|
||||||
|
#include <immintrin.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <concepts>
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
struct Expr
|
||||||
|
{
|
||||||
|
[[nodiscard]] inline
|
||||||
|
const Derived& self() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
float operator[](size_t i) const noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept expression = requires(T a)
|
||||||
|
{
|
||||||
|
{ a.eval() } -> std::same_as<__m128>;
|
||||||
|
}
|
||||||
|
&& std::derived_from<T, Expr<T>>;
|
||||||
|
|
||||||
|
class Scalar;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
concept vector_expression = expression<T> && !std::same_as<T, Scalar>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
constexpr bool tnvx_store_by_value = std::is_trivially_copyable_v<T>
|
||||||
|
&& std::is_trivially_destructible_v<T>
|
||||||
|
&& sizeof(T) <= 16;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using tnvx_type_storage = std::conditional_t<tnvx_store_by_value<T>, T, const T&>;
|
||||||
|
|
||||||
|
} // namespace tnvx
|
||||||
|
|
||||||
|
#include "expression_impl.hpp"
|
||||||
31
src/tenvex/internal/expression_impl.hpp
Normal file
31
src/tenvex/internal/expression_impl.hpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
TNVX_INLINE
|
||||||
|
const Derived& Expr<Derived>::self() const noexcept
|
||||||
|
{
|
||||||
|
return static_cast<const Derived&>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Expr<Derived>::eval() const noexcept
|
||||||
|
{
|
||||||
|
return self().eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Derived>
|
||||||
|
TNVX_INLINE
|
||||||
|
float Expr<Derived>::operator[](size_t i) const noexcept
|
||||||
|
{
|
||||||
|
alignas(16) float tmp[4];
|
||||||
|
_mm_store_ps(tmp, eval());
|
||||||
|
return tmp[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tnvx
|
||||||
27
src/tenvex/internal/magnitude.h
Normal file
27
src/tenvex/internal/magnitude.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
struct Magnitude : Expr<Magnitude<E>>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Magnitude(const E& TNVX_RESTRICT e) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_type_storage<E> _e;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Magnitude<E> magnitude(const Expr<E> e) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "magnitude_impl.hpp"
|
||||||
30
src/tenvex/internal/magnitude_impl.hpp
Normal file
30
src/tenvex/internal/magnitude_impl.hpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "magnitude.h"
|
||||||
|
#include "dot.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Magnitude<E>::Magnitude(const E& TNVX_RESTRICT e) noexcept
|
||||||
|
: _e(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Magnitude<E>::eval() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_sqrt_ps(Dot<E, E>(_e, _e).eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Magnitude<E> magnitude(const Expr<E> e) noexcept
|
||||||
|
{
|
||||||
|
return { e.self() };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
33
src/tenvex/internal/mul.h
Normal file
33
src/tenvex/internal/mul.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
#include "scalar.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
struct Mul : Expr<Mul<L, R>>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Mul(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_type_storage<L> _l;
|
||||||
|
tnvx_type_storage<R> _r;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Mul<E, Scalar> operator*(const Expr<E>& l, float r) noexcept;
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Mul<Scalar, E> operator*(float l, const Expr<E>& r) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "mul_impl.hpp"
|
||||||
37
src/tenvex/internal/mul_impl.hpp
Normal file
37
src/tenvex/internal/mul_impl.hpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "mul.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
inline Mul<L, R>::Mul(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
|
||||||
|
: _l(l)
|
||||||
|
, _r(r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Mul<L, R>::eval() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_mul_ps(_l.eval(), _r.eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Mul<E, Scalar> operator*(const Expr<E>& l, float r) noexcept
|
||||||
|
{
|
||||||
|
return { l.self(), Scalar(r) };
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Mul<Scalar, E> operator*(float l, const Expr<E>& r) noexcept
|
||||||
|
{
|
||||||
|
return { Scalar(l), r.self() };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
27
src/tenvex/internal/norm.h
Normal file
27
src/tenvex/internal/norm.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
struct Norm : Expr<Norm<E>>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Norm(const E& TNVX_RESTRICT e) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_type_storage<E> _e;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Norm<E> norm(const Expr<E> e) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "norm_impl.hpp"
|
||||||
36
src/tenvex/internal/norm_impl.hpp
Normal file
36
src/tenvex/internal/norm_impl.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "norm.h"
|
||||||
|
#include "dot.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Norm<E>::Norm(const E& TNVX_RESTRICT e) noexcept
|
||||||
|
: _e(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Norm<E>::eval() const noexcept
|
||||||
|
{
|
||||||
|
__m128 data = _e.eval();
|
||||||
|
__m128 mul = _mm_mul_ps(data, data);
|
||||||
|
__m128 shuf = _mm_shuffle_ps(mul, mul, _MM_SHUFFLE(2, 3, 0, 1));
|
||||||
|
__m128 sum = _mm_add_ps(mul, shuf);
|
||||||
|
shuf = _mm_movehl_ps(shuf, sum);
|
||||||
|
sum = _mm_add_ss(sum, shuf);
|
||||||
|
__m128 len = _mm_shuffle_ps(sum, sum, 0);
|
||||||
|
return _mm_div_ps(data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
Norm<E> norm(const Expr<E> e) noexcept
|
||||||
|
{
|
||||||
|
return { e.self() };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
25
src/tenvex/internal/scalar.h
Normal file
25
src/tenvex/internal/scalar.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Scalar : Expr<Scalar>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Scalar(float value) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
float operator[](size_t) const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _value;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "scalar_impl.hpp"
|
||||||
26
src/tenvex/internal/scalar_impl.hpp
Normal file
26
src/tenvex/internal/scalar_impl.hpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "scalar.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
Scalar::Scalar(float value) noexcept
|
||||||
|
: _value(value)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] TNVX_INLINE
|
||||||
|
__m128 Scalar::eval() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_set1_ps(_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] TNVX_INLINE
|
||||||
|
float Scalar::operator[](size_t) const noexcept
|
||||||
|
{
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
28
src/tenvex/internal/sub.h
Normal file
28
src/tenvex/internal/sub.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
struct Sub : Expr<Sub<L, R>>
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
Sub(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_type_storage<L> _l;
|
||||||
|
tnvx_type_storage<R> _r;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
Sub<L, R> operator-(const Expr<L>& l, const Expr<R>& r) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "sub_impl.hpp"
|
||||||
28
src/tenvex/internal/sub_impl.hpp
Normal file
28
src/tenvex/internal/sub_impl.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "sub.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
tnvx::Sub<L, R>::Sub(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
|
||||||
|
: _l(l), _r(r)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 Sub<L, R>::eval() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_sub_ps(_l.eval(), _r.eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression L, expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
Sub<L, R> operator-(const Expr<L>& l, const Expr<R>& r) noexcept
|
||||||
|
{
|
||||||
|
return { l.self(), r.self() };
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
9
src/tenvex/tenvex.h
Normal file
9
src/tenvex/tenvex.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vec2.h"
|
||||||
|
#include "vec3.h"
|
||||||
|
#include "vec4.h"
|
||||||
|
|
||||||
|
#include "internal/add.h"
|
||||||
|
#include "internal/sub.h"
|
||||||
|
#include "internal/mul.h"
|
||||||
10
src/tenvex/vec2.h
Normal file
10
src/tenvex/vec2.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
struct vec2
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tenvex
|
||||||
10
src/tenvex/vec3.h
Normal file
10
src/tenvex/vec3.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
struct vec3
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tenvex
|
||||||
36
src/tenvex/vec4.h
Normal file
36
src/tenvex/vec4.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "internal/expression.h"
|
||||||
|
|
||||||
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
struct alignas(16) vec4 : public Expr<vec4>
|
||||||
|
{
|
||||||
|
vec4() = default;
|
||||||
|
|
||||||
|
vec4(float x, float y, float z, float w);
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
vec4(const Expr<E>& expr);
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
vec4& operator=(const Expr<E>& expr);
|
||||||
|
|
||||||
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
float magnitude() const noexcept;
|
||||||
|
vec4 norm() const noexcept;
|
||||||
|
|
||||||
|
float x() const noexcept;
|
||||||
|
float y() const noexcept;
|
||||||
|
float z() const noexcept;
|
||||||
|
float w() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
__m128 _data;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace tenvex
|
||||||
Loading…
Reference in New Issue
Block a user