generated from aselimov/cpp_project_template
Update README and add norm calculations to vector
This commit is contained in:
parent
db60954ce4
commit
c9023f2f8b
29
README.md
29
README.md
@ -1,12 +1,21 @@
|
|||||||
# C++ Project Template
|
# Vec3
|
||||||
When setting out on a new project in C++ there are a few configuration steps
|
|
||||||
which need to be completed prior to actually getting down to writing code.
|
|
||||||
This repository is going to be a C++ project template that already has the
|
|
||||||
following components:
|
|
||||||
|
|
||||||
- Directory Structure
|
Simple header only library defining a 3 dimensional vector type.
|
||||||
- Make Build (CMake)
|
|
||||||
- CUDA integration
|
## Installation
|
||||||
- Unit Test Framework (Google Test)
|
|
||||||
- API Documentation (Doxygen)
|
To use from another CMake project you just need to add the following to your CMakeLists.txt:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
include(FetchContent)
|
||||||
|
FetchContent_Declare(Vec3
|
||||||
|
GIT_REPOSITORY https://www.alexselimov.com/git/aselimov/Vec3.git
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_GetProperties(Vec3)
|
||||||
|
if(NOT Vec3_POPULATED)
|
||||||
|
FetchContent_Populate(Vec3)
|
||||||
|
include_directories(${Vec3_SOURCE_DIR}/include)
|
||||||
|
endif()
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#ifndef VEC3_H
|
#ifndef VEC3_H
|
||||||
#define VEC3_H
|
#define VEC3_H
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
template <typename T> struct Vec3 {
|
template <typename T> struct Vec3 {
|
||||||
T x;
|
T x;
|
||||||
T y;
|
T y;
|
||||||
@ -20,14 +21,18 @@ template <typename T> struct Vec3 {
|
|||||||
z *= scalar;
|
z *= scalar;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline T dot(Vec3<T> other) {
|
inline T dot(Vec3<T> other) const {
|
||||||
return x * other.x + y * other.y + z * other.z;
|
return x * other.x + y * other.y + z * other.z;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Vec3<T> cross(Vec3<T> other) {
|
inline Vec3<T> cross(Vec3<T> other) const {
|
||||||
return {y * other.z - z * other.y, z * other.x - x * other.z,
|
return {y * other.z - z * other.y, z * other.x - x * other.z,
|
||||||
x * other.y - y * other.x};
|
x * other.y - y * other.x};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline double squared_norm2() const { return x * x + y * y + z * z; }
|
||||||
|
|
||||||
|
inline double norm2() const { return std::sqrt(squared_norm2()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,173 +7,173 @@
|
|||||||
class Vec3Test : public ::testing::Test {
|
class Vec3Test : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
// Test vectors that will be used across multiple tests
|
// Test vectors that will be used across multiple tests
|
||||||
Vec3<int> intVec1, intVec2;
|
Vec3<int> int_vec1, int_vec2;
|
||||||
Vec3<float> floatVec1, floatVec2;
|
Vec3<float> float_vec1, float_vec2;
|
||||||
Vec3<double> doubleVec1, doubleVec2;
|
Vec3<double> double_vec1, double_vec2;
|
||||||
|
|
||||||
void SetUp() override {
|
void SetUp() override {
|
||||||
// Initialize test vectors
|
// Initialize test vectors
|
||||||
intVec1 = {1, 2, 3};
|
int_vec1 = {1, 2, 3};
|
||||||
intVec2 = {4, 5, 6};
|
int_vec2 = {4, 5, 6};
|
||||||
|
|
||||||
floatVec1 = {1.5f, 2.5f, 3.5f};
|
float_vec1 = {1.5f, 2.5f, 3.5f};
|
||||||
floatVec2 = {4.5f, 5.5f, 6.5f};
|
float_vec2 = {4.5f, 5.5f, 6.5f};
|
||||||
|
|
||||||
doubleVec1 = {1.5, 2.5, 3.5};
|
double_vec1 = {1.5, 2.5, 3.5};
|
||||||
doubleVec2 = {4.5, 5.5, 6.5};
|
double_vec2 = {4.5, 5.5, 6.5};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Test vector addition
|
// Test vector addition
|
||||||
TEST_F(Vec3Test, Addition) {
|
TEST_F(Vec3Test, Addition) {
|
||||||
// Test integer vectors
|
// Test integer vectors
|
||||||
auto intResult = intVec1 + intVec2;
|
auto int_result = int_vec1 + int_vec2;
|
||||||
EXPECT_EQ(intResult.x, 5);
|
EXPECT_EQ(int_result.x, 5);
|
||||||
EXPECT_EQ(intResult.y, 7);
|
EXPECT_EQ(int_result.y, 7);
|
||||||
EXPECT_EQ(intResult.z, 9);
|
EXPECT_EQ(int_result.z, 9);
|
||||||
|
|
||||||
// Test float vectors
|
// Test float vectors
|
||||||
auto floatResult = floatVec1 + floatVec2;
|
auto float_result = float_vec1 + float_vec2;
|
||||||
EXPECT_FLOAT_EQ(floatResult.x, 6.0f);
|
EXPECT_FLOAT_EQ(float_result.x, 6.0f);
|
||||||
EXPECT_FLOAT_EQ(floatResult.y, 8.0f);
|
EXPECT_FLOAT_EQ(float_result.y, 8.0f);
|
||||||
EXPECT_FLOAT_EQ(floatResult.z, 10.0f);
|
EXPECT_FLOAT_EQ(float_result.z, 10.0f);
|
||||||
|
|
||||||
// Test double vectors
|
// Test double vectors
|
||||||
auto doubleResult = doubleVec1 + doubleVec2;
|
auto double_result = double_vec1 + double_vec2;
|
||||||
EXPECT_DOUBLE_EQ(doubleResult.x, 6.0);
|
EXPECT_DOUBLE_EQ(double_result.x, 6.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleResult.y, 8.0);
|
EXPECT_DOUBLE_EQ(double_result.y, 8.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleResult.z, 10.0);
|
EXPECT_DOUBLE_EQ(double_result.z, 10.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test vector subtraction
|
// Test vector subtraction
|
||||||
TEST_F(Vec3Test, Subtraction) {
|
TEST_F(Vec3Test, Subtraction) {
|
||||||
// Test integer vectors
|
// Test integer vectors
|
||||||
auto intResult = intVec2 - intVec1;
|
auto int_result = int_vec2 - int_vec1;
|
||||||
EXPECT_EQ(intResult.x, 3);
|
EXPECT_EQ(int_result.x, 3);
|
||||||
EXPECT_EQ(intResult.y, 3);
|
EXPECT_EQ(int_result.y, 3);
|
||||||
EXPECT_EQ(intResult.z, 3);
|
EXPECT_EQ(int_result.z, 3);
|
||||||
|
|
||||||
// Test float vectors
|
// Test float vectors
|
||||||
auto floatResult = floatVec2 - floatVec1;
|
auto float_result = float_vec2 - float_vec1;
|
||||||
EXPECT_FLOAT_EQ(floatResult.x, 3.0f);
|
EXPECT_FLOAT_EQ(float_result.x, 3.0f);
|
||||||
EXPECT_FLOAT_EQ(floatResult.y, 3.0f);
|
EXPECT_FLOAT_EQ(float_result.y, 3.0f);
|
||||||
EXPECT_FLOAT_EQ(floatResult.z, 3.0f);
|
EXPECT_FLOAT_EQ(float_result.z, 3.0f);
|
||||||
|
|
||||||
// Test double vectors
|
// Test double vectors
|
||||||
auto doubleResult = doubleVec2 - doubleVec1;
|
auto double_result = double_vec2 - double_vec1;
|
||||||
EXPECT_DOUBLE_EQ(doubleResult.x, 3.0);
|
EXPECT_DOUBLE_EQ(double_result.x, 3.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleResult.y, 3.0);
|
EXPECT_DOUBLE_EQ(double_result.y, 3.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleResult.z, 3.0);
|
EXPECT_DOUBLE_EQ(double_result.z, 3.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test vector scaling
|
// Test vector scaling
|
||||||
TEST_F(Vec3Test, Scale) {
|
TEST_F(Vec3Test, Scale) {
|
||||||
// Test integer scaling
|
// Test integer scaling
|
||||||
Vec3<int> intVecScaled = intVec1;
|
Vec3<int> int_vec_scaled = int_vec1;
|
||||||
intVecScaled.scale(2);
|
int_vec_scaled.scale(2);
|
||||||
EXPECT_EQ(intVecScaled.x, 2);
|
EXPECT_EQ(int_vec_scaled.x, 2);
|
||||||
EXPECT_EQ(intVecScaled.y, 4);
|
EXPECT_EQ(int_vec_scaled.y, 4);
|
||||||
EXPECT_EQ(intVecScaled.z, 6);
|
EXPECT_EQ(int_vec_scaled.z, 6);
|
||||||
|
|
||||||
// Test float scaling
|
// Test float scaling
|
||||||
Vec3<float> floatVecScaled = floatVec1;
|
Vec3<float> float_vec_scaled = float_vec1;
|
||||||
floatVecScaled.scale(2.0f);
|
float_vec_scaled.scale(2.0f);
|
||||||
EXPECT_FLOAT_EQ(floatVecScaled.x, 3.0f);
|
EXPECT_FLOAT_EQ(float_vec_scaled.x, 3.0f);
|
||||||
EXPECT_FLOAT_EQ(floatVecScaled.y, 5.0f);
|
EXPECT_FLOAT_EQ(float_vec_scaled.y, 5.0f);
|
||||||
EXPECT_FLOAT_EQ(floatVecScaled.z, 7.0f);
|
EXPECT_FLOAT_EQ(float_vec_scaled.z, 7.0f);
|
||||||
|
|
||||||
// Test double scaling
|
// Test double scaling
|
||||||
Vec3<double> doubleVecScaled = doubleVec1;
|
Vec3<double> double_vec_scaled = double_vec1;
|
||||||
doubleVecScaled.scale(2.0);
|
double_vec_scaled.scale(2.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleVecScaled.x, 3.0);
|
EXPECT_DOUBLE_EQ(double_vec_scaled.x, 3.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleVecScaled.y, 5.0);
|
EXPECT_DOUBLE_EQ(double_vec_scaled.y, 5.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleVecScaled.z, 7.0);
|
EXPECT_DOUBLE_EQ(double_vec_scaled.z, 7.0);
|
||||||
|
|
||||||
// Test scaling by zero
|
// Test scaling by zero
|
||||||
Vec3<float> zeroScaled = floatVec1;
|
Vec3<float> zero_scaled = float_vec1;
|
||||||
zeroScaled.scale(0.0f);
|
zero_scaled.scale(0.0f);
|
||||||
EXPECT_FLOAT_EQ(zeroScaled.x, 0.0f);
|
EXPECT_FLOAT_EQ(zero_scaled.x, 0.0f);
|
||||||
EXPECT_FLOAT_EQ(zeroScaled.y, 0.0f);
|
EXPECT_FLOAT_EQ(zero_scaled.y, 0.0f);
|
||||||
EXPECT_FLOAT_EQ(zeroScaled.z, 0.0f);
|
EXPECT_FLOAT_EQ(zero_scaled.z, 0.0f);
|
||||||
|
|
||||||
// Test scaling by negative number
|
// Test scaling by negative number
|
||||||
Vec3<int> negScaled = intVec1;
|
Vec3<int> neg_scaled = int_vec1;
|
||||||
negScaled.scale(-1);
|
neg_scaled.scale(-1);
|
||||||
EXPECT_EQ(negScaled.x, -1);
|
EXPECT_EQ(neg_scaled.x, -1);
|
||||||
EXPECT_EQ(negScaled.y, -2);
|
EXPECT_EQ(neg_scaled.y, -2);
|
||||||
EXPECT_EQ(negScaled.z, -3);
|
EXPECT_EQ(neg_scaled.z, -3);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test dot product
|
// Test dot product
|
||||||
TEST_F(Vec3Test, DotProduct) {
|
TEST_F(Vec3Test, DotProduct) {
|
||||||
// Test integer dot product
|
// Test integer dot product
|
||||||
int intDot = intVec1.dot(intVec2);
|
int int_dot = int_vec1.dot(int_vec2);
|
||||||
EXPECT_EQ(intDot, 32); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
|
EXPECT_EQ(int_dot, 32); // 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
|
||||||
|
|
||||||
// Test float dot product
|
// Test float dot product
|
||||||
float floatDot = floatVec1.dot(floatVec2);
|
float float_dot = float_vec1.dot(float_vec2);
|
||||||
EXPECT_FLOAT_EQ(
|
EXPECT_FLOAT_EQ(
|
||||||
floatDot,
|
float_dot,
|
||||||
43.25f); // 1.5*4.5 + 2.5*5.5 + 3.5*6.5 = 6.75 + 13.75 + 22.75 = 43.25
|
43.25f); // 1.5*4.5 + 2.5*5.5 + 3.5*6.5 = 6.75 + 13.75 + 22.75 = 43.25
|
||||||
|
|
||||||
// Test double dot product
|
// Test double dot product
|
||||||
double doubleDot = doubleVec1.dot(doubleVec2);
|
double double_dot = double_vec1.dot(double_vec2);
|
||||||
EXPECT_DOUBLE_EQ(doubleDot, 43.25); // Same calculation as float
|
EXPECT_DOUBLE_EQ(double_dot, 43.25); // Same calculation as float
|
||||||
|
|
||||||
// Test dot product with self (should equal squared length)
|
// Test dot product with self (should equal squared length)
|
||||||
int selfDot = intVec1.dot(intVec1);
|
int self_dot = int_vec1.dot(int_vec1);
|
||||||
EXPECT_EQ(selfDot, 14); // 1*1 + 2*2 + 3*3 = 1 + 4 + 9 = 14
|
EXPECT_EQ(self_dot, 14); // 1*1 + 2*2 + 3*3 = 1 + 4 + 9 = 14
|
||||||
|
|
||||||
// Test dot product with zero vector
|
// Test dot product with zero vector
|
||||||
Vec3<int> zeroVec = {0, 0, 0};
|
Vec3<int> zero_vec = {0, 0, 0};
|
||||||
EXPECT_EQ(intVec1.dot(zeroVec), 0);
|
EXPECT_EQ(int_vec1.dot(zero_vec), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test cross product
|
// Test cross product
|
||||||
TEST_F(Vec3Test, CrossProduct) {
|
TEST_F(Vec3Test, CrossProduct) {
|
||||||
// Test integer cross product
|
// Test integer cross product
|
||||||
auto intCross = intVec1.cross(intVec2);
|
auto int_cross = int_vec1.cross(int_vec2);
|
||||||
EXPECT_EQ(intCross.x, -3); // (2*6 - 3*5) = 12 - 15 = -3
|
EXPECT_EQ(int_cross.x, -3); // (2*6 - 3*5) = 12 - 15 = -3
|
||||||
EXPECT_EQ(intCross.y, 6); // (3*4 - 1*6) = 12 - 6 = 6
|
EXPECT_EQ(int_cross.y, 6); // (3*4 - 1*6) = 12 - 6 = 6
|
||||||
EXPECT_EQ(intCross.z, -3); // (1*5 - 2*4) = 5 - 8 = -3
|
EXPECT_EQ(int_cross.z, -3); // (1*5 - 2*4) = 5 - 8 = -3
|
||||||
|
|
||||||
// Test float cross product
|
// Test float cross product
|
||||||
auto floatCross = floatVec1.cross(floatVec2);
|
auto float_cross = float_vec1.cross(float_vec2);
|
||||||
EXPECT_FLOAT_EQ(floatCross.x,
|
EXPECT_FLOAT_EQ(float_cross.x,
|
||||||
-3.0f); // (2.5*6.5 - 3.5*5.5) = 16.25 - 19.25 = -3
|
-3.0f); // (2.5*6.5 - 3.5*5.5) = 16.25 - 19.25 = -3
|
||||||
EXPECT_FLOAT_EQ(floatCross.y,
|
EXPECT_FLOAT_EQ(float_cross.y,
|
||||||
6.0f); // (3.5*4.5 - 1.5*6.5) = 15.75 - 9.75 = 6
|
6.0f); // (3.5*4.5 - 1.5*6.5) = 15.75 - 9.75 = 6
|
||||||
EXPECT_FLOAT_EQ(floatCross.z,
|
EXPECT_FLOAT_EQ(float_cross.z,
|
||||||
-3.0f); // (1.5*5.5 - 2.5*4.5) = 8.25 - 11.25 = -3
|
-3.0f); // (1.5*5.5 - 2.5*4.5) = 8.25 - 11.25 = -3
|
||||||
|
|
||||||
// Test double cross product
|
// Test double cross product
|
||||||
auto doubleCross = doubleVec1.cross(doubleVec2);
|
auto double_cross = double_vec1.cross(double_vec2);
|
||||||
EXPECT_DOUBLE_EQ(doubleCross.x, -3.0);
|
EXPECT_DOUBLE_EQ(double_cross.x, -3.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleCross.y, 6.0);
|
EXPECT_DOUBLE_EQ(double_cross.y, 6.0);
|
||||||
EXPECT_DOUBLE_EQ(doubleCross.z, -3.0);
|
EXPECT_DOUBLE_EQ(double_cross.z, -3.0);
|
||||||
|
|
||||||
// Test cross product with self (should be zero)
|
// Test cross product with self (should be zero)
|
||||||
auto selfCross = intVec1.cross(intVec1);
|
auto self_cross = int_vec1.cross(int_vec1);
|
||||||
EXPECT_EQ(selfCross.x, 0);
|
EXPECT_EQ(self_cross.x, 0);
|
||||||
EXPECT_EQ(selfCross.y, 0);
|
EXPECT_EQ(self_cross.y, 0);
|
||||||
EXPECT_EQ(selfCross.z, 0);
|
EXPECT_EQ(self_cross.z, 0);
|
||||||
|
|
||||||
// Test cross product of standard basis vectors (i × j = k)
|
// Test cross product of standard basis vectors (i × j = k)
|
||||||
Vec3<int> i = {1, 0, 0};
|
Vec3<int> vec_i = {1, 0, 0};
|
||||||
Vec3<int> j = {0, 1, 0};
|
Vec3<int> vec_j = {0, 1, 0};
|
||||||
Vec3<int> k = {0, 0, 1};
|
Vec3<int> vec_k = {0, 0, 1};
|
||||||
|
|
||||||
auto i_cross_j = i.cross(j);
|
auto i_cross_j = vec_i.cross(vec_j);
|
||||||
EXPECT_EQ(i_cross_j.x, 0);
|
EXPECT_EQ(i_cross_j.x, 0);
|
||||||
EXPECT_EQ(i_cross_j.y, 0);
|
EXPECT_EQ(i_cross_j.y, 0);
|
||||||
EXPECT_EQ(i_cross_j.z, 1);
|
EXPECT_EQ(i_cross_j.z, 1);
|
||||||
|
|
||||||
auto j_cross_k = j.cross(k);
|
auto j_cross_k = vec_j.cross(vec_k);
|
||||||
EXPECT_EQ(j_cross_k.x, 1);
|
EXPECT_EQ(j_cross_k.x, 1);
|
||||||
EXPECT_EQ(j_cross_k.y, 0);
|
EXPECT_EQ(j_cross_k.y, 0);
|
||||||
EXPECT_EQ(j_cross_k.z, 0);
|
EXPECT_EQ(j_cross_k.z, 0);
|
||||||
|
|
||||||
auto k_cross_i = k.cross(i);
|
auto k_cross_i = vec_k.cross(vec_i);
|
||||||
EXPECT_EQ(k_cross_i.x, 0);
|
EXPECT_EQ(k_cross_i.x, 0);
|
||||||
EXPECT_EQ(k_cross_i.y, 1);
|
EXPECT_EQ(k_cross_i.y, 1);
|
||||||
EXPECT_EQ(k_cross_i.z, 0);
|
EXPECT_EQ(k_cross_i.z, 0);
|
||||||
@ -182,46 +182,121 @@ TEST_F(Vec3Test, CrossProduct) {
|
|||||||
// Test with edge cases
|
// Test with edge cases
|
||||||
TEST_F(Vec3Test, EdgeCases) {
|
TEST_F(Vec3Test, EdgeCases) {
|
||||||
// Test with max values
|
// Test with max values
|
||||||
Vec3<int> maxVec = {std::numeric_limits<int>::max(),
|
Vec3<int> max_vec = {std::numeric_limits<int>::max(),
|
||||||
std::numeric_limits<int>::max(),
|
std::numeric_limits<int>::max(),
|
||||||
std::numeric_limits<int>::max()};
|
std::numeric_limits<int>::max()};
|
||||||
|
|
||||||
// Addition with max values may overflow, but we want to test the operation
|
// Addition with max values may overflow, but we want to test the operation
|
||||||
// works
|
// works
|
||||||
auto maxAddition = maxVec + intVec1;
|
auto max_addition = max_vec + int_vec1;
|
||||||
|
|
||||||
// Test with min values
|
// Test with min values
|
||||||
Vec3<int> minVec = {std::numeric_limits<int>::min(),
|
Vec3<int> min_vec = {std::numeric_limits<int>::min(),
|
||||||
std::numeric_limits<int>::min(),
|
std::numeric_limits<int>::min(),
|
||||||
std::numeric_limits<int>::min()};
|
std::numeric_limits<int>::min()};
|
||||||
|
|
||||||
// Subtraction with min values may underflow, but we want to test the
|
// Subtraction with min values may underflow, but we want to test the
|
||||||
// operation works
|
// operation works
|
||||||
auto minSubtraction = minVec - intVec1;
|
auto min_subtraction = min_vec - int_vec1;
|
||||||
|
|
||||||
// Test with mixed values
|
// Test with mixed values
|
||||||
Vec3<double> mixedVec1 = {0.0, -1.0, std::numeric_limits<double>::infinity()};
|
Vec3<double> mixed_vec1 = {0.0, -1.0,
|
||||||
Vec3<double> mixedVec2 = {-0.0, 1.0,
|
std::numeric_limits<double>::infinity()};
|
||||||
-std::numeric_limits<double>::infinity()};
|
Vec3<double> mixed_vec2 = {-0.0, 1.0,
|
||||||
|
-std::numeric_limits<double>::infinity()};
|
||||||
|
|
||||||
auto mixedAddition = mixedVec1 + mixedVec2;
|
auto mixed_addition = mixed_vec1 + mixed_vec2;
|
||||||
// 0.0 + (-0.0) = 0.0
|
// 0.0 + (-0.0) = 0.0
|
||||||
EXPECT_DOUBLE_EQ(mixedAddition.x, 0.0);
|
EXPECT_DOUBLE_EQ(mixed_addition.x, 0.0);
|
||||||
// -1.0 + 1.0 = 0.0
|
// -1.0 + 1.0 = 0.0
|
||||||
EXPECT_DOUBLE_EQ(mixedAddition.y, 0.0);
|
EXPECT_DOUBLE_EQ(mixed_addition.y, 0.0);
|
||||||
// inf + (-inf) = NaN
|
// inf + (-inf) = NaN
|
||||||
EXPECT_TRUE(std::isnan(mixedAddition.z));
|
EXPECT_TRUE(std::isnan(mixed_addition.z));
|
||||||
|
|
||||||
// Test with NaN
|
// Test with NaN
|
||||||
Vec3<double> nanVec = {std::numeric_limits<double>::quiet_NaN(),
|
Vec3<double> nan_vec = {std::numeric_limits<double>::quiet_NaN(),
|
||||||
std::numeric_limits<double>::quiet_NaN(),
|
std::numeric_limits<double>::quiet_NaN(),
|
||||||
std::numeric_limits<double>::quiet_NaN()};
|
std::numeric_limits<double>::quiet_NaN()};
|
||||||
|
|
||||||
// Any operation with NaN should result in NaN
|
// Any operation with NaN should result in NaN
|
||||||
auto nanResult = doubleVec1 + nanVec;
|
auto nan_result = double_vec1 + nan_vec;
|
||||||
EXPECT_TRUE(std::isnan(nanResult.x));
|
EXPECT_TRUE(std::isnan(nan_result.x));
|
||||||
EXPECT_TRUE(std::isnan(nanResult.y));
|
EXPECT_TRUE(std::isnan(nan_result.y));
|
||||||
EXPECT_TRUE(std::isnan(nanResult.z));
|
EXPECT_TRUE(std::isnan(nan_result.z));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test squared_norm2 and norm2 methods
|
||||||
|
TEST_F(Vec3Test, NormMethods) {
|
||||||
|
// Test squared_norm2 for integer vector
|
||||||
|
EXPECT_DOUBLE_EQ(int_vec1.squared_norm2(), 14.0); // 1*1 + 2*2 + 3*3 = 14
|
||||||
|
|
||||||
|
// Test norm2 for integer vector
|
||||||
|
EXPECT_DOUBLE_EQ(int_vec1.norm2(), std::sqrt(14.0)); // √14 ≈ 3.741657...
|
||||||
|
|
||||||
|
// Test squared_norm2 for float vector
|
||||||
|
EXPECT_DOUBLE_EQ(
|
||||||
|
float_vec1.squared_norm2(),
|
||||||
|
20.75); // 1.5*1.5 + 2.5*2.5 + 3.5*3.5 = 2.25 + 6.25 + 12.25 = 20.75
|
||||||
|
|
||||||
|
// Test norm2 for float vector
|
||||||
|
EXPECT_DOUBLE_EQ(float_vec1.norm2(), std::sqrt(20.75)); // √20.75 ≈ 4.5552...
|
||||||
|
|
||||||
|
// Test squared_norm2 for double vector
|
||||||
|
EXPECT_DOUBLE_EQ(double_vec1.squared_norm2(),
|
||||||
|
20.75); // Same as float calculation
|
||||||
|
|
||||||
|
// Test norm2 for double vector
|
||||||
|
EXPECT_DOUBLE_EQ(double_vec1.norm2(), std::sqrt(20.75));
|
||||||
|
|
||||||
|
// Test with zero vector
|
||||||
|
Vec3<int> zero_vec = {0, 0, 0};
|
||||||
|
EXPECT_DOUBLE_EQ(zero_vec.squared_norm2(), 0.0);
|
||||||
|
EXPECT_DOUBLE_EQ(zero_vec.norm2(), 0.0);
|
||||||
|
|
||||||
|
// Test with unit vectors
|
||||||
|
Vec3<double> unit_x = {1.0, 0.0, 0.0};
|
||||||
|
Vec3<double> unit_y = {0.0, 1.0, 0.0};
|
||||||
|
Vec3<double> unit_z = {0.0, 0.0, 1.0};
|
||||||
|
|
||||||
|
EXPECT_DOUBLE_EQ(unit_x.squared_norm2(), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(unit_x.norm2(), 1.0);
|
||||||
|
|
||||||
|
EXPECT_DOUBLE_EQ(unit_y.squared_norm2(), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(unit_y.norm2(), 1.0);
|
||||||
|
|
||||||
|
EXPECT_DOUBLE_EQ(unit_z.squared_norm2(), 1.0);
|
||||||
|
EXPECT_DOUBLE_EQ(unit_z.norm2(), 1.0);
|
||||||
|
|
||||||
|
// Test with negative components
|
||||||
|
Vec3<int> neg_vec = {-1, -2, -3};
|
||||||
|
EXPECT_DOUBLE_EQ(neg_vec.squared_norm2(), 14.0); // (-1)² + (-2)² + (-3)² = 14
|
||||||
|
EXPECT_DOUBLE_EQ(neg_vec.norm2(), std::sqrt(14.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test norm methods with special values
|
||||||
|
TEST_F(Vec3Test, NormEdgeCases) {
|
||||||
|
// Test with infinity
|
||||||
|
Vec3<double> inf_vec = {std::numeric_limits<double>::infinity(), 0.0, 0.0};
|
||||||
|
EXPECT_TRUE(std::isinf(inf_vec.squared_norm2()));
|
||||||
|
EXPECT_TRUE(std::isinf(inf_vec.norm2()));
|
||||||
|
|
||||||
|
// Test with large values that might cause overflow in intermediate
|
||||||
|
// calculations
|
||||||
|
double large_val = std::sqrt(std::numeric_limits<double>::max()) / 2.0;
|
||||||
|
Vec3<double> large_vec = {large_val, large_val, large_val};
|
||||||
|
|
||||||
|
// The squared norm should be approximately 3 * large_val²
|
||||||
|
double expected_squared = 3.0 * large_val * large_val;
|
||||||
|
EXPECT_DOUBLE_EQ(large_vec.squared_norm2(), expected_squared);
|
||||||
|
|
||||||
|
// The norm should be √(3) * large_val
|
||||||
|
double expected_norm = std::sqrt(3.0) * large_val;
|
||||||
|
EXPECT_DOUBLE_EQ(large_vec.norm2(), expected_norm);
|
||||||
|
|
||||||
|
// Test with NaN values
|
||||||
|
Vec3<double> nan_vec = {std::numeric_limits<double>::quiet_NaN(), 0.0, 0.0};
|
||||||
|
EXPECT_TRUE(std::isnan(nan_vec.squared_norm2()));
|
||||||
|
EXPECT_TRUE(std::isnan(nan_vec.norm2()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main function that runs the tests
|
// Main function that runs the tests
|
||||||
|
Loading…
x
Reference in New Issue
Block a user