blob: afcb6e3d9670d2e86c9f28a444e6435fd1caa6b8 [file] [log] [blame]
Nicolas Capens598f8d82016-09-26 15:09:10 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "Reactor.hpp"
Ben Clayton1c82c7b2019-04-30 12:49:27 +010016#include "Coroutine.hpp"
Nicolas Capens598f8d82016-09-26 15:09:10 -040017
Nicolas Capens228b05d2016-10-12 15:27:04 -040018#include "gtest/gtest.h"
Nicolas Capens598f8d82016-09-26 15:09:10 -040019
Antonio Maioranobf151b82019-12-03 09:49:14 -050020#include <cmath>
Ben Claytonb1243732019-02-27 23:56:18 +000021#include <tuple>
22
Nicolas Capens48461502018-08-06 14:20:45 -040023using namespace rr;
Nicolas Capens598f8d82016-09-26 15:09:10 -040024
Antonio Maioranobf151b82019-12-03 09:49:14 -050025constexpr float PI = 3.141592653589793f;
26
27using float4 = float[4];
28
29// Value type wrapper around a float4
30struct float4_value
31{
32 float4_value() = default;
33 explicit float4_value(float rep) : v{ rep, rep, rep, rep } {}
34 float4_value(float x, float y, float z, float w) : v{ x, y, z, w } {}
35
36 bool operator==(const float4_value &rhs) const
37 {
38 return std::equal(std::begin(v), std::end(v), rhs.v);
39 }
40
41 // For gtest printing
42 friend std::ostream& operator<<(std::ostream& os, const float4_value& value) {
43 return os << "[" << value.v[0] << ", " << value.v[1] << ", " << value.v[2] << ", " << value.v[3] << "]";
44 }
45
46 float4 v;
47};
48
49// For gtest printing of pairs
50namespace std
51{
52 template <typename T, typename U>
53 std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& value) {
54 return os << "{ " << value.first << ", " << value.second << " }";
55 }
56}
57
58
59// Invoke a void(float4*) routine on &v.v, returning wrapped result in v
60template <typename RoutineType>
61float4_value invokeRoutine(RoutineType& routine, float4_value v)
62{
63 routine(&v.v);
64 return v;
65}
66
67// Invoke a void(float4*, float4*) routine on &v1.v, &v2.v returning wrapped result in v1
68template <typename RoutineType>
69float4_value invokeRoutine(RoutineType& routine, float4_value v1, float4_value v2)
70{
71 routine(&v1.v, &v2.v);
72 return v1;
73}
74
Nicolas Capens7d9f76d2016-09-29 13:39:44 -040075int reference(int *p, int y)
76{
Nicolas Capens8820f642016-09-30 04:42:43 -040077 int x = p[-1];
Nicolas Capens7d9f76d2016-09-29 13:39:44 -040078 int z = 4;
79
80 for(int i = 0; i < 10; i++)
81 {
82 z += (2 << i) - (i / 3);
83 }
84
85 int sum = x + y + z;
Nicolas Capens228b05d2016-10-12 15:27:04 -040086
Nicolas Capens7d9f76d2016-09-29 13:39:44 -040087 return sum;
88}
89
Nicolas Capensc07dc4b2018-08-06 14:20:45 -040090TEST(ReactorUnitTests, Sample)
Nicolas Capens598f8d82016-09-26 15:09:10 -040091{
Nicolas Capens157ba262019-12-10 17:49:14 -050092 FunctionT<int(int*, int)> function;
Nicolas Capens598f8d82016-09-26 15:09:10 -040093 {
Nicolas Capens157ba262019-12-10 17:49:14 -050094 Pointer<Int> p = function.Arg<0>();
95 Int x = p[-1];
96 Int y = function.Arg<1>();
97 Int z = 4;
98
99 For(Int i = 0, i < 10, i++)
Nicolas Capens598f8d82016-09-26 15:09:10 -0400100 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500101 z += (2 << i) - (i / 3);
Nicolas Capens598f8d82016-09-26 15:09:10 -0400102 }
103
Nicolas Capens157ba262019-12-10 17:49:14 -0500104 Float4 v;
105 v.z = As<Float>(z);
106 z = As<Int>(Float(Float4(v.xzxx).y));
Nicolas Capens598f8d82016-09-26 15:09:10 -0400107
Nicolas Capens157ba262019-12-10 17:49:14 -0500108 Int sum = x + y + z;
109
110 Return(sum);
Nicolas Capens598f8d82016-09-26 15:09:10 -0400111 }
112
Nicolas Capens157ba262019-12-10 17:49:14 -0500113 auto routine = function("one");
114
115 if(routine)
116 {
117 int one[2] = {1, 0};
118 int result = routine(&one[1], 2);
119 EXPECT_EQ(result, reference(&one[1], 2));
120 }
Nicolas Capens228b05d2016-10-12 15:27:04 -0400121}
Nicolas Capens598f8d82016-09-26 15:09:10 -0400122
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400123TEST(ReactorUnitTests, Uninitialized)
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500124{
Nicolas Capens157ba262019-12-10 17:49:14 -0500125 FunctionT<int()> function;
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500126 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500127 Int a;
128 Int z = 4;
129 Int q;
130 Int c;
131 Int p;
132 Bool b;
133
134 q += q;
135
136 If(b)
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500137 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500138 c = p;
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500139 }
140
Nicolas Capens157ba262019-12-10 17:49:14 -0500141 Return(a + z + q + c);
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500142 }
143
Nicolas Capens157ba262019-12-10 17:49:14 -0500144 auto routine = function("one");
145
146 if(routine)
147 {
148 int result = routine();
149 EXPECT_EQ(result, result); // Anything is fine, just don't crash
150 }
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500151}
152
Nicolas Capens0192d152019-03-27 14:46:07 -0400153TEST(ReactorUnitTests, Unreachable)
154{
Nicolas Capens157ba262019-12-10 17:49:14 -0500155 FunctionT<int(int)> function;
Nicolas Capens0192d152019-03-27 14:46:07 -0400156 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500157 Int a = function.Arg<0>();
158 Int z = 4;
Nicolas Capens0192d152019-03-27 14:46:07 -0400159
Nicolas Capens157ba262019-12-10 17:49:14 -0500160 Return(a + z);
Nicolas Capens0192d152019-03-27 14:46:07 -0400161
Nicolas Capens157ba262019-12-10 17:49:14 -0500162 // Code beyond this point is unreachable but should not cause any
163 // compilation issues.
Nicolas Capens0192d152019-03-27 14:46:07 -0400164
Nicolas Capens157ba262019-12-10 17:49:14 -0500165 z += a;
Nicolas Capens0192d152019-03-27 14:46:07 -0400166 }
167
Nicolas Capens157ba262019-12-10 17:49:14 -0500168 auto routine = function("one");
169
170 if(routine)
171 {
172 int result = routine(16);
173 EXPECT_EQ(result, 20);
174 }
Nicolas Capens0192d152019-03-27 14:46:07 -0400175}
176
177TEST(ReactorUnitTests, VariableAddress)
178{
Nicolas Capens157ba262019-12-10 17:49:14 -0500179 FunctionT<int(int)> function;
Nicolas Capens0192d152019-03-27 14:46:07 -0400180 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500181 Int a = function.Arg<0>();
182 Int z = 0;
183 Pointer<Int> p = &z;
184 *p = 4;
Nicolas Capens0192d152019-03-27 14:46:07 -0400185
Nicolas Capens157ba262019-12-10 17:49:14 -0500186 Return(a + z);
Nicolas Capens0192d152019-03-27 14:46:07 -0400187 }
188
Nicolas Capens157ba262019-12-10 17:49:14 -0500189 auto routine = function("one");
190
191 if(routine)
192 {
193 int result = routine(16);
194 EXPECT_EQ(result, 20);
195 }
Nicolas Capens0192d152019-03-27 14:46:07 -0400196}
197
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400198TEST(ReactorUnitTests, SubVectorLoadStore)
Nicolas Capens23d99a42016-09-30 14:57:16 -0400199{
Nicolas Capens157ba262019-12-10 17:49:14 -0500200 FunctionT<int(void*, void*)> function;
Nicolas Capens23d99a42016-09-30 14:57:16 -0400201 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500202 Pointer<Byte> in = function.Arg<0>();
203 Pointer<Byte> out = function.Arg<1>();
204
205 *Pointer<Int4>(out + 16 * 0) = *Pointer<Int4>(in + 16 * 0);
206 *Pointer<Short4>(out + 16 * 1) = *Pointer<Short4>(in + 16 * 1);
207 *Pointer<Byte8>(out + 16 * 2) = *Pointer<Byte8>(in + 16 * 2);
208 *Pointer<Byte4>(out + 16 * 3) = *Pointer<Byte4>(in + 16 * 3);
209 *Pointer<Short2>(out + 16 * 4) = *Pointer<Short2>(in + 16 * 4);
210
211 Return(0);
212 }
213
214 auto routine = function("one");
215
216 if(routine)
217 {
218 int8_t in[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
219 17, 18, 19, 20, 21, 22, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0,
220 25, 26, 27, 28, 29, 30, 31, 32, 0, 0, 0, 0, 0, 0, 0, 0,
221 33, 34, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
222 37, 38, 39, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
223
224 int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
225 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
226 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
227 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
228 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
229
230 routine(in, out);
231
232 for(int row = 0; row < 5; row++)
Nicolas Capens23d99a42016-09-30 14:57:16 -0400233 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500234 for(int col = 0; col < 16; col++)
Nicolas Capens23d99a42016-09-30 14:57:16 -0400235 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500236 int i = row * 16 + col;
Nicolas Capens23d99a42016-09-30 14:57:16 -0400237
Nicolas Capens157ba262019-12-10 17:49:14 -0500238 if(in[i] == 0)
239 {
240 EXPECT_EQ(out[i], -1) << "Row " << row << " column " << col << " not left untouched.";
241 }
242 else
243 {
244 EXPECT_EQ(out[i], in[i]) << "Row " << row << " column " << col << " not equal to input.";
Nicolas Capens23d99a42016-09-30 14:57:16 -0400245 }
246 }
247 }
248 }
Nicolas Capens23d99a42016-09-30 14:57:16 -0400249}
250
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400251TEST(ReactorUnitTests, VectorConstant)
Nicolas Capens8dfd9a72016-10-13 17:44:51 -0400252{
Nicolas Capens157ba262019-12-10 17:49:14 -0500253 FunctionT<int(void*)> function;
Nicolas Capens8dfd9a72016-10-13 17:44:51 -0400254 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500255 Pointer<Byte> out = function.Arg<0>();
256
257 *Pointer<Int4>(out + 16 * 0) = Int4(0x04030201, 0x08070605, 0x0C0B0A09, 0x100F0E0D);
258 *Pointer<Short4>(out + 16 * 1) = Short4(0x1211, 0x1413, 0x1615, 0x1817);
259 *Pointer<Byte8>(out + 16 * 2) = Byte8(0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20);
260 *Pointer<Int2>(out + 16 * 3) = Int2(0x24232221, 0x28272625);
261
262 Return(0);
263 }
264
265 auto routine = function("one");
266
267 if(routine)
268 {
269 int8_t out[16 * 4] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
270 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
271 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
272 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
273
274 int8_t exp[16 * 4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
275 17, 18, 19, 20, 21, 22, 23, 24, -1, -1, -1, -1, -1, -1, -1, -1,
276 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1,
277 33, 34, 35, 36, 37, 38, 39, 40, -1, -1, -1, -1, -1, -1, -1, -1};
278
279 routine(out);
280
281 for(int row = 0; row < 4; row++)
Nicolas Capens8dfd9a72016-10-13 17:44:51 -0400282 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500283 for(int col = 0; col < 16; col++)
Nicolas Capens8dfd9a72016-10-13 17:44:51 -0400284 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500285 int i = row * 16 + col;
Nicolas Capens8dfd9a72016-10-13 17:44:51 -0400286
Nicolas Capens157ba262019-12-10 17:49:14 -0500287 EXPECT_EQ(out[i], exp[i]);
Nicolas Capens8dfd9a72016-10-13 17:44:51 -0400288 }
289 }
290 }
Nicolas Capens8dfd9a72016-10-13 17:44:51 -0400291}
292
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400293TEST(ReactorUnitTests, Concatenate)
Nicolas Capensc70a1162016-12-03 00:16:14 -0500294{
Nicolas Capens157ba262019-12-10 17:49:14 -0500295 FunctionT<int(void*)> function;
Nicolas Capensc70a1162016-12-03 00:16:14 -0500296 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500297 Pointer<Byte> out = function.Arg<0>();
298
299 *Pointer<Int4>(out + 16 * 0) = Int4(Int2(0x04030201, 0x08070605), Int2(0x0C0B0A09, 0x100F0E0D));
300 *Pointer<Short8>(out + 16 * 1) = Short8(Short4(0x0201, 0x0403, 0x0605, 0x0807), Short4(0x0A09, 0x0C0B, 0x0E0D, 0x100F));
301
302 Return(0);
303 }
304
305 auto routine = function("one");
306
307 if(routine)
308 {
309 int8_t ref[16 * 5] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
310 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
311
312 int8_t out[16 * 5] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
313 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
314
315 routine(out);
316
317 for(int row = 0; row < 2; row++)
Nicolas Capensc70a1162016-12-03 00:16:14 -0500318 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500319 for(int col = 0; col < 16; col++)
Nicolas Capensc70a1162016-12-03 00:16:14 -0500320 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500321 int i = row * 16 + col;
Nicolas Capensc70a1162016-12-03 00:16:14 -0500322
Nicolas Capens157ba262019-12-10 17:49:14 -0500323 EXPECT_EQ(out[i], ref[i]) << "Row " << row << " column " << col << " not equal to reference.";
Nicolas Capensc70a1162016-12-03 00:16:14 -0500324 }
325 }
326 }
Nicolas Capensc70a1162016-12-03 00:16:14 -0500327}
328
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400329TEST(ReactorUnitTests, Swizzle)
Nicolas Capens363b61e2016-10-21 13:19:34 -0400330{
Ben Clayton8701dc42019-12-05 21:27:03 +0000331 auto swizzleCode = [](int i) -> uint16_t
332 {
333 auto x = (i >> 0) & 0x03;
334 auto y = (i >> 2) & 0x03;
335 auto z = (i >> 4) & 0x03;
336 auto w = (i >> 6) & 0x03;
337 return (x << 12) | (y << 8) | (z << 4) | (w << 0);
338 };
339
Nicolas Capens363b61e2016-10-21 13:19:34 -0400340 {
Antonio Maiorano03935ae2019-10-29 16:20:27 -0400341 FunctionT<int(void*)> function;
Nicolas Capens363b61e2016-10-21 13:19:34 -0400342 {
343 Pointer<Byte> out = function.Arg<0>();
344
345 for(int i = 0; i < 256; i++)
346 {
Ben Clayton8701dc42019-12-05 21:27:03 +0000347 *Pointer<Float4>(out + 16 * i) = Swizzle(Float4(1.0f, 2.0f, 3.0f, 4.0f), swizzleCode(i));
Nicolas Capens363b61e2016-10-21 13:19:34 -0400348 }
349
350 for(int i = 0; i < 256; i++)
Ben Clayton8701dc42019-12-05 21:27:03 +0000351 {
352 *Pointer<Float4>(out + 16 * (256 + i)) = ShuffleLowHigh(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f), swizzleCode(i));
Nicolas Capens363b61e2016-10-21 13:19:34 -0400353 }
354
355 *Pointer<Float4>(out + 16 * (512 + 0)) = UnpackLow(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f));
356 *Pointer<Float4>(out + 16 * (512 + 1)) = UnpackHigh(Float4(1.0f, 2.0f, 3.0f, 4.0f), Float4(5.0f, 6.0f, 7.0f, 8.0f));
Nicolas Capens20e22c42016-10-25 17:32:37 -0400357 *Pointer<Int2>(out + 16 * (512 + 2)) = UnpackLow(Short4(1, 2, 3, 4), Short4(5, 6, 7, 8));
358 *Pointer<Int2>(out + 16 * (512 + 3)) = UnpackHigh(Short4(1, 2, 3, 4), Short4(5, 6, 7, 8));
359 *Pointer<Short4>(out + 16 * (512 + 4)) = UnpackLow(Byte8(1, 2, 3, 4, 5, 6, 7, 8), Byte8(9, 10, 11, 12, 13, 14, 15, 16));
360 *Pointer<Short4>(out + 16 * (512 + 5)) = UnpackHigh(Byte8(1, 2, 3, 4, 5, 6, 7, 8), Byte8(9, 10, 11, 12, 13, 14, 15, 16));
Nicolas Capens363b61e2016-10-21 13:19:34 -0400361
Casey Dahlin9d56da22017-10-03 13:23:11 -0700362 for(int i = 0; i < 256; i++)
363 {
364 *Pointer<Short4>(out + 16 * (512 + 6) + (8 * i)) =
Ben Clayton8701dc42019-12-05 21:27:03 +0000365 Swizzle(Short4(1, 2, 3, 4), swizzleCode(i));
Casey Dahlin9d56da22017-10-03 13:23:11 -0700366 }
367
368 for(int i = 0; i < 256; i++)
369 {
370 *Pointer<Int4>(out + 16 * (512 + 6 + i) + (8 * 256)) =
Ben Clayton8701dc42019-12-05 21:27:03 +0000371 Swizzle(Int4(1, 2, 3, 4), swizzleCode(i));
Casey Dahlin9d56da22017-10-03 13:23:11 -0700372 }
373
Nicolas Capens363b61e2016-10-21 13:19:34 -0400374 Return(0);
375 }
376
Antonio Maiorano03935ae2019-10-29 16:20:27 -0400377 auto routine = function("one");
Nicolas Capens363b61e2016-10-21 13:19:34 -0400378
379 if(routine)
380 {
Nicolas Capens20e22c42016-10-25 17:32:37 -0400381 struct
Nicolas Capens363b61e2016-10-21 13:19:34 -0400382 {
Nicolas Capens20e22c42016-10-25 17:32:37 -0400383 float f[256 + 256 + 2][4];
Casey Dahlin9d56da22017-10-03 13:23:11 -0700384 int i[388][4];
Nicolas Capens20e22c42016-10-25 17:32:37 -0400385 } out;
Nicolas Capens363b61e2016-10-21 13:19:34 -0400386
Nicolas Capens20e22c42016-10-25 17:32:37 -0400387 memset(&out, 0, sizeof(out));
Nicolas Capens363b61e2016-10-21 13:19:34 -0400388
Antonio Maiorano03935ae2019-10-29 16:20:27 -0400389 routine(&out);
Nicolas Capens363b61e2016-10-21 13:19:34 -0400390
Nicolas Capens20e22c42016-10-25 17:32:37 -0400391 for(int i = 0; i < 256; i++)
Nicolas Capens363b61e2016-10-21 13:19:34 -0400392 {
Nicolas Capens20e22c42016-10-25 17:32:37 -0400393 EXPECT_EQ(out.f[i][0], float((i >> 0) & 0x03) + 1.0f);
394 EXPECT_EQ(out.f[i][1], float((i >> 2) & 0x03) + 1.0f);
395 EXPECT_EQ(out.f[i][2], float((i >> 4) & 0x03) + 1.0f);
396 EXPECT_EQ(out.f[i][3], float((i >> 6) & 0x03) + 1.0f);
Nicolas Capens363b61e2016-10-21 13:19:34 -0400397 }
Nicolas Capens20e22c42016-10-25 17:32:37 -0400398
399 for(int i = 0; i < 256; i++)
400 {
401 EXPECT_EQ(out.f[256 + i][0], float((i >> 0) & 0x03) + 1.0f);
402 EXPECT_EQ(out.f[256 + i][1], float((i >> 2) & 0x03) + 1.0f);
403 EXPECT_EQ(out.f[256 + i][2], float((i >> 4) & 0x03) + 5.0f);
404 EXPECT_EQ(out.f[256 + i][3], float((i >> 6) & 0x03) + 5.0f);
405 }
406
407 EXPECT_EQ(out.f[512 + 0][0], 1.0f);
408 EXPECT_EQ(out.f[512 + 0][1], 5.0f);
409 EXPECT_EQ(out.f[512 + 0][2], 2.0f);
410 EXPECT_EQ(out.f[512 + 0][3], 6.0f);
411
412 EXPECT_EQ(out.f[512 + 1][0], 3.0f);
413 EXPECT_EQ(out.f[512 + 1][1], 7.0f);
414 EXPECT_EQ(out.f[512 + 1][2], 4.0f);
415 EXPECT_EQ(out.f[512 + 1][3], 8.0f);
416
417 EXPECT_EQ(out.i[0][0], 0x00050001);
418 EXPECT_EQ(out.i[0][1], 0x00060002);
419 EXPECT_EQ(out.i[0][2], 0x00000000);
420 EXPECT_EQ(out.i[0][3], 0x00000000);
421
422 EXPECT_EQ(out.i[1][0], 0x00070003);
423 EXPECT_EQ(out.i[1][1], 0x00080004);
424 EXPECT_EQ(out.i[1][2], 0x00000000);
425 EXPECT_EQ(out.i[1][3], 0x00000000);
426
427 EXPECT_EQ(out.i[2][0], 0x0A020901);
428 EXPECT_EQ(out.i[2][1], 0x0C040B03);
429 EXPECT_EQ(out.i[2][2], 0x00000000);
430 EXPECT_EQ(out.i[2][3], 0x00000000);
431
432 EXPECT_EQ(out.i[3][0], 0x0E060D05);
433 EXPECT_EQ(out.i[3][1], 0x10080F07);
434 EXPECT_EQ(out.i[3][2], 0x00000000);
435 EXPECT_EQ(out.i[3][3], 0x00000000);
Casey Dahlin9d56da22017-10-03 13:23:11 -0700436
437 for(int i = 0; i < 256; i++)
438 {
439 EXPECT_EQ(out.i[4 + i/2][0 + (i%2) * 2] & 0xFFFF,
440 ((i >> 0) & 0x03) + 1);
441 EXPECT_EQ(out.i[4 + i/2][0 + (i%2) * 2] >> 16,
442 ((i >> 2) & 0x03) + 1);
443 EXPECT_EQ(out.i[4 + i/2][1 + (i%2) * 2] & 0xFFFF,
444 ((i >> 4) & 0x03) + 1);
445 EXPECT_EQ(out.i[4 + i/2][1 + (i%2) * 2] >> 16,
446 ((i >> 6) & 0x03) + 1);
447 }
448
449 for(int i = 0; i < 256; i++)
450 {
451 EXPECT_EQ(out.i[132 + i][0], ((i >> 0) & 0x03) + 1);
452 EXPECT_EQ(out.i[132 + i][1], ((i >> 2) & 0x03) + 1);
453 EXPECT_EQ(out.i[132 + i][2], ((i >> 4) & 0x03) + 1);
454 EXPECT_EQ(out.i[132 + i][3], ((i >> 6) & 0x03) + 1);
455 }
Nicolas Capens363b61e2016-10-21 13:19:34 -0400456 }
457 }
Nicolas Capens363b61e2016-10-21 13:19:34 -0400458}
459
David 'Digit' Turnerb9f03f42019-12-04 19:32:34 +0100460TEST(ReactorUnitTests, Blend)
461{
462 {
463 // |select| is [0aaa:0bbb:0ccc:0ddd] where |aaa|, |bbb|, |ccc|
464 // and |ddd| are 7-bit selection indices. For a total (1 << 12)
465 // possibilities.
466 const int kSelectRange = 1 << 12;
467
468 // Unfortunately, testing the whole kSelectRange results in a test
469 // that is far too slow to run, because LLVM spends exponentially more
470 // time optimizing the function below as the number of test cases
471 // increases.
472 //
473 // To work-around the problem, only test a subset of the range by
474 // skipping every kRangeIncrement value.
475 //
476 // Set this value to 1 if you want to test the whole implementation,
477 // which will take a little less than 2 minutes on a fast workstation.
478 //
479 // The default value here takes about 1390ms, which is a little more than
480 // what the Swizzle test takes (993 ms) on my machine. A non-power-of-2
481 // value ensures a better spread over possible values.
482 const int kRangeIncrement = 11;
483
484 auto rangeIndexToSelect = [](int i) {
485 return static_cast<unsigned short>(
486 (((i >> 9) & 7) << 0) |
487 (((i >> 6) & 7) << 4) |
488 (((i >> 3) & 7) << 8) |
489 (((i >> 0) & 7) << 12)
490 );
491 };
492
493 FunctionT<int(void*)> function;
494 {
495 Pointer<Byte> out = function.Arg<0>();
496
497 for(int i = 0; i < kSelectRange; i += kRangeIncrement)
498 {
499 unsigned short select = rangeIndexToSelect(i);
500
Ben Claytonc166eb72019-12-06 07:57:12 +0000501 *Pointer<Float4>(out + 16 * i) = Shuffle(Float4(1.0f, 2.0f, 3.0f, 4.0f),
502 Float4(5.0f, 6.0f, 7.0f, 8.0f),
503 select);
David 'Digit' Turnerb9f03f42019-12-04 19:32:34 +0100504
Ben Claytonc166eb72019-12-06 07:57:12 +0000505 *Pointer<Int4>(out + (kSelectRange + i) * 16) = Shuffle(Int4(10, 11, 12, 13),
506 Int4(14, 15, 16, 17),
507 select);
David 'Digit' Turnerb9f03f42019-12-04 19:32:34 +0100508
Ben Claytonc166eb72019-12-06 07:57:12 +0000509 *Pointer<UInt4>(out + (2 * kSelectRange + i) * 16) = Shuffle(UInt4(100, 101, 102, 103),
510 UInt4(104, 105, 106, 107),
511 select);
David 'Digit' Turnerb9f03f42019-12-04 19:32:34 +0100512 }
513
514 Return(0);
515 }
516
517 auto routine = function("one");
518
519 if(routine)
520 {
521 struct
522 {
523 float f[kSelectRange][4];
524 int i[kSelectRange][4];
525 unsigned u[kSelectRange][4];
526 } out;
527
528 memset(&out, 0, sizeof(out));
529
530 routine(&out);
531
532 for(int i = 0; i < kSelectRange; i += kRangeIncrement)
533 {
534 EXPECT_EQ(out.f[i][0], float(1.0f + (i & 7)));
535 EXPECT_EQ(out.f[i][1], float(1.0f + ((i >> 3) & 7)));
536 EXPECT_EQ(out.f[i][2], float(1.0f + ((i >> 6) & 7)));
537 EXPECT_EQ(out.f[i][3], float(1.0f + ((i >> 9) & 7)));
538 }
539
540 for(int i = 0; i < kSelectRange; i += kRangeIncrement)
541 {
542 EXPECT_EQ(out.i[i][0], int(10 + (i & 7)));
543 EXPECT_EQ(out.i[i][1], int(10 + ((i >> 3) & 7)));
544 EXPECT_EQ(out.i[i][2], int(10 + ((i >> 6) & 7)));
545 EXPECT_EQ(out.i[i][3], int(10 + ((i >> 9) & 7)));
546 }
547
548 for(int i = 0; i < kSelectRange; i += kRangeIncrement)
549 {
550 EXPECT_EQ(out.u[i][0], unsigned(100 + (i & 7)));
551 EXPECT_EQ(out.u[i][1], unsigned(100 + ((i >> 3) & 7)));
552 EXPECT_EQ(out.u[i][2], unsigned(100 + ((i >> 6) & 7)));
553 EXPECT_EQ(out.u[i][3], unsigned(100 + ((i >> 9) & 7)));
554 }
555 }
556 }
557
558}
559
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400560TEST(ReactorUnitTests, Branching)
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400561{
Nicolas Capens157ba262019-12-10 17:49:14 -0500562 FunctionT<int()> function;
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400563 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500564 Int x = 0;
565
566 For(Int i = 0, i < 8, i++)
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400567 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500568 If(i < 2)
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400569 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500570 x += 1;
571 }
572 Else If(i < 4)
573 {
574 x += 10;
575 }
576 Else If(i < 6)
577 {
578 x += 100;
579 }
580 Else
581 {
582 x += 1000;
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400583 }
584
Nicolas Capens157ba262019-12-10 17:49:14 -0500585 For(Int i = 0, i < 5, i++)
586 x += 10000;
587 }
Nicolas Capensb0eb3772016-10-24 17:49:13 -0400588
Nicolas Capens157ba262019-12-10 17:49:14 -0500589 For(Int i = 0, i < 10, i++)
590 for(int i = 0; i < 10; i++)
591 For(Int i = 0, i < 10, i++)
Nicolas Capensb0eb3772016-10-24 17:49:13 -0400592 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500593 x += 1000000;
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400594 }
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400595
Nicolas Capens157ba262019-12-10 17:49:14 -0500596 For(Int i = 0, i < 2, i++)
597 If(x == 1000402222)
598 {
599 If(x != 1000402222)
600 x += 1000000000;
601 }
602 Else
603 x = -5;
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400604
Nicolas Capens157ba262019-12-10 17:49:14 -0500605 Return(x);
606 }
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400607
Nicolas Capens157ba262019-12-10 17:49:14 -0500608 auto routine = function("one");
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400609
Nicolas Capens157ba262019-12-10 17:49:14 -0500610 if(routine)
611 {
612 int result = routine();
613
614 EXPECT_EQ(result, 1000402222);
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400615 }
616
Nicolas Capens9ed1a182016-10-24 09:52:23 -0400617}
618
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400619TEST(ReactorUnitTests, MinMax)
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400620{
Nicolas Capens157ba262019-12-10 17:49:14 -0500621 FunctionT<int(void*)> function;
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400622 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500623 Pointer<Byte> out = function.Arg<0>();
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400624
Nicolas Capens157ba262019-12-10 17:49:14 -0500625 *Pointer<Float4>(out + 16 * 0) = Min(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
626 *Pointer<Float4>(out + 16 * 1) = Max(Float4(1.0f, 0.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400627
Nicolas Capens157ba262019-12-10 17:49:14 -0500628 *Pointer<Int4>(out + 16 * 2) = Min(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
629 *Pointer<Int4>(out + 16 * 3) = Max(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
630 *Pointer<UInt4>(out + 16 * 4) = Min(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0));
631 *Pointer<UInt4>(out + 16 * 5) = Max(UInt4(1, 0, -1, -0), UInt4(0, 1, 0, +0));
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400632
Nicolas Capens157ba262019-12-10 17:49:14 -0500633 *Pointer<Short4>(out + 16 * 6) = Min(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0));
634 *Pointer<Short4>(out + 16 * 7) = Max(Short4(1, 0, -1, -0), Short4(0, 1, 0, +0));
635 *Pointer<UShort4>(out + 16 * 8) = Min(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0));
636 *Pointer<UShort4>(out + 16 * 9) = Max(UShort4(1, 0, -1, -0), UShort4(0, 1, 0, +0));
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400637
Nicolas Capens157ba262019-12-10 17:49:14 -0500638 Return(0);
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400639 }
640
Nicolas Capens157ba262019-12-10 17:49:14 -0500641 auto routine = function("one");
642
643 if(routine)
644 {
645 unsigned int out[10][4];
646
647 memset(&out, 0, sizeof(out));
648
649 routine(&out);
650
651 EXPECT_EQ(out[0][0], 0x00000000u);
652 EXPECT_EQ(out[0][1], 0x00000000u);
653 EXPECT_EQ(out[0][2], 0x00000000u);
654 EXPECT_EQ(out[0][3], 0x80000000u);
655
656 EXPECT_EQ(out[1][0], 0x3F800000u);
657 EXPECT_EQ(out[1][1], 0x3F800000u);
658 EXPECT_EQ(out[1][2], 0x00000000u);
659 EXPECT_EQ(out[1][3], 0x80000000u);
660
661 EXPECT_EQ(out[2][0], 0x00000000u);
662 EXPECT_EQ(out[2][1], 0x00000000u);
663 EXPECT_EQ(out[2][2], 0xFFFFFFFFu);
664 EXPECT_EQ(out[2][3], 0x00000000u);
665
666 EXPECT_EQ(out[3][0], 0x00000001u);
667 EXPECT_EQ(out[3][1], 0x00000001u);
668 EXPECT_EQ(out[3][2], 0x00000000u);
669 EXPECT_EQ(out[3][3], 0x00000000u);
670
671 EXPECT_EQ(out[4][0], 0x00000000u);
672 EXPECT_EQ(out[4][1], 0x00000000u);
673 EXPECT_EQ(out[4][2], 0x00000000u);
674 EXPECT_EQ(out[4][3], 0x00000000u);
675
676 EXPECT_EQ(out[5][0], 0x00000001u);
677 EXPECT_EQ(out[5][1], 0x00000001u);
678 EXPECT_EQ(out[5][2], 0xFFFFFFFFu);
679 EXPECT_EQ(out[5][3], 0x00000000u);
680
681 EXPECT_EQ(out[6][0], 0x00000000u);
682 EXPECT_EQ(out[6][1], 0x0000FFFFu);
683 EXPECT_EQ(out[6][2], 0x00000000u);
684 EXPECT_EQ(out[6][3], 0x00000000u);
685
686 EXPECT_EQ(out[7][0], 0x00010001u);
687 EXPECT_EQ(out[7][1], 0x00000000u);
688 EXPECT_EQ(out[7][2], 0x00000000u);
689 EXPECT_EQ(out[7][3], 0x00000000u);
690
691 EXPECT_EQ(out[8][0], 0x00000000u);
692 EXPECT_EQ(out[8][1], 0x00000000u);
693 EXPECT_EQ(out[8][2], 0x00000000u);
694 EXPECT_EQ(out[8][3], 0x00000000u);
695
696 EXPECT_EQ(out[9][0], 0x00010001u);
697 EXPECT_EQ(out[9][1], 0x0000FFFFu);
698 EXPECT_EQ(out[9][2], 0x00000000u);
699 EXPECT_EQ(out[9][3], 0x00000000u);
700 }
Nicolas Capens53a8a3f2016-10-26 00:23:12 -0400701}
702
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400703TEST(ReactorUnitTests, NotNeg)
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500704{
Nicolas Capens157ba262019-12-10 17:49:14 -0500705 FunctionT<int(void*)> function;
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500706 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500707 Pointer<Byte> out = function.Arg<0>();
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500708
Nicolas Capens157ba262019-12-10 17:49:14 -0500709 *Pointer<Int>(out + 16 * 0) = ~Int(0x55555555);
710 *Pointer<Short>(out + 16 * 1) = ~Short(0x5555);
711 *Pointer<Int4>(out + 16 * 2) = ~Int4(0x55555555, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF);
712 *Pointer<Short4>(out + 16 * 3) = ~Short4(0x5555, 0xAAAA, 0x0000, 0xFFFF);
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500713
Nicolas Capens157ba262019-12-10 17:49:14 -0500714 *Pointer<Int>(out + 16 * 4) = -Int(0x55555555);
715 *Pointer<Short>(out + 16 * 5) = -Short(0x5555);
716 *Pointer<Int4>(out + 16 * 6) = -Int4(0x55555555, 0xAAAAAAAA, 0x00000000, 0xFFFFFFFF);
717 *Pointer<Short4>(out + 16 * 7) = -Short4(0x5555, 0xAAAA, 0x0000, 0xFFFF);
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500718
Nicolas Capens157ba262019-12-10 17:49:14 -0500719 *Pointer<Float4>(out + 16 * 8) = -Float4(1.0f, -1.0f, 0.0f, -0.0f);
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500720
Nicolas Capens157ba262019-12-10 17:49:14 -0500721 Return(0);
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500722 }
723
Nicolas Capens157ba262019-12-10 17:49:14 -0500724 auto routine = function("one");
725
726 if(routine)
727 {
728 unsigned int out[10][4];
729
730 memset(&out, 0, sizeof(out));
731
732 routine(&out);
733
734 EXPECT_EQ(out[0][0], 0xAAAAAAAAu);
735 EXPECT_EQ(out[0][1], 0x00000000u);
736 EXPECT_EQ(out[0][2], 0x00000000u);
737 EXPECT_EQ(out[0][3], 0x00000000u);
738
739 EXPECT_EQ(out[1][0], 0x0000AAAAu);
740 EXPECT_EQ(out[1][1], 0x00000000u);
741 EXPECT_EQ(out[1][2], 0x00000000u);
742 EXPECT_EQ(out[1][3], 0x00000000u);
743
744 EXPECT_EQ(out[2][0], 0xAAAAAAAAu);
745 EXPECT_EQ(out[2][1], 0x55555555u);
746 EXPECT_EQ(out[2][2], 0xFFFFFFFFu);
747 EXPECT_EQ(out[2][3], 0x00000000u);
748
749 EXPECT_EQ(out[3][0], 0x5555AAAAu);
750 EXPECT_EQ(out[3][1], 0x0000FFFFu);
751 EXPECT_EQ(out[3][2], 0x00000000u);
752 EXPECT_EQ(out[3][3], 0x00000000u);
753
754 EXPECT_EQ(out[4][0], 0xAAAAAAABu);
755 EXPECT_EQ(out[4][1], 0x00000000u);
756 EXPECT_EQ(out[4][2], 0x00000000u);
757 EXPECT_EQ(out[4][3], 0x00000000u);
758
759 EXPECT_EQ(out[5][0], 0x0000AAABu);
760 EXPECT_EQ(out[5][1], 0x00000000u);
761 EXPECT_EQ(out[5][2], 0x00000000u);
762 EXPECT_EQ(out[5][3], 0x00000000u);
763
764 EXPECT_EQ(out[6][0], 0xAAAAAAABu);
765 EXPECT_EQ(out[6][1], 0x55555556u);
766 EXPECT_EQ(out[6][2], 0x00000000u);
767 EXPECT_EQ(out[6][3], 0x00000001u);
768
769 EXPECT_EQ(out[7][0], 0x5556AAABu);
770 EXPECT_EQ(out[7][1], 0x00010000u);
771 EXPECT_EQ(out[7][2], 0x00000000u);
772 EXPECT_EQ(out[7][3], 0x00000000u);
773
774 EXPECT_EQ(out[8][0], 0xBF800000u);
775 EXPECT_EQ(out[8][1], 0x3F800000u);
776 EXPECT_EQ(out[8][2], 0x80000000u);
777 EXPECT_EQ(out[8][3], 0x00000000u);
778 }
Nicolas Capensc5c0c332016-11-08 11:37:01 -0500779}
780
Nicolas Capenscf79a622019-12-09 17:07:41 -0500781TEST(ReactorUnitTests, FPtoUI)
782{
783 FunctionT<int(void*)> function;
784 {
785 Pointer<Byte> out = function.Arg<0>();
786
787 *Pointer<UInt>(out + 0) = UInt(Float(0xF0000000u));
788 *Pointer<UInt>(out + 4) = UInt(Float(0xC0000000u));
789 *Pointer<UInt>(out + 8) = UInt(Float(0x00000001u));
790 *Pointer<UInt>(out + 12) = UInt(Float(0xF000F000u));
791
792 *Pointer<UInt4>(out + 16) = UInt4(Float4(0xF0000000u, 0x80000000u, 0x00000000u, 0xCCCC0000u));
793
794 Return(0);
795 }
796
797 auto routine = function("one");
798
799 if(routine)
800 {
801 unsigned int out[2][4];
802
803 memset(&out, 0, sizeof(out));
804
805 routine(&out);
806
807 EXPECT_EQ(out[0][0], 0xF0000000u);
808 EXPECT_EQ(out[0][1], 0xC0000000u);
809 EXPECT_EQ(out[0][2], 0x00000001u);
810 EXPECT_EQ(out[0][3], 0xF000F000u);
811
812 EXPECT_EQ(out[1][0], 0xF0000000u);
813 EXPECT_EQ(out[1][1], 0x80000000u);
814 EXPECT_EQ(out[1][2], 0x00000000u);
815 EXPECT_EQ(out[1][3], 0xCCCC0000u);
816 }
817}
818
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400819TEST(ReactorUnitTests, VectorCompare)
Nicolas Capens5e6ca092017-01-13 15:09:21 -0500820{
Nicolas Capens157ba262019-12-10 17:49:14 -0500821 FunctionT<int(void*)> function;
Nicolas Capens5e6ca092017-01-13 15:09:21 -0500822 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500823 Pointer<Byte> out = function.Arg<0>();
Nicolas Capens5e6ca092017-01-13 15:09:21 -0500824
Nicolas Capens157ba262019-12-10 17:49:14 -0500825 *Pointer<Int4>(out + 16 * 0) = CmpEQ(Float4(1.0f, 1.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
826 *Pointer<Int4>(out + 16 * 1) = CmpEQ(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
827 *Pointer<Byte8>(out + 16 * 2) = CmpEQ(SByte8(1, 2, 3, 4, 5, 6, 7, 8), SByte8(7, 6, 5, 4, 3, 2, 1, 0));
Nicolas Capens5e6ca092017-01-13 15:09:21 -0500828
Nicolas Capens157ba262019-12-10 17:49:14 -0500829 *Pointer<Int4>(out + 16 * 3) = CmpNLT(Float4(1.0f, 1.0f, -0.0f, +0.0f), Float4(0.0f, 1.0f, +0.0f, -0.0f));
830 *Pointer<Int4>(out + 16 * 4) = CmpNLT(Int4(1, 0, -1, -0), Int4(0, 1, 0, +0));
831 *Pointer<Byte8>(out + 16 * 5) = CmpGT(SByte8(1, 2, 3, 4, 5, 6, 7, 8), SByte8(7, 6, 5, 4, 3, 2, 1, 0));
Nicolas Capens5e6ca092017-01-13 15:09:21 -0500832
Nicolas Capens157ba262019-12-10 17:49:14 -0500833 Return(0);
Nicolas Capens5e6ca092017-01-13 15:09:21 -0500834 }
835
Nicolas Capens157ba262019-12-10 17:49:14 -0500836 auto routine = function("one");
837
838 if(routine)
839 {
840 unsigned int out[6][4];
841
842 memset(&out, 0, sizeof(out));
843
844 routine(&out);
845
846 EXPECT_EQ(out[0][0], 0x00000000u);
847 EXPECT_EQ(out[0][1], 0xFFFFFFFFu);
848 EXPECT_EQ(out[0][2], 0xFFFFFFFFu);
849 EXPECT_EQ(out[0][3], 0xFFFFFFFFu);
850
851 EXPECT_EQ(out[1][0], 0x00000000u);
852 EXPECT_EQ(out[1][1], 0x00000000u);
853 EXPECT_EQ(out[1][2], 0x00000000u);
854 EXPECT_EQ(out[1][3], 0xFFFFFFFFu);
855
856 EXPECT_EQ(out[2][0], 0xFF000000u);
857 EXPECT_EQ(out[2][1], 0x00000000u);
858
859 EXPECT_EQ(out[3][0], 0xFFFFFFFFu);
860 EXPECT_EQ(out[3][1], 0xFFFFFFFFu);
861 EXPECT_EQ(out[3][2], 0xFFFFFFFFu);
862 EXPECT_EQ(out[3][3], 0xFFFFFFFFu);
863
864 EXPECT_EQ(out[4][0], 0xFFFFFFFFu);
865 EXPECT_EQ(out[4][1], 0x00000000u);
866 EXPECT_EQ(out[4][2], 0x00000000u);
867 EXPECT_EQ(out[4][3], 0xFFFFFFFFu);
868
869 EXPECT_EQ(out[5][0], 0x00000000u);
870 EXPECT_EQ(out[5][1], 0xFFFFFFFFu);
871 }
Nicolas Capens5e6ca092017-01-13 15:09:21 -0500872}
873
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400874TEST(ReactorUnitTests, SaturatedAddAndSubtract)
Casey Dahlin642fc922017-09-28 17:18:41 -0700875{
Nicolas Capens157ba262019-12-10 17:49:14 -0500876 FunctionT<int(void*)> function;
Casey Dahlin642fc922017-09-28 17:18:41 -0700877 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500878 Pointer<Byte> out = function.Arg<0>();
Casey Dahlin642fc922017-09-28 17:18:41 -0700879
Nicolas Capens157ba262019-12-10 17:49:14 -0500880 *Pointer<Byte8>(out + 8 * 0) =
881 AddSat(Byte8(1, 2, 3, 4, 5, 6, 7, 8),
882 Byte8(7, 6, 5, 4, 3, 2, 1, 0));
883 *Pointer<Byte8>(out + 8 * 1) =
884 AddSat(Byte8(0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE),
885 Byte8(7, 6, 5, 4, 3, 2, 1, 0));
886 *Pointer<Byte8>(out + 8 * 2) =
887 SubSat(Byte8(1, 2, 3, 4, 5, 6, 7, 8),
888 Byte8(7, 6, 5, 4, 3, 2, 1, 0));
Casey Dahlin642fc922017-09-28 17:18:41 -0700889
Nicolas Capens157ba262019-12-10 17:49:14 -0500890 *Pointer<SByte8>(out + 8 * 3) =
891 AddSat(SByte8(1, 2, 3, 4, 5, 6, 7, 8),
892 SByte8(7, 6, 5, 4, 3, 2, 1, 0));
893 *Pointer<SByte8>(out + 8 * 4) =
894 AddSat(SByte8(0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E),
895 SByte8(7, 6, 5, 4, 3, 2, 1, 0));
896 *Pointer<SByte8>(out + 8 * 5) =
897 AddSat(SByte8(0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88),
898 SByte8(-7, -6, -5, -4, -3, -2, -1, -0));
899 *Pointer<SByte8>(out + 8 * 6) =
900 SubSat(SByte8(0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88),
901 SByte8(7, 6, 5, 4, 3, 2, 1, 0));
Casey Dahlin642fc922017-09-28 17:18:41 -0700902
Nicolas Capens157ba262019-12-10 17:49:14 -0500903 *Pointer<Short4>(out + 8 * 7) =
904 AddSat(Short4(1, 2, 3, 4), Short4(3, 2, 1, 0));
905 *Pointer<Short4>(out + 8 * 8) =
906 AddSat(Short4(0x7FFE, 0x7FFE, 0x7FFE, 0x7FFE),
907 Short4(3, 2, 1, 0));
908 *Pointer<Short4>(out + 8 * 9) =
909 AddSat(Short4(0x8001, 0x8002, 0x8003, 0x8004),
910 Short4(-3, -2, -1, -0));
911 *Pointer<Short4>(out + 8 * 10) =
912 SubSat(Short4(0x8001, 0x8002, 0x8003, 0x8004),
913 Short4(3, 2, 1, 0));
Casey Dahlin642fc922017-09-28 17:18:41 -0700914
Nicolas Capens157ba262019-12-10 17:49:14 -0500915 *Pointer<UShort4>(out + 8 * 11) =
916 AddSat(UShort4(1, 2, 3, 4), UShort4(3, 2, 1, 0));
917 *Pointer<UShort4>(out + 8 * 12) =
918 AddSat(UShort4(0xFFFE, 0xFFFE, 0xFFFE, 0xFFFE),
919 UShort4(3, 2, 1, 0));
920 *Pointer<UShort4>(out + 8 * 13) =
921 SubSat(UShort4(1, 2, 3, 4), UShort4(3, 2, 1, 0));
Casey Dahlin642fc922017-09-28 17:18:41 -0700922
Nicolas Capens157ba262019-12-10 17:49:14 -0500923 Return(0);
Casey Dahlin642fc922017-09-28 17:18:41 -0700924 }
925
Nicolas Capens157ba262019-12-10 17:49:14 -0500926 auto routine = function("one");
927
928 if(routine)
929 {
930 unsigned int out[14][2];
931
932 memset(&out, 0, sizeof(out));
933
934 routine(&out);
935
936 EXPECT_EQ(out[0][0], 0x08080808u);
937 EXPECT_EQ(out[0][1], 0x08080808u);
938
939 EXPECT_EQ(out[1][0], 0xFFFFFFFFu);
940 EXPECT_EQ(out[1][1], 0xFEFFFFFFu);
941
942 EXPECT_EQ(out[2][0], 0x00000000u);
943 EXPECT_EQ(out[2][1], 0x08060402u);
944
945 EXPECT_EQ(out[3][0], 0x08080808u);
946 EXPECT_EQ(out[3][1], 0x08080808u);
947
948 EXPECT_EQ(out[4][0], 0x7F7F7F7Fu);
949 EXPECT_EQ(out[4][1], 0x7E7F7F7Fu);
950
951 EXPECT_EQ(out[5][0], 0x80808080u);
952 EXPECT_EQ(out[5][1], 0x88868482u);
953
954 EXPECT_EQ(out[6][0], 0x80808080u);
955 EXPECT_EQ(out[6][1], 0x88868482u);
956
957 EXPECT_EQ(out[7][0], 0x00040004u);
958 EXPECT_EQ(out[7][1], 0x00040004u);
959
960 EXPECT_EQ(out[8][0], 0x7FFF7FFFu);
961 EXPECT_EQ(out[8][1], 0x7FFE7FFFu);
962
963 EXPECT_EQ(out[9][0], 0x80008000u);
964 EXPECT_EQ(out[9][1], 0x80048002u);
965
966 EXPECT_EQ(out[10][0], 0x80008000u);
967 EXPECT_EQ(out[10][1], 0x80048002u);
968
969 EXPECT_EQ(out[11][0], 0x00040004u);
970 EXPECT_EQ(out[11][1], 0x00040004u);
971
972 EXPECT_EQ(out[12][0], 0xFFFFFFFFu);
973 EXPECT_EQ(out[12][1], 0xFFFEFFFFu);
974
975 EXPECT_EQ(out[13][0], 0x00000000u);
976 EXPECT_EQ(out[13][1], 0x00040002u);
977 }
Casey Dahlin642fc922017-09-28 17:18:41 -0700978}
979
Nicolas Capensc07dc4b2018-08-06 14:20:45 -0400980TEST(ReactorUnitTests, Unpack)
Casey Dahlin4e759e42017-09-29 13:43:18 -0700981{
Nicolas Capens157ba262019-12-10 17:49:14 -0500982 FunctionT<int(void*, void*)> function;
Casey Dahlin4e759e42017-09-29 13:43:18 -0700983 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500984 Pointer<Byte> in = function.Arg<0>();
985 Pointer<Byte> out = function.Arg<1>();
Casey Dahlin4e759e42017-09-29 13:43:18 -0700986
Nicolas Capens157ba262019-12-10 17:49:14 -0500987 Byte4 test_byte_a = *Pointer<Byte4>(in + 4 * 0);
988 Byte4 test_byte_b = *Pointer<Byte4>(in + 4 * 1);
Casey Dahlin4e759e42017-09-29 13:43:18 -0700989
Nicolas Capens157ba262019-12-10 17:49:14 -0500990 *Pointer<Short4>(out + 8 * 0) =
991 Unpack(test_byte_a, test_byte_b);
Casey Dahlin4e759e42017-09-29 13:43:18 -0700992
Nicolas Capens157ba262019-12-10 17:49:14 -0500993 *Pointer<Short4>(out + 8 * 1) = Unpack(test_byte_a);
Casey Dahlin4e759e42017-09-29 13:43:18 -0700994
Nicolas Capens157ba262019-12-10 17:49:14 -0500995 Return(0);
Casey Dahlin4e759e42017-09-29 13:43:18 -0700996 }
997
Nicolas Capens157ba262019-12-10 17:49:14 -0500998 auto routine = function("one");
999
1000 if(routine)
1001 {
1002 unsigned int in[1][2];
1003 unsigned int out[2][2];
1004
1005 memset(&out, 0, sizeof(out));
1006
1007 in[0][0] = 0xABCDEF12u;
1008 in[0][1] = 0x34567890u;
1009
1010 routine(&in, &out);
1011
1012 EXPECT_EQ(out[0][0], 0x78EF9012u);
1013 EXPECT_EQ(out[0][1], 0x34AB56CDu);
1014
1015 EXPECT_EQ(out[1][0], 0xEFEF1212u);
1016 EXPECT_EQ(out[1][1], 0xABABCDCDu);
1017 }
Casey Dahlin4e759e42017-09-29 13:43:18 -07001018}
1019
Nicolas Capensc07dc4b2018-08-06 14:20:45 -04001020TEST(ReactorUnitTests, Pack)
Casey Dahlin11658122017-09-29 16:32:32 -07001021{
Nicolas Capens157ba262019-12-10 17:49:14 -05001022 FunctionT<int(void*)> function;
Casey Dahlin11658122017-09-29 16:32:32 -07001023 {
Nicolas Capens157ba262019-12-10 17:49:14 -05001024 Pointer<Byte> out = function.Arg<0>();
Casey Dahlin11658122017-09-29 16:32:32 -07001025
Nicolas Capens157ba262019-12-10 17:49:14 -05001026 *Pointer<SByte8>(out + 8 * 0) =
1027 PackSigned(Short4(-1, -2, 1, 2),
1028 Short4(3, 4, -3, -4));
Casey Dahlin11658122017-09-29 16:32:32 -07001029
Nicolas Capens157ba262019-12-10 17:49:14 -05001030 *Pointer<Byte8>(out + 8 * 1) =
1031 PackUnsigned(Short4(-1, -2, 1, 2),
1032 Short4(3, 4, -3, -4));
Casey Dahlin11658122017-09-29 16:32:32 -07001033
Nicolas Capens157ba262019-12-10 17:49:14 -05001034 *Pointer<Short8>(out + 8 * 2) =
1035 PackSigned(Int4(-1, -2, 1, 2),
1036 Int4(3, 4, -3, -4));
Casey Dahlin11658122017-09-29 16:32:32 -07001037
Nicolas Capens157ba262019-12-10 17:49:14 -05001038 *Pointer<UShort8>(out + 8 * 4) =
1039 PackUnsigned(Int4(-1, -2, 1, 2),
1040 Int4(3, 4, -3, -4));
Casey Dahlin11658122017-09-29 16:32:32 -07001041
Nicolas Capens157ba262019-12-10 17:49:14 -05001042 Return(0);
Casey Dahlin11658122017-09-29 16:32:32 -07001043 }
1044
Nicolas Capens157ba262019-12-10 17:49:14 -05001045 auto routine = function("one");
1046
1047 if(routine)
1048 {
1049 unsigned int out[6][2];
1050
1051 memset(&out, 0, sizeof(out));
1052
1053 routine(&out);
1054
1055 EXPECT_EQ(out[0][0], 0x0201FEFFu);
1056 EXPECT_EQ(out[0][1], 0xFCFD0403u);
1057
1058 EXPECT_EQ(out[1][0], 0x02010000u);
1059 EXPECT_EQ(out[1][1], 0x00000403u);
1060
1061 EXPECT_EQ(out[2][0], 0xFFFEFFFFu);
1062 EXPECT_EQ(out[2][1], 0x00020001u);
1063
1064 EXPECT_EQ(out[3][0], 0x00040003u);
1065 EXPECT_EQ(out[3][1], 0xFFFCFFFDu);
1066
1067 EXPECT_EQ(out[4][0], 0x00000000u);
1068 EXPECT_EQ(out[4][1], 0x00020001u);
1069
1070 EXPECT_EQ(out[5][0], 0x00040003u);
1071 EXPECT_EQ(out[5][1], 0x00000000u);
1072 }
Casey Dahlin11658122017-09-29 16:32:32 -07001073}
1074
Nicolas Capensc07dc4b2018-08-06 14:20:45 -04001075TEST(ReactorUnitTests, MulHigh)
Nicolas Capens92593eb2018-02-14 14:52:49 -05001076{
Nicolas Capens157ba262019-12-10 17:49:14 -05001077 FunctionT<int(void*)> function;
Casey Dahlin36fad3c2017-10-02 15:02:02 -07001078 {
Nicolas Capens157ba262019-12-10 17:49:14 -05001079 Pointer<Byte> out = function.Arg<0>();
Casey Dahlin36fad3c2017-10-02 15:02:02 -07001080
Nicolas Capens157ba262019-12-10 17:49:14 -05001081 *Pointer<Short4>(out + 16 * 0) =
1082 MulHigh(Short4(0x01AA, 0x02DD, 0x03EE, 0xF422),
1083 Short4(0x01BB, 0x02CC, 0x03FF, 0xF411));
1084 *Pointer<UShort4>(out + 16 * 1) =
1085 MulHigh(UShort4(0x01AA, 0x02DD, 0x03EE, 0xF422),
1086 UShort4(0x01BB, 0x02CC, 0x03FF, 0xF411));
Casey Dahlin36fad3c2017-10-02 15:02:02 -07001087
Nicolas Capens157ba262019-12-10 17:49:14 -05001088 *Pointer<Int4>(out + 16 * 2) =
1089 MulHigh(Int4(0x000001AA, 0x000002DD, 0xC8000000, 0xF8000000),
1090 Int4(0x000001BB, 0x84000000, 0x000003EE, 0xD7000000));
1091 *Pointer<UInt4>(out + 16 * 3) =
1092 MulHigh(UInt4(0x000001AAu, 0x000002DDu, 0xC8000000u, 0xD8000000u),
1093 UInt4(0x000001BBu, 0x84000000u, 0x000003EEu, 0xD7000000u));
Chris Forbesaa8f6992019-03-01 14:18:30 -08001094
Nicolas Capens157ba262019-12-10 17:49:14 -05001095 *Pointer<Int4>(out + 16 * 4) =
1096 MulHigh(Int4(0x7FFFFFFF, 0x7FFFFFFF, 0x80008000, 0xFFFFFFFF),
1097 Int4(0x7FFFFFFF, 0x80000000, 0x80008000, 0xFFFFFFFF));
1098 *Pointer<UInt4>(out + 16 * 5) =
1099 MulHigh(UInt4(0x7FFFFFFFu, 0x7FFFFFFFu, 0x80008000u, 0xFFFFFFFFu),
1100 UInt4(0x7FFFFFFFu, 0x80000000u, 0x80008000u, 0xFFFFFFFFu));
Chris Forbesaa8f6992019-03-01 14:18:30 -08001101
Nicolas Capens157ba262019-12-10 17:49:14 -05001102 // (U)Short8 variants currently unimplemented.
Chris Forbesaa8f6992019-03-01 14:18:30 -08001103
Nicolas Capens157ba262019-12-10 17:49:14 -05001104 Return(0);
Casey Dahlin36fad3c2017-10-02 15:02:02 -07001105 }
1106
Nicolas Capens157ba262019-12-10 17:49:14 -05001107 auto routine = function("one");
1108
1109 if(routine)
1110 {
1111 unsigned int out[6][4];
1112
1113 memset(&out, 0, sizeof(out));
1114
1115 routine(&out);
1116
1117 EXPECT_EQ(out[0][0], 0x00080002u);
1118 EXPECT_EQ(out[0][1], 0x008D000Fu);
1119
1120 EXPECT_EQ(out[1][0], 0x00080002u);
1121 EXPECT_EQ(out[1][1], 0xE8C0000Fu);
1122
1123 EXPECT_EQ(out[2][0], 0x00000000u);
1124 EXPECT_EQ(out[2][1], 0xFFFFFE9Cu);
1125 EXPECT_EQ(out[2][2], 0xFFFFFF23u);
1126 EXPECT_EQ(out[2][3], 0x01480000u);
1127
1128 EXPECT_EQ(out[3][0], 0x00000000u);
1129 EXPECT_EQ(out[3][1], 0x00000179u);
1130 EXPECT_EQ(out[3][2], 0x00000311u);
1131 EXPECT_EQ(out[3][3], 0xB5680000u);
1132
1133 EXPECT_EQ(out[4][0], 0x3FFFFFFFu);
1134 EXPECT_EQ(out[4][1], 0xC0000000u);
1135 EXPECT_EQ(out[4][2], 0x3FFF8000u);
1136 EXPECT_EQ(out[4][3], 0x00000000u);
1137
1138 EXPECT_EQ(out[5][0], 0x3FFFFFFFu);
1139 EXPECT_EQ(out[5][1], 0x3FFFFFFFu);
1140 EXPECT_EQ(out[5][2], 0x40008000u);
1141 EXPECT_EQ(out[5][3], 0xFFFFFFFEu);
1142 }
Casey Dahlin36fad3c2017-10-02 15:02:02 -07001143}
1144
Nicolas Capensc07dc4b2018-08-06 14:20:45 -04001145TEST(ReactorUnitTests, MulAdd)
Nicolas Capens92593eb2018-02-14 14:52:49 -05001146{
Nicolas Capens157ba262019-12-10 17:49:14 -05001147 FunctionT<int(void*)> function;
Casey Dahlinb098c542017-10-03 11:24:01 -07001148 {
Nicolas Capens157ba262019-12-10 17:49:14 -05001149 Pointer<Byte> out = function.Arg<0>();
Casey Dahlinb098c542017-10-03 11:24:01 -07001150
Nicolas Capens157ba262019-12-10 17:49:14 -05001151 *Pointer<Int2>(out + 8 * 0) =
1152 MulAdd(Short4(0x1aa, 0x2dd, 0x3ee, 0xF422),
1153 Short4(0x1bb, 0x2cc, 0x3ff, 0xF411));
Casey Dahlinb098c542017-10-03 11:24:01 -07001154
Nicolas Capens157ba262019-12-10 17:49:14 -05001155 // (U)Short8 variant is mentioned but unimplemented
1156 Return(0);
Casey Dahlinb098c542017-10-03 11:24:01 -07001157 }
1158
Nicolas Capens157ba262019-12-10 17:49:14 -05001159 auto routine = function("one");
1160
1161 if(routine)
1162 {
1163 unsigned int out[1][2];
1164
1165 memset(&out, 0, sizeof(out));
1166
1167 routine(&out);
1168
1169 EXPECT_EQ(out[0][0], 0x000AE34Au);
1170 EXPECT_EQ(out[0][1], 0x009D5254u);
1171 }
Casey Dahlinb098c542017-10-03 11:24:01 -07001172}
1173
Ben Clayton204a4102019-07-31 13:17:47 +01001174TEST(ReactorUnitTests, PointersEqual)
1175{
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001176 FunctionT<int(void*, void*)> function;
Ben Clayton204a4102019-07-31 13:17:47 +01001177 {
1178 Pointer<Byte> ptrA = function.Arg<0>();
1179 Pointer<Byte> ptrB = function.Arg<1>();
1180 If (ptrA == ptrB)
1181 {
1182 Return(1);
1183 }
1184 Else
1185 {
1186 Return(0);
1187 }
1188 }
1189
1190 auto routine = function("one");
Ben Clayton204a4102019-07-31 13:17:47 +01001191 int* a = reinterpret_cast<int*>(uintptr_t(0x0000000000000000));
1192 int* b = reinterpret_cast<int*>(uintptr_t(0x00000000F0000000));
1193 int* c = reinterpret_cast<int*>(uintptr_t(0xF000000000000000));
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001194 EXPECT_EQ(routine(&a, &a), 1);
1195 EXPECT_EQ(routine(&b, &b), 1);
1196 EXPECT_EQ(routine(&c, &c), 1);
Ben Clayton204a4102019-07-31 13:17:47 +01001197
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001198 EXPECT_EQ(routine(&a, &b), 0);
1199 EXPECT_EQ(routine(&b, &a), 0);
1200 EXPECT_EQ(routine(&b, &c), 0);
1201 EXPECT_EQ(routine(&c, &b), 0);
1202 EXPECT_EQ(routine(&c, &a), 0);
1203 EXPECT_EQ(routine(&a, &c), 0);
Ben Clayton204a4102019-07-31 13:17:47 +01001204}
1205
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001206TEST(ReactorUnitTests, Args_2Mixed)
1207{
1208 // 2 mixed type args
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001209 FunctionT<float(int, float)> function;
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001210 {
1211 Int a = function.Arg<0>();
1212 Float b = function.Arg<1>();
1213 Return(Float(a) + b);
1214 }
1215
1216 if (auto routine = function("one"))
1217 {
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001218 float result = routine(1, 2.f);
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001219 EXPECT_EQ(result, 3.f);
1220 }
1221}
1222
1223TEST(ReactorUnitTests, Args_4Mixed)
1224{
1225 // 4 mixed type args (max register allocation on Windows)
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001226 FunctionT<float(int, float, int, float)> function;
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001227 {
1228 Int a = function.Arg<0>();
1229 Float b = function.Arg<1>();
1230 Int c = function.Arg<2>();
1231 Float d = function.Arg<3>();
1232 Return(Float(a) + b + Float(c) + d);
1233 }
1234
1235 if (auto routine = function("one"))
1236 {
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001237 float result = routine(1, 2.f, 3, 4.f);
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001238 EXPECT_EQ(result, 10.f);
1239 }
1240}
1241
1242TEST(ReactorUnitTests, Args_5Mixed)
1243{
1244 // 5 mixed type args (5th spills over to stack on Windows)
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001245 FunctionT<float(int, float, int, float, int)> function;
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001246 {
1247 Int a = function.Arg<0>();
1248 Float b = function.Arg<1>();
1249 Int c = function.Arg<2>();
1250 Float d = function.Arg<3>();
1251 Int e = function.Arg<4>();
1252 Return(Float(a) + b + Float(c) + d + Float(e));
1253 }
1254
1255 if (auto routine = function("one"))
1256 {
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001257 float result = routine(1, 2.f, 3, 4.f, 5);
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001258 EXPECT_EQ(result, 15.f);
1259 }
1260}
1261
1262TEST(ReactorUnitTests, Args_GreaterThan5Mixed)
1263{
1264 // >5 mixed type args
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001265 FunctionT<float(int, float, int, float, int, float, int, float, int, float)> function;
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001266 {
1267 Int a = function.Arg<0>();
1268 Float b = function.Arg<1>();
1269 Int c = function.Arg<2>();
1270 Float d = function.Arg<3>();
1271 Int e = function.Arg<4>();
1272 Float f = function.Arg<5>();
1273 Int g = function.Arg<6>();
1274 Float h = function.Arg<7>();
1275 Int i = function.Arg<8>();
1276 Float j = function.Arg<9>();
1277 Return(Float(a) + b + Float(c) + d + Float(e) + f + Float(g) + h + Float(i) + j);
1278 }
1279
1280 if (auto routine = function("one"))
1281 {
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001282 float result = routine(1, 2.f, 3, 4.f, 5, 6.f, 7, 8.f, 9, 10.f);
Antonio Maiorano29ba7a02019-10-11 15:23:56 -04001283 EXPECT_EQ(result, 55.f);
1284 }
1285}
1286
Ben Claytond853c122019-04-16 17:51:49 -04001287TEST(ReactorUnitTests, Call)
1288{
Ben Claytond853c122019-04-16 17:51:49 -04001289 struct Class
1290 {
Ben Clayton51f08312019-11-08 14:39:26 +00001291 static int Callback(Class *p, int i, float f)
Ben Claytond853c122019-04-16 17:51:49 -04001292 {
Ben Clayton51f08312019-11-08 14:39:26 +00001293 p->i = i;
1294 p->f = f;
Ben Claytond853c122019-04-16 17:51:49 -04001295 return i + int(f);
1296 }
1297
1298 int i = 0;
1299 float f = 0.0f;
1300 };
1301
Ben Clayton51f08312019-11-08 14:39:26 +00001302 FunctionT<int(void*)> function;
Ben Claytond853c122019-04-16 17:51:49 -04001303 {
Ben Clayton51f08312019-11-08 14:39:26 +00001304 Pointer<Byte> c = function.Arg<0>();
1305 auto res = Call(Class::Callback, c, 10, 20.0f);
1306 Return(res);
Ben Claytond853c122019-04-16 17:51:49 -04001307 }
Ben Clayton51f08312019-11-08 14:39:26 +00001308
1309 auto routine = function("one");
1310
1311 Class c;
1312 int res = routine(&c);
1313 EXPECT_EQ(res, 30);
1314 EXPECT_EQ(c.i, 10);
1315 EXPECT_EQ(c.f, 20.0f);
1316}
1317
Ben Claytonb7eb3a82019-11-19 00:43:50 +00001318TEST(ReactorUnitTests, CallMemberFunction)
1319{
Ben Claytonb7eb3a82019-11-19 00:43:50 +00001320 struct Class
1321 {
1322 int Callback(int argI, float argF)
1323 {
1324 i = argI;
1325 f = argF;
1326 return i + int(f);
1327 }
1328
1329 int i = 0;
1330 float f = 0.0f;
1331 };
1332
1333 Class c;
1334
1335 FunctionT<int()> function;
1336 {
1337 auto res = Call(&Class::Callback, &c, 10, 20.0f);
1338 Return(res);
1339 }
1340
1341 auto routine = function("one");
1342
1343 int res = routine();
1344 EXPECT_EQ(res, 30);
1345 EXPECT_EQ(c.i, 10);
1346 EXPECT_EQ(c.f, 20.0f);
1347}
1348
1349TEST(ReactorUnitTests, CallMemberFunctionIndirect)
1350{
Ben Claytonb7eb3a82019-11-19 00:43:50 +00001351 struct Class
1352 {
1353 int Callback(int argI, float argF)
1354 {
1355 i = argI;
1356 f = argF;
1357 return i + int(f);
1358 }
1359
1360 int i = 0;
1361 float f = 0.0f;
1362 };
1363
1364 FunctionT<int(void*)> function;
1365 {
1366 Pointer<Byte> c = function.Arg<0>();
1367 auto res = Call(&Class::Callback, c, 10, 20.0f);
1368 Return(res);
1369 }
1370
1371 auto routine = function("one");
1372
1373 Class c;
1374 int res = routine(&c);
1375 EXPECT_EQ(res, 30);
1376 EXPECT_EQ(c.i, 10);
1377 EXPECT_EQ(c.f, 20.0f);
1378}
1379
Ben Clayton51f08312019-11-08 14:39:26 +00001380TEST(ReactorUnitTests, CallImplicitCast)
1381{
Ben Clayton51f08312019-11-08 14:39:26 +00001382 struct Class
1383 {
1384 static void Callback(Class *c, const char* s)
1385 {
1386 c->str = s;
1387 }
1388 std::string str;
1389 };
1390
1391 FunctionT<void(Class *c, const char *s)> function;
1392 {
1393 Pointer<Byte> c = function.Arg<0>();
1394 Pointer<Byte> s = function.Arg<1>();
1395 Call(Class::Callback, c, s);
1396 }
1397
1398 auto routine = function("one");
1399
1400 Class c;
1401 routine(&c, "hello world");
1402 EXPECT_EQ(c.str, "hello world");
Antonio Maioranob7dad7d2019-10-11 15:26:58 -04001403}
Ben Claytond853c122019-04-16 17:51:49 -04001404
Antonio Maiorano01386d12019-11-20 14:43:48 -05001405TEST(ReactorUnitTests, Call_Args4)
1406{
1407 struct Class
1408 {
1409 static int Func(int a, int b, int c, int d)
1410 {
1411 return a + b + c + d;
1412 }
1413 };
1414
1415 {
1416 FunctionT<int()> function;
1417 {
1418 auto res = Call(Class::Func, 1, 2, 3, 4);
1419 Return(res);
1420 }
1421
1422 auto routine = function("one");
1423
1424 if(routine)
1425 {
1426 int res = routine();
1427 EXPECT_EQ(res, 1 + 2 + 3 + 4);
1428 }
1429 }
1430}
1431
1432TEST(ReactorUnitTests, Call_Args5)
1433{
1434 struct Class
1435 {
1436 static int Func(int a, int b, int c, int d, int e)
1437 {
1438 return a + b + c + d + e;
1439 }
1440 };
1441
1442 {
1443 FunctionT<int()> function;
1444 {
1445 auto res = Call(Class::Func, 1, 2, 3, 4, 5);
1446 Return(res);
1447 }
1448
1449 auto routine = function("one");
1450
1451 if(routine)
1452 {
1453 int res = routine();
1454 EXPECT_EQ(res, 1 + 2 + 3 + 4 + 5);
1455 }
1456 }
1457}
1458
1459TEST(ReactorUnitTests, Call_ArgsMany)
1460{
1461 struct Class
1462 {
1463 static int Func(int a, int b, int c, int d, int e, int f, int g, int h)
1464 {
1465 return a + b + c + d + e + f + g + h;
1466 }
1467 };
1468
1469 {
1470 FunctionT<int()> function;
1471 {
1472 auto res = Call(Class::Func, 1, 2, 3, 4, 5, 6, 7, 8);
1473 Return(res);
1474 }
1475
1476 auto routine = function("one");
1477
1478 if(routine)
1479 {
1480 int res = routine();
1481 EXPECT_EQ(res, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
1482 }
1483 }
1484}
1485
1486TEST(ReactorUnitTests, Call_ArgsMixed)
1487{
1488 struct Class
1489 {
1490 static int Func(int a, float b, int* c, float* d, int e, float f, int* g, float* h)
1491 {
1492 return a + b + *c + *d + e + f + *g + *h;
1493 }
1494 };
1495
1496 {
1497 FunctionT<int()> function;
1498 {
1499 Int c(3);
1500 Float d(4);
1501 Int g(7);
1502 Float h(8);
1503 auto res = Call(Class::Func, 1, 2.f, &c, &d, 5, 6.f, &g, &h);
1504 Return(res);
1505 }
1506
1507 auto routine = function("one");
1508
1509 if(routine)
1510 {
1511 int res = routine();
1512 EXPECT_EQ(res, 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8);
1513 }
1514 }
1515}
1516
1517TEST(ReactorUnitTests, Call_ArgsPointer)
1518{
1519 struct Class
1520 {
1521 static int Func(int *a)
1522 {
1523 return *a;
1524 }
1525 };
1526
1527 {
1528 FunctionT<int()> function;
1529 {
1530 Int a(12345);
1531 auto res = Call(Class::Func, &a);
1532 Return(res);
1533 }
1534
1535 auto routine = function("one");
1536
1537 if(routine)
1538 {
1539 int res = routine();
1540 EXPECT_EQ(res, 12345);
1541 }
1542 }
1543}
1544
1545
Antonio Maioranob7dad7d2019-10-11 15:26:58 -04001546TEST(ReactorUnitTests, CallExternalCallRoutine)
1547{
Antonio Maioranob7dad7d2019-10-11 15:26:58 -04001548 // routine1 calls Class::Func, passing it a pointer to routine2, and Class::Func calls routine2
1549
1550 auto routine2 = [] {
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001551 FunctionT<float(float, int)> function;
Antonio Maioranob7dad7d2019-10-11 15:26:58 -04001552 {
1553 Float a = function.Arg<0>();
1554 Int b = function.Arg<1>();
1555 Return(a + Float(b));
1556 }
1557 return function("two");
1558 }();
1559
1560 struct Class
1561 {
1562 static float Func(void* p, float a, int b)
1563 {
1564 auto funcToCall = reinterpret_cast<float(*)(float, int)>(p);
1565 return funcToCall(a, b);
1566 }
1567 };
1568
1569 auto routine1 = [] {
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001570 FunctionT<float(void*, float, int)> function;
Antonio Maioranob7dad7d2019-10-11 15:26:58 -04001571 {
1572 Pointer<Byte> funcToCall = function.Arg<0>();
1573 Float a = function.Arg<1>();
1574 Int b = function.Arg<2>();
1575 Float result = Call(Class::Func, funcToCall, a, b);
1576 Return(result);
1577 }
1578 return function("one");
1579 }();
1580
Antonio Maiorano03935ae2019-10-29 16:20:27 -04001581 float result = routine1((void*)routine2.getEntry(), 12.f, 13);
Antonio Maioranob7dad7d2019-10-11 15:26:58 -04001582 EXPECT_EQ(result, 25.f);
Ben Claytond853c122019-04-16 17:51:49 -04001583}
1584
Stephen White17078c72019-02-27 14:39:14 -05001585// Check that a complex generated function which utilizes all 8 or 16 XMM
1586// registers computes the correct result.
1587// (Note that due to MSC's lack of support for inline assembly in x64,
Ben Claytonb1243732019-02-27 23:56:18 +00001588// this test does not actually check that the register contents are
Stephen White17078c72019-02-27 14:39:14 -05001589// preserved, just that the generated function computes the correct value.
1590// It's necessary to inspect the registers in a debugger to actually verify.)
1591TEST(ReactorUnitTests, PreserveXMMRegisters)
1592{
Nicolas Capens157ba262019-12-10 17:49:14 -05001593 FunctionT<void(void*, void*)> function;
Stephen White17078c72019-02-27 14:39:14 -05001594 {
Nicolas Capens157ba262019-12-10 17:49:14 -05001595 Pointer<Byte> in = function.Arg<0>();
1596 Pointer<Byte> out = function.Arg<1>();
Stephen White17078c72019-02-27 14:39:14 -05001597
Nicolas Capens157ba262019-12-10 17:49:14 -05001598 Float4 a = *Pointer<Float4>(in + 16 * 0);
1599 Float4 b = *Pointer<Float4>(in + 16 * 1);
1600 Float4 c = *Pointer<Float4>(in + 16 * 2);
1601 Float4 d = *Pointer<Float4>(in + 16 * 3);
1602 Float4 e = *Pointer<Float4>(in + 16 * 4);
1603 Float4 f = *Pointer<Float4>(in + 16 * 5);
1604 Float4 g = *Pointer<Float4>(in + 16 * 6);
1605 Float4 h = *Pointer<Float4>(in + 16 * 7);
1606 Float4 i = *Pointer<Float4>(in + 16 * 8);
1607 Float4 j = *Pointer<Float4>(in + 16 * 9);
1608 Float4 k = *Pointer<Float4>(in + 16 * 10);
1609 Float4 l = *Pointer<Float4>(in + 16 * 11);
1610 Float4 m = *Pointer<Float4>(in + 16 * 12);
1611 Float4 n = *Pointer<Float4>(in + 16 * 13);
1612 Float4 o = *Pointer<Float4>(in + 16 * 14);
1613 Float4 p = *Pointer<Float4>(in + 16 * 15);
Stephen White17078c72019-02-27 14:39:14 -05001614
Nicolas Capens157ba262019-12-10 17:49:14 -05001615 Float4 ab = a + b;
1616 Float4 cd = c + d;
1617 Float4 ef = e + f;
1618 Float4 gh = g + h;
1619 Float4 ij = i + j;
1620 Float4 kl = k + l;
1621 Float4 mn = m + n;
1622 Float4 op = o + p;
Stephen White17078c72019-02-27 14:39:14 -05001623
Nicolas Capens157ba262019-12-10 17:49:14 -05001624 Float4 abcd = ab + cd;
1625 Float4 efgh = ef + gh;
1626 Float4 ijkl = ij + kl;
1627 Float4 mnop = mn + op;
Stephen White17078c72019-02-27 14:39:14 -05001628
Nicolas Capens157ba262019-12-10 17:49:14 -05001629 Float4 abcdefgh = abcd + efgh;
1630 Float4 ijklmnop = ijkl + mnop;
1631 Float4 sum = abcdefgh + ijklmnop;
1632 *Pointer<Float4>(out) = sum;
1633 Return();
Stephen White17078c72019-02-27 14:39:14 -05001634 }
1635
Nicolas Capens157ba262019-12-10 17:49:14 -05001636 auto routine = function("one");
1637 assert(routine);
1638
1639 float input[64] = { 1.0f, 0.0f, 0.0f, 0.0f,
1640 -1.0f, 1.0f, -1.0f, 0.0f,
1641 1.0f, 2.0f, -2.0f, 0.0f,
1642 -1.0f, 3.0f, -3.0f, 0.0f,
1643 1.0f, 4.0f, -4.0f, 0.0f,
1644 -1.0f, 5.0f, -5.0f, 0.0f,
1645 1.0f, 6.0f, -6.0f, 0.0f,
1646 -1.0f, 7.0f, -7.0f, 0.0f,
1647 1.0f, 8.0f, -8.0f, 0.0f,
1648 -1.0f, 9.0f, -9.0f, 0.0f,
1649 1.0f, 10.0f, -10.0f, 0.0f,
1650 -1.0f, 11.0f, -11.0f, 0.0f,
1651 1.0f, 12.0f, -12.0f, 0.0f,
1652 -1.0f, 13.0f, -13.0f, 0.0f,
1653 1.0f, 14.0f, -14.0f, 0.0f,
1654 -1.0f, 15.0f, -15.0f, 0.0f };
1655
1656 float result[4];
1657
1658 routine(input, result);
1659
1660 EXPECT_EQ(result[0], 0.0f);
1661 EXPECT_EQ(result[1], 120.0f);
1662 EXPECT_EQ(result[2], -120.0f);
1663 EXPECT_EQ(result[3], 0.0f);
Stephen White17078c72019-02-27 14:39:14 -05001664}
1665
Ben Claytonb1243732019-02-27 23:56:18 +00001666template <typename T>
Ben Clayton51f08312019-11-08 14:39:26 +00001667class CToReactorTCastTest : public ::testing::Test
Nicolas Capensf0d22ad2019-03-15 17:22:42 -04001668{
Ben Claytonf3b57972019-03-15 09:56:47 +00001669public:
1670 using CType = typename std::tuple_element<0, T>::type;
1671 using ReactorType = typename std::tuple_element<1, T>::type;
1672};
1673
Ben Clayton51f08312019-11-08 14:39:26 +00001674using CToReactorTCastTestTypes = ::testing::Types
Ben Claytonf3b57972019-03-15 09:56:47 +00001675 < // Subset of types that can be used as arguments.
Nicolas Capensf0d22ad2019-03-15 17:22:42 -04001676 // std::pair<bool, Bool>, FIXME(capn): Not supported as argument type by Subzero.
1677 // std::pair<uint8_t, Byte>, FIXME(capn): Not supported as argument type by Subzero.
1678 // std::pair<int8_t, SByte>, FIXME(capn): Not supported as argument type by Subzero.
1679 // std::pair<int16_t, Short>, FIXME(capn): Not supported as argument type by Subzero.
1680 // std::pair<uint16_t, UShort>, FIXME(capn): Not supported as argument type by Subzero.
Ben Claytonf3b57972019-03-15 09:56:47 +00001681 std::pair<int, Int>,
1682 std::pair<unsigned int, UInt>,
1683 std::pair<float, Float>
1684 >;
1685
Ben Clayton51f08312019-11-08 14:39:26 +00001686TYPED_TEST_SUITE(CToReactorTCastTest, CToReactorTCastTestTypes);
Ben Claytonf3b57972019-03-15 09:56:47 +00001687
Ben Clayton51f08312019-11-08 14:39:26 +00001688TYPED_TEST(CToReactorTCastTest, Casts)
Nicolas Capensf0d22ad2019-03-15 17:22:42 -04001689{
Ben Claytonf3b57972019-03-15 09:56:47 +00001690 using CType = typename TestFixture::CType;
1691 using ReactorType = typename TestFixture::ReactorType;
1692
Ben Clayton6897e9b2019-07-16 17:27:27 +01001693 std::shared_ptr<Routine> routine;
Ben Claytonf3b57972019-03-15 09:56:47 +00001694
1695 {
1696 Function< Int(ReactorType) > function;
1697 {
1698 ReactorType a = function.template Arg<0>();
1699 ReactorType b = CType{};
1700 RValue<ReactorType> c = RValue<ReactorType>(CType{});
1701 Bool same = (a == b) && (a == c);
1702 Return(IfThenElse(same, Int(1), Int(0))); // TODO: Ability to use Bools as return values.
1703 }
1704
1705 routine = function("one");
1706
1707 if(routine)
1708 {
1709 auto callable = (int(*)(CType))routine->getEntry();
1710 CType in = {};
1711 EXPECT_EQ(callable(in), 1);
1712 }
1713 }
1714
Ben Claytonf3b57972019-03-15 09:56:47 +00001715}
1716
1717template <typename T>
Nicolas Capensf0d22ad2019-03-15 17:22:42 -04001718class GEPTest : public ::testing::Test
1719{
Ben Claytonb1243732019-02-27 23:56:18 +00001720public:
1721 using CType = typename std::tuple_element<0, T>::type;
1722 using ReactorType = typename std::tuple_element<1, T>::type;
1723};
1724
1725using GEPTestTypes = ::testing::Types
1726 <
Ben Claytonf3b57972019-03-15 09:56:47 +00001727 std::pair<bool, Bool>,
Ben Claytonb1243732019-02-27 23:56:18 +00001728 std::pair<int8_t, Byte>,
1729 std::pair<int8_t, SByte>,
1730 std::pair<int8_t[4], Byte4>,
1731 std::pair<int8_t[4], SByte4>,
1732 std::pair<int8_t[8], Byte8>,
1733 std::pair<int8_t[8], SByte8>,
1734 std::pair<int8_t[16], Byte16>,
1735 std::pair<int8_t[16], SByte16>,
1736 std::pair<int16_t, Short>,
1737 std::pair<int16_t, UShort>,
1738 std::pair<int16_t[2], Short2>,
1739 std::pair<int16_t[2], UShort2>,
1740 std::pair<int16_t[4], Short4>,
1741 std::pair<int16_t[4], UShort4>,
1742 std::pair<int16_t[8], Short8>,
1743 std::pair<int16_t[8], UShort8>,
1744 std::pair<int, Int>,
1745 std::pair<int, UInt>,
1746 std::pair<int[2], Int2>,
1747 std::pair<int[2], UInt2>,
1748 std::pair<int[4], Int4>,
1749 std::pair<int[4], UInt4>,
1750 std::pair<int64_t, Long>,
1751 std::pair<int16_t, Half>,
1752 std::pair<float, Float>,
1753 std::pair<float[2], Float2>,
1754 std::pair<float[4], Float4>
1755 >;
1756
Alexis Hetu79d4ac92019-06-03 11:31:46 -04001757TYPED_TEST_SUITE(GEPTest, GEPTestTypes);
Ben Claytonb1243732019-02-27 23:56:18 +00001758
Nicolas Capensf0d22ad2019-03-15 17:22:42 -04001759TYPED_TEST(GEPTest, PtrOffsets)
1760{
Ben Claytonb1243732019-02-27 23:56:18 +00001761 using CType = typename TestFixture::CType;
1762 using ReactorType = typename TestFixture::ReactorType;
1763
Ben Clayton6897e9b2019-07-16 17:27:27 +01001764 std::shared_ptr<Routine> routine;
Ben Claytonb1243732019-02-27 23:56:18 +00001765
1766 {
1767 Function< Pointer<ReactorType>(Pointer<ReactorType>, Int) > function;
1768 {
1769 Pointer<ReactorType> pointer = function.template Arg<0>();
1770 Int index = function.template Arg<1>();
1771 Return(&pointer[index]);
1772 }
1773
1774 routine = function("one");
1775
1776 if(routine)
1777 {
1778 auto callable = (CType*(*)(CType*, unsigned int))routine->getEntry();
1779
1780 union PtrInt {
1781 CType* p;
1782 size_t i;
1783 };
1784
1785 PtrInt base;
1786 base.i = 0x10000;
1787
1788 for (int i = 0; i < 5; i++)
1789 {
1790 PtrInt reference;
1791 reference.p = &base.p[i];
1792
1793 PtrInt result;
1794 result.p = callable(base.p, i);
1795
1796 auto expect = reference.i - base.i;
1797 auto got = result.i - base.i;
1798
1799 EXPECT_EQ(got, expect) << "i:" << i;
1800 }
1801 }
1802 }
1803
Ben Claytonb1243732019-02-27 23:56:18 +00001804}
1805
Ben Clayton1c82c7b2019-04-30 12:49:27 +01001806TEST(ReactorUnitTests, Coroutines_Fibonacci)
1807{
1808 if (!rr::Caps.CoroutinesSupported)
1809 {
1810 SUCCEED() << "Coroutines not supported";
1811 return;
1812 }
1813
1814 Coroutine<int()> function;
1815 {
1816 Yield(Int(0));
1817 Yield(Int(1));
1818 Int current = 1;
1819 Int next = 1;
1820 While (true) {
1821 Yield(next);
1822 auto tmp = current + next;
1823 current = next;
1824 next = tmp;
1825 }
1826 }
1827
1828 auto coroutine = function();
1829
1830 int32_t expected[] =
1831 {
1832 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,
1833 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,
1834 317811,
1835 };
1836
1837 auto count = sizeof(expected) / sizeof(expected[0]);
1838
1839 for (size_t i = 0; i < count; i++)
1840 {
1841 int out = 0;
1842 EXPECT_EQ(coroutine->await(out), true);
1843 EXPECT_EQ(out, expected[i]);
1844 }
1845}
1846
1847TEST(ReactorUnitTests, Coroutines_Parameters)
1848{
1849 if (!rr::Caps.CoroutinesSupported)
1850 {
1851 SUCCEED() << "Coroutines not supported";
1852 return;
1853 }
1854
1855 Coroutine<uint8_t(uint8_t* data, int count)> function;
1856 {
1857 Pointer<Byte> data = function.Arg<0>();
1858 Int count = function.Arg<1>();
1859
1860 For(Int i = 0, i < count, i++)
1861 {
1862 Yield(data[i]);
1863 }
1864 }
1865
1866 uint8_t data[] = {10, 20, 30};
1867 auto coroutine = function(&data[0], 3);
1868
1869 uint8_t out = 0;
1870 EXPECT_EQ(coroutine->await(out), true);
1871 EXPECT_EQ(out, 10); out = 0;
1872 EXPECT_EQ(coroutine->await(out), true);
1873 EXPECT_EQ(out, 20); out = 0;
1874 EXPECT_EQ(coroutine->await(out), true);
1875 EXPECT_EQ(out, 30); out = 99;
1876 EXPECT_EQ(coroutine->await(out), false);
1877 EXPECT_EQ(out, 99);
1878 EXPECT_EQ(coroutine->await(out), false);
1879 EXPECT_EQ(out, 99);
1880}
1881
Antonio Maioranobf151b82019-12-03 09:49:14 -05001882
1883template <typename TestFuncType, typename RefFuncType, typename TestValueType>
1884struct IntrinsicTestParams
1885{
1886 std::function<TestFuncType> testFunc; // Function we're testing (Reactor)
1887 std::function<RefFuncType> refFunc; // Reference function to test against (C)
1888 std::vector<TestValueType> testValues; // Values to input to functions
1889};
1890
1891using IntrinsicTestParams_Float = IntrinsicTestParams<RValue<Float>(RValue<Float>), float(float), float>;
1892using IntrinsicTestParams_Float4 = IntrinsicTestParams<RValue<Float4>(RValue<Float4>), float(float), float>;
1893using IntrinsicTestParams_Float4_Float4 = IntrinsicTestParams<RValue<Float4>(RValue<Float4>, RValue<Float4>), float(float, float), std::pair<float, float>>;
1894
1895struct IntrinsicTest_Float : public testing::TestWithParam<IntrinsicTestParams_Float>
1896{
1897 void test()
1898 {
1899 FunctionT<float(float)> function;
1900 {
1901 Return(GetParam().testFunc((Float(function.Arg<0>()))));
1902 }
1903
1904 auto routine = function("one");
1905
1906 for (auto&& v : GetParam().testValues)
1907 {
1908 SCOPED_TRACE(v);
1909 EXPECT_FLOAT_EQ(routine(v), GetParam().refFunc(v));
1910 }
1911 }
1912};
1913
1914struct IntrinsicTest_Float4 : public testing::TestWithParam<IntrinsicTestParams_Float4>
1915{
1916 void test()
1917 {
1918 FunctionT<void(float4*)> function;
1919 {
1920 Pointer<Float4> a = function.Arg<0>();
1921 *a = GetParam().testFunc(*a);
1922 Return();
1923 }
1924
1925 auto routine = function("one");
1926
1927 for (auto&& v : GetParam().testValues)
1928 {
1929 SCOPED_TRACE(v);
1930 float4_value result = invokeRoutine(routine, float4_value{ v });
1931 float4_value expected = float4_value{ GetParam().refFunc(v) };
1932 EXPECT_FLOAT_EQ(result.v[0], expected.v[0]);
1933 EXPECT_FLOAT_EQ(result.v[1], expected.v[1]);
1934 EXPECT_FLOAT_EQ(result.v[2], expected.v[2]);
1935 EXPECT_FLOAT_EQ(result.v[3], expected.v[3]);
1936 }
1937 }
1938};
1939
1940struct IntrinsicTest_Float4_Float4 : public testing::TestWithParam<IntrinsicTestParams_Float4_Float4>
1941{
1942 void test()
1943 {
1944 FunctionT<void(float4*, float4*)> function;
1945 {
1946 Pointer<Float4> a = function.Arg<0>();
1947 Pointer<Float4> b = function.Arg<1>();
1948 *a = GetParam().testFunc(*a, *b);
1949 Return();
1950 }
1951
1952 auto routine = function("one");
1953
1954 for (auto&& v : GetParam().testValues)
1955 {
1956 SCOPED_TRACE(v);
1957 float4_value result = invokeRoutine(routine, float4_value{ v.first }, float4_value{ v.second });
1958 float4_value expected = float4_value{ GetParam().refFunc(v.first, v.second) };
1959 EXPECT_FLOAT_EQ(result.v[0], expected.v[0]);
1960 EXPECT_FLOAT_EQ(result.v[1], expected.v[1]);
1961 EXPECT_FLOAT_EQ(result.v[2], expected.v[2]);
1962 EXPECT_FLOAT_EQ(result.v[3], expected.v[3]);
1963 }
1964 }
1965};
1966
1967INSTANTIATE_TEST_SUITE_P(IntrinsicTestParams_Float, IntrinsicTest_Float, testing::Values(
1968 IntrinsicTestParams_Float{ [](Float v) { return rr::Exp2(v); }, exp2f, {0.f, 1.f, 12345.f} },
1969 IntrinsicTestParams_Float{ [](Float v) { return rr::Log2(v); }, log2f, {0.f, 1.f, 12345.f} },
1970 IntrinsicTestParams_Float{ [](Float v) { return rr::Sqrt(v); }, sqrtf, {0.f, 1.f, 12345.f} }
1971));
1972
1973INSTANTIATE_TEST_SUITE_P(IntrinsicTestParams_Float4, IntrinsicTest_Float4, testing::Values(
1974 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Sin(v); }, sinf, {0.f, 1.f, PI, 12345.f} },
1975 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Cos(v); }, cosf, {0.f, 1.f, PI, 12345.f} },
1976 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Tan(v); }, tanf, {0.f, 1.f, PI, 12345.f} },
1977 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Asin(v); }, asinf, {0.f, 1.f, -1.f} },
1978 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Acos(v); }, acosf, {0.f, 1.f, -1.f} },
1979 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Atan(v); }, atanf, {0.f, 1.f, PI, 12345.f} },
1980 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Sinh(v); }, sinhf, {0.f, 1.f, PI, 12345.f} },
1981 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Cosh(v); }, coshf, {0.f, 1.f, PI, 12345.f} },
1982 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Tanh(v); }, tanhf, {0.f, 1.f, PI, 12345.f} },
1983 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Asinh(v); }, asinhf, {0.f, 1.f, PI, 12345.f} },
1984 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Acosh(v); }, acoshf, { 1.f, PI, 12345.f} },
1985 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Atanh(v); }, atanhf, {0.f, 1.f, -1.f} },
1986 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Exp(v); }, expf, {0.f, 1.f, PI, 12345.f} },
1987 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Log(v); }, logf, {0.f, 1.f, PI, 12345.f} },
1988 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Exp2(v); }, exp2f, {0.f, 1.f, PI, 12345.f} },
1989 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Log2(v); }, log2f, {0.f, 1.f, PI, 12345.f} },
1990 IntrinsicTestParams_Float4{ [](RValue<Float4> v) { return rr::Sqrt(v); }, sqrtf, {0.f, 1.f, PI, 12345.f} }
1991));
1992
1993INSTANTIATE_TEST_SUITE_P(IntrinsicTestParams_Float4_Float4, IntrinsicTest_Float4_Float4, testing::Values(
1994 IntrinsicTestParams_Float4_Float4{ [](RValue<Float4> v1, RValue<Float4> v2) { return Atan2(v1, v2); }, atan2f, { {0.f, 0.f}, {0.f, -1.f}, {-1.f, 0.f}, {12345.f, 12345.f} } },
1995 IntrinsicTestParams_Float4_Float4{ [](RValue<Float4> v1, RValue<Float4> v2) { return Pow(v1, v2); }, powf, { {0.f, 0.f}, {0.f, -1.f}, {-1.f, 0.f}, {12345.f, 12345.f} } }
1996));
1997
1998TEST_P(IntrinsicTest_Float, Test) { test(); }
1999TEST_P(IntrinsicTest_Float4, Test) { test(); }
2000TEST_P(IntrinsicTest_Float4_Float4, Test) { test(); }
2001
2002TEST(ReactorUnitTests, Intrinsics_Ctlz)
2003{
2004 // ctlz: counts number of leading zeros
2005
2006 {
2007 Function<UInt(UInt x)> function;
2008 {
2009 UInt x = function.Arg<0>();
2010 Return(rr::Ctlz(x, false));
2011 }
2012 auto routine = function("one");
2013 auto callable = (uint32_t(*)(uint32_t))routine->getEntry();
2014
2015
2016 for (uint32_t i = 0; i < 31; ++i) {
2017 uint32_t result = callable(1 << i);
2018 EXPECT_EQ(result, 31 - i);
2019 }
2020
2021 // Input 0 should return 32 for isZeroUndef == false
2022 {
2023 uint32_t result = callable(0);
2024 EXPECT_EQ(result, 32u);
2025 }
2026 }
2027
2028 {
2029 Function<Void(Pointer<UInt4>, UInt x)> function;
2030 {
2031 Pointer<UInt4> out = function.Arg<0>();
2032 UInt x = function.Arg<1>();
2033 *out = rr::Ctlz(UInt4(x), false);
2034 }
2035 auto routine = function("one");
2036 auto callable = (void(*)(uint32_t*, uint32_t))routine->getEntry();
2037
2038 uint32_t x[4];
2039
2040 for (uint32_t i = 0; i < 31; ++i) {
2041 callable(x, 1 << i);
2042 EXPECT_EQ(x[0], 31 - i);
2043 EXPECT_EQ(x[1], 31 - i);
2044 EXPECT_EQ(x[2], 31 - i);
2045 EXPECT_EQ(x[3], 31 - i);
2046 }
2047
2048 // Input 0 should return 32 for isZeroUndef == false
2049 {
2050 callable(x, 0);
2051 EXPECT_EQ(x[0], 32u);
2052 EXPECT_EQ(x[1], 32u);
2053 EXPECT_EQ(x[2], 32u);
2054 EXPECT_EQ(x[3], 32u);
2055 }
2056 }
2057}
2058
2059TEST(ReactorUnitTests, Intrinsics_Cttz)
2060{
2061 // cttz: counts number of trailing zeros
2062
2063 {
2064 Function<UInt(UInt x)> function;
2065 {
2066 UInt x = function.Arg<0>();
2067 Return(rr::Cttz(x, false));
2068 }
2069 auto routine = function("one");
2070 auto callable = (uint32_t(*)(uint32_t))routine->getEntry();
2071
2072
2073 for (uint32_t i = 0; i < 31; ++i) {
2074 uint32_t result = callable(1 << i);
2075 EXPECT_EQ(result, i);
2076 }
2077
2078 // Input 0 should return 32 for isZeroUndef == false
2079 {
2080 uint32_t result = callable(0);
2081 EXPECT_EQ(result, 32u);
2082 }
2083 }
2084
2085 {
2086 Function<Void(Pointer<UInt4>, UInt x)> function;
2087 {
2088 Pointer<UInt4> out = function.Arg<0>();
2089 UInt x = function.Arg<1>();
2090 *out = rr::Cttz(UInt4(x), false);
2091 }
2092 auto routine = function("one");
2093 auto callable = (void(*)(uint32_t*, uint32_t))routine->getEntry();
2094
2095 uint32_t x[4];
2096
2097 for (uint32_t i = 0; i < 31; ++i) {
2098 callable(x, 1 << i);
2099 EXPECT_EQ(x[0], i);
2100 EXPECT_EQ(x[1], i);
2101 EXPECT_EQ(x[2], i);
2102 EXPECT_EQ(x[3], i);
2103 }
2104
2105 // Input 0 should return 32 for isZeroUndef == false
2106 {
2107 callable(x, 0);
2108 EXPECT_EQ(x[0], 32u);
2109 EXPECT_EQ(x[1], 32u);
2110 EXPECT_EQ(x[2], 32u);
2111 EXPECT_EQ(x[3], 32u);
2112 }
2113 }
2114}
2115
2116TEST(ReactorUnitTests, Intrinsics_Scatter)
2117{
2118 Function<Void(Pointer<Float> base, Pointer<Float4> val, Pointer<Int4> offsets)> function;
2119 {
2120 Pointer<Float> base = function.Arg<0>();
2121 Pointer<Float4> val = function.Arg<1>();
2122 Pointer<Int4> offsets = function.Arg<2>();
2123
2124 auto mask = Int4(~0, ~0, ~0, ~0);
2125 unsigned int alignment = 1;
2126 Scatter(base, *val, *offsets, mask, alignment);
2127 }
2128
2129 float buffer[16] = {0};
2130
2131 constexpr auto elemSize = sizeof(buffer[0]);
2132
2133 int offsets[] =
2134 {
2135 1 *elemSize,
2136 6 *elemSize,
2137 11 *elemSize,
2138 13 *elemSize
2139 };
2140
2141 float val[4] = {10, 60, 110, 130};
2142
2143 auto routine = function("one");
2144 auto entry = (void(*)(float*, float*, int*))routine->getEntry();
2145
2146 entry(buffer, val, offsets);
2147
2148 EXPECT_EQ(buffer[offsets[0] / sizeof(buffer[0])], 10);
2149 EXPECT_EQ(buffer[offsets[1] / sizeof(buffer[0])], 60);
2150 EXPECT_EQ(buffer[offsets[2] / sizeof(buffer[0])], 110);
2151 EXPECT_EQ(buffer[offsets[3] / sizeof(buffer[0])], 130);
2152}
2153
2154TEST(ReactorUnitTests, Intrinsics_Gather)
2155{
2156 Function<Void(Pointer<Float> base, Pointer<Int4> offsets, Pointer<Float4> result)> function;
2157 {
2158 Pointer<Float> base = function.Arg<0>();
2159 Pointer<Int4> offsets = function.Arg<1>();
2160 Pointer<Float4> result = function.Arg<2>();
2161
2162 auto mask = Int4(~0, ~0, ~0, ~0);
2163 unsigned int alignment = 1;
2164 bool zeroMaskedLanes = true;
2165 *result = Gather(base, *offsets, mask, alignment, zeroMaskedLanes);
2166 }
2167
2168 float buffer[] =
2169 {
2170 0, 10, 20, 30,
2171 40, 50, 60, 70,
2172 80, 90, 100, 110,
2173 120, 130, 140, 150
2174 };
2175
2176 constexpr auto elemSize = sizeof(buffer[0]);
2177
2178 int offsets[] =
2179 {
2180 1 *elemSize,
2181 6 *elemSize,
2182 11 *elemSize,
2183 13 *elemSize
2184 };
2185
2186 auto routine = function("one");
2187 auto entry = (void(*)(float*, int*, float*))routine->getEntry();
2188
2189 float result[4] = {};
2190 entry(buffer, offsets, result);
2191
2192 EXPECT_EQ(result[0], 10);
2193 EXPECT_EQ(result[1], 60);
2194 EXPECT_EQ(result[2], 110);
2195 EXPECT_EQ(result[3], 130);
2196}
2197
Antonio Maiorano7ffda5b2019-11-20 15:31:51 -05002198TEST(ReactorUnitTests, ExtractFromRValue)
2199{
2200 Function<Void(Pointer<Int4> values, Pointer<Int4> result)> function;
2201 {
2202 Pointer<Int4> vIn = function.Arg<0>();
2203 Pointer<Int4> resultIn = function.Arg<1>();
2204
2205 RValue<Int4> v = *vIn;
2206
2207 Int4 result(678);
2208
2209 If(Extract(v, 0) == 42)
2210 {
2211 result = Insert(result, 1, 0);
2212 }
2213
2214 If(Extract(v, 1) == 42)
2215 {
2216 result = Insert(result, 1, 1);
2217 }
2218
2219 *resultIn = result;
2220
2221 Return();
2222 }
2223
2224 auto routine = function("one");
2225 auto entry = (void(*)(int*, int*))routine->getEntry();
2226
2227 int v[4] = { 42, 42, 42, 42 };
2228 int result[4] = { 99, 99, 99, 99 };
2229 entry(v, result);
2230 EXPECT_EQ(result[0], 1);
2231 EXPECT_EQ(result[1], 1);
2232 EXPECT_EQ(result[2], 678);
2233 EXPECT_EQ(result[3], 678);
2234}
2235
Nicolas Capens228b05d2016-10-12 15:27:04 -04002236int main(int argc, char **argv)
2237{
2238 ::testing::InitGoogleTest(&argc, argv);
2239 return RUN_ALL_TESTS();
Nicolas Capens598f8d82016-09-26 15:09:10 -04002240}
Ben Clayton351be422019-04-30 12:26:57 +01002241
2242////////////////////////////////
2243// Trait compile time checks. //
2244////////////////////////////////
2245
Ben Clayton51f08312019-11-08 14:39:26 +00002246// Assert CToReactorT resolves to expected types.
2247static_assert(std::is_same<CToReactorT<void>, Void>::value, "");
2248static_assert(std::is_same<CToReactorT<bool>, Bool>::value, "");
2249static_assert(std::is_same<CToReactorT<uint8_t>, Byte>::value, "");
2250static_assert(std::is_same<CToReactorT<int8_t>, SByte>::value, "");
2251static_assert(std::is_same<CToReactorT<int16_t>, Short>::value, "");
2252static_assert(std::is_same<CToReactorT<uint16_t>, UShort>::value, "");
2253static_assert(std::is_same<CToReactorT<int32_t>, Int>::value, "");
2254static_assert(std::is_same<CToReactorT<uint64_t>, Long>::value, "");
2255static_assert(std::is_same<CToReactorT<uint32_t>, UInt>::value, "");
2256static_assert(std::is_same<CToReactorT<float>, Float>::value, "");
Ben Clayton351be422019-04-30 12:26:57 +01002257
Ben Clayton51f08312019-11-08 14:39:26 +00002258// Assert CToReactorT for known pointer types resolves to expected types.
2259static_assert(std::is_same<CToReactorT<void*>, Pointer<Byte>>::value, "");
2260static_assert(std::is_same<CToReactorT<bool*>, Pointer<Bool>>::value, "");
2261static_assert(std::is_same<CToReactorT<uint8_t*>, Pointer<Byte>>::value, "");
2262static_assert(std::is_same<CToReactorT<int8_t*>, Pointer<SByte>>::value, "");
2263static_assert(std::is_same<CToReactorT<int16_t*>, Pointer<Short>>::value, "");
2264static_assert(std::is_same<CToReactorT<uint16_t*>, Pointer<UShort>>::value, "");
2265static_assert(std::is_same<CToReactorT<int32_t*>, Pointer<Int>>::value, "");
2266static_assert(std::is_same<CToReactorT<uint64_t*>, Pointer<Long>>::value, "");
2267static_assert(std::is_same<CToReactorT<uint32_t*>, Pointer<UInt>>::value, "");
2268static_assert(std::is_same<CToReactorT<float*>, Pointer<Float>>::value, "");
2269static_assert(std::is_same<CToReactorT<uint16_t**>, Pointer<Pointer<UShort>>>::value, "");
2270static_assert(std::is_same<CToReactorT<uint16_t***>, Pointer<Pointer<Pointer<UShort>>>>::value, "");
Ben Clayton351be422019-04-30 12:26:57 +01002271
Ben Clayton51f08312019-11-08 14:39:26 +00002272// Assert CToReactorT for unknown pointer types resolves to Pointer<Byte>.
Ben Clayton351be422019-04-30 12:26:57 +01002273struct S{};
Ben Clayton51f08312019-11-08 14:39:26 +00002274static_assert(std::is_same<CToReactorT<S*>, Pointer<Byte>>::value, "");
2275static_assert(std::is_same<CToReactorT<S**>, Pointer<Pointer<Byte>>>::value, "");
2276static_assert(std::is_same<CToReactorT<S***>, Pointer<Pointer<Pointer<Byte>>>>::value, "");
Ben Clayton351be422019-04-30 12:26:57 +01002277
2278// Assert IsRValue<> resolves true for RValue<> types.
2279static_assert(IsRValue<RValue<Void>>::value, "");
2280static_assert(IsRValue<RValue<Bool>>::value, "");
2281static_assert(IsRValue<RValue<Byte>>::value, "");
2282static_assert(IsRValue<RValue<SByte>>::value, "");
2283static_assert(IsRValue<RValue<Short>>::value, "");
2284static_assert(IsRValue<RValue<UShort>>::value, "");
2285static_assert(IsRValue<RValue<Int>>::value, "");
2286static_assert(IsRValue<RValue<Long>>::value, "");
2287static_assert(IsRValue<RValue<UInt>>::value, "");
2288static_assert(IsRValue<RValue<Float>>::value, "");
2289
2290// Assert IsLValue<> resolves true for LValue types.
2291static_assert(IsLValue<Bool>::value, "");
2292static_assert(IsLValue<Byte>::value, "");
2293static_assert(IsLValue<SByte>::value, "");
2294static_assert(IsLValue<Short>::value, "");
2295static_assert(IsLValue<UShort>::value, "");
2296static_assert(IsLValue<Int>::value, "");
2297static_assert(IsLValue<Long>::value, "");
2298static_assert(IsLValue<UInt>::value, "");
2299static_assert(IsLValue<Float>::value, "");
2300
Ben Clayton208ed402019-05-03 22:30:03 +01002301// Assert IsReference<> resolves true for Reference types.
2302static_assert(IsReference<Reference<Bool>>::value, "");
2303static_assert(IsReference<Reference<Byte>>::value, "");
2304static_assert(IsReference<Reference<SByte>>::value, "");
2305static_assert(IsReference<Reference<Short>>::value, "");
2306static_assert(IsReference<Reference<UShort>>::value, "");
2307static_assert(IsReference<Reference<Int>>::value, "");
2308static_assert(IsReference<Reference<Long>>::value, "");
2309static_assert(IsReference<Reference<UInt>>::value, "");
2310static_assert(IsReference<Reference<Float>>::value, "");
2311
Ben Clayton351be422019-04-30 12:26:57 +01002312// Assert IsRValue<> resolves false for LValue types.
2313static_assert(!IsRValue<Void>::value, "");
2314static_assert(!IsRValue<Bool>::value, "");
2315static_assert(!IsRValue<Byte>::value, "");
2316static_assert(!IsRValue<SByte>::value, "");
2317static_assert(!IsRValue<Short>::value, "");
2318static_assert(!IsRValue<UShort>::value, "");
2319static_assert(!IsRValue<Int>::value, "");
2320static_assert(!IsRValue<Long>::value, "");
2321static_assert(!IsRValue<UInt>::value, "");
2322static_assert(!IsRValue<Float>::value, "");
2323
Ben Clayton208ed402019-05-03 22:30:03 +01002324// Assert IsRValue<> resolves false for Reference types.
2325static_assert(!IsRValue<Reference<Void>>::value, "");
2326static_assert(!IsRValue<Reference<Bool>>::value, "");
2327static_assert(!IsRValue<Reference<Byte>>::value, "");
2328static_assert(!IsRValue<Reference<SByte>>::value, "");
2329static_assert(!IsRValue<Reference<Short>>::value, "");
2330static_assert(!IsRValue<Reference<UShort>>::value, "");
2331static_assert(!IsRValue<Reference<Int>>::value, "");
2332static_assert(!IsRValue<Reference<Long>>::value, "");
2333static_assert(!IsRValue<Reference<UInt>>::value, "");
2334static_assert(!IsRValue<Reference<Float>>::value, "");
2335
Ben Clayton351be422019-04-30 12:26:57 +01002336// Assert IsRValue<> resolves false for C types.
2337static_assert(!IsRValue<void>::value, "");
2338static_assert(!IsRValue<bool>::value, "");
2339static_assert(!IsRValue<uint8_t>::value, "");
2340static_assert(!IsRValue<int8_t>::value, "");
2341static_assert(!IsRValue<int16_t>::value, "");
2342static_assert(!IsRValue<uint16_t>::value, "");
2343static_assert(!IsRValue<int32_t>::value, "");
2344static_assert(!IsRValue<uint64_t>::value, "");
2345static_assert(!IsRValue<uint32_t>::value, "");
2346static_assert(!IsRValue<float>::value, "");
2347
2348// Assert IsLValue<> resolves false for RValue<> types.
2349static_assert(!IsLValue<RValue<Void>>::value, "");
2350static_assert(!IsLValue<RValue<Bool>>::value, "");
2351static_assert(!IsLValue<RValue<Byte>>::value, "");
2352static_assert(!IsLValue<RValue<SByte>>::value, "");
2353static_assert(!IsLValue<RValue<Short>>::value, "");
2354static_assert(!IsLValue<RValue<UShort>>::value, "");
2355static_assert(!IsLValue<RValue<Int>>::value, "");
2356static_assert(!IsLValue<RValue<Long>>::value, "");
2357static_assert(!IsLValue<RValue<UInt>>::value, "");
2358static_assert(!IsLValue<RValue<Float>>::value, "");
2359
2360// Assert IsLValue<> resolves false for Void type.
2361static_assert(!IsLValue<Void>::value, "");
2362
Ben Clayton208ed402019-05-03 22:30:03 +01002363// Assert IsLValue<> resolves false for Reference<> types.
2364static_assert(!IsLValue<Reference<Void>>::value, "");
2365static_assert(!IsLValue<Reference<Bool>>::value, "");
2366static_assert(!IsLValue<Reference<Byte>>::value, "");
2367static_assert(!IsLValue<Reference<SByte>>::value, "");
2368static_assert(!IsLValue<Reference<Short>>::value, "");
2369static_assert(!IsLValue<Reference<UShort>>::value, "");
2370static_assert(!IsLValue<Reference<Int>>::value, "");
2371static_assert(!IsLValue<Reference<Long>>::value, "");
2372static_assert(!IsLValue<Reference<UInt>>::value, "");
2373static_assert(!IsLValue<Reference<Float>>::value, "");
2374
Ben Clayton351be422019-04-30 12:26:57 +01002375// Assert IsLValue<> resolves false for C types.
2376static_assert(!IsLValue<void>::value, "");
2377static_assert(!IsLValue<bool>::value, "");
2378static_assert(!IsLValue<uint8_t>::value, "");
2379static_assert(!IsLValue<int8_t>::value, "");
2380static_assert(!IsLValue<int16_t>::value, "");
2381static_assert(!IsLValue<uint16_t>::value, "");
2382static_assert(!IsLValue<int32_t>::value, "");
2383static_assert(!IsLValue<uint64_t>::value, "");
2384static_assert(!IsLValue<uint32_t>::value, "");
2385static_assert(!IsLValue<float>::value, "");
2386
2387// Assert IsDefined<> resolves true for RValue<> types.
2388static_assert(IsDefined<RValue<Void>>::value, "");
2389static_assert(IsDefined<RValue<Bool>>::value, "");
2390static_assert(IsDefined<RValue<Byte>>::value, "");
2391static_assert(IsDefined<RValue<SByte>>::value, "");
2392static_assert(IsDefined<RValue<Short>>::value, "");
2393static_assert(IsDefined<RValue<UShort>>::value, "");
2394static_assert(IsDefined<RValue<Int>>::value, "");
2395static_assert(IsDefined<RValue<Long>>::value, "");
2396static_assert(IsDefined<RValue<UInt>>::value, "");
2397static_assert(IsDefined<RValue<Float>>::value, "");
2398
2399// Assert IsDefined<> resolves true for LValue types.
2400static_assert(IsDefined<Void>::value, "");
2401static_assert(IsDefined<Bool>::value, "");
2402static_assert(IsDefined<Byte>::value, "");
2403static_assert(IsDefined<SByte>::value, "");
2404static_assert(IsDefined<Short>::value, "");
2405static_assert(IsDefined<UShort>::value, "");
2406static_assert(IsDefined<Int>::value, "");
2407static_assert(IsDefined<Long>::value, "");
2408static_assert(IsDefined<UInt>::value, "");
2409static_assert(IsDefined<Float>::value, "");
2410
Ben Clayton208ed402019-05-03 22:30:03 +01002411// Assert IsDefined<> resolves true for Reference<> types.
2412static_assert(IsDefined<Reference<Bool>>::value, "");
2413static_assert(IsDefined<Reference<Byte>>::value, "");
2414static_assert(IsDefined<Reference<SByte>>::value, "");
2415static_assert(IsDefined<Reference<Short>>::value, "");
2416static_assert(IsDefined<Reference<UShort>>::value, "");
2417static_assert(IsDefined<Reference<Int>>::value, "");
2418static_assert(IsDefined<Reference<Long>>::value, "");
2419static_assert(IsDefined<Reference<UInt>>::value, "");
2420static_assert(IsDefined<Reference<Float>>::value, "");
2421
Ben Clayton351be422019-04-30 12:26:57 +01002422// Assert IsDefined<> resolves true for C types.
2423static_assert(IsDefined<void>::value, "");
2424static_assert(IsDefined<bool>::value, "");
2425static_assert(IsDefined<uint8_t>::value, "");
2426static_assert(IsDefined<int8_t>::value, "");
2427static_assert(IsDefined<int16_t>::value, "");
2428static_assert(IsDefined<uint16_t>::value, "");
2429static_assert(IsDefined<int32_t>::value, "");
2430static_assert(IsDefined<uint64_t>::value, "");
2431static_assert(IsDefined<uint32_t>::value, "");
2432static_assert(IsDefined<float>::value, "");