Compare commits
3 Commits
aecca0d9a8
...
b6ef759e9f
| Author | SHA1 | Date | |
|---|---|---|---|
| b6ef759e9f | |||
| 6da0449d82 | |||
| 6f7dbe7528 |
@ -89,4 +89,9 @@ inline bool approx_eq(vec4 a, vec4 b, float eps = 1e-6f) noexcept
|
|||||||
&& std::fabs(a.w() - b.w()) <= eps;
|
&& std::fabs(a.w() - b.w()) <= eps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline vec4 operator-(vec4 v) noexcept
|
||||||
|
{
|
||||||
|
return { -v.x(), -v.y(), -v.z(), -v.w() };
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -13,6 +13,12 @@
|
|||||||
namespace tnvx::detail
|
namespace tnvx::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
[[nodiscard]] TNVX_INLINE
|
||||||
|
float to_float(vf4 v)
|
||||||
|
{
|
||||||
|
return _mm_cvtss_f32(v);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] TNVX_INLINE
|
[[nodiscard]] TNVX_INLINE
|
||||||
bool eq(vf4 a, vf4 b)
|
bool eq(vf4 a, vf4 b)
|
||||||
{
|
{
|
||||||
@ -39,6 +45,12 @@ float get_lane(vf4 v) noexcept
|
|||||||
return _mm_cvtss_f32(_mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, lane)));
|
return _mm_cvtss_f32(_mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, lane)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] TNVX_INLINE
|
||||||
|
vf4 neg(vf4 v) noexcept
|
||||||
|
{
|
||||||
|
return _mm_xor_ps(v, _mm_set1_ps(-0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] TNVX_INLINE
|
[[nodiscard]] TNVX_INLINE
|
||||||
vf4 add(vf4 l, vf4 r) noexcept
|
vf4 add(vf4 l, vf4 r) noexcept
|
||||||
{
|
{
|
||||||
|
|||||||
@ -24,7 +24,7 @@ template<vec_expr L, vec_expr R>
|
|||||||
TNVX_INLINE
|
TNVX_INLINE
|
||||||
Dot3<L, R>::operator float() const noexcept
|
Dot3<L, R>::operator float() const noexcept
|
||||||
{
|
{
|
||||||
return _mm_cvtss_f32(eval());
|
return detail::to_float(eval());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<vec_expr L, vec_expr R>
|
template<vec_expr L, vec_expr R>
|
||||||
|
|||||||
36
src/tenvex/expressions/neg.h
Normal file
36
src/tenvex/expressions/neg.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "core.h"
|
||||||
|
#include "expression.h"
|
||||||
|
#include "traits.h"
|
||||||
|
#include "concepts.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
struct Neg : Expr<Neg<E>>
|
||||||
|
{
|
||||||
|
TNVX_INLINE
|
||||||
|
explicit Neg(const E& TNVX_RESTRICT e) noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] TNVX_INLINE
|
||||||
|
vf4 eval() const noexcept;
|
||||||
|
|
||||||
|
[[nodiscard]] TNVX_INLINE
|
||||||
|
operator float() const noexcept requires scalar_expr<E>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
tnvx_ref_or_value_t<E> _e;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<vec_expr E> inline constexpr bool is_vec_expr<Neg<E>> = true;
|
||||||
|
template<scalar_expr E> inline constexpr bool is_scalar_expr<Neg<E>> = true;
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
[[nodiscard]] TNVX_INLINE
|
||||||
|
Neg<E> operator-(const E& e) noexcept;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "neg_impl.hpp"
|
||||||
36
src/tenvex/expressions/neg_impl.hpp
Normal file
36
src/tenvex/expressions/neg_impl.hpp
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "neg.h"
|
||||||
|
|
||||||
|
namespace tnvx
|
||||||
|
{
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
tnvx::Neg<E>::Neg(const E& TNVX_RESTRICT e) noexcept
|
||||||
|
: _e(e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
vf4 Neg<E>::eval() const noexcept
|
||||||
|
{
|
||||||
|
return detail::neg(_e.eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Neg<E>::operator float() const noexcept requires scalar_expr<E>
|
||||||
|
{
|
||||||
|
return detail::to_float(eval());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<expression E>
|
||||||
|
TNVX_INLINE
|
||||||
|
Neg<E> operator-(const E& e) noexcept
|
||||||
|
{
|
||||||
|
return Neg<E>(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -35,9 +35,6 @@ struct alignas(16) vec4 : Expr<vec4>
|
|||||||
[[nodiscard]] TNVX_INLINE
|
[[nodiscard]] TNVX_INLINE
|
||||||
vf4 eval() const noexcept;
|
vf4 eval() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]] TNVX_INLINE
|
|
||||||
vec4 operator-() const noexcept;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
vf4 _data;
|
vf4 _data;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "expressions/neg.h"
|
||||||
#include "expressions/add.h"
|
#include "expressions/add.h"
|
||||||
#include "expressions/sub.h"
|
#include "expressions/sub.h"
|
||||||
#include "expressions/scalar.h"
|
#include "expressions/scalar.h"
|
||||||
|
|||||||
@ -253,4 +253,34 @@ TEST(naive_vec4, cross_parallel)
|
|||||||
EXPECT_TRUE(approx_eq(cross3(a, b), check));
|
EXPECT_TRUE(approx_eq(cross3(a, b), check));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, neg_basic)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, -2.0f, 3.0f, -4.0f };
|
||||||
|
vec4 check = { -1.0f, 2.0f, -3.0f, 4.0f };
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(-a, check));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, neg_zero)
|
||||||
|
{
|
||||||
|
vec4 a = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(-a, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, neg_double)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(-(-a), a));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, neg_compound)
|
||||||
|
{
|
||||||
|
vec4 a = { 5.0f, 3.0f, 1.0f, 0.0f };
|
||||||
|
vec4 b = { 2.0f, 1.0f, 4.0f, 0.0f };
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(a + (-b), a - b));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -257,8 +257,8 @@ TEST(vec4, dot3_times_literal_collapses)
|
|||||||
|
|
||||||
auto r = dot3(a, b) * 2.0f;
|
auto r = dot3(a, b) * 2.0f;
|
||||||
|
|
||||||
static_assert(!std::is_same_v<decltype(r), float>);
|
EXPECT_TRUE((!std::same_as<decltype(r), float>));
|
||||||
static_assert(scalar_expr<decltype(r)>);
|
EXPECT_TRUE((scalar_expr<decltype(r)>));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(vec4, magnitude3_times_literal_collapses)
|
TEST(vec4, magnitude3_times_literal_collapses)
|
||||||
@ -267,8 +267,74 @@ TEST(vec4, magnitude3_times_literal_collapses)
|
|||||||
|
|
||||||
auto r = magnitude3(a) * 2.0f;
|
auto r = magnitude3(a) * 2.0f;
|
||||||
|
|
||||||
static_assert(!std::is_same_v<decltype(r), float>);
|
EXPECT_TRUE((!std::same_as<decltype(r), float>));
|
||||||
static_assert(scalar_expr<decltype(r)>);
|
EXPECT_TRUE((scalar_expr<decltype(r)>));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(vec4, neg_basic)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, -2.0f, 3.0f, -4.0f };
|
||||||
|
vec4 check = { -1.0f, 2.0f, -3.0f, 4.0f };
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(-a, check));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(vec4, neg_zero)
|
||||||
|
{
|
||||||
|
vec4 a = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(-a, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(vec4, neg_double)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(-(-a), a));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(vec4, neg_compound)
|
||||||
|
{
|
||||||
|
vec4 a = { 5.0f, 3.0f, 1.0f, 0.0f };
|
||||||
|
vec4 b = { 2.0f, 1.0f, 4.0f, 0.0f };
|
||||||
|
vec4 check = { 3.0f, 2.0f, -3.0f, 0.0f };
|
||||||
|
vec4 result = a + (-b);
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(vec4, neg_expression)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 2.0f, 3.0f, 0.0f };
|
||||||
|
vec4 b = { 4.0f, 5.0f, 6.0f, 0.0f };
|
||||||
|
vec4 check = { -5.0f, -7.0f, -9.0f, 0.0f };
|
||||||
|
vec4 result = -(a + b);
|
||||||
|
|
||||||
|
|
||||||
|
EXPECT_TRUE((vec_expr<decltype(-(a + b))>));
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(vec4, neg_scalar_stays_lazy)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
vec4 b = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
float check = -1.0f;
|
||||||
|
float result = -dot3(a, b);
|
||||||
|
|
||||||
|
EXPECT_TRUE((scalar_expr<decltype(-dot3(a, b))>));
|
||||||
|
EXPECT_FLOAT_EQ(check, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(vec4, neg_scalar_in_expression)
|
||||||
|
{
|
||||||
|
vec4 a = { 2.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
vec4 b = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
vec4 c = { 1.0f, 1.0f, 1.0f, 0.0f };
|
||||||
|
vec4 check = { -2.0f, -2.0f, -2.0f, 0.0f };
|
||||||
|
|
||||||
|
vec4 result = c * (-dot3(a, b));
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user