Add naive implementation and test/benchmark
This commit is contained in:
parent
7960ad6cf6
commit
28e60f22e6
93
premake5.lua
93
premake5.lua
@ -44,50 +44,6 @@ project "gtest"
|
|||||||
filter "system:macosx"
|
filter "system:macosx"
|
||||||
pic "on"
|
pic "on"
|
||||||
|
|
||||||
project "benchmark"
|
|
||||||
location "build"
|
|
||||||
kind "StaticLib"
|
|
||||||
language "C++"
|
|
||||||
cppdialect "C++20"
|
|
||||||
staticruntime "on"
|
|
||||||
|
|
||||||
targetdir ("bin/" .. outputdir .. "/output")
|
|
||||||
objdir ("bin/" .. outputdir .. "/intermediate")
|
|
||||||
|
|
||||||
files {
|
|
||||||
"thirdparty/benchmark/src/**.cc",
|
|
||||||
}
|
|
||||||
|
|
||||||
removefiles {
|
|
||||||
"thirdparty/benchmark/src/benchmark_main.cc",
|
|
||||||
}
|
|
||||||
|
|
||||||
includedirs {
|
|
||||||
"thirdparty/benchmark/include",
|
|
||||||
"thirdparty/benchmark/src",
|
|
||||||
}
|
|
||||||
|
|
||||||
defines { "BENCHMARK_STATIC_DEFINE", "HAVE_STD_REGEX" }
|
|
||||||
|
|
||||||
filter "configurations:debug"
|
|
||||||
runtime "Debug"
|
|
||||||
symbols "on"
|
|
||||||
optimize "off"
|
|
||||||
|
|
||||||
filter "configurations:release"
|
|
||||||
runtime "Release"
|
|
||||||
symbols "on"
|
|
||||||
optimize "Speed"
|
|
||||||
|
|
||||||
filter "system:windows"
|
|
||||||
systemversion "latest"
|
|
||||||
|
|
||||||
filter "system:linux"
|
|
||||||
pic "on"
|
|
||||||
|
|
||||||
filter "system:macosx"
|
|
||||||
pic "on"
|
|
||||||
|
|
||||||
project "gtest_main"
|
project "gtest_main"
|
||||||
location "build"
|
location "build"
|
||||||
kind "StaticLib"
|
kind "StaticLib"
|
||||||
@ -120,6 +76,51 @@ project "gtest_main"
|
|||||||
filter "system:windows"
|
filter "system:windows"
|
||||||
systemversion "latest"
|
systemversion "latest"
|
||||||
|
|
||||||
|
project "benchmark"
|
||||||
|
location "build"
|
||||||
|
kind "StaticLib"
|
||||||
|
language "C++"
|
||||||
|
cppdialect "C++20"
|
||||||
|
staticruntime "on"
|
||||||
|
|
||||||
|
targetdir ("bin/" .. outputdir .. "/output")
|
||||||
|
objdir ("bin/" .. outputdir .. "/intermediate")
|
||||||
|
|
||||||
|
files {
|
||||||
|
"thirdparty/benchmark/src/**.cc",
|
||||||
|
}
|
||||||
|
|
||||||
|
removefiles {
|
||||||
|
"thirdparty/benchmark/src/benchmark_main.cc",
|
||||||
|
}
|
||||||
|
|
||||||
|
includedirs {
|
||||||
|
"thirdparty/benchmark/include",
|
||||||
|
"thirdparty/benchmark/src",
|
||||||
|
}
|
||||||
|
|
||||||
|
defines { "BENCHMARK_STATIC_DEFINE", "HAVE_STD_REGEX" }
|
||||||
|
|
||||||
|
filter "configurations:debug"
|
||||||
|
runtime "Debug"
|
||||||
|
symbols "on"
|
||||||
|
optimize "off"
|
||||||
|
|
||||||
|
filter "configurations:release"
|
||||||
|
defines { "NDEBUG" }
|
||||||
|
runtime "Release"
|
||||||
|
symbols "on"
|
||||||
|
optimize "Speed"
|
||||||
|
|
||||||
|
filter "system:windows"
|
||||||
|
systemversion "latest"
|
||||||
|
|
||||||
|
filter "system:linux"
|
||||||
|
pic "on"
|
||||||
|
|
||||||
|
filter "system:macosx"
|
||||||
|
pic "on"
|
||||||
|
|
||||||
project "tenvex"
|
project "tenvex"
|
||||||
location "build"
|
location "build"
|
||||||
kind "None"
|
kind "None"
|
||||||
@ -176,6 +177,7 @@ project "tenvex_tests"
|
|||||||
|
|
||||||
includedirs {
|
includedirs {
|
||||||
"src/tenvex",
|
"src/tenvex",
|
||||||
|
"src/naive",
|
||||||
"thirdparty/gtest/googletest/include",
|
"thirdparty/gtest/googletest/include",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +224,7 @@ project "tenvex_bench"
|
|||||||
}
|
}
|
||||||
|
|
||||||
includedirs {
|
includedirs {
|
||||||
|
"src/naive",
|
||||||
"src/tenvex",
|
"src/tenvex",
|
||||||
"thirdparty/benchmark/include",
|
"thirdparty/benchmark/include",
|
||||||
}
|
}
|
||||||
@ -240,7 +243,7 @@ project "tenvex_bench"
|
|||||||
runtime "Release"
|
runtime "Release"
|
||||||
symbols "on"
|
symbols "on"
|
||||||
optimize "Speed"
|
optimize "Speed"
|
||||||
defines { "TENVEX_RELEASE" }
|
defines { "TENVEX_RELEASE", "NDEBUG" }
|
||||||
|
|
||||||
filter "system:windows"
|
filter "system:windows"
|
||||||
systemversion "latest"
|
systemversion "latest"
|
||||||
|
|||||||
92
src/benchmarks/bench_naive.cpp
Normal file
92
src/benchmarks/bench_naive.cpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#include "naive_vec4.h"
|
||||||
|
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
using namespace naive;
|
||||||
|
|
||||||
|
// File-local; mirrors make_vecs from bench_vec4.cpp with the same seed,
|
||||||
|
// so the naive and tenvex benchmarks run on identical input data.
|
||||||
|
static std::vector<vec4> make_vecs(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), 0.0f });
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void BM_Naive_Dot3_Latency(benchmark::State& state)
|
||||||
|
{
|
||||||
|
vec4 a { 1.0f, 2.0f, 3.0f, 0.0f };
|
||||||
|
vec4 b { 0.5f, 0.5f, 0.5f, 0.0f };
|
||||||
|
float acc = 0.0f;
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
vec4 bb = b + vec4 { acc, 0.0f, 0.0f, 0.0f };
|
||||||
|
float d = dot3(a, bb);
|
||||||
|
acc = d * 1e-7f;
|
||||||
|
benchmark::DoNotOptimize(acc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Naive_Dot3_Latency);
|
||||||
|
|
||||||
|
static void BM_Naive_Norm3_Latency(benchmark::State& state)
|
||||||
|
{
|
||||||
|
vec4 v { 1.0f, 2.0f, 3.0f, 1.0f };
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
v = norm3(v) + vec4 { 1e-3f, 2e-3f, 3e-3f, 0.0f };
|
||||||
|
benchmark::DoNotOptimize(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Naive_Norm3_Latency);
|
||||||
|
|
||||||
|
static void BM_Naive_Dot3_Throughput(benchmark::State& state)
|
||||||
|
{
|
||||||
|
const auto a = make_vecs(1024, 1);
|
||||||
|
const auto b = make_vecs(1024, 2);
|
||||||
|
std::size_t i = 0;
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
float d = dot3(a[i], b[i]);
|
||||||
|
benchmark::DoNotOptimize(d);
|
||||||
|
i = (i + 1) & 1023;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Naive_Dot3_Throughput);
|
||||||
|
|
||||||
|
static void BM_Naive_Compound(benchmark::State& state)
|
||||||
|
{
|
||||||
|
const auto va = make_vecs(1024, 1);
|
||||||
|
const auto vb = make_vecs(1024, 2);
|
||||||
|
const auto vc = make_vecs(1024, 3);
|
||||||
|
std::size_t i = 0;
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
vec4 r = norm3(va[i] + vb[i] * 2.0f) * dot3(vb[i], vc[i]) + vc[i] * 3.0f;
|
||||||
|
benchmark::DoNotOptimize(r);
|
||||||
|
i = (i + 1) & 1023;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Naive_Compound);
|
||||||
|
|
||||||
|
static void BM_Naive_FacingSameWay(benchmark::State& state)
|
||||||
|
{
|
||||||
|
vec4 fa = norm3(vec4 { 1.0f, 0.0f, 0.2f, 0.0f });
|
||||||
|
vec4 fb = vec4 { 0.9f, 0.1f, 0.1f, 0.0f };
|
||||||
|
float jitter = 0.0f;
|
||||||
|
for (auto _ : state)
|
||||||
|
{
|
||||||
|
vec4 f = norm3(fb + vec4 { jitter, 0.0f, 0.0f, 0.0f });
|
||||||
|
float c = dot3(fa, f);
|
||||||
|
bool same = c > 0.95f;
|
||||||
|
jitter = c * 1e-6f;
|
||||||
|
benchmark::DoNotOptimize(same);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BENCHMARK(BM_Naive_FacingSameWay);
|
||||||
92
src/naive/naive_vec4.h
Normal file
92
src/naive/naive_vec4.h
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace naive
|
||||||
|
{
|
||||||
|
|
||||||
|
struct vec4
|
||||||
|
{
|
||||||
|
vec4() noexcept = default;
|
||||||
|
|
||||||
|
vec4(float x, float y, float z, float w = 0.0f) noexcept
|
||||||
|
: _x(x), _y(y), _z(z), _w(w)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] float x() const noexcept { return _x; }
|
||||||
|
[[nodiscard]] float y() const noexcept { return _y; }
|
||||||
|
[[nodiscard]] float z() const noexcept { return _z; }
|
||||||
|
[[nodiscard]] float w() const noexcept { return _w; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _x, _y, _z, _w;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] inline vec4 operator+(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 operator-(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 operator*(vec4 v, float s) noexcept
|
||||||
|
{
|
||||||
|
return { v.x() * s, v.y() * s, v.z() * s, v.w() * s };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline vec4 operator*(float s, vec4 v) noexcept
|
||||||
|
{
|
||||||
|
return v * s;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline vec4 operator/(vec4 v, float s) noexcept
|
||||||
|
{
|
||||||
|
const float inv = 1.0f / s; // one division, then multiplies
|
||||||
|
return { v.x() * inv, v.y() * inv, v.z() * inv, v.w() * inv };
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline float dot3(vec4 a, vec4 b) noexcept
|
||||||
|
{
|
||||||
|
return a.x() * b.x() + a.y() * b.y() + a.z() * b.z();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline vec4 cross3(vec4 a, vec4 b) noexcept
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
a.y() * b.z() - a.z() * b.y(),
|
||||||
|
a.z() * b.x() - a.x() * b.z(),
|
||||||
|
a.x() * b.y() - a.y() * b.x(),
|
||||||
|
0.0f
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline float magnitude3(vec4 v) noexcept
|
||||||
|
{
|
||||||
|
return std::sqrt(dot3(v, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] inline vec4 norm3(vec4 v) noexcept
|
||||||
|
{
|
||||||
|
const float inv = 1.0f / magnitude3(v); // normalize xyz, keep w
|
||||||
|
return { v.x() * inv, v.y() * inv, v.z() * inv, v.w() };
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(vec4 a, vec4 b) noexcept
|
||||||
|
{
|
||||||
|
return a.x() == b.x() && a.y() == b.y()
|
||||||
|
&& a.z() == b.z() && a.w() == b.w();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool approx_eq(vec4 a, vec4 b, float eps = 1e-6f) noexcept
|
||||||
|
{
|
||||||
|
return std::fabs(a.x() - b.x()) <= eps
|
||||||
|
&& std::fabs(a.y() - b.y()) <= eps
|
||||||
|
&& std::fabs(a.z() - b.z()) <= eps
|
||||||
|
&& std::fabs(a.w() - b.w()) <= eps;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
256
src/tests/naive_tests.cpp
Normal file
256
src/tests/naive_tests.cpp
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
#include "naive_vec4.h"
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace naive
|
||||||
|
{
|
||||||
|
|
||||||
|
TEST(naive_vec4, add)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 2.0f, 3.0f, 4.0f };
|
||||||
|
vec4 b = { 4.0f, 3.0f, 2.0f, 1.0f };
|
||||||
|
vec4 check = { 5.0f, 5.0f, 5.0f, 5.0f };
|
||||||
|
vec4 result = a + b;
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, mixed_type_add)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 2.0f, 3.0f, 0.0f };
|
||||||
|
vec4 b = { 1.0f, 1.0f, 1.0f, 0.0f };
|
||||||
|
vec4 c = { 2.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
vec4 check = { 4.0f, 3.0f, 4.0f, 0.0f };
|
||||||
|
|
||||||
|
vec4 result = a + b + c;
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, sub)
|
||||||
|
{
|
||||||
|
vec4 a = { 5.0f, 5.0f, 5.0f, 5.0f };
|
||||||
|
vec4 b = { 4.0f, 3.0f, 2.0f, 1.0f };
|
||||||
|
vec4 check = { 1.0f, 2.0f, 3.0f, 4.0f };
|
||||||
|
vec4 result = a - b;
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, mult_a)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 2.0f, 0.0f, 0.0f };
|
||||||
|
float b = 3.0f;
|
||||||
|
vec4 check = { 3.0f, 6.0f, 0.0f, 0.0f };
|
||||||
|
vec4 result = a * b;
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, mult_b)
|
||||||
|
{
|
||||||
|
float a = 2.0f;
|
||||||
|
vec4 b = { 1.0f, 0.0f, 2.0f, 0.0f };
|
||||||
|
vec4 check = { 2.0f, 0.0f, 4.0f, 0.0f };
|
||||||
|
vec4 result = a * b;
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, div)
|
||||||
|
{
|
||||||
|
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(naive_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 = dot3(a, b);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(check, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_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 = cross3(a, b);
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, 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(naive_vec4, norm_b)
|
||||||
|
{
|
||||||
|
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, 1e-3f));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, magnitude_a)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
float check = 1.0f;
|
||||||
|
float result = magnitude3(a);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(check, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, magnitude_b)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 0.0f, 1.0f, 0.0f };
|
||||||
|
float check = 1.4142135f;
|
||||||
|
float result = magnitude3(a);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(check, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, expression_a)
|
||||||
|
{
|
||||||
|
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 = dot3(a, b) * 3.0f * c;
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, expression_b)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 1.0f, 1.0f, 0.0f };
|
||||||
|
vec4 b = { 0.0f, 1.0f, 0.0f, 0.0f };
|
||||||
|
vec4 c = { 1.15f, 0.0f, 11.0f, 0.0f };
|
||||||
|
|
||||||
|
vec4 check = { 33.0f, 0.0f, -3.45f, 0.0f };
|
||||||
|
|
||||||
|
vec4 result = dot3(a, b) * 3.0f * cross3(b, c);
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, expression_c)
|
||||||
|
{
|
||||||
|
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.24264050f, 5.65685463f, 10.0710678f, 0.0f };
|
||||||
|
|
||||||
|
vec4 tmp1 = norm3(a + b * 2.0f) * dot3(b, c);
|
||||||
|
vec4 tmp2 = c * 3.0f;
|
||||||
|
|
||||||
|
vec4 result = tmp1 + tmp2;
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result, 1e-3f));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, expression_d)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
vec4 b = { 0.0f, 2.0f, 0.0f, 0.0f };
|
||||||
|
vec4 c = { 0.0f, 0.0f, 3.0f, 0.0f };
|
||||||
|
vec4 result = (a + b) * 2.0f + c - a;
|
||||||
|
vec4 check = { 1.0f, 4.0f, 3.0f, 0.0f };
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, expression_from_temporaries)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 2.0f, 3.0f, 0.0f };
|
||||||
|
vec4 b = { 4.0f, 5.0f, 6.0f, 0.0f };
|
||||||
|
vec4 check = { 2.0f, 4.0f, 6.0f, 0.0f };
|
||||||
|
vec4 result = (a + b) + (a - b);
|
||||||
|
|
||||||
|
EXPECT_TRUE(approx_eq(check, result));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_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(cross3(a, b), cross3(b, a) * -1.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, w_is_zero_with_nonzero_input_w)
|
||||||
|
{
|
||||||
|
vec4 a = { 1.0f, 0.0f, 0.0f, 5.0f };
|
||||||
|
vec4 b = { 0.0f, 1.0f, 0.0f, 7.0f };
|
||||||
|
|
||||||
|
vec4 r = cross3(a, b);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(r.w(), 0.0f);
|
||||||
|
EXPECT_FLOAT_EQ(r.z(), 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, preserves_nontrivial_w)
|
||||||
|
{
|
||||||
|
vec4 a = { 0.0f, 3.0f, 0.0f, 9.0f };
|
||||||
|
vec4 r = norm3(a);
|
||||||
|
|
||||||
|
EXPECT_FLOAT_EQ(r.y(), 1.0f);
|
||||||
|
EXPECT_FLOAT_EQ(r.w(), 9.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_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(dot3(a, b), dot3(b, a));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, norm_magnitude)
|
||||||
|
{
|
||||||
|
vec4 a = { 3.0f, 1.0f, 4.0f, 0.0f };
|
||||||
|
|
||||||
|
EXPECT_NEAR(magnitude3(norm3(a)), 1.0f, 1e-6f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_vec4, zero_vector_is_nan)
|
||||||
|
{
|
||||||
|
vec4 z = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
vec4 r = norm3(z);
|
||||||
|
|
||||||
|
EXPECT_TRUE(std::isnan(r.x()));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_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(dot3(a, b), 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(naive_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(cross3(a, b), check));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user