Skip to content

Commit 271eb3d

Browse files
authored
Add comprehensive yup_simd unit tests for all classes
1 parent 4e04a79 commit 271eb3d

7 files changed

Lines changed: 1355 additions & 1 deletion

tests/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ set (target_gtest_modules "")
5555
set (target_preloaded "")
5656
set (target_modules
5757
yup_core
58+
yup_simd
5859
yup_audio_basics
5960
yup_audio_devices
6061
yup_audio_formats

tests/yup_simd.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@
2424
#include "yup_simd/yup_AffineTransformOperations.cpp"
2525
#include "yup_simd/yup_ColorVectorOperations.cpp"
2626
#include "yup_simd/yup_SIMDRegister.cpp"
27+
#include "yup_simd/yup_Vec.cpp"

tests/yup_simd/yup_AffineTransformOperations.cpp

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,24 @@
2525

2626
using namespace yup;
2727

28-
TEST (AffineTransformOpsTests, TransformPointsMatchesScalarReference)
28+
class AffineTransformOpsTests : public ::testing::Test
29+
{
30+
protected:
31+
static void transformScalar (const float* srcXs, const float* srcYs,
32+
float* dstXs, float* dstYs, int numPoints,
33+
float sx, float shx, float tx, float shy, float sy, float ty) noexcept
34+
{
35+
for (int i = 0; i < numPoints; ++i)
36+
{
37+
const float x = srcXs[i];
38+
const float y = srcYs[i];
39+
dstXs[i] = sx * x + shx * y + tx;
40+
dstYs[i] = shy * x + sy * y + ty;
41+
}
42+
}
43+
};
44+
45+
TEST_F (AffineTransformOpsTests, TransformPointsMatchesScalarReference)
2946
{
3047
constexpr int numPoints = 6;
3148
const float srcXs[numPoints] = { -2.0f, -1.0f, 0.0f, 1.0f, 2.0f, 3.0f };
@@ -48,3 +65,162 @@ TEST (AffineTransformOpsTests, TransformPointsMatchesScalarReference)
4865
EXPECT_NEAR (dstYs[i], shy * srcXs[i] + sy * srcYs[i] + ty, 1.0e-5f);
4966
}
5067
}
68+
69+
TEST_F (AffineTransformOpsTests, TransformPointsInPlace)
70+
{
71+
constexpr int numPoints = 5;
72+
float xs[numPoints] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
73+
float ys[numPoints] = { 5.0f, 4.0f, 3.0f, 2.0f, 1.0f };
74+
75+
const float origXs[numPoints] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
76+
const float origYs[numPoints] = { 5.0f, 4.0f, 3.0f, 2.0f, 1.0f };
77+
78+
constexpr float sx = 2.0f, shx = 0.5f, tx = 1.0f;
79+
constexpr float shy = -0.5f, sy = 3.0f, ty = -1.0f;
80+
81+
AffineTransformOperations::transformPoints (xs, ys, numPoints, sx, shx, tx, shy, sy, ty);
82+
83+
for (int i = 0; i < numPoints; ++i)
84+
{
85+
EXPECT_NEAR (xs[i], sx * origXs[i] + shx * origYs[i] + tx, 1.0e-5f);
86+
EXPECT_NEAR (ys[i], shy * origXs[i] + sy * origYs[i] + ty, 1.0e-5f);
87+
}
88+
}
89+
90+
TEST_F (AffineTransformOpsTests, IdentityTransformLeavesPointsUnchanged)
91+
{
92+
constexpr int numPoints = 8;
93+
const float srcXs[numPoints] = { 1.0f, -2.0f, 3.0f, -4.0f, 5.0f, -6.0f, 7.0f, -8.0f };
94+
const float srcYs[numPoints] = { 8.0f, -7.0f, 6.0f, -5.0f, 4.0f, -3.0f, 2.0f, -1.0f };
95+
float dstXs[numPoints] = {};
96+
float dstYs[numPoints] = {};
97+
98+
// Identity: sx=1, shx=0, tx=0, shy=0, sy=1, ty=0
99+
AffineTransformOperations::transformPoints (srcXs, srcYs, dstXs, dstYs, numPoints, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
100+
101+
for (int i = 0; i < numPoints; ++i)
102+
{
103+
EXPECT_FLOAT_EQ (dstXs[i], srcXs[i]);
104+
EXPECT_FLOAT_EQ (dstYs[i], srcYs[i]);
105+
}
106+
}
107+
108+
TEST_F (AffineTransformOpsTests, PureTranslation)
109+
{
110+
constexpr int numPoints = 6;
111+
const float srcXs[numPoints] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
112+
const float srcYs[numPoints] = { 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };
113+
float dstXs[numPoints] = {};
114+
float dstYs[numPoints] = {};
115+
116+
constexpr float tx = 100.0f, ty = 200.0f;
117+
118+
// Pure translation: sx=1, shx=0, shy=0, sy=1
119+
AffineTransformOperations::transformPoints (srcXs, srcYs, dstXs, dstYs, numPoints, 1.0f, 0.0f, tx, 0.0f, 1.0f, ty);
120+
121+
for (int i = 0; i < numPoints; ++i)
122+
{
123+
EXPECT_FLOAT_EQ (dstXs[i], srcXs[i] + tx);
124+
EXPECT_FLOAT_EQ (dstYs[i], srcYs[i] + ty);
125+
}
126+
}
127+
128+
TEST_F (AffineTransformOpsTests, PureScale)
129+
{
130+
constexpr int numPoints = 8;
131+
const float srcXs[numPoints] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
132+
const float srcYs[numPoints] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f };
133+
float dstXs[numPoints] = {};
134+
float dstYs[numPoints] = {};
135+
136+
constexpr float sx = 2.0f, sy = -0.5f;
137+
138+
AffineTransformOperations::transformPoints (srcXs, srcYs, dstXs, dstYs, numPoints, sx, 0.0f, 0.0f, 0.0f, sy, 0.0f);
139+
140+
for (int i = 0; i < numPoints; ++i)
141+
{
142+
EXPECT_FLOAT_EQ (dstXs[i], sx * srcXs[i]);
143+
EXPECT_FLOAT_EQ (dstYs[i], sy * srcYs[i]);
144+
}
145+
}
146+
147+
TEST_F (AffineTransformOpsTests, SinglePointTransform)
148+
{
149+
const float srcX = 3.0f;
150+
const float srcY = 4.0f;
151+
float dstX = 0.0f;
152+
float dstY = 0.0f;
153+
154+
constexpr float sx = 2.0f, shx = 1.0f, tx = -1.0f;
155+
constexpr float shy = 0.5f, sy = -1.0f, ty = 3.0f;
156+
157+
AffineTransformOperations::transformPoints (&srcX, &srcY, &dstX, &dstY, 1, sx, shx, tx, shy, sy, ty);
158+
159+
EXPECT_NEAR (dstX, sx * srcX + shx * srcY + tx, 1.0e-5f);
160+
EXPECT_NEAR (dstY, shy * srcX + sy * srcY + ty, 1.0e-5f);
161+
}
162+
163+
TEST_F (AffineTransformOpsTests, ZeroPointsDoesNothing)
164+
{
165+
float dstXs[4] = { 99.0f, 99.0f, 99.0f, 99.0f };
166+
float dstYs[4] = { 99.0f, 99.0f, 99.0f, 99.0f };
167+
168+
// numPoints=0 should not write to output
169+
AffineTransformOperations::transformPoints (nullptr, nullptr, dstXs, dstYs, 0, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
170+
171+
for (int i = 0; i < 4; ++i)
172+
{
173+
EXPECT_FLOAT_EQ (dstXs[i], 99.0f);
174+
EXPECT_FLOAT_EQ (dstYs[i], 99.0f);
175+
}
176+
}
177+
178+
TEST_F (AffineTransformOpsTests, LargeBufferMatchesScalarReference)
179+
{
180+
constexpr int numPoints = 100;
181+
float srcXs[numPoints], srcYs[numPoints];
182+
float dstXs[numPoints], dstYs[numPoints];
183+
float refXs[numPoints], refYs[numPoints];
184+
185+
for (int i = 0; i < numPoints; ++i)
186+
{
187+
srcXs[i] = (float) (i - 50);
188+
srcYs[i] = (float) (i * 2 - 100);
189+
}
190+
191+
constexpr float sx = 1.5f, shx = 0.3f, tx = 7.0f;
192+
constexpr float shy = -0.2f, sy = 2.0f, ty = -3.0f;
193+
194+
AffineTransformOperations::transformPoints (srcXs, srcYs, dstXs, dstYs, numPoints, sx, shx, tx, shy, sy, ty);
195+
transformScalar (srcXs, srcYs, refXs, refYs, numPoints, sx, shx, tx, shy, sy, ty);
196+
197+
for (int i = 0; i < numPoints; ++i)
198+
{
199+
EXPECT_NEAR (dstXs[i], refXs[i], 1.0e-4f);
200+
EXPECT_NEAR (dstYs[i], refYs[i], 1.0e-4f);
201+
}
202+
}
203+
204+
TEST_F (AffineTransformOpsTests, ThreePointsUsesScalarTail)
205+
{
206+
// 3 points: the SIMD path handles 4 at a time, so all 3 go through scalar tail
207+
constexpr int numPoints = 3;
208+
const float srcXs[numPoints] = { 1.0f, 2.0f, 3.0f };
209+
const float srcYs[numPoints] = { 4.0f, 5.0f, 6.0f };
210+
float dstXs[numPoints] = {};
211+
float dstYs[numPoints] = {};
212+
float refXs[numPoints] = {};
213+
float refYs[numPoints] = {};
214+
215+
constexpr float sx = 2.0f, shx = 0.5f, tx = 1.0f;
216+
constexpr float shy = -0.5f, sy = 3.0f, ty = -1.0f;
217+
218+
AffineTransformOperations::transformPoints (srcXs, srcYs, dstXs, dstYs, numPoints, sx, shx, tx, shy, sy, ty);
219+
transformScalar (srcXs, srcYs, refXs, refYs, numPoints, sx, shx, tx, shy, sy, ty);
220+
221+
for (int i = 0; i < numPoints; ++i)
222+
{
223+
EXPECT_NEAR (dstXs[i], refXs[i], 1.0e-5f);
224+
EXPECT_NEAR (dstYs[i], refYs[i], 1.0e-5f);
225+
}
226+
}

0 commit comments

Comments
 (0)