Update currenct expressions list

This commit is contained in:
Artem Zyktin 2026-05-30 19:35:07 +08:00
parent df718217d2
commit bf74d7163f
27 changed files with 544 additions and 95 deletions

View File

@ -1,12 +1,10 @@
#pragma once
#include "defines.h"
#include "core.h"
#include "expression.h"
#include "concepts.h"
#include "traits.h"
#include <immintrin.h>
namespace tnvx
{
@ -17,7 +15,7 @@ struct Add : Expr<Add<L, R>>
Add(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
[[nodiscard]] TNVX_INLINE
__m128 eval() const noexcept;
vf4 eval() const noexcept;
private:
tnvx_ref_or_value_t<L> _l;
@ -26,7 +24,7 @@ private:
template<vec_expr L, vec_expr R>
[[nodiscard]] TNVX_INLINE
Add<L, R> operator+(const L& l, const R& r) noexcept;
Add<L, R> operator+(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
template<vec_expr L, vec_expr R>
inline constexpr bool is_vec_expr<Add<L, R>> = true;

View File

@ -1,6 +1,5 @@
#pragma once
#include "defines.h"
#include "add.h"
namespace tnvx
@ -16,14 +15,14 @@ Add<L, R>::Add(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
template<vec_expr L, vec_expr R>
[[nodiscard]] TNVX_INLINE
__m128 Add<L, R>::eval() const noexcept
vf4 Add<L, R>::eval() const noexcept
{
return _mm_add_ps(_l.eval(), _r.eval());
return detail::add(_l.eval(), _r.eval());
}
template<vec_expr L, vec_expr R>
[[nodiscard]] TNVX_INLINE
Add<L, R> operator+(const L& l, const R& r) noexcept
Add<L, R> operator+(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
{
return { l, r };
}

View File

@ -11,7 +11,7 @@ namespace tnvx
template<typename T>
concept expression = requires (T t)
{
{ t.eval() } -> std::same_as<__m128>;
{ t.eval() } -> std::same_as<vf4>;
{ t.self() } -> std::same_as<const T&>;
}
&& std::is_base_of_v<Expr<T>, T>;

View File

@ -0,0 +1,3 @@
#pragma once
#define HAS_SSE42 1

View File

@ -0,0 +1,88 @@
#pragma once
#include "config.h"
#include "defines.h"
#if defined(HAS_SSE42)
#include <smmintrin.h>
using vf4 = __m128;
#else
#endif
namespace tnvx::detail
{
[[nodiscard]] TNVX_INLINE
bool eq(vf4 a, vf4 b)
{
return _mm_movemask_ps(_mm_cmpeq_ps(a, b)) == 0b1111;
}
[[nodiscard]] TNVX_INLINE
bool approx_eq(vf4 a, vf4 b, float eps) noexcept
{
vf4 abs_diff = _mm_andnot_ps(_mm_set1_ps(-0.0f), _mm_sub_ps(a, b));
return _mm_movemask_ps(_mm_cmple_ps(abs_diff, _mm_set1_ps(eps))) == 0b1111;
}
[[nodiscard]] TNVX_INLINE
vf4 scalar(float value) noexcept
{
return _mm_set_ps1(value);
}
[[nodiscard]] TNVX_INLINE
vf4 add(vf4 l, vf4 r) noexcept
{
return _mm_add_ps(l, r);
}
[[nodiscard]] TNVX_INLINE
vf4 sub(vf4 l, vf4 r) noexcept
{
return _mm_sub_ps(l, r);
}
[[nodiscard]] TNVX_INLINE
vf4 mul(vf4 l, vf4 r) noexcept
{
return _mm_mul_ps(l, r);
}
[[nodiscard]] TNVX_INLINE
vf4 div(vf4 l, vf4 r) noexcept
{
return _mm_div_ps(l, r);
}
[[nodiscard]] TNVX_INLINE
vf4 dot3(vf4 l, vf4 r) noexcept
{
return _mm_dp_ps(l, r, 0b01111111);
}
[[nodiscard]] TNVX_INLINE
vf4 magnitude3(vf4 v) noexcept
{
return _mm_sqrt_ps(_mm_dp_ps(v, v, 0b01111111));
}
[[nodiscard]] TNVX_INLINE
vf4 norm3(vf4 v) noexcept
{
return _mm_blend_ps(_mm_div_ps(v, magnitude3(v)), v, 0b1000);
}
[[nodiscard]] TNVX_INLINE
vf4 cross3(vf4 l, vf4 r) noexcept
{
vf4 a_yzx = _mm_shuffle_ps(l, l, _MM_SHUFFLE(3, 0, 2, 1));
vf4 b_yzx = _mm_shuffle_ps(r, r, _MM_SHUFFLE(3, 0, 2, 1));
vf4 t = _mm_sub_ps(_mm_mul_ps(l, b_yzx),
_mm_mul_ps(a_yzx, r));
return _mm_shuffle_ps(t, t, _MM_SHUFFLE(3, 0, 2, 1));
}
}

View File

@ -0,0 +1,33 @@
#pragma once
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
namespace tnvx
{
template<vec_expr L, vec_expr R>
struct Cross3 : Expr<Cross3<L, R>>
{
TNVX_INLINE
Cross3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
[[nodiscard]] TNVX_INLINE
vf4 eval() const noexcept;
private:
tnvx_ref_or_value_t<L> _l;
tnvx_ref_or_value_t<R> _r;
};
template<vec_expr L, vec_expr R>
[[nodiscard]] TNVX_INLINE
Cross3<L, R> cross3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
template<vec_expr L, vec_expr R> inline constexpr bool is_vec_expr<Cross3<L, R>> = true;
}
#include "cross3_impl.hpp"

View File

@ -0,0 +1,30 @@
#pragma once
#include "cross3.h"
namespace tnvx
{
template<vec_expr L, vec_expr R>
TNVX_INLINE
Cross3<L, R>::Cross3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
: _l(l)
, _r(r)
{
}
template<vec_expr L, vec_expr R>
TNVX_INLINE
vf4 Cross3<L, R>::eval() const noexcept
{
return detail::cross3(_l.eval(), _r.eval());
}
template<vec_expr L, vec_expr R>
TNVX_INLINE
Cross3<L, R> cross3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
{
return { l, r };
}
}

View File

@ -9,4 +9,4 @@
#else
#define TNVX_INLINE inline
#define TNVX_RESTRICT
#endif
#endif

View File

@ -0,0 +1,35 @@
#pragma once
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
#include "scalar.h"
namespace tnvx
{
template<vec_expr L, scalar_expr R>
struct Div : Expr<Div<L, R>>
{
TNVX_INLINE
Div(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
[[nodiscard]] TNVX_INLINE
vf4 eval() const noexcept;
private:
tnvx_ref_or_value_t<L> _l;
tnvx_ref_or_value_t<R> _r;
};
template<vec_expr E>
[[nodiscard]] TNVX_INLINE
Div<E, Scalar> operator/(const E& TNVX_RESTRICT l, float r) noexcept;
template<vec_expr L, scalar_expr R> inline constexpr bool is_vec_expr<Div<L, R>> = true;
}
#include "div_impl.hpp"

View File

@ -0,0 +1,30 @@
#pragma once
#include "div.h"
namespace tnvx
{
template<vec_expr L, scalar_expr R>
TNVX_INLINE
tnvx::Div<L, R>::Div(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
: _l(l)
, _r(r)
{
}
template<vec_expr L, scalar_expr R>
TNVX_INLINE
vf4 Div<L, R>::eval() const noexcept
{
return detail::div(_l.eval(), _r.eval());
}
template<vec_expr E>
TNVX_INLINE
Div<E, Scalar> operator/(const E& TNVX_RESTRICT l, float r) noexcept
{
return { l, Scalar(r) };
}
}

View File

@ -0,0 +1,36 @@
#pragma once
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
namespace tnvx
{
template<vec_expr L, vec_expr R>
struct Dot3 : Expr<Dot3<L, R>>
{
TNVX_INLINE
Dot3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
[[nodiscard]] TNVX_INLINE
vf4 eval() const noexcept;
[[nodiscard]] TNVX_INLINE
operator float() const noexcept;
private:
tnvx_ref_or_value_t<L> _l;
tnvx_ref_or_value_t<R> _r;
};
template<vec_expr L, vec_expr R>
[[nodiscard]] TNVX_INLINE
Dot3<L, R> dot3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
template<vec_expr L, vec_expr R> inline constexpr bool is_scalar_expr<Dot3<L, R>> = true;
}
#include "dot3_impl.h"

View File

@ -0,0 +1,37 @@
#pragma once
#include "dot3.h"
namespace tnvx
{
template<vec_expr L, vec_expr R>
TNVX_INLINE
Dot3<L, R>::Dot3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
: _l(l)
, _r(r)
{
}
template<vec_expr L, vec_expr R>
TNVX_INLINE
vf4 Dot3<L, R>::eval() const noexcept
{
return detail::dot3(_l.eval(), _r.eval());
}
template<vec_expr L, vec_expr R>
TNVX_INLINE
Dot3<L, R>::operator float() const noexcept
{
return _mm_cvtss_f32(eval());
}
template<vec_expr L, vec_expr R>
TNVX_INLINE
Dot3<L, R> dot3(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
{
return { l, r };
}
}

View File

@ -1,8 +1,6 @@
#pragma once
#include "defines.h"
#include <immintrin.h>
#include "core.h"
namespace tnvx
{

View File

@ -0,0 +1,35 @@
#pragma once
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
namespace tnvx
{
template<vec_expr E>
struct Magn3 : Expr<Magn3<E>>
{
TNVX_INLINE
explicit Magn3(const E& TNVX_RESTRICT e) noexcept;
[[nodiscard]] TNVX_INLINE
vf4 eval() const noexcept;
[[nodiscard]] TNVX_INLINE
operator float() const noexcept;
private:
tnvx_ref_or_value_t<E> _e;
};
template<vec_expr E>
TNVX_INLINE
Magn3<E> magnitude3(const E& TNVX_RESTRICT e) noexcept;
template<vec_expr E> inline constexpr bool is_scalar_expr<Magn3<E>> = true;
}
#include "magnitude3_impl.hpp"

View File

@ -0,0 +1,37 @@
#pragma once
#include "magnitude3.h"
#include "dot3.h"
namespace tnvx
{
template<vec_expr E>
TNVX_INLINE
Magn3<E>::Magn3(const E& TNVX_RESTRICT e) noexcept
: _e(e)
{
}
template<vec_expr E>
TNVX_INLINE
vf4 Magn3<E>::eval() const noexcept
{
return detail::magnitude3(_e.eval());
}
template<vec_expr E>
TNVX_INLINE
Magn3<E>::operator float() const noexcept
{
return _mm_cvtss_f32(eval());
}
template<vec_expr E>
TNVX_INLINE
Magn3<E> magnitude3(const E& TNVX_RESTRICT e) noexcept
{
return Magn3<E>(e);
}
}

View File

@ -1,14 +1,12 @@
#pragma once
#include "defines.h"
#include "traits.h"
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
#include "scalar.h"
#include <immintrin.h>
namespace tnvx
{
@ -16,10 +14,10 @@ template<expression L, expression R>
struct Mul : Expr<Mul<L, R>>
{
TNVX_INLINE
Mul(const L& l, const R& r) noexcept;
Mul(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
[[nodiscard]] TNVX_INLINE
__m128 eval() const noexcept;
vf4 eval() const noexcept;
private:
tnvx_ref_or_value_t<L> _l;
@ -28,15 +26,15 @@ private:
template<vec_expr E>
[[nodiscard]] TNVX_INLINE
Mul<E, Scalar> operator*(const E& l, float r) noexcept;
Mul<E, Scalar> operator*(const E& TNVX_RESTRICT l, float r) noexcept;
template<vec_expr E>
[[nodiscard]] TNVX_INLINE
Mul<Scalar, E> operator*(float l, const E& r) noexcept;
Mul<Scalar, E> operator*(float l, const E& TNVX_RESTRICT r) noexcept;
template<scalar_expr L, scalar_expr R>
[[nodiscard]] TNVX_INLINE
Mul<L, R> operator*(const L& l, const R& r) noexcept;
Mul<L, R> operator*(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
template<vec_expr L, scalar_expr R> inline constexpr bool is_vec_expr<Mul<L, R>> = true;
template<scalar_expr L, vec_expr R> inline constexpr bool is_vec_expr<Mul<L, R>> = true;

View File

@ -7,7 +7,7 @@ namespace tnvx
template<expression L, expression R>
TNVX_INLINE
Mul<L, R>::Mul(const L& l, const R& r) noexcept
Mul<L, R>::Mul(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
: _l(l)
, _r(r)
{
@ -15,28 +15,28 @@ Mul<L, R>::Mul(const L& l, const R& r) noexcept
template<expression L, expression R>
TNVX_INLINE
__m128 Mul<L, R>::eval() const noexcept
vf4 Mul<L, R>::eval() const noexcept
{
return _mm_mul_ps(_l.eval(), _r.eval());
}
template<vec_expr E>
TNVX_INLINE
Mul<E, Scalar> operator*(const E& l, float r) noexcept
Mul<E, Scalar> operator*(const E& TNVX_RESTRICT l, float r) noexcept
{
return { l, Scalar(r) };
}
template<vec_expr E>
TNVX_INLINE
Mul<Scalar, E> operator*(float l, const E& r) noexcept
Mul<Scalar, E> operator*(float l, const E& TNVX_RESTRICT r) noexcept
{
return { Scalar(l), r };
}
template<scalar_expr L, scalar_expr R>
TNVX_INLINE
Mul<L, R> operator*(const L& l, const R& r) noexcept
Mul<L, R> operator*(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
{
return { l, r };
}

View File

@ -0,0 +1,31 @@
#pragma once
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
namespace tnvx
{
template<vec_expr E>
struct Norm3 : Expr<Norm3<E>>
{
TNVX_INLINE
explicit Norm3(const E& TNVX_RESTRICT e) noexcept;
[[nodiscard]] TNVX_INLINE
vf4 eval() const noexcept;
private:
tnvx_ref_or_value_t<E> _e;
};
template<vec_expr E>
[[nodiscard]] TNVX_INLINE
Norm3<E> norm3(const E& TNVX_RESTRICT e) noexcept;
template<vec_expr E> inline constexpr bool is_vec_expr<Norm3<E>> = true;
}
#include "norm3_impl.hpp"

View File

@ -0,0 +1,29 @@
#pragma once
#include "norm3.h"
namespace tnvx
{
template<vec_expr E>
TNVX_INLINE
Norm3<E>::Norm3(const E& TNVX_RESTRICT e) noexcept
: _e(e)
{
}
template<vec_expr E>
TNVX_INLINE
vf4 Norm3<E>::eval() const noexcept
{
return detail::norm3(_e.eval());
}
template<vec_expr E>
TNVX_INLINE
Norm3<E> norm3(const E& TNVX_RESTRICT e) noexcept
{
return Norm3<E>(e);
}
}

View File

@ -1,12 +1,10 @@
#pragma once
#include "defines.h"
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
#include <immintrin.h>
namespace tnvx
{
@ -16,10 +14,10 @@ struct Scalar : Expr<Scalar>
explicit Scalar(float value) noexcept;
[[nodiscard]] TNVX_INLINE
__m128 eval() const noexcept;
vf4 eval() const noexcept;
private:
__m128 _value;
vf4 _value;
};
template<>

View File

@ -8,11 +8,11 @@ namespace tnvx
TNVX_INLINE
Scalar::Scalar(float value) noexcept
{
_value = _mm_set1_ps(value);
_value = detail::scalar(value);
}
TNVX_INLINE
__m128 Scalar::eval() const noexcept
vf4 Scalar::eval() const noexcept
{
return _value;
}

View File

@ -1,12 +1,10 @@
#pragma once
#include "defines.h"
#include "core.h"
#include "expression.h"
#include "concepts.h"
#include "traits.h"
#include <immintrin.h>
namespace tnvx
{
@ -17,7 +15,7 @@ struct Sub : Expr<Sub<L, R>>
Sub(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
[[nodiscard]] TNVX_INLINE
__m128 eval() const noexcept;
vf4 eval() const noexcept;
private:
tnvx_ref_or_value_t<L> _l;
@ -26,10 +24,9 @@ private:
template<vec_expr L, vec_expr R>
[[nodiscard]] TNVX_INLINE
Sub<L, R> operator-(const L& l, const R& r) noexcept;
Sub<L, R> operator-(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept;
template<vec_expr L, vec_expr R>
inline constexpr bool is_vec_expr<Sub<L, R>> = true;
template<vec_expr L, vec_expr R> inline constexpr bool is_vec_expr<Sub<L, R>> = true;
}

View File

@ -15,14 +15,14 @@ Sub<L, R>::Sub(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
template<vec_expr L, vec_expr R>
TNVX_INLINE
__m128 Sub<L, R>::eval() const noexcept
vf4 Sub<L, R>::eval() const noexcept
{
return _mm_sub_ps(_l.eval(), _r.eval());
return detail::sub(_l.eval(), _r.eval());
}
template<vec_expr L, vec_expr R>
TNVX_INLINE
Sub<L, R> operator-(const L& l, const R& r) noexcept
Sub<L, R> operator-(const L& TNVX_RESTRICT l, const R& TNVX_RESTRICT r) noexcept
{
return { l, r };
}

View File

@ -1,12 +1,10 @@
#pragma once
#include "defines.h"
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
#include <immintrin.h>
namespace tnvx
{
@ -20,17 +18,16 @@ struct alignas(16) vec4 : Expr<vec4>
template<vec_expr E>
TNVX_INLINE
vec4(const E& e) noexcept;
vec4(const E& TNVX_RESTRICT e) noexcept;
[[nodiscaed]] TNVX_INLINE
__m128 eval() const noexcept;
[[nodiscard]] TNVX_INLINE
vf4 eval() const noexcept;
private:
__m128 _data;
vf4 _data;
};
template<>
inline constexpr bool is_vec_expr<vec4> = true;
template<> inline constexpr bool is_vec_expr<vec4> = true;
TNVX_INLINE
bool approx_eq(const vec4& lhs, const vec4& rhs, float eps = 1e-6f) noexcept;
@ -39,3 +36,5 @@ TNVX_INLINE
bool operator==(const vec4& lhs, const vec4& rhs) noexcept;
}
#include "vec4_impl.hpp"

View File

@ -1 +1,39 @@

#pragma once
#include "vec4.h"
namespace tnvx
{
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;
}
template<vec_expr E>
TNVX_INLINE
vec4::vec4(const E& TNVX_RESTRICT e) noexcept
: _data(e.eval())
{
}
TNVX_INLINE
bool approx_eq(const vec4& lhs, const vec4& rhs, float eps) noexcept
{
return detail::approx_eq(lhs.eval(), rhs.eval(), eps);
}
TNVX_INLINE
bool tnvx::operator==(const vec4& lhs, const vec4& rhs) noexcept
{
return detail::eq(lhs.eval(), rhs.eval());
}
}

View File

@ -1,11 +1,12 @@
#pragma once
#include "expressions/defines.h"
#include "expressions/traits.h"
#include "expressions/expression.h"
#include "expressions/concepts.h"
#include "expressions/add.h"
#include "expressions/sub.h"
#include "expressions/scalar.h"
#include "expressions/mul.h"
#include "expressions/div.h"
#include "expressions/dot3.h"
#include "expressions/magnitude3.h"
#include "expressions/norm3.h"
#include "expressions/cross3.h"
#include "expressions/vec4.h"

View File

@ -45,12 +45,21 @@ TEST(vec4, mult_b)
EXPECT_TRUE(approx_eq(check, result));
}
TEST(vec4, dot)
TEST(vec4, div)
{
vec4 a = { 1.0f, 0.0f, 3.0f, 0.0f };
vec4 b = { 1.0f, 2.0f, 3.0f, 1.0f };
vec4 a = { 3.0f, 6.0f, 0.0f, 0.0f };
float b = 3.0f;
vec4 check = { 1.0f, 2.0f, 0.0f, 0.0f };
vec4 result = a / b;
EXPECT_TRUE(approx_eq(check, result));
}
TEST(vec4, dot3)
{
vec4 a = { 1.0f, 0.0f, 3.0f, 1.0f };
vec4 b = { 1.0f, 2.0f, 3.0f, 4.0f };
float check = 10.0f;
float result = dot(a, b);
float result = dot3(a, b);
EXPECT_FLOAT_EQ(check, result);
}
@ -60,25 +69,25 @@ TEST(vec4, cross)
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 b = { 0.0f, 1.0f, 0.0f, 0.0f };
vec4 check = { 0.0f, 0.0f, 1.0f, 0.0f };
vec4 result = cross(a, b);
vec4 result = cross3(a, b);
EXPECT_TRUE(approx_eq(check, result));
}
TEST(vec4, norm_a)
{
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 check = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 result = norm(a);
vec4 a = { 1.0f, 0.0f, 0.0f, 1.0f };
vec4 check = { 1.0f, 0.0f, 0.0f, 1.0f };
vec4 result = norm3(a);
EXPECT_TRUE(approx_eq(check, result));
}
TEST(vec4, norm_b)
{
vec4 a = { 1.0f, 0.0f, 1.0f, 0.0f };
vec4 check = { 0.707106f, 0.0f, 0.707106f, 0.0f };
vec4 result = norm(a);
vec4 a = { 1.0f, 0.0f, 1.0f, 1.0f };
vec4 check = { 0.707106f, 0.0f, 0.707106f, 1.0f };
vec4 result = norm3(a);
EXPECT_TRUE(approx_eq(check, result));
}
@ -87,7 +96,7 @@ TEST(vec4, magnitude_a)
{
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
float check = 1.0f;
float result = magnitude(a);
float result = magnitude3(a);
EXPECT_FLOAT_EQ(check, result);
}
@ -96,20 +105,20 @@ TEST(vec4, magnitude_b)
{
vec4 a = { 1.0f, 0.0f, 1.0f, 0.0f };
float check = 1.4142135f;
float result = magnitude(a);
float result = magnitude3(a);
EXPECT_FLOAT_EQ(check, result);
}
TEST(vec4, expression_a)
{
vec4 a = { 1.0f, 1.0f, 1.0f, 0.0f };
vec4 b = { 0.0f, 1.0f, 0.0f, 0.0f };
vec4 a = { 1.0f, 1.0f, 1.0f, 1.0f };
vec4 b = { 0.0f, 1.0f, 0.0f, 3.0f };
vec4 c = { 1.15f, 0.0f, 11.0f, 0.0f };
vec4 check = { 3.45f, 0.0f, 33.0f, 0.0f };
vec4 result = dot(a, b) * 3.0f * c;
vec4 result = dot3(a, b) * 3.0f * c;
EXPECT_TRUE(approx_eq(check, result));
}
@ -122,7 +131,7 @@ TEST(vec4, expression_b)
vec4 check = { 33.0f, 0.0f, -3.45f, 0.0f };
vec4 result = dot(a, b) * 3.0f * cross(b, c);
vec4 result = dot3(a, b) * 3.0f * cross3(b, c);
EXPECT_TRUE(approx_eq(check, result));
}
@ -133,22 +142,12 @@ TEST(vec4, expression_c)
vec4 b = { 4.0f, 5.0f, 6.0f, 0.0f };
vec4 c = { 1.0f, 0.0f, 1.0f, 0.0f };
vec4 check = { 7.243f, 5.657f, 10.071f, 0.0f };
vec4 check = { 7.24264050f, 5.65685463f, 10.0710678f, 0.0f };
vec4 result = norm(a + b * 2.0f) * dot(b, c) + c * 3.0f;
vec4 tmp1 = norm3(a + b * 2.0f) * dot3(b, c);
vec4 tmp2 = c * 3.0f;
EXPECT_TRUE(approx_eq(check, result));
}
TEST(vec4, expression_d)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 0.0f };
vec4 b = { 4.0f, 5.0f, 6.0f, 0.0f };
vec4 c = { 1.0f, 0.0f, 1.0f, 0.0f };
vec4 check = { 7.243f, 5.657f, 10.071f, 0.0f };
vec4 result = magnitude(a) * dot(b, c) + c * 3.0f;
vec4 result = tmp1 + tmp2;
EXPECT_TRUE(approx_eq(check, result));
}
@ -157,27 +156,27 @@ TEST(vec4, cross_anticommutative)
{
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 b = { 0.0f, 1.0f, 0.0f, 0.0f };
EXPECT_TRUE(approx_eq(cross(a, b), cross(b, a) * -1.0f));
EXPECT_TRUE(approx_eq(cross3(a, b), cross3(b, a) * -1.0f));
}
TEST(vec4, dot_commutative)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 0.0f };
vec4 b = { 4.0f, 5.0f, 6.0f, 0.0f };
EXPECT_FLOAT_EQ(dot(a, b), dot(b, a));
EXPECT_FLOAT_EQ(dot3(a, b), dot3(b, a));
}
TEST(vec4, norm_magnitude)
{
vec4 a = { 3.0f, 1.0f, 4.0f, 0.0f };
EXPECT_NEAR(magnitude(norm(a)), 1.0f, 1e-5f);
EXPECT_NEAR(magnitude3(norm3(a)), 1.0f, 1e-5f);
}
TEST(vec4, dot_perpendicular)
{
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 b = { 0.0f, 1.0f, 0.0f, 0.0f };
EXPECT_FLOAT_EQ(dot(a, b), 0.0f);
EXPECT_FLOAT_EQ(dot3(a, b), 0.0f);
}
TEST(vec4, cross_parallel)
@ -185,7 +184,7 @@ TEST(vec4, cross_parallel)
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 b = { 2.0f, 0.0f, 0.0f, 0.0f };
vec4 check = { 0.0f, 0.0f, 0.0f, 0.0f };
EXPECT_TRUE(approx_eq(cross(a, b), check));
EXPECT_TRUE(approx_eq(cross3(a, b), check));
}
}