Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/common-tests/gsvector_tests.cpp
7322 views
1
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "common/gsvector.h"
5
6
#include "gtest/gtest.h"
7
8
static constexpr s8 s8t(int v)
9
{
10
return static_cast<s8>(static_cast<s32>(v));
11
}
12
13
static constexpr s16 s16t(int v)
14
{
15
return static_cast<s16>(static_cast<s32>(v));
16
}
17
18
// GSVector2i Tests
19
TEST(GSVector2iTest, Construction)
20
{
21
// Default constructor
22
[[maybe_unused]] GSVector2i v1;
23
// Values are uninitialized, so we don't test them
24
25
// Single value constructor
26
GSVector2i v2(42);
27
EXPECT_EQ(v2.x, 42);
28
EXPECT_EQ(v2.y, 42);
29
30
// Two value constructor
31
GSVector2i v3(10, 20);
32
EXPECT_EQ(v3.x, 10);
33
EXPECT_EQ(v3.y, 20);
34
35
// 16-bit constructor
36
GSVector2i v4(s16(1), s16(2), s16(3), s16(4));
37
EXPECT_EQ(v4.S16[0], 1);
38
EXPECT_EQ(v4.S16[1], 2);
39
EXPECT_EQ(v4.S16[2], 3);
40
EXPECT_EQ(v4.S16[3], 4);
41
42
// 8-bit constructor
43
GSVector2i v5(s8t(1), s8t(2), s8t(3), s8t(4), s8t(5), s8t(6), s8t(7), s8t(8));
44
for (int i = 0; i < 8; i++)
45
{
46
EXPECT_EQ(v5.S8[i], i + 1);
47
}
48
49
// Copy constructor
50
GSVector2i v6(v3);
51
EXPECT_EQ(v6.x, 10);
52
EXPECT_EQ(v6.y, 20);
53
}
54
55
TEST(GSVector2iTest, ConstexprCreation)
56
{
57
constexpr auto v1 = GSVector2i::cxpr(5, 10);
58
EXPECT_EQ(v1.x, 5);
59
EXPECT_EQ(v1.y, 10);
60
61
constexpr auto v2 = GSVector2i::cxpr(7);
62
EXPECT_EQ(v2.x, 7);
63
EXPECT_EQ(v2.y, 7);
64
65
constexpr auto v3 = GSVector2i::cxpr16(s16(255));
66
for (int i = 0; i < 4; i++)
67
{
68
EXPECT_EQ(v3.S16[i], 255);
69
}
70
}
71
72
TEST(GSVector2iTest, SaturationOperations)
73
{
74
GSVector2i v1(100, 200);
75
GSVector2i min_val(-50, -100);
76
GSVector2i max_val(150, 250);
77
78
auto sat_result = v1.sat_s32(min_val, max_val);
79
EXPECT_EQ(sat_result.x, 100); // Within range
80
EXPECT_EQ(sat_result.y, 200); // Within range
81
82
GSVector2i v2(300, -150);
83
auto sat_result2 = v2.sat_s32(min_val, max_val);
84
EXPECT_EQ(sat_result2.x, 150); // Clamped to max
85
EXPECT_EQ(sat_result2.y, -100); // Clamped to min
86
}
87
88
TEST(GSVector2iTest, MinMaxVertical)
89
{
90
GSVector2i v1(10, 20);
91
92
EXPECT_EQ(v1.minv_s32(), 10);
93
EXPECT_EQ(v1.maxv_s32(), 20);
94
EXPECT_EQ(v1.addv_s32(), 30);
95
96
GSVector2i v2(s8t(0x50), s8t(0x40), s8t(0x30), s8t(0x20), s8t(0x80), s8t(0x70), s8t(0x60), s8t(0x10)); // 8-bit values
97
EXPECT_EQ(v2.minv_u8(), 0x10u);
98
EXPECT_EQ(v2.maxv_u8(), 0x80u);
99
100
GSVector2i v3(s16t(0x1000), s16t(0x2000), s16t(0x3000), s16t(0x4000)); // 16-bit values
101
EXPECT_EQ(v3.minv_u16(), 0x1000u);
102
EXPECT_EQ(v3.maxv_u16(), 0x4000u);
103
}
104
105
TEST(GSVector2iTest, ClampOperations)
106
{
107
// Test clamp8 which does pu16().upl8()
108
GSVector2i v1(300, 400, -100, 500); // Values that exceed 8-bit range
109
auto clamped = v1.clamp8();
110
// This should pack to 16-bit unsigned with saturation, then unpack low 8-bit
111
for (int i = 0; i < 8; i++)
112
{
113
EXPECT_GE(clamped.U8[i], 0);
114
EXPECT_LE(clamped.U8[i], 255);
115
}
116
}
117
118
TEST(GSVector2iTest, BlendOperations)
119
{
120
GSVector2i v1(s8t(0x11), s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88));
121
GSVector2i v2(s8t(0xAA), s8t(0xBB), s8t(0xCC), s8t(0xDD), s8t(0xEE), s8t(0xFF), s8t(0x00), s8t(0x11));
122
GSVector2i mask(s8t(0x80), s8t(0x00), s8t(0x80), s8t(0x00), s8t(0x80), s8t(0x00), s8t(0x80),
123
s8t(0x00)); // Alternate selection
124
125
auto blend_result = v1.blend8(v2, mask);
126
EXPECT_EQ(blend_result.U8[0], 0xAAu); // mask bit set, select from v2
127
EXPECT_EQ(blend_result.U8[1], 0x22u); // mask bit clear, select from v1
128
EXPECT_EQ(blend_result.U8[2], 0xCCu); // mask bit set, select from v2
129
EXPECT_EQ(blend_result.U8[3], 0x44u); // mask bit clear, select from v1
130
}
131
132
TEST(GSVector2iTest, BlendTemplated)
133
{
134
GSVector2i v1(s16t(0x1111), s16t(0x2222), s16t(0x3333), s16t(0x4444));
135
GSVector2i v2(s16t(0xAAAA), s16t(0xBBBB), s16t(0xCCCC), s16t(0xDDDD));
136
137
// Test blend16 with mask 0x5 (binary 0101) - select elements 0 and 2 from v2
138
auto blend16_result = v1.blend16<0x5>(v2);
139
EXPECT_EQ(blend16_result.U16[0], 0xAAAAu); // bit 0 set, select from v2
140
EXPECT_EQ(blend16_result.U16[1], 0x2222u); // bit 1 clear, select from v1
141
EXPECT_EQ(blend16_result.U16[2], 0xCCCCu); // bit 2 set, select from v2
142
EXPECT_EQ(blend16_result.U16[3], 0x4444u); // bit 3 clear, select from v1
143
144
// Test blend32 with mask 0x1 - select element 0 from v2
145
auto blend32_result = v1.blend32<0x1>(v2);
146
EXPECT_EQ(blend32_result.U32[0], 0xBBBBAAAAu); // bit 0 set, select from v2
147
EXPECT_EQ(blend32_result.U32[1], 0x44443333u); // bit 1 clear, select from v1
148
}
149
150
TEST(GSVector2iTest, ShuffleOperations)
151
{
152
GSVector2i v1(s8t(0x10), s8t(0x20), s8t(0x30), s8t(0x40), s8t(0x50), s8t(0x60), s8t(0x70), s8t(0x80));
153
GSVector2i shuffle_mask(s8t(0x00), s8t(0x02), s8t(0x04), s8t(0x06), s8t(0x80), s8t(0x81), s8t(0x82),
154
s8t(0x83)); // Mix indices and zero
155
156
auto shuffled = v1.shuffle8(shuffle_mask);
157
EXPECT_EQ(shuffled.S8[0], s8t(0x10)); // Index 0
158
EXPECT_EQ(shuffled.S8[1], s8t(0x30)); // Index 2
159
EXPECT_EQ(shuffled.S8[2], s8t(0x50)); // Index 4
160
EXPECT_EQ(shuffled.S8[3], s8t(0x70)); // Index 6
161
EXPECT_EQ(shuffled.S8[4], s8t(0)); // High bit set, zero
162
EXPECT_EQ(shuffled.S8[5], s8t(0)); // High bit set, zero
163
}
164
165
TEST(GSVector2iTest, PackingOperations)
166
{
167
// Test ps16 - pack signed 16-bit to signed 8-bit with saturation
168
GSVector2i v1(300, -200, 100, 400); // 16-bit values, some out of 8-bit range
169
auto packed_s = v1.ps16();
170
EXPECT_EQ(packed_s.S8[0], 127); // 300 saturated to max s8
171
EXPECT_EQ(packed_s.S8[1], -128); // -200 saturated to min s8
172
EXPECT_EQ(packed_s.S8[2], 100); // 100 within range
173
EXPECT_EQ(packed_s.S8[3], 127); // 400 saturated to max s8
174
175
// Test pu16 - pack unsigned 16-bit to unsigned 8-bit with saturation
176
GSVector2i v2(100, 300, 50, 400);
177
auto packed_u = v2.pu16();
178
EXPECT_EQ(packed_u.U8[0], 100); // 100 within range
179
EXPECT_EQ(packed_u.U8[1], 255); // 300 saturated to max u8
180
EXPECT_EQ(packed_u.U8[2], 50); // 50 within range
181
EXPECT_EQ(packed_u.U8[3], 255); // 400 saturated to max u8
182
}
183
184
TEST(GSVector2iTest, UnpackOperations)
185
{
186
GSVector2i v1(0x12, 0x34, 0x56, 0x78);
187
188
auto upl8_result = v1.upl8();
189
EXPECT_EQ(upl8_result.U8[0], 0x12);
190
EXPECT_EQ(upl8_result.U8[1], 0);
191
EXPECT_EQ(upl8_result.U8[2], 0);
192
EXPECT_EQ(upl8_result.U8[3], 0);
193
EXPECT_EQ(upl8_result.U8[4], 0x34);
194
EXPECT_EQ(upl8_result.U8[5], 0);
195
EXPECT_EQ(upl8_result.U8[6], 0);
196
EXPECT_EQ(upl8_result.U8[7], 0);
197
198
auto upl16_result = v1.upl16();
199
EXPECT_EQ(upl16_result.U16[0], 0x12);
200
EXPECT_EQ(upl16_result.U16[1], 0);
201
EXPECT_EQ(upl16_result.U16[2], 0x34);
202
EXPECT_EQ(upl16_result.U16[3], 0);
203
}
204
205
TEST(GSVector2iTest, TypeConversions)
206
{
207
GSVector2i v1(0x12, 0x34, 0x56, 0x78);
208
209
// Test u8to16
210
auto s8to16_result = v1.u8to16();
211
EXPECT_EQ(s8to16_result.S16[0], 0x12);
212
EXPECT_EQ(s8to16_result.S16[1], 0);
213
EXPECT_EQ(s8to16_result.S16[2], 0x34);
214
EXPECT_EQ(s8to16_result.S16[3], 0);
215
216
// Test u8to32
217
auto u8to32_result = v1.u8to32();
218
EXPECT_EQ(u8to32_result.U32[0], 0x12u);
219
EXPECT_EQ(u8to32_result.U32[1], 0u);
220
}
221
222
TEST(GSVector2iTest, ByteShifts)
223
{
224
GSVector2i v1(s8t(0x12), s8t(0x34), s8t(0x56), s8t(0x78), s8t(0x9A), s8t(0xBC), s8t(0xDE), s8t(0xF0));
225
226
// Test srl<2> - shift right logical by 2 bytes
227
auto srl_result = v1.srl<2>();
228
EXPECT_EQ(srl_result.U8[0], 0x56u);
229
EXPECT_EQ(srl_result.U8[1], 0x78u);
230
EXPECT_EQ(srl_result.U8[2], 0x9Au);
231
EXPECT_EQ(srl_result.U8[3], 0xBCu);
232
EXPECT_EQ(srl_result.U8[4], 0xDEu);
233
EXPECT_EQ(srl_result.U8[5], 0xF0u);
234
EXPECT_EQ(srl_result.U8[6], 0u);
235
EXPECT_EQ(srl_result.U8[7], 0u);
236
237
// Test sll<3> - shift left logical by 3 bytes
238
auto sll_result = v1.sll<3>();
239
EXPECT_EQ(sll_result.U8[0], 0u);
240
EXPECT_EQ(sll_result.U8[1], 0u);
241
EXPECT_EQ(sll_result.U8[2], 0u);
242
EXPECT_EQ(sll_result.U8[3], 0x12u);
243
EXPECT_EQ(sll_result.U8[4], 0x34u);
244
EXPECT_EQ(sll_result.U8[5], 0x56u);
245
EXPECT_EQ(sll_result.U8[6], 0x78u);
246
EXPECT_EQ(sll_result.U8[7], 0x9Au);
247
}
248
249
TEST(GSVector2iTest, ArithmeticWith16BitElements)
250
{
251
GSVector2i v1(100, 200, 300, 400);
252
GSVector2i v2(50, 60, 70, 80);
253
254
auto add16_result = v1.add16(v2);
255
EXPECT_EQ(add16_result.S16[0], 150);
256
EXPECT_EQ(add16_result.S16[1], 260);
257
EXPECT_EQ(add16_result.S16[2], 370);
258
EXPECT_EQ(add16_result.S16[3], 480);
259
260
auto sub16_result = v1.sub16(v2);
261
EXPECT_EQ(sub16_result.S16[0], 50);
262
EXPECT_EQ(sub16_result.S16[1], 140);
263
EXPECT_EQ(sub16_result.S16[2], 230);
264
EXPECT_EQ(sub16_result.S16[3], 320);
265
266
auto mul16_result = v1.mul16l(v2);
267
EXPECT_EQ(mul16_result.S16[0], 5000);
268
EXPECT_EQ(mul16_result.S16[1], 12000);
269
EXPECT_EQ(mul16_result.S16[2], 21000);
270
EXPECT_EQ(mul16_result.S16[3], 32000);
271
}
272
273
TEST(GSVector2iTest, ArithmeticWith8BitElements)
274
{
275
GSVector2i v1(10, 20, 30, 40, 50, 60, 70, 80);
276
GSVector2i v2(5, 8, 12, 16, 20, 24, 28, 32);
277
278
auto add8_result = v1.add8(v2);
279
for (int i = 0; i < 8; i++)
280
{
281
EXPECT_EQ(add8_result.S8[i], v1.S8[i] + v2.S8[i]);
282
}
283
284
auto sub8_result = v1.sub8(v2);
285
for (int i = 0; i < 8; i++)
286
{
287
EXPECT_EQ(sub8_result.S8[i], v1.S8[i] - v2.S8[i]);
288
}
289
}
290
291
TEST(GSVector2iTest, SaturatedArithmetic)
292
{
293
// Test signed saturation
294
GSVector2i v1(120, -120, 100, -100, 0, 0, 0, 0);
295
GSVector2i v2(50, -50, 60, -60, 0, 0, 0, 0);
296
297
auto adds8_result = v1.adds8(v2);
298
EXPECT_EQ(adds8_result.S8[0], 127); // 120 + 50 = 170, saturated to 127
299
EXPECT_EQ(adds8_result.S8[1], -128); // -120 + (-50) = -170, saturated to -128
300
EXPECT_EQ(adds8_result.S8[2], 127); // 100 + 60 = 160, saturated to 127
301
EXPECT_EQ(adds8_result.S8[3], -128); // -100 + (-60) = -160, saturated to -128
302
303
auto subs8_result = v1.subs8(v2);
304
EXPECT_EQ(subs8_result.S8[0], 70); // 120 - 50 = 70
305
EXPECT_EQ(subs8_result.S8[1], -70); // -120 - (-50) = -70
306
EXPECT_EQ(subs8_result.S8[2], 40); // 100 - 60 = 40
307
EXPECT_EQ(subs8_result.S8[3], -40); // -100 - (-60) = -40
308
}
309
310
TEST(GSVector2iTest, UnsignedSaturatedArithmetic)
311
{
312
GSVector2i v1(s8t(200), s8t(100), s8t(150), s8t(50), s8t(0), s8t(0), s8t(0), s8t(0));
313
GSVector2i v2(s8t(80), s8t(120), s8t(30), s8t(70), s8t(0), s8t(0), s8t(0), s8t(0));
314
315
auto addus8_result = v1.addus8(v2);
316
EXPECT_EQ(addus8_result.U8[0], 255); // 200 + 80 = 280, saturated to 255
317
EXPECT_EQ(addus8_result.U8[1], 220); // 100 + 120 = 220
318
EXPECT_EQ(addus8_result.U8[2], 180); // 150 + 30 = 180
319
EXPECT_EQ(addus8_result.U8[3], 120); // 50 + 70 = 120
320
321
auto subus8_result = v1.subus8(v2);
322
EXPECT_EQ(subus8_result.U8[0], 120); // 200 - 80 = 120
323
EXPECT_EQ(subus8_result.U8[1], 0); // 100 - 120 = -20, saturated to 0
324
EXPECT_EQ(subus8_result.U8[2], 120); // 150 - 30 = 120
325
EXPECT_EQ(subus8_result.U8[3], 0); // 50 - 70 = -20, saturated to 0
326
}
327
328
TEST(GSVector2iTest, AverageOperations)
329
{
330
GSVector2i v1(s8t(100), s8t(200), s8t(50), s8t(150), s8t(0), s8t(0), s8t(0), s8t(0));
331
GSVector2i v2(s8t(80), s8t(180), s8t(70), s8t(130), s8t(0), s8t(0), s8t(0), s8t(0));
332
333
auto avg8_result = v1.avg8(v2);
334
EXPECT_EQ(avg8_result.U8[0], 90); // (100 + 80) / 2 = 90
335
EXPECT_EQ(avg8_result.U8[1], 190); // (200 + 180) / 2 = 190
336
EXPECT_EQ(avg8_result.U8[2], 60); // (50 + 70) / 2 = 60
337
EXPECT_EQ(avg8_result.U8[3], 140); // (150 + 130) / 2 = 140
338
339
auto avg16_result = v1.avg16(v2);
340
EXPECT_EQ(avg16_result.U16[0], (51300 + 46160) / 2); // Average of packed 16-bit values
341
EXPECT_EQ(avg16_result.U16[1], (38450 + 33350) / 2);
342
}
343
344
TEST(GSVector2iTest, ComparisonOperations)
345
{
346
GSVector2i v1(10, 20, 30, 40, 50, 60, 70, 80);
347
GSVector2i v2(5, 25, 30, 45, 55, 55, 75, 75);
348
349
// Test eq8
350
auto eq8_result = v1.eq8(v2);
351
EXPECT_EQ(eq8_result.S8[0], 0); // 10 != 5
352
EXPECT_EQ(eq8_result.S8[1], 0); // 20 != 25
353
EXPECT_EQ(eq8_result.S8[2], -1); // 30 == 30
354
EXPECT_EQ(eq8_result.S8[3], 0); // 40 != 45
355
356
// Test neq8
357
auto neq8_result = v1.neq8(v2);
358
EXPECT_EQ(neq8_result.S8[0], -1); // 10 != 5
359
EXPECT_EQ(neq8_result.S8[1], -1); // 20 != 25
360
EXPECT_EQ(neq8_result.S8[2], 0); // 30 == 30
361
EXPECT_EQ(neq8_result.S8[3], -1); // 40 != 45
362
363
// Test gt8
364
auto gt8_result = v1.gt8(v2);
365
EXPECT_EQ(gt8_result.S8[0], -1); // 10 > 5
366
EXPECT_EQ(gt8_result.S8[1], 0); // 20 < 25
367
EXPECT_EQ(gt8_result.S8[2], 0); // 30 == 30
368
EXPECT_EQ(gt8_result.S8[3], 0); // 40 < 45
369
370
// Test ge8
371
auto ge8_result = v1.ge8(v2);
372
EXPECT_EQ(ge8_result.S8[0], -1); // 10 >= 5
373
EXPECT_EQ(ge8_result.S8[1], 0); // 20 < 25
374
EXPECT_EQ(ge8_result.S8[2], -1); // 30 >= 30
375
EXPECT_EQ(ge8_result.S8[3], 0); // 40 < 45
376
377
// Test lt8
378
auto lt8_result = v1.lt8(v2);
379
EXPECT_EQ(lt8_result.S8[0], 0); // 10 > 5
380
EXPECT_EQ(lt8_result.S8[1], -1); // 20 < 25
381
EXPECT_EQ(lt8_result.S8[2], 0); // 30 == 30
382
EXPECT_EQ(lt8_result.S8[3], -1); // 40 < 45
383
384
// Test le8
385
auto le8_result = v1.le8(v2);
386
EXPECT_EQ(le8_result.S8[0], 0); // 10 > 5
387
EXPECT_EQ(le8_result.S8[1], -1); // 20 <= 25
388
EXPECT_EQ(le8_result.S8[2], -1); // 30 <= 30
389
EXPECT_EQ(le8_result.S8[3], -1); // 40 <= 45
390
}
391
392
TEST(GSVector2iTest, MaskAndBooleanOperations)
393
{
394
GSVector2i v1(s8t(0x80), s8t(0x40), s8t(0x80), s8t(0x00), s8t(0x80), s8t(0x80), s8t(0x00), s8t(0x80));
395
396
s32 mask_result = v1.mask();
397
// Mask should be formed from high bits of each byte
398
s32 expected_mask = 0x01 | 0x04 | 0x10 | 0x20 | 0x80; // Bits 0, 2, 4, 5, 7
399
EXPECT_EQ(mask_result & 0xB5, expected_mask & 0xB5); // Check set bits
400
401
// Test alltrue and allfalse
402
GSVector2i all_ones;
403
all_ones.U64[0] = 0xFFFFFFFFFFFFFFFFULL;
404
EXPECT_TRUE(all_ones.alltrue());
405
EXPECT_FALSE(all_ones.allfalse());
406
407
GSVector2i all_zeros;
408
all_zeros.U64[0] = 0;
409
EXPECT_FALSE(all_zeros.alltrue());
410
EXPECT_TRUE(all_zeros.allfalse());
411
}
412
413
TEST(GSVector2iTest, InsertExtractOperations)
414
{
415
GSVector2i v1(0x12345678, 0x9ABCDEF0);
416
417
// Test insert/extract 8-bit
418
auto v_insert8 = v1.insert8<0>(0x55);
419
EXPECT_EQ(v_insert8.extract8<0>(), 0x55);
420
EXPECT_EQ(v1.extract8<1>(), s8t(0x56));
421
422
// Test insert/extract 16-bit
423
auto v_insert16 = v1.insert16<1>(0x1234);
424
EXPECT_EQ(v_insert16.extract16<1>(), 0x1234);
425
EXPECT_EQ(v1.extract16<0>(), static_cast<s16>(0x5678));
426
427
// Test insert/extract 32-bit
428
auto v_insert32 = v1.insert32<0>(0xAABBCCDD);
429
EXPECT_EQ(v_insert32.extract32<0>(), static_cast<s32>(0xAABBCCDD));
430
EXPECT_EQ(v1.extract32<1>(), static_cast<s32>(0x9ABCDEF0));
431
}
432
433
TEST(GSVector2iTest, LoadStoreOperations)
434
{
435
// Test load32
436
s32 value = 0x12345678;
437
auto loaded32 = GSVector2i::load32(&value);
438
EXPECT_EQ(loaded32.x, 0x12345678);
439
EXPECT_EQ(loaded32.y, 0);
440
441
// Test set32
442
auto set32_result = GSVector2i::set32(0xAABBCCDD);
443
EXPECT_EQ(set32_result.x, static_cast<s32>(0xAABBCCDD));
444
EXPECT_EQ(set32_result.y, 0);
445
446
// Test store32
447
s32 output_value;
448
GSVector2i::store32(&output_value, loaded32);
449
EXPECT_EQ(output_value, 0x12345678);
450
451
// Test full load/store
452
s32 data[2] = {0x11111111, 0x22222222};
453
auto loaded = GSVector2i::load<true>(data);
454
EXPECT_EQ(loaded.S32[0], 0x11111111);
455
EXPECT_EQ(loaded.S32[1], 0x22222222);
456
457
s32 output[2];
458
GSVector2i::store<true>(output, loaded);
459
EXPECT_EQ(output[0], 0x11111111);
460
EXPECT_EQ(output[1], 0x22222222);
461
}
462
463
TEST(GSVector2iTest, BitwiseAssignmentOperations)
464
{
465
GSVector2i v1(0xF0F0F0F0, 0x0F0F0F0F);
466
GSVector2i v2(0xAAAAAAAA, 0x55555555);
467
468
// Test &=
469
GSVector2i v_and = v1;
470
v_and &= v2;
471
EXPECT_EQ(v_and.U32[0], 0xA0A0A0A0u);
472
EXPECT_EQ(v_and.U32[1], 0x05050505u);
473
474
// Test |=
475
GSVector2i v_or = v1;
476
v_or |= v2;
477
EXPECT_EQ(v_or.U32[0], 0xFAFAFAFAu);
478
EXPECT_EQ(v_or.U32[1], 0x5F5F5F5Fu);
479
480
// Test ^=
481
GSVector2i v_xor = v1;
482
v_xor ^= v2;
483
EXPECT_EQ(v_xor.U32[0], 0x5A5A5A5Au);
484
EXPECT_EQ(v_xor.U32[1], 0x5A5A5A5Au);
485
}
486
487
TEST(GSVector2iTest, BitwiseScalarOperations)
488
{
489
GSVector2i v1(0xF0F0F0F0, 0x0F0F0F0F);
490
s32 scalar = 0xAAAAAAAA;
491
492
auto and_result = v1 & scalar;
493
EXPECT_EQ(and_result.U32[0], 0xA0A0A0A0u);
494
EXPECT_EQ(and_result.U32[1], 0x0A0A0A0Au);
495
496
auto or_result = v1 | scalar;
497
EXPECT_EQ(or_result.U32[0], 0xFAFAFAFAu);
498
EXPECT_EQ(or_result.U32[1], 0xAFAFAFAFu);
499
500
auto xor_result = v1 ^ scalar;
501
EXPECT_EQ(xor_result.U32[0], 0x5A5A5A5Au);
502
EXPECT_EQ(xor_result.U32[1], 0xA5A5A5A5u);
503
}
504
505
TEST(GSVector2iTest, NotOperation)
506
{
507
GSVector2i v1(0xF0F0F0F0, 0x0F0F0F0F);
508
auto not_result = ~v1;
509
EXPECT_EQ(not_result.U32[0], 0x0F0F0F0Fu);
510
EXPECT_EQ(not_result.U32[1], 0xF0F0F0F0u);
511
}
512
513
// GSVector2 Tests
514
TEST(GSVector2Test, Construction)
515
{
516
// Single value constructor
517
GSVector2 v1(3.14f);
518
EXPECT_FLOAT_EQ(v1.x, 3.14f);
519
EXPECT_FLOAT_EQ(v1.y, 3.14f);
520
521
// Two value constructor (float)
522
GSVector2 v2(1.5f, 2.5f);
523
EXPECT_FLOAT_EQ(v2.x, 1.5f);
524
EXPECT_FLOAT_EQ(v2.y, 2.5f);
525
526
// Two value constructor (int)
527
GSVector2 v3(10, 20);
528
EXPECT_FLOAT_EQ(v3.x, 10.0f);
529
EXPECT_FLOAT_EQ(v3.y, 20.0f);
530
531
// Single int constructor
532
GSVector2 v4(42);
533
EXPECT_FLOAT_EQ(v4.x, 42.0f);
534
EXPECT_FLOAT_EQ(v4.y, 42.0f);
535
}
536
537
TEST(GSVector2Test, BlendOperations)
538
{
539
GSVector2 v1(1.0f, 2.0f);
540
GSVector2 v2(3.0f, 4.0f);
541
542
// Test templated blend32
543
auto blend_result = v1.blend32<1>(v2); // mask = 1, select x from v1, y from v2
544
EXPECT_FLOAT_EQ(blend_result.x, 3.0f); // From v2
545
EXPECT_FLOAT_EQ(blend_result.y, 2.0f); // From v1
546
547
// Test mask-based blend32
548
GSVector2 mask;
549
mask.U32[0] = 0x80000000u; // High bit set
550
mask.U32[1] = 0x00000000u; // High bit clear
551
auto mask_blend_result = v1.blend32(v2, mask);
552
EXPECT_FLOAT_EQ(mask_blend_result.x, 3.0f); // From v2 (mask high bit set)
553
EXPECT_FLOAT_EQ(mask_blend_result.y, 2.0f); // From v1 (mask high bit clear)
554
}
555
556
TEST(GSVector2Test, MaskOperations)
557
{
558
GSVector2 v1;
559
v1.U32[0] = 0x80000000u; // High bit set
560
v1.U32[1] = 0x40000000u; // Second bit set
561
562
int mask_result = v1.mask();
563
EXPECT_EQ(mask_result, 0x1); // One bit should be set in result
564
}
565
566
TEST(GSVector2Test, ReplaceNaN)
567
{
568
GSVector2 v1(1.0f, std::numeric_limits<float>::quiet_NaN());
569
GSVector2 replacement(99.0f, 88.0f);
570
571
auto result = v1.replace_nan(replacement);
572
EXPECT_FLOAT_EQ(result.x, 1.0f); // Not NaN, keep original
573
EXPECT_FLOAT_EQ(result.y, 88.0f); // Was NaN, use replacement
574
}
575
576
TEST(GSVector2Test, InsertExtract)
577
{
578
GSVector2 v1(1.0f, 2.0f);
579
GSVector2 v2(3.0f, 4.0f);
580
581
// Test insert32
582
auto insert_result = v1.insert32<1, 0>(v2); // Insert v2[1] into v1[0]
583
EXPECT_FLOAT_EQ(insert_result.x, 4.0f); // v2[1]
584
EXPECT_FLOAT_EQ(insert_result.y, 2.0f); // Original v1[1]
585
586
// Test extract32
587
GSVector2 v3;
588
v3.I32[0] = 0x12345678;
589
v3.I32[1] = 0x9ABCDEF0;
590
EXPECT_EQ(v3.extract32<0>(), 0x12345678);
591
EXPECT_EQ(v3.extract32<1>(), static_cast<s32>(0x9ABCDEF0));
592
}
593
594
TEST(GSVector2Test, ComparisonOperators)
595
{
596
GSVector2 v1(1.0f, 2.0f);
597
GSVector2 v2(1.0f, 3.0f);
598
599
auto eq_result = v1 == v2;
600
EXPECT_EQ(eq_result.I32[0], -1); // 1.0 == 1.0
601
EXPECT_EQ(eq_result.I32[1], 0); // 2.0 != 3.0
602
603
auto neq_result = v1 != v2;
604
EXPECT_EQ(neq_result.I32[0], 0); // 1.0 == 1.0
605
EXPECT_EQ(neq_result.I32[1], -1); // 2.0 != 3.0
606
607
auto gt_result = v1 > v2;
608
EXPECT_EQ(gt_result.I32[0], 0); // 1.0 == 1.0
609
EXPECT_EQ(gt_result.I32[1], 0); // 2.0 < 3.0
610
611
auto lt_result = v1 < v2;
612
EXPECT_EQ(lt_result.I32[0], 0); // 1.0 == 1.0
613
EXPECT_EQ(lt_result.I32[1], -1); // 2.0 < 3.0
614
615
auto ge_result = v1 >= v2;
616
EXPECT_EQ(ge_result.I32[0], -1); // 1.0 >= 1.0
617
EXPECT_EQ(ge_result.I32[1], 0); // 2.0 < 3.0
618
619
auto le_result = v1 <= v2;
620
EXPECT_EQ(le_result.I32[0], -1); // 1.0 <= 1.0
621
EXPECT_EQ(le_result.I32[1], -1); // 2.0 <= 3.0
622
}
623
624
TEST(GSVector2Test, XfffffffffConstant)
625
{
626
const auto all_ones = GSVector2::xffffffff();
627
EXPECT_EQ(all_ones.U64[0], 0xFFFFFFFFFFFFFFFFULL);
628
}
629
630
// GSVector4i Tests
631
TEST(GSVector4iTest, ConstexprCreation8Bit)
632
{
633
constexpr auto v1 = GSVector4i::cxpr8(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
634
for (int i = 0; i < 16; i++)
635
{
636
EXPECT_EQ(v1.S8[i], i + 1);
637
}
638
}
639
640
TEST(GSVector4iTest, MaddOperations)
641
{
642
GSVector4i v1(1, 2, 3, 4, 5, 6, 7, 8); // 16-bit values
643
GSVector4i v2(2, 3, 4, 5, 6, 7, 8, 9);
644
645
auto madd_result = v1.madd_s16(v2);
646
EXPECT_EQ(madd_result.S32[0], 1 * 2 + 2 * 3); // 2 + 6 = 8
647
EXPECT_EQ(madd_result.S32[1], 3 * 4 + 4 * 5); // 12 + 20 = 32
648
EXPECT_EQ(madd_result.S32[2], 5 * 6 + 6 * 7); // 30 + 42 = 72
649
EXPECT_EQ(madd_result.S32[3], 7 * 8 + 8 * 9); // 56 + 72 = 128
650
}
651
652
TEST(GSVector4iTest, HorizontalAdd)
653
{
654
GSVector4i v1(10, 20, 30, 40);
655
656
auto addp_result = v1.addp_s32();
657
EXPECT_EQ(addp_result.x, 30); // 10 + 20
658
EXPECT_EQ(addp_result.y, 70); // 30 + 40
659
EXPECT_EQ(addp_result.z, 30);
660
EXPECT_EQ(addp_result.w, 70);
661
}
662
663
TEST(GSVector4iTest, VerticalMinMaxU8)
664
{
665
GSVector4i v1(s8t(10), s8t(50), s8t(30), s8t(200), s8t(15), s8t(100), s8t(5), s8t(250), s8t(80), s8t(20), s8t(60),
666
s8t(40), s8t(90), s8t(70), s8t(180), s8t(1));
667
668
EXPECT_EQ(v1.minv_u8(), 1u);
669
EXPECT_EQ(v1.maxv_u8(), 250u);
670
}
671
672
TEST(GSVector4iTest, VerticalMinMaxU16)
673
{
674
GSVector4i v1(1000, 2000, 500, 3000, 1500, 800, 2500, 100);
675
676
EXPECT_EQ(v1.minv_u16(), 100u);
677
EXPECT_EQ(v1.maxv_u16(), 3000u);
678
}
679
680
TEST(GSVector4iTest, HaddS16)
681
{
682
GSVector4i v1(10, 20, 30, 40, 50, 60, 70, 80);
683
GSVector4i v2(1, 2, 3, 4, 5, 6, 7, 8);
684
685
auto hadds_result = v1.hadds16(v2);
686
// First vector: pairs (10,20), (30,40), (50,60), (70,80)
687
// Second vector: pairs (1,2), (3,4), (5,6), (7,8)
688
EXPECT_EQ(hadds_result.S16[0], 30); // 10 + 20
689
EXPECT_EQ(hadds_result.S16[1], 70); // 30 + 40
690
EXPECT_EQ(hadds_result.S16[2], 110); // 50 + 60
691
EXPECT_EQ(hadds_result.S16[3], 150); // 70 + 80
692
EXPECT_EQ(hadds_result.S16[4], 3); // 1 + 2
693
EXPECT_EQ(hadds_result.S16[5], 7); // 3 + 4
694
EXPECT_EQ(hadds_result.S16[6], 11); // 5 + 6
695
EXPECT_EQ(hadds_result.S16[7], 15); // 7 + 8
696
}
697
698
TEST(GSVector4iTest, BlendOperationsAdvanced)
699
{
700
GSVector4i v1(s8t(0x11), s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88), s8t(0x99),
701
s8t(0xAA), s8t(0xBB), s8t(0xCC), s8t(0xDD), s8t(0xEE), s8t(0xFF), s8t(0x00));
702
GSVector4i v2(s8t(0xA1), s8t(0xB2), s8t(0xC3), s8t(0xD4), s8t(0xE5), s8t(0xF6), s8t(0x07), s8t(0x18), s8t(0x29),
703
s8t(0x3A), s8t(0x4B), s8t(0x5C), s8t(0x6D), s8t(0x7E), s8t(0x8F), s8t(0x90));
704
GSVector4i mask_blend(s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00),
705
s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00), s8t(0xFF), s8t(0x00));
706
707
auto blend_result = v1.blend(v2, mask_blend);
708
// The blend operation should mix bits based on the mask
709
// Where mask bit is 1, select from v2; where 0, select from v1
710
for (int i = 0; i < 2; i++)
711
{
712
u64 expected = (v2.U64[i] & mask_blend.U64[i]) | (v1.U64[i] & ~mask_blend.U64[i]);
713
EXPECT_EQ(blend_result.U64[i], expected);
714
}
715
}
716
717
TEST(GSVector4iTest, AdvancedPackingWithTwoVectors)
718
{
719
GSVector4i v1(100, 200, 300, 400); // 32-bit signed values
720
GSVector4i v2(500, 600, 700, 800);
721
722
auto ps32_result = v1.ps32(v2);
723
// Should pack both vectors' 32-bit values to 16-bit with saturation
724
EXPECT_EQ(ps32_result.S16[0], 100);
725
EXPECT_EQ(ps32_result.S16[1], 200);
726
EXPECT_EQ(ps32_result.S16[2], 300);
727
EXPECT_EQ(ps32_result.S16[3], 400);
728
EXPECT_EQ(ps32_result.S16[4], 500);
729
EXPECT_EQ(ps32_result.S16[5], 600);
730
EXPECT_EQ(ps32_result.S16[6], 700);
731
EXPECT_EQ(ps32_result.S16[7], 800);
732
}
733
734
TEST(GSVector4iTest, AdvancedUnpackingWithTwoVectors)
735
{
736
GSVector4i v1(s8t(0x11), s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88), s8t(0x99),
737
s8t(0xAA), s8t(0xBB), s8t(0xCC), s8t(0xDD), s8t(0xEE), s8t(0xFF), s8t(0x00));
738
GSVector4i v2(s8t(0xA1), s8t(0xB2), s8t(0xC3), s8t(0xD4), s8t(0xE5), s8t(0xF6), s8t(0x07), s8t(0x18), s8t(0x29),
739
s8t(0x3A), s8t(0x4B), s8t(0x5C), s8t(0x6D), s8t(0x7E), s8t(0x8F), s8t(0x90));
740
741
auto upl8_result = v1.upl8(v2);
742
// Should interleave low 8 bytes from both vectors
743
EXPECT_EQ(upl8_result.S8[0], s8t(0x11)); // v1[0]
744
EXPECT_EQ(upl8_result.S8[1], s8t(0xA1)); // v2[0]
745
EXPECT_EQ(upl8_result.S8[2], s8t(0x22)); // v1[1]
746
EXPECT_EQ(upl8_result.S8[3], s8t(0xB2)); // v2[1]
747
748
auto uph8_result = v1.uph8(v2);
749
// Should interleave high 8 bytes from both vectors
750
EXPECT_EQ(uph8_result.S8[0], s8t(0x99)); // v1[8]
751
EXPECT_EQ(uph8_result.S8[1], s8t(0x29)); // v2[8]
752
EXPECT_EQ(uph8_result.S8[2], s8t(0xAA)); // v1[9]
753
EXPECT_EQ(uph8_result.S8[3], s8t(0x3A)); // v2[9]
754
}
755
756
TEST(GSVector4iTest, Type64BitConversions)
757
{
758
GSVector4i v1(s8t(0x12), s8t(0x34), s8t(0x56), s8t(0x78), s8t(0x9A), s8t(0xBC), s8t(0xDE), s8t(0xF0), s8t(0x11),
759
s8t(0x22), s8t(0x33), s8t(0x44), s8t(0x55), s8t(0x66), s8t(0x77), s8t(0x88));
760
761
// Test s8to64
762
auto s8to64_result = v1.s8to64();
763
EXPECT_EQ(s8to64_result.S64[0], 0x12);
764
EXPECT_EQ(s8to64_result.S64[1], 0x34);
765
766
// Test u16to64
767
auto u16to64_result = v1.u16to64();
768
EXPECT_EQ(u16to64_result.U64[0], 0x3412u); // Little endian 16-bit
769
EXPECT_EQ(u16to64_result.U64[1], 0x7856u);
770
771
// Test s32to64
772
auto s32to64_result = v1.s32to64();
773
EXPECT_EQ(s32to64_result.S64[0], static_cast<s64>(0x0000000078563412LL));
774
EXPECT_EQ(s32to64_result.S64[1], static_cast<s64>(0xFFFFFFFFF0DEBC9ALL));
775
}
776
777
TEST(GSVector4iTest, Shift64BitOperations)
778
{
779
GSVector4i v1;
780
v1.U64[0] = 0x123456789ABCDEF0ULL;
781
v1.U64[1] = 0xFEDCBA0987654321ULL;
782
783
// Test sll64
784
auto sll64_result = v1.sll64<4>();
785
EXPECT_EQ(sll64_result.U64[0], 0x23456789ABCDEF00ULL);
786
EXPECT_EQ(sll64_result.U64[1], 0xEDCBA09876543210ULL);
787
788
// Test srl64
789
auto srl64_result = v1.srl64<4>();
790
EXPECT_EQ(srl64_result.U64[0], 0x0123456789ABCDEFULL);
791
EXPECT_EQ(srl64_result.U64[1], 0x0FEDCBA098765432ULL);
792
}
793
794
#ifdef GSVECTOR_HAS_SRLV
795
TEST(GSVector4iTest, VariableShifts)
796
{
797
GSVector4i v1(0x1000, 0x2000, 0x4000, 0x8000, 0x1000, 0x2000, 0x4000, 0x8000);
798
GSVector4i shift_amounts(1, 2, 3, 4, 1, 2, 3, 4);
799
800
auto sllv16_result = v1.sllv16(shift_amounts);
801
EXPECT_EQ(sllv16_result.U16[0], 0x2000); // 0x1000 << 1
802
EXPECT_EQ(sllv16_result.U16[1], 0x8000); // 0x2000 << 2
803
EXPECT_EQ(sllv16_result.U16[2], 0x0000); // 0x4000 << 3 (overflow)
804
EXPECT_EQ(sllv16_result.U16[3], 0x0000); // 0x8000 << 4 (overflow)
805
EXPECT_EQ(sllv16_result.U16[4], 0x2000); // 0x1000 << 1
806
EXPECT_EQ(sllv16_result.U16[5], 0x8000); // 0x2000 << 2
807
EXPECT_EQ(sllv16_result.U16[6], 0x0000); // 0x4000 << 3 (overflow)
808
EXPECT_EQ(sllv16_result.U16[7], 0x0000); // 0x8000 << 4 (overflow)
809
810
auto srlv16_result = v1.srlv16(shift_amounts);
811
EXPECT_EQ(srlv16_result.U16[0], 0x0800); // 0x1000 >> 1
812
EXPECT_EQ(srlv16_result.U16[1], 0x0800); // 0x2000 >> 2
813
EXPECT_EQ(srlv16_result.U16[2], 0x0800); // 0x4000 >> 3
814
EXPECT_EQ(srlv16_result.U16[3], 0x0800); // 0x8000 >> 4
815
EXPECT_EQ(srlv16_result.U16[4], 0x0800); // 0x1000 >> 1
816
EXPECT_EQ(srlv16_result.U16[5], 0x0800); // 0x2000 >> 2
817
EXPECT_EQ(srlv16_result.U16[6], 0x0800); // 0x4000 >> 3
818
EXPECT_EQ(srlv16_result.U16[7], 0x0800); // 0x8000 >> 4
819
}
820
#endif
821
822
TEST(GSVector4iTest, MultiplicationOperations)
823
{
824
GSVector4i v1(10, 20, 30, 40, 50, 60, 70, 80);
825
GSVector4i v2(2, 3, 4, 5, 6, 7, 8, 9);
826
827
// Test mul16hs - high 16 bits of 16-bit multiplication
828
auto mul16hs_result = v1.mul16hs(v2);
829
// For 16-bit values, this should mostly be 0 unless we have large values
830
for (int i = 0; i < 8; i++)
831
{
832
s32 expected = (v1.S16[i] * v2.S16[i]) >> 16;
833
EXPECT_EQ(mul16hs_result.S16[i], expected);
834
}
835
836
// Test mul16hrs - rounded high 16 bits
837
auto mul16hrs_result = v1.mul16hrs(v2);
838
for (int i = 0; i < 8; i++)
839
{
840
const s16 expected = static_cast<s16>((((v1.S16[i] * v2.S16[i]) >> 14) + 1) >> 1);
841
EXPECT_EQ(mul16hrs_result.S16[i], expected);
842
}
843
}
844
845
TEST(GSVector4iTest, Eq64Operations)
846
{
847
GSVector4i v1;
848
GSVector4i v2;
849
v1.S64[0] = 0x123456789ABCDEF0LL;
850
v1.S64[1] = 0xFEDCBA0987654321LL;
851
v2.S64[0] = 0x123456789ABCDEF0LL; // Same as v1[0]
852
v2.S64[1] = 0x1111111111111111LL; // Different from v1[1]
853
854
auto eq64_result = v1.eq64(v2);
855
EXPECT_EQ(eq64_result.S64[0], -1); // Equal
856
EXPECT_EQ(eq64_result.S64[1], 0); // Not equal
857
}
858
859
TEST(GSVector4iTest, InsertExtract64Bit)
860
{
861
GSVector4i v1(0x12345678, 0x9ABCDEF0, 0x11111111, 0x22222222);
862
863
// Test insert64
864
auto v_insert64 = v1.insert64<0>(static_cast<s64>(0x9999888877776666ULL));
865
EXPECT_EQ(v_insert64.extract64<0>(), static_cast<s64>(0x9999888877776666ULL));
866
EXPECT_EQ(v_insert64.extract64<1>(), v1.extract64<1>());
867
868
// Test extract64
869
EXPECT_EQ(v1.extract64<0>(), static_cast<s64>(0x9ABCDEF012345678ULL)); // Little endian combination
870
EXPECT_EQ(v1.extract64<1>(), static_cast<s64>(0x2222222211111111ULL));
871
}
872
873
TEST(GSVector4iTest, LoadStoreSpecialOperations)
874
{
875
// Test loadnt (non-temporal load)
876
alignas(VECTOR_ALIGNMENT) static constexpr const s32 data[4] = {0x11111111, 0x22222222, 0x33333333, 0x44444444};
877
auto loaded_nt = GSVector4i::loadnt(data);
878
for (int i = 0; i < 4; i++)
879
{
880
EXPECT_EQ(loaded_nt.S32[i], data[i]);
881
}
882
883
// Test storent (non-temporal store)
884
alignas(VECTOR_ALIGNMENT) s32 output_nt[4];
885
GSVector4i::storent(output_nt, loaded_nt);
886
for (int i = 0; i < 4; i++)
887
{
888
EXPECT_EQ(output_nt[i], data[i]);
889
}
890
891
// Test zext32
892
auto zext_result = GSVector4i::zext32(0x12345678);
893
EXPECT_EQ(zext_result.x, 0x12345678);
894
EXPECT_EQ(zext_result.y, 0);
895
EXPECT_EQ(zext_result.z, 0);
896
EXPECT_EQ(zext_result.w, 0);
897
}
898
899
TEST(GSVector4iTest, LoadStoreHalfOperations)
900
{
901
// Test loadl and loadh
902
u64 data[2] = {0x123456789ABCDEF0ULL, 0xFEDCBA0987654321ULL};
903
904
auto loaded_low = GSVector4i::loadl<true>(data);
905
EXPECT_EQ(loaded_low.U64[0], data[0]);
906
EXPECT_EQ(loaded_low.U64[1], 0u);
907
908
auto loaded_high = GSVector4i::loadh<true>(data);
909
EXPECT_EQ(loaded_high.U64[0], 0u);
910
EXPECT_EQ(loaded_high.U64[1], data[0]);
911
912
// Test storel and storeh
913
GSVector4i test_vec;
914
test_vec.U64[0] = 0xAAAABBBBCCCCDDDDULL;
915
test_vec.U64[1] = 0xEEEEFFFF00001111ULL;
916
917
s32 output_low[2];
918
GSVector4i::storel<true>(output_low, test_vec);
919
EXPECT_EQ(reinterpret_cast<u64*>(output_low)[0], test_vec.U64[0]);
920
921
s32 output_high[2];
922
GSVector4i::storeh<true>(output_high, test_vec);
923
EXPECT_EQ(reinterpret_cast<u64*>(output_high)[0], test_vec.U64[1]);
924
}
925
926
TEST(GSVector4iTest, BroadcastOperations)
927
{
928
GSVector4i v1(10, 20, 30, 40);
929
930
auto broadcast_result = GSVector4i::broadcast128(v1);
931
// In no-SIMD implementation, this just returns the same vector
932
EXPECT_EQ(broadcast_result.x, v1.x);
933
EXPECT_EQ(broadcast_result.y, v1.y);
934
EXPECT_EQ(broadcast_result.z, v1.z);
935
EXPECT_EQ(broadcast_result.w, v1.w);
936
}
937
938
TEST(GSVector4iTest, StaticHelperFunctions)
939
{
940
GSVector2i xy(10, 20);
941
GSVector2i zw(30, 40);
942
943
auto xyxy_result1 = GSVector4i::xyxy(xy, zw);
944
EXPECT_EQ(xyxy_result1.x, 10);
945
EXPECT_EQ(xyxy_result1.y, 20);
946
EXPECT_EQ(xyxy_result1.z, 30);
947
EXPECT_EQ(xyxy_result1.w, 40);
948
949
auto xyxy_result2 = GSVector4i::xyxy(xy);
950
EXPECT_EQ(xyxy_result2.x, 10);
951
EXPECT_EQ(xyxy_result2.y, 20);
952
EXPECT_EQ(xyxy_result2.z, 10);
953
EXPECT_EQ(xyxy_result2.w, 20);
954
}
955
956
// GSVector4 Tests
957
TEST(GSVector4Test, DoubleOperations)
958
{
959
// Test all 64-bit double operations
960
GSVector4 v1 = GSVector4::f64(3.14159, 2.71828);
961
GSVector4 v2 = GSVector4::f64(1.41421, 1.73205);
962
963
auto add64_result = v1.add64(v2);
964
EXPECT_DOUBLE_EQ(add64_result.F64[0], 3.14159 + 1.41421);
965
EXPECT_DOUBLE_EQ(add64_result.F64[1], 2.71828 + 1.73205);
966
967
auto sub64_result = v1.sub64(v2);
968
EXPECT_DOUBLE_EQ(sub64_result.F64[0], 3.14159 - 1.41421);
969
EXPECT_DOUBLE_EQ(sub64_result.F64[1], 2.71828 - 1.73205);
970
971
auto mul64_result = v1.mul64(v2);
972
EXPECT_DOUBLE_EQ(mul64_result.F64[0], 3.14159 * 1.41421);
973
EXPECT_DOUBLE_EQ(mul64_result.F64[1], 2.71828 * 1.73205);
974
975
auto div64_result = v1.div64(v2);
976
EXPECT_DOUBLE_EQ(div64_result.F64[0], 3.14159 / 1.41421);
977
EXPECT_DOUBLE_EQ(div64_result.F64[1], 2.71828 / 1.73205);
978
}
979
980
TEST(GSVector4Test, BasicOps)
981
{
982
GSVector4 v(1.0f, -2.0f, 3.5f, -4.5f);
983
984
EXPECT_FLOAT_EQ(v.addv(), (1.0f - 2.0f + 3.5f - 4.5f));
985
EXPECT_FLOAT_EQ(v.minv(), -4.5f);
986
EXPECT_FLOAT_EQ(v.maxv(), 3.5f);
987
988
auto av = v.abs();
989
EXPECT_FLOAT_EQ(av.x, 1.0f);
990
EXPECT_FLOAT_EQ(av.y, 2.0f);
991
EXPECT_FLOAT_EQ(av.z, 3.5f);
992
EXPECT_FLOAT_EQ(av.w, 4.5f);
993
994
auto nv = v.neg();
995
EXPECT_FLOAT_EQ(nv.x, -1.0f);
996
EXPECT_FLOAT_EQ(nv.y, 2.0f);
997
EXPECT_FLOAT_EQ(nv.z, -3.5f);
998
EXPECT_FLOAT_EQ(nv.w, 4.5f);
999
1000
auto fl = GSVector4(1.9f, -1.2f, 3.01f, -3.99f).floor();
1001
EXPECT_FLOAT_EQ(fl.x, 1.0f);
1002
EXPECT_FLOAT_EQ(fl.y, -2.0f);
1003
EXPECT_FLOAT_EQ(fl.z, 3.0f);
1004
EXPECT_FLOAT_EQ(fl.w, -4.0f);
1005
1006
auto cl = GSVector4(1.1f, -1.2f, 3.01f, -3.99f).ceil();
1007
EXPECT_FLOAT_EQ(cl.x, 2.0f);
1008
EXPECT_FLOAT_EQ(cl.y, -1.0f);
1009
EXPECT_FLOAT_EQ(cl.z, 4.0f);
1010
EXPECT_FLOAT_EQ(cl.w, -3.0f);
1011
1012
// sat(scale)
1013
auto sat_scaled = GSVector4(-5.0f, 10.0f, 500.0f, 260.0f).sat(255.0f);
1014
EXPECT_FLOAT_EQ(sat_scaled.x, 0.0f);
1015
EXPECT_FLOAT_EQ(sat_scaled.y, 10.0f);
1016
EXPECT_FLOAT_EQ(sat_scaled.z, 255.0f);
1017
EXPECT_FLOAT_EQ(sat_scaled.w, 255.0f);
1018
1019
// sat(minmax vector) : x/z clamped to [min.x, min.z], y/w to [min.y, min.w]
1020
GSVector4 range(0.0f, -1.0f, 2.0f, 1.0f);
1021
auto sat_pair = v.sat(range);
1022
EXPECT_FLOAT_EQ(sat_pair.x, 1.0f); // within [0,2]
1023
EXPECT_FLOAT_EQ(sat_pair.y, -1.0f); // clamped to -1
1024
EXPECT_FLOAT_EQ(sat_pair.z, 2.0f); // clamped to 2
1025
EXPECT_FLOAT_EQ(sat_pair.w, -1.0f); // clamped to -1
1026
}
1027
1028
TEST(GSVector4Test, BlendAndMask)
1029
{
1030
GSVector4 a(1, 2, 3, 4);
1031
GSVector4 b(5, 6, 7, 8);
1032
1033
// Template blend32<mask> (selects only lanes 0/1 from the 'v' argument per bit)
1034
auto tb = a.blend32<0b1010>(b);
1035
EXPECT_FLOAT_EQ(tb.x, 1.0f); // bit0 = 0 -> v[0]
1036
EXPECT_FLOAT_EQ(tb.y, 6.0f); // bit1 = 1 -> v[1]
1037
EXPECT_FLOAT_EQ(tb.z, 3.0f); // bit2 = 0 -> v[0]
1038
EXPECT_FLOAT_EQ(tb.w, 8.0f); // bit3 = 1 -> v[1]
1039
1040
// Masked blend: high bit set -> take from second vector argument (b); else from 'a'
1041
GSVector4 mask;
1042
mask.U32[0] = 0x00000000u;
1043
mask.U32[1] = 0x80000000u;
1044
mask.U32[2] = 0x00000000u;
1045
mask.U32[3] = 0x80000000u;
1046
auto mb = a.blend32(b, mask);
1047
EXPECT_FLOAT_EQ(mb.x, a.x);
1048
EXPECT_FLOAT_EQ(mb.y, b.y);
1049
EXPECT_FLOAT_EQ(mb.z, a.z);
1050
EXPECT_FLOAT_EQ(mb.w, b.w);
1051
1052
// mask() bit packing (bits 31,23,15,7)
1053
GSVector4 m;
1054
m.U32[0] = 0x80000000u; // sets bit 0
1055
m.U32[1] = 0x40000000u; // sets bit 1
1056
m.U32[2] = 0x20000000u; // sets bit 2
1057
m.U32[3] = 0x10000000u; // sets bit 3
1058
EXPECT_EQ(m.mask(), 0x1);
1059
}
1060
1061
TEST(GSVector4Test, HorizontalAndInterleave)
1062
{
1063
GSVector4 v(1, 2, 10, 20);
1064
auto hadd0 = v.hadd();
1065
EXPECT_FLOAT_EQ(hadd0.x, 3);
1066
EXPECT_FLOAT_EQ(hadd0.y, 30);
1067
EXPECT_FLOAT_EQ(hadd0.z, 3);
1068
EXPECT_FLOAT_EQ(hadd0.w, 30);
1069
1070
auto hsub0 = v.hsub();
1071
EXPECT_FLOAT_EQ(hsub0.x, -1);
1072
EXPECT_FLOAT_EQ(hsub0.y, -10);
1073
EXPECT_FLOAT_EQ(hsub0.z, -1);
1074
EXPECT_FLOAT_EQ(hsub0.w, -10);
1075
1076
GSVector4 v2(3, 4, 5, 6);
1077
auto hadd1 = v.hadd(v2);
1078
EXPECT_FLOAT_EQ(hadd1.x, 3);
1079
EXPECT_FLOAT_EQ(hadd1.y, 30);
1080
EXPECT_FLOAT_EQ(hadd1.z, 7);
1081
EXPECT_FLOAT_EQ(hadd1.w, 11);
1082
1083
auto hsub1 = v.hsub(v2);
1084
EXPECT_FLOAT_EQ(hsub1.x, -1);
1085
EXPECT_FLOAT_EQ(hsub1.y, -10);
1086
EXPECT_FLOAT_EQ(hsub1.z, -1);
1087
EXPECT_FLOAT_EQ(hsub1.w, -1);
1088
1089
// Interleave / low-high helpers
1090
GSVector4 a(1, 2, 3, 4);
1091
GSVector4 b(5, 6, 7, 8);
1092
auto upl = a.upl(b);
1093
EXPECT_FLOAT_EQ(upl.x, 1);
1094
EXPECT_FLOAT_EQ(upl.y, 5);
1095
EXPECT_FLOAT_EQ(upl.z, 2);
1096
EXPECT_FLOAT_EQ(upl.w, 6);
1097
auto uph = a.uph(b);
1098
EXPECT_FLOAT_EQ(uph.x, 3);
1099
EXPECT_FLOAT_EQ(uph.y, 7);
1100
EXPECT_FLOAT_EQ(uph.z, 4);
1101
EXPECT_FLOAT_EQ(uph.w, 8);
1102
auto l2h = a.l2h(b);
1103
EXPECT_FLOAT_EQ(l2h.x, 1);
1104
EXPECT_FLOAT_EQ(l2h.y, 2);
1105
EXPECT_FLOAT_EQ(l2h.z, 5);
1106
EXPECT_FLOAT_EQ(l2h.w, 6);
1107
auto h2l = a.h2l(b);
1108
EXPECT_FLOAT_EQ(h2l.x, 7);
1109
EXPECT_FLOAT_EQ(h2l.y, 8);
1110
EXPECT_FLOAT_EQ(h2l.z, 3);
1111
EXPECT_FLOAT_EQ(h2l.w, 4);
1112
}
1113
1114
TEST(GSVector4Test, BroadcastAndInsertExtract)
1115
{
1116
GSVector4 v(9, 2, 3, 4);
1117
auto bc_self = v.broadcast32();
1118
EXPECT_FLOAT_EQ(bc_self.x, 9);
1119
EXPECT_FLOAT_EQ(bc_self.y, 9);
1120
EXPECT_FLOAT_EQ(bc_self.z, 9);
1121
EXPECT_FLOAT_EQ(bc_self.w, 9);
1122
1123
auto bc_static = GSVector4::broadcast32(v);
1124
EXPECT_FLOAT_EQ(bc_static.z, 9);
1125
1126
GSVector4 a(1, 2, 3, 4);
1127
GSVector4 b(5, 6, 7, 8);
1128
auto ins_from_other = a.insert32<2, 0>(b); // copy b.z into a.x
1129
EXPECT_FLOAT_EQ(ins_from_other.x, 7);
1130
EXPECT_FLOAT_EQ(ins_from_other.y, 2);
1131
EXPECT_FLOAT_EQ(ins_from_other.z, 3);
1132
EXPECT_FLOAT_EQ(ins_from_other.w, 4);
1133
1134
auto ins_scalar = a.insert32<1>(42.0f);
1135
EXPECT_FLOAT_EQ(ins_scalar.x, 1);
1136
EXPECT_FLOAT_EQ(ins_scalar.y, 42.0f);
1137
EXPECT_FLOAT_EQ(ins_scalar.z, 3);
1138
EXPECT_FLOAT_EQ(ins_scalar.w, 4);
1139
1140
EXPECT_FLOAT_EQ(a.extract32<0>(), 1.0f);
1141
EXPECT_FLOAT_EQ(a.extract32<3>(), 4.0f);
1142
}
1143
1144
TEST(GSVector4Test, BitwiseAndAndNot)
1145
{
1146
GSVector4 a;
1147
a.U32[0] = 0xFFFFFFFFu;
1148
a.U32[1] = 0x00FF00FFu;
1149
a.U32[2] = 0x12345678u;
1150
a.U32[3] = 0xAAAAAAAAu;
1151
1152
GSVector4 b;
1153
b.U32[0] = 0x0F0F0F0Fu;
1154
b.U32[1] = 0xFF00FF00u;
1155
b.U32[2] = 0xFFFFFFFFu;
1156
b.U32[3] = 0x55555555u;
1157
1158
auto vand = a & b;
1159
EXPECT_EQ(vand.U32[0], 0x0F0F0F0Fu);
1160
EXPECT_EQ(vand.U32[1], 0x00000000u);
1161
EXPECT_EQ(vand.U32[2], 0x12345678u);
1162
EXPECT_EQ(vand.U32[3], 0x00000000u);
1163
1164
auto vor = a | b;
1165
EXPECT_EQ(vor.U32[0], 0xFFFFFFFFu);
1166
EXPECT_EQ(vor.U32[1], 0xFFFFFFFFu);
1167
EXPECT_EQ(vor.U32[2], 0xFFFFFFFFu);
1168
EXPECT_EQ(vor.U32[3], 0xFFFFFFFFu);
1169
1170
auto vxor = a ^ b;
1171
EXPECT_EQ(vxor.U32[0], 0xF0F0F0F0u);
1172
EXPECT_EQ(vxor.U32[1], 0xFFFFFFFFu);
1173
EXPECT_EQ(vxor.U32[2], 0xEDCBA987u);
1174
EXPECT_EQ(vxor.U32[3], 0xFFFFFFFFu);
1175
1176
auto an = a.andnot(b); // (~b) & a
1177
EXPECT_EQ(an.U32[0], (~b.U32[0]) & a.U32[0]);
1178
EXPECT_EQ(an.U32[1], (~b.U32[1]) & a.U32[1]);
1179
EXPECT_EQ(an.U32[2], (~b.U32[2]) & a.U32[2]);
1180
EXPECT_EQ(an.U32[3], (~b.U32[3]) & a.U32[3]);
1181
}
1182
1183
TEST(GSVector4Test, ReplaceNaN)
1184
{
1185
GSVector4 v(1.0f, std::numeric_limits<float>::quiet_NaN(), -5.0f, std::numeric_limits<float>::quiet_NaN());
1186
GSVector4 repl(10.0f, 20.0f, 30.0f, 40.0f);
1187
auto r = v.replace_nan(repl);
1188
EXPECT_FLOAT_EQ(r.x, 1.0f); // kept
1189
EXPECT_FLOAT_EQ(r.y, 20.0f); // replaced
1190
EXPECT_FLOAT_EQ(r.z, -5.0f); // kept
1191
EXPECT_FLOAT_EQ(r.w, 40.0f); // replaced
1192
}
1193
1194
TEST(GSVector4Test, DoubleExtendedOps)
1195
{
1196
GSVector4 d = GSVector4::f64(-4.0, 9.0);
1197
auto sq = d.sqr64();
1198
EXPECT_DOUBLE_EQ(sq.F64[0], 16.0);
1199
EXPECT_DOUBLE_EQ(sq.F64[1], 81.0);
1200
1201
auto rt = GSVector4::f64(4.0, 9.0).sqrt64();
1202
EXPECT_DOUBLE_EQ(rt.F64[0], 2.0);
1203
EXPECT_DOUBLE_EQ(rt.F64[1], 3.0);
1204
1205
auto ab = d.abs64();
1206
EXPECT_DOUBLE_EQ(ab.F64[0], 4.0);
1207
EXPECT_DOUBLE_EQ(ab.F64[1], 9.0);
1208
1209
auto ng = d.neg64();
1210
EXPECT_DOUBLE_EQ(ng.F64[0], 4.0);
1211
EXPECT_DOUBLE_EQ(ng.F64[1], -9.0);
1212
1213
GSVector4 d2 = GSVector4::f64(-2.0, 10.0);
1214
EXPECT_DOUBLE_EQ(d.min64(d2).F64[0], -4.0);
1215
EXPECT_DOUBLE_EQ(d.min64(d2).F64[1], 9.0);
1216
EXPECT_DOUBLE_EQ(d.max64(d2).F64[0], -2.0);
1217
EXPECT_DOUBLE_EQ(d.max64(d2).F64[1], 10.0);
1218
1219
auto gt = d.gt64(d2);
1220
EXPECT_EQ(gt.U64[0], 0ULL); // -4 > -2 ? no
1221
EXPECT_EQ(gt.U64[1], 0ULL); // 9 > 10 ? no
1222
auto lt = d.lt64(d2);
1223
EXPECT_NE(lt.U64[0], 0ULL); // -4 < -2
1224
EXPECT_NE(lt.U64[1], 0ULL); // 9 < 10
1225
auto ge = d.ge64(d2);
1226
EXPECT_EQ(ge.U64[0], 0ULL); // -4 >= -2 ? no
1227
EXPECT_EQ(ge.U64[1], 0ULL); // 9 >= 10 ? no
1228
auto le = d.le64(d2);
1229
EXPECT_NE(le.U64[0], 0ULL);
1230
EXPECT_NE(le.U64[1], 0ULL);
1231
auto eq = d.eq64(d);
1232
EXPECT_EQ(eq.U64[0], 0xFFFFFFFFFFFFFFFFULL);
1233
EXPECT_EQ(eq.U64[1], 0xFFFFFFFFFFFFFFFFULL);
1234
}
1235
1236
TEST(GSVector4Test, FloatToDoubleConversions)
1237
{
1238
GSVector4 vf(1.25f, 2.75f, 3.0f, 4.0f);
1239
auto fd = GSVector4::f32to64(vf);
1240
EXPECT_DOUBLE_EQ(fd.F64[0], 1.25);
1241
EXPECT_DOUBLE_EQ(fd.F64[1], 2.75);
1242
1243
GSVector4 vd = GSVector4::f64(5.9, -2.1);
1244
auto i32 = vd.f64toi32();
1245
EXPECT_EQ(i32.S32[0], 5);
1246
EXPECT_EQ(i32.S32[1], -2);
1247
}
1248
1249
// Cross-class conversion tests
1250
TEST(GSVectorTest, ConversionsGSVector2iGSVector2)
1251
{
1252
GSVector2i vi(42, 84);
1253
GSVector2 vf(vi);
1254
EXPECT_FLOAT_EQ(vf.x, 42.0f);
1255
EXPECT_FLOAT_EQ(vf.y, 84.0f);
1256
1257
GSVector2 vf2(3.14f, 2.71f);
1258
GSVector2i vi2(vf2);
1259
EXPECT_EQ(vi2.x, 3);
1260
EXPECT_EQ(vi2.y, 2);
1261
1262
// Test cast operations
1263
auto cast_result = GSVector2::cast(vi);
1264
// Cast preserves bit pattern, so we can't directly compare float values
1265
EXPECT_EQ(cast_result.I32[0], 42);
1266
EXPECT_EQ(cast_result.I32[1], 84);
1267
1268
auto cast_result2 = GSVector2i::cast(vf2);
1269
// Cast preserves bit pattern
1270
EXPECT_EQ(cast_result2.U32[0], vf2.U32[0]);
1271
EXPECT_EQ(cast_result2.U32[1], vf2.U32[1]);
1272
}
1273
1274
// width() tests
1275
TEST(GSVectorTest, Width_ReturnsCorrectValue)
1276
{
1277
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1278
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1279
1280
EXPECT_FLOAT_EQ(rect1.width(), 40.0f); // 50 - 10 = 40
1281
EXPECT_FLOAT_EQ(rect2.width(), 70.0f); // 100 - 30 = 70
1282
}
1283
1284
TEST(GSVectorTest, Width_EmptyRect_ReturnsZero)
1285
{
1286
const GSVector4 emptyRect = GSVector4(0.0f, 0.0f, 0.0f, 0.0f);
1287
const GSVector4 zeroSizeRect = GSVector4(25.0f, 35.0f, 25.0f, 35.0f);
1288
1289
EXPECT_FLOAT_EQ(emptyRect.width(), 0.0f);
1290
EXPECT_FLOAT_EQ(zeroSizeRect.width(), 0.0f);
1291
}
1292
1293
TEST(GSVectorTest, Width_InvalidRect_ReturnsNegative)
1294
{
1295
const GSVector4 invalidRect = GSVector4(50.0f, 80.0f, 10.0f, 20.0f); // right < left, bottom < top
1296
1297
EXPECT_FLOAT_EQ(invalidRect.width(), -40.0f); // 10 - 50 = -40
1298
}
1299
1300
// height() tests
1301
TEST(GSVectorTest, Height_ReturnsCorrectValue)
1302
{
1303
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1304
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1305
1306
EXPECT_FLOAT_EQ(rect1.height(), 60.0f); // 80 - 20 = 60
1307
EXPECT_FLOAT_EQ(rect2.height(), 80.0f); // 120 - 40 = 80
1308
}
1309
1310
TEST(GSVectorTest, Height_EmptyRect_ReturnsZero)
1311
{
1312
const GSVector4 emptyRect = GSVector4(0.0f, 0.0f, 0.0f, 0.0f);
1313
const GSVector4 zeroSizeRect = GSVector4(25.0f, 35.0f, 25.0f, 35.0f);
1314
1315
EXPECT_FLOAT_EQ(emptyRect.height(), 0.0f);
1316
EXPECT_FLOAT_EQ(zeroSizeRect.height(), 0.0f);
1317
}
1318
1319
TEST(GSVectorTest, Height_InvalidRect_ReturnsNegative)
1320
{
1321
const GSVector4 invalidRect = GSVector4(50.0f, 80.0f, 10.0f, 20.0f); // right < left, bottom < top
1322
1323
EXPECT_FLOAT_EQ(invalidRect.height(), -60.0f); // 20 - 80 = -60
1324
}
1325
1326
// rsize() tests
1327
TEST(GSVectorTest, Rsize_ReturnsCorrectSize)
1328
{
1329
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1330
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1331
1332
GSVector2 size1 = rect1.rsize();
1333
EXPECT_FLOAT_EQ(size1.x, 40.0f);
1334
EXPECT_FLOAT_EQ(size1.y, 60.0f);
1335
1336
GSVector2 size2 = rect2.rsize();
1337
EXPECT_FLOAT_EQ(size2.x, 70.0f);
1338
EXPECT_FLOAT_EQ(size2.y, 80.0f);
1339
}
1340
1341
TEST(GSVectorTest, Rsize_EmptyRect_ReturnsZeroSize)
1342
{
1343
const GSVector4 emptyRect = GSVector4(0.0f, 0.0f, 0.0f, 0.0f);
1344
1345
GSVector2 size = emptyRect.rsize();
1346
EXPECT_FLOAT_EQ(size.x, 0.0f);
1347
EXPECT_FLOAT_EQ(size.y, 0.0f);
1348
}
1349
1350
// rvalid() tests
1351
TEST(GSVectorTest, Rvalid_ValidRect_ReturnsTrue)
1352
{
1353
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1354
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1355
EXPECT_TRUE(rect1.rvalid());
1356
EXPECT_TRUE(rect2.rvalid());
1357
}
1358
1359
TEST(GSVectorTest, Rvalid_EmptyRect_ReturnsFalse)
1360
{
1361
const GSVector4 emptyRect = GSVector4(0.0f, 0.0f, 0.0f, 0.0f);
1362
const GSVector4 zeroSizeRect = GSVector4(25.0f, 35.0f, 25.0f, 35.0f);
1363
1364
// Empty rect where left==right and top==bottom is considered invalid
1365
EXPECT_FALSE(emptyRect.rvalid());
1366
EXPECT_FALSE(zeroSizeRect.rvalid());
1367
}
1368
1369
TEST(GSVectorTest, Rvalid_InvalidRect_ReturnsFalse)
1370
{
1371
const GSVector4 invalidRect = GSVector4(50.0f, 80.0f, 10.0f, 20.0f); // right < left, bottom < top
1372
EXPECT_FALSE(invalidRect.rvalid());
1373
}
1374
1375
TEST(GSVectorTest, Rvalid_PartiallyInvalid_ReturnsFalse)
1376
{
1377
const GSVector4 invalidWidth(50.0f, 20.0f, 10.0f, 80.0f); // right < left
1378
const GSVector4 invalidHeight(10.0f, 80.0f, 50.0f, 20.0f); // bottom < top
1379
1380
EXPECT_FALSE(invalidWidth.rvalid());
1381
EXPECT_FALSE(invalidHeight.rvalid());
1382
}
1383
1384
// rempty() tests
1385
TEST(GSVectorTest, Rempty_EmptyRect_ReturnsTrue)
1386
{
1387
const GSVector4 emptyRect = GSVector4(0.0f, 0.0f, 0.0f, 0.0f);
1388
const GSVector4 zeroSizeRect = GSVector4(25.0f, 35.0f, 25.0f, 35.0f);
1389
EXPECT_TRUE(emptyRect.rempty());
1390
EXPECT_TRUE(zeroSizeRect.rempty());
1391
}
1392
1393
TEST(GSVectorTest, Rempty_NonEmptyRect_ReturnsFalse)
1394
{
1395
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1396
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1397
EXPECT_FALSE(rect1.rempty());
1398
EXPECT_FALSE(rect2.rempty());
1399
}
1400
1401
TEST(GSVectorTest, Rempty_ZeroWidthOnly_ReturnsTrue)
1402
{
1403
GSVector4 zeroWidth(25.0f, 20.0f, 25.0f, 80.0f); // width = 0, height > 0
1404
EXPECT_TRUE(zeroWidth.rempty());
1405
}
1406
1407
TEST(GSVectorTest, Rempty_ZeroHeightOnly_ReturnsTrue)
1408
{
1409
GSVector4 zeroHeight(10.0f, 50.0f, 40.0f, 50.0f); // width > 0, height = 0
1410
EXPECT_TRUE(zeroHeight.rempty());
1411
}
1412
1413
TEST(GSVectorTest, Rempty_InvalidRect_ReturnsTrue)
1414
{
1415
const GSVector4 invalidRect = GSVector4(50.0f, 80.0f, 10.0f, 20.0f); // right < left, bottom < top
1416
1417
// Invalid rects are considered empty
1418
EXPECT_TRUE(invalidRect.rempty());
1419
}
1420
1421
// runion() tests
1422
TEST(GSVectorTest, Runion_OverlappingRects_ReturnsCorrectUnion)
1423
{
1424
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1425
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1426
1427
GSVector4 result = rect1.runion(rect2);
1428
1429
// Union should be min of lefts/tops and max of rights/bottoms
1430
EXPECT_FLOAT_EQ(result.left, 10.0f); // min(10, 30)
1431
EXPECT_FLOAT_EQ(result.top, 20.0f); // min(20, 40)
1432
EXPECT_FLOAT_EQ(result.right, 100.0f); // max(50, 100)
1433
EXPECT_FLOAT_EQ(result.bottom, 120.0f); // max(80, 120)
1434
}
1435
1436
TEST(GSVectorTest, Runion_NonOverlappingRects_ReturnsEnclosingRect)
1437
{
1438
GSVector4 rectA(0.0f, 0.0f, 10.0f, 10.0f);
1439
GSVector4 rectB(50.0f, 50.0f, 60.0f, 60.0f);
1440
1441
GSVector4 result = rectA.runion(rectB);
1442
1443
EXPECT_FLOAT_EQ(result.left, 0.0f);
1444
EXPECT_FLOAT_EQ(result.top, 0.0f);
1445
EXPECT_FLOAT_EQ(result.right, 60.0f);
1446
EXPECT_FLOAT_EQ(result.bottom, 60.0f);
1447
}
1448
1449
TEST(GSVectorTest, Runion_ContainedRect_ReturnsOuterRect)
1450
{
1451
GSVector4 outer(0.0f, 0.0f, 100.0f, 100.0f);
1452
GSVector4 inner(25.0f, 25.0f, 75.0f, 75.0f);
1453
1454
GSVector4 result = outer.runion(inner);
1455
1456
EXPECT_FLOAT_EQ(result.left, 0.0f);
1457
EXPECT_FLOAT_EQ(result.top, 0.0f);
1458
EXPECT_FLOAT_EQ(result.right, 100.0f);
1459
EXPECT_FLOAT_EQ(result.bottom, 100.0f);
1460
}
1461
1462
TEST(GSVectorTest, Runion_WithEmptyRect_ReturnsOtherRect)
1463
{
1464
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1465
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1466
const GSVector4 emptyRect = GSVector4(0.0f, 0.0f, 0.0f, 0.0f);
1467
1468
GSVector4 result = rect1.runion(emptyRect);
1469
1470
// Union with empty rect at origin
1471
EXPECT_FLOAT_EQ(result.left, 0.0f); // min(10, 0)
1472
EXPECT_FLOAT_EQ(result.top, 0.0f); // min(20, 0)
1473
EXPECT_FLOAT_EQ(result.right, 50.0f); // max(50, 0)
1474
EXPECT_FLOAT_EQ(result.bottom, 80.0f); // max(80, 0)
1475
}
1476
1477
TEST(GSVectorTest, Runion_IdenticalRects_ReturnsSameRect)
1478
{
1479
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1480
1481
GSVector4 result = rect1.runion(rect1);
1482
1483
EXPECT_FLOAT_EQ(result.left, rect1.left);
1484
EXPECT_FLOAT_EQ(result.top, rect1.top);
1485
EXPECT_FLOAT_EQ(result.right, rect1.right);
1486
EXPECT_FLOAT_EQ(result.bottom, rect1.bottom);
1487
}
1488
1489
TEST(GSVectorTest, Runion_NegativeCoordinates_ReturnsCorrectUnion)
1490
{
1491
GSVector4 rectA(-50.0f, -40.0f, -10.0f, -5.0f);
1492
GSVector4 rectB(-30.0f, -20.0f, 10.0f, 15.0f);
1493
1494
GSVector4 result = rectA.runion(rectB);
1495
1496
EXPECT_FLOAT_EQ(result.left, -50.0f); // min(-50, -30)
1497
EXPECT_FLOAT_EQ(result.top, -40.0f); // min(-40, -20)
1498
EXPECT_FLOAT_EQ(result.right, 10.0f); // max(-10, 10)
1499
EXPECT_FLOAT_EQ(result.bottom, 15.0f); // max(-5, 15)
1500
}
1501
1502
TEST(GSVectorTest, Runion_IsCommutative)
1503
{
1504
const GSVector4 rect1 = GSVector4(10.0f, 20.0f, 50.0f, 80.0f); // left=10, top=20, right=50, bottom=80
1505
const GSVector4 rect2 = GSVector4(30.0f, 40.0f, 100.0f, 120.0f);
1506
1507
GSVector4 result1 = rect1.runion(rect2);
1508
GSVector4 result2 = rect2.runion(rect1);
1509
1510
EXPECT_TRUE(result1.eq(result2));
1511
}
1512
1513