Update operations
This commit is contained in:
parent
61e03f653f
commit
06a233c464
@ -18,7 +18,6 @@ TNVX_INLINE
|
|||||||
__m128 Add<L, R>::eval() const noexcept
|
__m128 Add<L, R>::eval() const noexcept
|
||||||
{
|
{
|
||||||
return _mm_add_ps(_l.eval(), _r.eval());
|
return _mm_add_ps(_l.eval(), _r.eval());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<expression L, expression R>
|
template<expression L, expression R>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ __m128 Cross<L, R>::eval() const noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<vector_expression L, vector_expression R>
|
template<vector_expression L, vector_expression R>
|
||||||
Cross<L, R> cross(const Expr<L>& l, const Expr<L>& r) noexcept
|
Cross<L, R> cross(const Expr<L>& l, const Expr<R>& r) noexcept
|
||||||
{
|
{
|
||||||
return { l.self(), r.self() };
|
return { l.self(), r.self() };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
#include "scalar.h"
|
|
||||||
#include "../vec4.h"
|
|
||||||
|
|
||||||
namespace tnvx
|
namespace tnvx
|
||||||
{
|
{
|
||||||
|
|
||||||
template<vector_expression L, vector_expression R>
|
template<vector_expression L, vector_expression R>
|
||||||
requires (!std::same_as<L, Scalar> && !std::same_as<R, Scalar>)
|
struct Dot : Expr<Dot<L, R>>
|
||||||
struct Dot : Expr<Dot>
|
|
||||||
{
|
{
|
||||||
inline
|
inline
|
||||||
Dot(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
|
Dot(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
|
||||||
@ -17,6 +14,9 @@ struct Dot : Expr<Dot>
|
|||||||
[[nodiscard]] inline
|
[[nodiscard]] inline
|
||||||
__m128 eval() const noexcept;
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
operator float() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tnvx_type_storage<L> _l;
|
tnvx_type_storage<L> _l;
|
||||||
tnvx_type_storage<R> _r;
|
tnvx_type_storage<R> _r;
|
||||||
@ -24,7 +24,15 @@ private:
|
|||||||
|
|
||||||
template<vector_expression L, vector_expression R>
|
template<vector_expression L, vector_expression R>
|
||||||
[[nodiscard]] inline
|
[[nodiscard]] inline
|
||||||
Dot<L, R> dot(const Expr<L>& l, const Expr<L>& r) noexcept;
|
Dot<L, R> dot(const Expr<L>& l, const Expr<R>& r) noexcept;
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
float operator*(const Dot<L, R>& l, float r) noexcept;
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
[[nodiscard]] inline
|
||||||
|
float operator*(float l, const Dot<L, R>& r) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -29,9 +29,32 @@ __m128 Dot<L, R>::eval() const noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<vector_expression L, vector_expression R>
|
template<vector_expression L, vector_expression R>
|
||||||
Dot<L, R> dot(const Expr<L>& l, const Expr<L>& r) noexcept
|
TNVX_INLINE
|
||||||
|
Dot<L, R>::operator float() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
Dot<L, R> dot(const Expr<L>& l, const Expr<R>& r) noexcept
|
||||||
{
|
{
|
||||||
return { l.self(), r.self() };
|
return { l.self(), r.self() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
TNVX_INLINE
|
||||||
|
float operator*(const Dot<L, R>& l, float r) noexcept
|
||||||
|
{
|
||||||
|
return static_cast<float>(l) * r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression L, vector_expression R>
|
||||||
|
float operator*(float l, const Dot<L, R>& r) noexcept
|
||||||
|
{
|
||||||
|
return l * static_cast<float>(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ concept expression = requires(T a)
|
|||||||
}
|
}
|
||||||
&& std::derived_from<T, Expr<T>>;
|
&& std::derived_from<T, Expr<T>>;
|
||||||
|
|
||||||
class Scalar;
|
struct Scalar;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
concept vector_expression = expression<T> && !std::same_as<T, Scalar>;
|
concept vector_expression = expression<T> && !std::same_as<T, Scalar>;
|
||||||
|
|||||||
@ -14,13 +14,16 @@ struct Magnitude : Expr<Magnitude<E>>
|
|||||||
[[nodiscard]] inline
|
[[nodiscard]] inline
|
||||||
__m128 eval() const noexcept;
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
operator float() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tnvx_type_storage<E> _e;
|
tnvx_type_storage<E> _e;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<vector_expression E>
|
template<vector_expression E>
|
||||||
[[nodiscard]] inline
|
[[nodiscard]] inline
|
||||||
Magnitude<E> magnitude(const Expr<E> e) noexcept;
|
Magnitude<E> magnitude(const Expr<E>& e) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,12 +17,19 @@ template<vector_expression E>
|
|||||||
TNVX_INLINE
|
TNVX_INLINE
|
||||||
__m128 Magnitude<E>::eval() const noexcept
|
__m128 Magnitude<E>::eval() const noexcept
|
||||||
{
|
{
|
||||||
return _mm_sqrt_ps(Dot<E, E>(_e, _e).eval());
|
return _mm_sqrt_ss(Dot<E, E>(_e, _e).eval());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<vector_expression E>
|
template<vector_expression E>
|
||||||
TNVX_INLINE
|
TNVX_INLINE
|
||||||
Magnitude<E> magnitude(const Expr<E> e) noexcept
|
Magnitude<E>::operator float() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<vector_expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Magnitude<E> magnitude(const Expr<E>& e) noexcept
|
||||||
{
|
{
|
||||||
return { e.self() };
|
return { e.self() };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,10 @@ private:
|
|||||||
tnvx_type_storage<R> _r;
|
tnvx_type_storage<R> _r;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//template<vector_expression L, vector_expression R>
|
||||||
|
//[[nodiscard]] inline
|
||||||
|
//Mul<L, R> operator*(const Expr<L>& l, const Expr<R>& r) noexcept;
|
||||||
|
|
||||||
template<expression E>
|
template<expression E>
|
||||||
[[nodiscard]] inline
|
[[nodiscard]] inline
|
||||||
Mul<E, Scalar> operator*(const Expr<E>& l, float r) noexcept;
|
Mul<E, Scalar> operator*(const Expr<E>& l, float r) noexcept;
|
||||||
|
|||||||
@ -20,6 +20,13 @@ __m128 Mul<L, R>::eval() const noexcept
|
|||||||
return _mm_mul_ps(_l.eval(), _r.eval());
|
return _mm_mul_ps(_l.eval(), _r.eval());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//template<vector_expression L, vector_expression R>
|
||||||
|
//TNVX_INLINE
|
||||||
|
//Mul<L, R> operator*(const Expr<L>& l, const Expr<R>& r) noexcept
|
||||||
|
//{
|
||||||
|
// return { l.self(), r.self() };
|
||||||
|
//}
|
||||||
|
|
||||||
template<expression E>
|
template<expression E>
|
||||||
TNVX_INLINE
|
TNVX_INLINE
|
||||||
Mul<E, Scalar> operator*(const Expr<E>& l, float r) noexcept
|
Mul<E, Scalar> operator*(const Expr<E>& l, float r) noexcept
|
||||||
|
|||||||
@ -20,7 +20,7 @@ private:
|
|||||||
|
|
||||||
template<vector_expression E>
|
template<vector_expression E>
|
||||||
[[nodiscard]] inline
|
[[nodiscard]] inline
|
||||||
Norm<E> norm(const Expr<E> e) noexcept;
|
Norm<E> norm(const Expr<E>& e) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -17,18 +17,19 @@ template<vector_expression E>
|
|||||||
TNVX_INLINE
|
TNVX_INLINE
|
||||||
__m128 Norm<E>::eval() const noexcept
|
__m128 Norm<E>::eval() const noexcept
|
||||||
{
|
{
|
||||||
__m128 data = _e.eval();
|
__m128 data = _e.eval();
|
||||||
__m128 mul = _mm_mul_ps(data, data);
|
__m128 mul = _mm_mul_ps(data, data);
|
||||||
__m128 shuf = _mm_shuffle_ps(mul, mul, _MM_SHUFFLE(2, 3, 0, 1));
|
__m128 shuf = _mm_shuffle_ps(mul, mul, _MM_SHUFFLE(2, 3, 0, 1));
|
||||||
__m128 sum = _mm_add_ps(mul, shuf);
|
__m128 sum = _mm_add_ps(mul, shuf);
|
||||||
shuf = _mm_movehl_ps(shuf, sum);
|
shuf = _mm_movehl_ps(shuf, sum);
|
||||||
sum = _mm_add_ss(sum, shuf);
|
sum = _mm_add_ss(sum, shuf);
|
||||||
__m128 len = _mm_shuffle_ps(sum, sum, 0);
|
__m128 len = _mm_shuffle_ps(sum, sum, 0);
|
||||||
return _mm_div_ps(data, len);
|
__m128 sqrt_len = _mm_sqrt_ps(len);
|
||||||
|
return _mm_div_ps(data, sqrt_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<vector_expression E>
|
template<vector_expression E>
|
||||||
Norm<E> norm(const Expr<E> e) noexcept
|
Norm<E> norm(const Expr<E>& e) noexcept
|
||||||
{
|
{
|
||||||
return { e.self() };
|
return { e.self() };
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,3 +5,8 @@
|
|||||||
#include "internal/add.h"
|
#include "internal/add.h"
|
||||||
#include "internal/sub.h"
|
#include "internal/sub.h"
|
||||||
#include "internal/mul.h"
|
#include "internal/mul.h"
|
||||||
|
#include "internal/dot.h"
|
||||||
|
#include "internal/cross.h"
|
||||||
|
#include "internal/norm.h"
|
||||||
|
#include "internal/magnitude.h"
|
||||||
|
#include "internal/scalar.h"
|
||||||
|
|||||||
@ -4,33 +4,60 @@
|
|||||||
|
|
||||||
#include <immintrin.h>
|
#include <immintrin.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace tnvx
|
namespace tnvx
|
||||||
{
|
{
|
||||||
|
|
||||||
struct alignas(16) vec4 : public Expr<vec4>
|
struct alignas(16) vec4 : Expr<vec4>
|
||||||
{
|
{
|
||||||
vec4() = default;
|
vec4() = default;
|
||||||
|
|
||||||
vec4(float x, float y, float z, float w);
|
inline
|
||||||
|
vec4(float x, float y, float z, float w) noexcept;
|
||||||
|
|
||||||
template<typename E>
|
template<typename E>
|
||||||
vec4(const Expr<E>& expr);
|
inline
|
||||||
|
vec4(const Expr<E>& expr) noexcept;
|
||||||
|
|
||||||
template<typename E>
|
template<typename E>
|
||||||
vec4& operator=(const Expr<E>& expr);
|
inline
|
||||||
|
vec4& operator=(const Expr<E>& expr) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
__m128 eval() const noexcept;
|
__m128 eval() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
float magnitude() const noexcept;
|
float magnitude() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
vec4 norm() const noexcept;
|
vec4 norm() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
float x() const noexcept;
|
float x() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
float y() const noexcept;
|
float y() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
float z() const noexcept;
|
float z() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
float w() const noexcept;
|
float w() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] inline
|
||||||
|
std::array<float, 4> data() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
__m128 _data;
|
__m128 _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace tenvex
|
inline
|
||||||
|
bool operator==(const vec4& a, const vec4& b) noexcept;
|
||||||
|
|
||||||
|
inline
|
||||||
|
bool approx_eq(const vec4& a, const vec4& b, float eps = 1e-3f) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "vec4_impl.hpp"
|
||||||
|
|||||||
96
src/tenvex/vec4_impl.hpp
Normal file
96
src/tenvex/vec4_impl.hpp
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "vec4.h"
|
||||||
|
#include "internal/magnitude.h"
|
||||||
|
#include "internal/norm.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
TNVX_INLINE
|
||||||
|
vec4::vec4(const Expr<E>& expr) noexcept
|
||||||
|
: _data(expr.eval())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
TNVX_INLINE
|
||||||
|
vec4& vec4::operator=(const Expr<E>& expr) noexcept
|
||||||
|
{
|
||||||
|
_data = expr.eval();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
vec4::vec4(float x, float y, float z, float w) noexcept
|
||||||
|
{
|
||||||
|
_data = _mm_set_ps(w, z, y, x);
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
__m128 vec4::eval() const noexcept
|
||||||
|
{
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
float vec4::magnitude() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(Magnitude<vec4>(*this).eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
vec4 vec4::norm() const noexcept
|
||||||
|
{
|
||||||
|
return { Norm<vec4>(*this) };
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
float vec4::x() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
float vec4::y() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(_mm_shuffle_ps(_data, _data, _MM_SHUFFLE(1, 1, 1, 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
float vec4::z() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(_mm_shuffle_ps(_data, _data, _MM_SHUFFLE(2, 2, 2, 2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
float vec4::w() const noexcept
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(_mm_shuffle_ps(_data, _data, _MM_SHUFFLE(3, 3, 3, 3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
std::array<float, 4> vec4::data() const noexcept
|
||||||
|
{
|
||||||
|
std::array<float, 4> result;
|
||||||
|
_mm_storeu_ps(result.data(), _data);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
bool operator==(const vec4& a, const vec4& b) noexcept
|
||||||
|
{
|
||||||
|
return _mm_movemask_ps(_mm_cmpeq_ps(a.eval(), b.eval())) == 0xF;
|
||||||
|
}
|
||||||
|
|
||||||
|
TNVX_INLINE
|
||||||
|
bool approx_eq(const vec4& a, const vec4& b, float eps) noexcept
|
||||||
|
{
|
||||||
|
__m128 epsilon = _mm_set1_ps(eps);
|
||||||
|
__m128 diff = _mm_sub_ps(a.eval(), b.eval());
|
||||||
|
__m128 abs_diff = _mm_andnot_ps(_mm_set1_ps(-0.0f), diff);
|
||||||
|
return _mm_movemask_ps(_mm_cmplt_ps(abs_diff, epsilon)) == 0xF;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user