Compare commits

..

No commits in common. "2010504e84e0db2245b24afac69838d0d85353b2" and "fd917bffba1f746024a0e5401083ae8b6ea5f685" have entirely different histories.

9 changed files with 0 additions and 270 deletions

View File

@ -20,17 +20,6 @@ static std::vector<vec4> make_vecs(int n, unsigned seed)
return v;
}
static std::vector<vec4> make_points(int n, unsigned seed)
{
std::mt19937 rng(seed);
std::uniform_real_distribution<float> d(-1.0f, 1.0f);
std::vector<vec4> v;
v.reserve(n);
for (int i = 0; i < n; ++i)
v.push_back(vec4{ d(rng), d(rng), d(rng), 1.0f });
return v;
}
static void BM_Naive_Dot3_Latency(benchmark::State& state)
{
vec4 a { 1.0f, 2.0f, 3.0f, 0.0f };
@ -101,32 +90,3 @@ static void BM_Naive_FacingSameWay(benchmark::State& state)
}
}
BENCHMARK(BM_Naive_FacingSameWay);
static void BM_Naive_Dot4_Latency(benchmark::State& state)
{
vec4 a{ 1.0f, 2.0f, 3.0f, 1.0f };
vec4 b{ 0.5f, 0.5f, 0.5f, 0.5f };
float acc = 0.0f;
for (auto _ : state)
{
vec4 bb = b + vec4{ acc, 0.0f, 0.0f, 0.0f };
float d = dot4(a, bb);
acc = d * 1e-7f;
benchmark::DoNotOptimize(acc);
}
}
BENCHMARK(BM_Naive_Dot4_Latency);
static void BM_Naive_Dot4_Throughput(benchmark::State& state)
{
const auto a = make_points(1024, 1);
const auto b = make_points(1024, 2);
std::size_t i = 0;
for (auto _ : state)
{
float d = dot4(a[i], b[i]);
benchmark::DoNotOptimize(d);
i = (i + 1) & 1023;
}
}
BENCHMARK(BM_Naive_Dot4_Throughput);

View File

@ -20,17 +20,6 @@ static std::vector<vec4> make_vecs(int n, unsigned seed)
return v;
}
inline std::vector<tnvx::vec4> make_points(int n, unsigned seed)
{
std::mt19937 rng(seed);
std::uniform_real_distribution<float> d(-1.0f, 1.0f);
std::vector<tnvx::vec4> v;
v.reserve(n);
for (int i = 0; i < n; ++i)
v.push_back(tnvx::vec4{ d(rng), d(rng), d(rng), 1.0f }); // w=1: point
return v;
}
// =====================================================================
// LATENCY: each iteration depends on the previous result (serial chain).
// This is the metric for scattered everyday math: the result is needed
@ -144,32 +133,3 @@ static void BM_FacingSameWay(benchmark::State& state)
}
}
BENCHMARK(BM_FacingSameWay);
static void BM_Dot4_Latency(benchmark::State& state)
{
vec4 a{ 1.0f, 2.0f, 3.0f, 1.0f };
vec4 b{ 0.5f, 0.5f, 0.5f, 0.5f };
float acc = 0.0f;
for (auto _ : state)
{
vec4 bb = b + vec4{ acc, 0.0f, 0.0f, 0.0f };
float d = dot4(a, bb);
acc = d * 1e-7f;
benchmark::DoNotOptimize(acc);
}
}
BENCHMARK(BM_Dot4_Latency);
static void BM_Dot4_Throughput(benchmark::State& state)
{
const auto a = make_points(1024, 1);
const auto b = make_points(1024, 2);
std::size_t i = 0;
for (auto _ : state)
{
float d = dot4(a[i], b[i]);
benchmark::DoNotOptimize(d);
i = (i + 1) & 1023;
}
}
BENCHMARK(BM_Dot4_Throughput);

View File

@ -54,11 +54,6 @@ private:
return a.x() * b.x() + a.y() * b.y() + a.z() * b.z();
}
[[nodiscard]] inline float dot4(vec4 a, vec4 b) noexcept
{
return a.x() * b.x() + a.y() * b.y() + a.z() * b.z() + a.w() * b.w();
}
[[nodiscard]] inline vec4 cross3(vec4 a, vec4 b) noexcept
{
return {

View File

@ -87,14 +87,6 @@ vf4 dot3(vf4 l, vf4 r) noexcept
return _mm_shuffle_ps(xyz, xyz, _MM_SHUFFLE(0, 0, 0, 0));
}
[[nodiscard]] TNVX_INLINE
vf4 dot4(vf4 l, vf4 r) noexcept
{
vf4 t = _mm_mul_ps(l, r);
vf4 h = _mm_hadd_ps(t, t);
return _mm_hadd_ps(h, h);
}
[[nodiscard]] TNVX_INLINE
vf4 magnitude3(vf4 v) noexcept
{

View File

@ -1,43 +0,0 @@
#pragma once
#include "core.h"
#include "expression.h"
#include "traits.h"
#include "concepts.h"
namespace tnvx
{
template<vec_expr L, vec_expr R>
struct Dot4 : Expr<Dot4<L, R>>
{
TNVX_INLINE
Dot4(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> inline constexpr bool is_scalar_expr<Dot4<L, R>> = true;
template<vec_expr L, vec_expr R>
[[nodiscard]] TNVX_INLINE
Dot3<L, R> dot4(const L& l, const R& r) noexcept;
template<vec_expr L, vec_expr R>
TNVX_INLINE
Dot3<L, R> dot4(const L& l, const R& r) noexcept
{
return { l, r };
}
}
#include "dot4_impl.hpp"

View File

@ -1,30 +0,0 @@
#pragma once
#include "dot4.h"
namespace tnvx
{
template<vec_expr L, vec_expr R>
TNVX_INLINE
Dot4<L, R>::Dot4(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 Dot4<L, R>::eval() const noexcept
{
return detail::dot4(_l.eval(), _r.eval());
}
template<vec_expr L, vec_expr R>
TNVX_INLINE
Dot4<L, R>::operator float() const noexcept
{
return detail::to_float(eval());
}
}

View File

@ -7,7 +7,6 @@
#include "expressions/mul.h"
#include "expressions/div.h"
#include "expressions/dot3.h"
#include "expressions/dot4.h"
#include "expressions/magnitude3.h"
#include "expressions/norm3.h"
#include "expressions/cross3.h"

View File

@ -283,40 +283,4 @@ TEST(naive_vec4, neg_compound)
EXPECT_TRUE(approx_eq(a + (-b), a - b));
}
TEST(naive_vec4, dot4_basic)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
vec4 b = { 1.0f, 2.0f, 3.0f, 4.0f };
EXPECT_FLOAT_EQ(dot4(a, b), 30.0f);
}
TEST(naive_vec4, dot4_w_matters)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
vec4 b = { 1.0f, 2.0f, 3.0f, 4.0f };
EXPECT_FLOAT_EQ(dot3(a, b), 14.0f);
EXPECT_FLOAT_EQ(dot4(a, b), 30.0f);
}
TEST(naive_vec4, dot4_w_only)
{
vec4 a = { 0.0f, 0.0f, 0.0f, 5.0f };
vec4 b = { 0.0f, 0.0f, 0.0f, 3.0f };
EXPECT_FLOAT_EQ(dot4(a, b), 15.0f);
}
TEST(naive_vec4, dot4_commutative)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
vec4 b = { 4.0f, 3.0f, 2.0f, 1.0f };
EXPECT_FLOAT_EQ(dot4(a, b), dot4(b, a));
}
TEST(naive_vec4, dot4_w_zero_matches_dot3)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 0.0f };
vec4 b = { 4.0f, 5.0f, 6.0f, 0.0f };
EXPECT_FLOAT_EQ(dot4(a, b), dot3(a, b));
}
}

View File

@ -337,71 +337,4 @@ TEST(vec4, neg_scalar_in_expression)
EXPECT_TRUE(approx_eq(check, result));
}
TEST(vec4, dot4_basic)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
vec4 b = { 1.0f, 2.0f, 3.0f, 4.0f };
float check = 30.0f;
float result = dot4(a, b);
EXPECT_FLOAT_EQ(check, result);
}
TEST(vec4, dot4_w_zero_matches_dot3)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 0.0f };
vec4 b = { 4.0f, 5.0f, 6.0f, 0.0f };
EXPECT_FLOAT_EQ(float(dot4(a, b)), float(dot3(a, b)));
}
TEST(vec4, dot4_w_matters)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
vec4 b = { 1.0f, 2.0f, 3.0f, 4.0f };
float check1 = 14.0f;
float result1 = dot3(a, b);
float check2 = 30.0f;
float result2 = dot4(a, b);
EXPECT_FLOAT_EQ(check1, result1);
EXPECT_FLOAT_EQ(check2, result2);
}
TEST(vec4, dot4_w_only)
{
vec4 a = { 0.0f, 0.0f, 0.0f, 5.0f };
vec4 b = { 0.0f, 0.0f, 0.0f, 3.0f };
float check = 15.0f;
float result = dot4(a, b);
EXPECT_FLOAT_EQ(check, result);
}
TEST(vec4, dot4_perpendicular)
{
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 b = { 0.0f, 1.0f, 0.0f, 0.0f };
float check = 0.0f;
float result = dot4(a, b);
EXPECT_FLOAT_EQ(check, result);
}
TEST(vec4, dot4_commutative)
{
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
vec4 b = { 4.0f, 3.0f, 2.0f, 1.0f };
EXPECT_FLOAT_EQ(float(dot4(a, b)), float(dot4(b, a)));
}
TEST(vec4, dot4_collapses)
{
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
vec4 b = { 0.0f, 1.0f, 0.0f, 0.0f };
EXPECT_TRUE((scalar_expr<decltype(dot4(a, b) * 2.0f)>));
}
}