usearch 2.10.2 → 2.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/README.md +1 -1
  2. package/binding.gyp +101 -0
  3. package/c/CMakeLists.txt +27 -0
  4. package/c/README.md +34 -0
  5. package/c/lib.cpp +362 -0
  6. package/c/test.c +382 -0
  7. package/c/usearch.h +356 -0
  8. package/cmake/clipp.cmake +7 -0
  9. package/cmake/config.cmake.in +15 -0
  10. package/cmake/emscripten.cmake +8 -0
  11. package/cmake/jemalloc.cmake +62 -0
  12. package/cmake/pkg-config.pc.in +4 -0
  13. package/cmake/usearchConfigVersion.cmake.in +20 -0
  14. package/cpp/CMakeLists.txt +14 -0
  15. package/cpp/README.md +161 -0
  16. package/cpp/bench.cpp +616 -0
  17. package/cpp/test.cpp +324 -0
  18. package/fp16/CMakeLists.txt +176 -0
  19. package/fp16/LICENSE +11 -0
  20. package/fp16/README.md +20 -0
  21. package/fp16/bench/alt-element.cc +89 -0
  22. package/fp16/bench/from-alt-array.cc +175 -0
  23. package/fp16/bench/from-ieee-array.cc +399 -0
  24. package/fp16/bench/ieee-element.cc +272 -0
  25. package/fp16/bench/to-alt-array.cc +91 -0
  26. package/fp16/bench/to-ieee-array.cc +303 -0
  27. package/fp16/cmake/DownloadGoogleBenchmark.cmake +15 -0
  28. package/fp16/cmake/DownloadGoogleTest.cmake +15 -0
  29. package/fp16/cmake/DownloadPSimd.cmake +15 -0
  30. package/fp16/configure.py +65 -0
  31. package/fp16/confu.yaml +8 -0
  32. package/fp16/include/fp16/__init__.py +0 -0
  33. package/fp16/include/fp16/avx.py +50 -0
  34. package/fp16/include/fp16/avx2.py +53 -0
  35. package/fp16/include/fp16/bitcasts.h +92 -0
  36. package/fp16/include/fp16/fp16.h +451 -0
  37. package/fp16/include/fp16/psimd.h +131 -0
  38. package/fp16/include/fp16.h +11 -0
  39. package/fp16/jni/Android.mk +6 -0
  40. package/fp16/jni/Application.mk +4 -0
  41. package/fp16/test/alt-from-fp32-value.cc +498 -0
  42. package/fp16/test/alt-to-fp32-bits.cc +263 -0
  43. package/fp16/test/alt-to-fp32-psimd.cc +145 -0
  44. package/fp16/test/alt-to-fp32-value.cc +348 -0
  45. package/fp16/test/alt-to-fp32x2-psimd.cc +245 -0
  46. package/fp16/test/bitcasts.cc +56 -0
  47. package/fp16/test/ieee-from-fp32-value.cc +523 -0
  48. package/fp16/test/ieee-to-fp32-bits.cc +333 -0
  49. package/fp16/test/ieee-to-fp32-psimd.cc +312 -0
  50. package/fp16/test/ieee-to-fp32-value.cc +420 -0
  51. package/fp16/test/ieee-to-fp32x2-psimd.cc +541 -0
  52. package/fp16/test/peachpy/alt-xmm-to-fp32-xmm-avx.cc +96 -0
  53. package/fp16/test/peachpy/alt-xmm-to-fp32-ymm-avx2.cc +96 -0
  54. package/fp16/test/peachpy/stubs.py +38 -0
  55. package/fp16/test/tables.cc +530 -0
  56. package/fp16/test/tables.h +13 -0
  57. package/fp16/third-party/THHalf.h +92 -0
  58. package/fp16/third-party/eigen-half.h +170 -0
  59. package/fp16/third-party/float16-compressor.h +80 -0
  60. package/fp16/third-party/half.hpp +2916 -0
  61. package/fp16/third-party/npy-halffloat.h +328 -0
  62. package/include/usearch/index.hpp +3838 -0
  63. package/include/usearch/index_dense.hpp +2004 -0
  64. package/include/usearch/index_plugins.hpp +2255 -0
  65. package/javascript/dist-package-cjs.json +3 -0
  66. package/javascript/dist-package-esm.json +3 -0
  67. package/javascript/lib.cpp +350 -0
  68. package/javascript/node-gyp-build.d.ts +1 -0
  69. package/javascript/tsconfig-base.json +25 -0
  70. package/javascript/tsconfig-cjs.json +8 -0
  71. package/javascript/tsconfig-esm.json +8 -0
  72. package/javascript/usearch.test.js +84 -0
  73. package/javascript/usearch.ts +640 -0
  74. package/package.json +10 -3
  75. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  76. package/prebuilds/linux-arm64/usearch.node +0 -0
  77. package/prebuilds/linux-x64/usearch.node +0 -0
  78. package/prebuilds/win32-ia32/usearch.node +0 -0
  79. package/prebuilds/win32-x64/usearch.node +0 -0
  80. package/simsimd/.releaserc +87 -0
  81. package/simsimd/CONTRIBUTING.md +114 -0
  82. package/simsimd/Cargo.lock +709 -0
  83. package/simsimd/Cargo.toml +44 -0
  84. package/simsimd/LICENSE +201 -0
  85. package/simsimd/README.md +708 -0
  86. package/simsimd/binding.gyp +36 -0
  87. package/simsimd/build.rs +51 -0
  88. package/simsimd/c/lib.c +110 -0
  89. package/simsimd/include/simsimd/binary.h +258 -0
  90. package/simsimd/include/simsimd/dot.h +1237 -0
  91. package/simsimd/include/simsimd/geospatial.h +37 -0
  92. package/simsimd/include/simsimd/probability.h +563 -0
  93. package/simsimd/include/simsimd/simsimd.h +1129 -0
  94. package/simsimd/include/simsimd/spatial.h +1019 -0
  95. package/simsimd/include/simsimd/types.h +309 -0
  96. package/simsimd/javascript/bench.js +127 -0
  97. package/simsimd/javascript/dist-package-cjs.json +3 -0
  98. package/simsimd/javascript/dist-package-esm.json +3 -0
  99. package/simsimd/javascript/fallback.ts +203 -0
  100. package/simsimd/javascript/lib.c +107 -0
  101. package/simsimd/javascript/node-gyp-build.d.ts +1 -0
  102. package/simsimd/javascript/simsimd.ts +135 -0
  103. package/simsimd/javascript/test.mjs +179 -0
  104. package/simsimd/javascript/tsconfig-base.json +37 -0
  105. package/simsimd/javascript/tsconfig-cjs.json +8 -0
  106. package/simsimd/javascript/tsconfig-esm.json +8 -0
  107. package/simsimd/package-lock.json +1709 -0
  108. package/simsimd/package.json +61 -0
  109. package/simsimd/rust/benches/cosine.rs +27 -0
  110. package/simsimd/rust/benches/native.rs +30 -0
  111. package/simsimd/rust/benches/sqeuclidean.rs +27 -0
  112. package/simsimd/rust/lib.rs +778 -0
@@ -0,0 +1,541 @@
1
+ #include <gtest/gtest.h>
2
+
3
+ #include <cstdint>
4
+
5
+ #include <fp16.h>
6
+ #include <fp16/psimd.h>
7
+
8
+
9
+ TEST(FP16_IEEE_TO_FP32x2_PSIMD, infinity) {
10
+ const uint16_t positive_infinity_f16 = UINT16_C(0x7C00);
11
+ const uint16_t negative_infinity_f16 = UINT16_C(0xFC00);
12
+
13
+ const uint32_t positive_infinity_f32 = UINT32_C(0x7F800000);
14
+ const uint32_t negative_infinity_f32 = UINT32_C(0xFF800000);
15
+
16
+ const psimd_u16 fp16 = {
17
+ positive_infinity_f16, negative_infinity_f16,
18
+ negative_infinity_f16, positive_infinity_f16,
19
+ positive_infinity_f16, positive_infinity_f16,
20
+ negative_infinity_f16, negative_infinity_f16
21
+ };
22
+ const psimd_u32x2 fp32 =
23
+ psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
24
+
25
+ EXPECT_EQ(positive_infinity_f32, fp32.lo[0]) <<
26
+ std::hex << std::uppercase << std::setfill('0') <<
27
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
28
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
29
+ "F32 = 0x" << std::setw(8) << positive_infinity_f32;
30
+ EXPECT_EQ(negative_infinity_f32, fp32.lo[1]) <<
31
+ std::hex << std::uppercase << std::setfill('0') <<
32
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
33
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
34
+ "F32 = 0x" << std::setw(8) << negative_infinity_f32;
35
+ EXPECT_EQ(negative_infinity_f32, fp32.lo[2]) <<
36
+ std::hex << std::uppercase << std::setfill('0') <<
37
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
38
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
39
+ "F32 = 0x" << std::setw(8) << negative_infinity_f32;
40
+ EXPECT_EQ(positive_infinity_f32, fp32.lo[3]) <<
41
+ std::hex << std::uppercase << std::setfill('0') <<
42
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
43
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
44
+ "F32 = 0x" << std::setw(8) << positive_infinity_f32;
45
+ EXPECT_EQ(positive_infinity_f32, fp32.hi[0]) <<
46
+ std::hex << std::uppercase << std::setfill('0') <<
47
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
48
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
49
+ "F32 = 0x" << std::setw(8) << positive_infinity_f32;
50
+ EXPECT_EQ(positive_infinity_f32, fp32.hi[1]) <<
51
+ std::hex << std::uppercase << std::setfill('0') <<
52
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
53
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
54
+ "F32 = 0x" << std::setw(8) << positive_infinity_f32;
55
+ EXPECT_EQ(negative_infinity_f32, fp32.hi[2]) <<
56
+ std::hex << std::uppercase << std::setfill('0') <<
57
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
58
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
59
+ "F32 = 0x" << std::setw(8) << negative_infinity_f32;
60
+ EXPECT_EQ(negative_infinity_f32, fp32.hi[3]) <<
61
+ std::hex << std::uppercase << std::setfill('0') <<
62
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
63
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
64
+ "F32 = 0x" << std::setw(8) << negative_infinity_f32;
65
+ }
66
+
67
+ TEST(FP16_IEEE_TO_FP32x2_PSIMD, positive_nan) {
68
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
69
+ const psimd_u16 fp16 = {
70
+ (uint16_t) (h + 0x7C00 + (h == 0)) /* Avoid infinity */,
71
+ (uint16_t) (h + 0x7C01),
72
+ (uint16_t) (h + 0x7C02),
73
+ (uint16_t) (h + 0x7C03),
74
+ (uint16_t) (h + 0x7C04),
75
+ (uint16_t) (h + 0x7C05),
76
+ (uint16_t) (h + 0x7C06),
77
+ (uint16_t) (h + 0x7C07),
78
+ };
79
+ const psimd_u32x2 fp32 =
80
+ psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
81
+
82
+ /* Check sign */
83
+ EXPECT_EQ(fp32.lo[0] & UINT32_C(0x80000000), 0) <<
84
+ std::hex << std::uppercase << std::setfill('0') <<
85
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
86
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
87
+ EXPECT_EQ(fp32.lo[1] & UINT32_C(0x80000000), 0) <<
88
+ std::hex << std::uppercase << std::setfill('0') <<
89
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
90
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
91
+ EXPECT_EQ(fp32.lo[2] & UINT32_C(0x80000000), 0) <<
92
+ std::hex << std::uppercase << std::setfill('0') <<
93
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
94
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
95
+ EXPECT_EQ(fp32.lo[3] & UINT32_C(0x80000000), 0) <<
96
+ std::hex << std::uppercase << std::setfill('0') <<
97
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
98
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
99
+ EXPECT_EQ(fp32.hi[0] & UINT32_C(0x80000000), 0) <<
100
+ std::hex << std::uppercase << std::setfill('0') <<
101
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
102
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
103
+ EXPECT_EQ(fp32.hi[1] & UINT32_C(0x80000000), 0) <<
104
+ std::hex << std::uppercase << std::setfill('0') <<
105
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
106
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
107
+ EXPECT_EQ(fp32.hi[2] & UINT32_C(0x80000000), 0) <<
108
+ std::hex << std::uppercase << std::setfill('0') <<
109
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
110
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
111
+ EXPECT_EQ(fp32.hi[3] & UINT32_C(0x80000000), 0) <<
112
+ std::hex << std::uppercase << std::setfill('0') <<
113
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
114
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
115
+
116
+ /* Check exponent */
117
+ EXPECT_EQ(fp32.lo[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
118
+ std::hex << std::uppercase << std::setfill('0') <<
119
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
120
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
121
+ EXPECT_EQ(fp32.lo[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
122
+ std::hex << std::uppercase << std::setfill('0') <<
123
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
124
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
125
+ EXPECT_EQ(fp32.lo[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
126
+ std::hex << std::uppercase << std::setfill('0') <<
127
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
128
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
129
+ EXPECT_EQ(fp32.lo[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
130
+ std::hex << std::uppercase << std::setfill('0') <<
131
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
132
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
133
+ EXPECT_EQ(fp32.hi[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
134
+ std::hex << std::uppercase << std::setfill('0') <<
135
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
136
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
137
+ EXPECT_EQ(fp32.hi[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
138
+ std::hex << std::uppercase << std::setfill('0') <<
139
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
140
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
141
+ EXPECT_EQ(fp32.hi[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
142
+ std::hex << std::uppercase << std::setfill('0') <<
143
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
144
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
145
+ EXPECT_EQ(fp32.hi[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
146
+ std::hex << std::uppercase << std::setfill('0') <<
147
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
148
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
149
+
150
+ /* Check mantissa */
151
+ EXPECT_NE(fp32.lo[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
152
+ std::hex << std::uppercase << std::setfill('0') <<
153
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
154
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
155
+ EXPECT_NE(fp32.lo[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
156
+ std::hex << std::uppercase << std::setfill('0') <<
157
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
158
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
159
+ EXPECT_NE(fp32.lo[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
160
+ std::hex << std::uppercase << std::setfill('0') <<
161
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
162
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
163
+ EXPECT_NE(fp32.lo[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
164
+ std::hex << std::uppercase << std::setfill('0') <<
165
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
166
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
167
+ EXPECT_NE(fp32.hi[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
168
+ std::hex << std::uppercase << std::setfill('0') <<
169
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
170
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
171
+ EXPECT_NE(fp32.hi[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
172
+ std::hex << std::uppercase << std::setfill('0') <<
173
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
174
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
175
+ EXPECT_NE(fp32.hi[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
176
+ std::hex << std::uppercase << std::setfill('0') <<
177
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
178
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
179
+ EXPECT_NE(fp32.hi[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
180
+ std::hex << std::uppercase << std::setfill('0') <<
181
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
182
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
183
+ }
184
+ }
185
+
186
+ TEST(FP16_IEEE_TO_FP32x2_PSIMD, negative_nan) {
187
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
188
+ const psimd_u16 fp16 = {
189
+ (uint16_t) (h + 0xFC00 + (h == 0)) /* Avoid infinity */,
190
+ (uint16_t) (h + 0xFC01),
191
+ (uint16_t) (h + 0xFC02),
192
+ (uint16_t) (h + 0xFC03),
193
+ (uint16_t) (h + 0xFC04),
194
+ (uint16_t) (h + 0xFC05),
195
+ (uint16_t) (h + 0xFC06),
196
+ (uint16_t) (h + 0xFC07),
197
+ };
198
+ const psimd_u32x2 fp32 =
199
+ psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
200
+
201
+ /* Check sign */
202
+ EXPECT_EQ(fp32.lo[0] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
203
+ std::hex << std::uppercase << std::setfill('0') <<
204
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
205
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
206
+ EXPECT_EQ(fp32.lo[1] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
207
+ std::hex << std::uppercase << std::setfill('0') <<
208
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
209
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
210
+ EXPECT_EQ(fp32.lo[2] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
211
+ std::hex << std::uppercase << std::setfill('0') <<
212
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
213
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
214
+ EXPECT_EQ(fp32.lo[3] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
215
+ std::hex << std::uppercase << std::setfill('0') <<
216
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
217
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
218
+ EXPECT_EQ(fp32.hi[0] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
219
+ std::hex << std::uppercase << std::setfill('0') <<
220
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
221
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
222
+ EXPECT_EQ(fp32.hi[1] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
223
+ std::hex << std::uppercase << std::setfill('0') <<
224
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
225
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
226
+ EXPECT_EQ(fp32.hi[2] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
227
+ std::hex << std::uppercase << std::setfill('0') <<
228
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
229
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
230
+ EXPECT_EQ(fp32.hi[3] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
231
+ std::hex << std::uppercase << std::setfill('0') <<
232
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
233
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
234
+
235
+ /* Check exponent */
236
+ EXPECT_EQ(fp32.lo[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
237
+ std::hex << std::uppercase << std::setfill('0') <<
238
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
239
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
240
+ EXPECT_EQ(fp32.lo[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
241
+ std::hex << std::uppercase << std::setfill('0') <<
242
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
243
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
244
+ EXPECT_EQ(fp32.lo[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
245
+ std::hex << std::uppercase << std::setfill('0') <<
246
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
247
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
248
+ EXPECT_EQ(fp32.lo[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
249
+ std::hex << std::uppercase << std::setfill('0') <<
250
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
251
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
252
+ EXPECT_EQ(fp32.hi[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
253
+ std::hex << std::uppercase << std::setfill('0') <<
254
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
255
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
256
+ EXPECT_EQ(fp32.hi[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
257
+ std::hex << std::uppercase << std::setfill('0') <<
258
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
259
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
260
+ EXPECT_EQ(fp32.hi[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
261
+ std::hex << std::uppercase << std::setfill('0') <<
262
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
263
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
264
+ EXPECT_EQ(fp32.hi[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
265
+ std::hex << std::uppercase << std::setfill('0') <<
266
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
267
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
268
+
269
+ /* Check mantissa */
270
+ EXPECT_NE(fp32.lo[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
271
+ std::hex << std::uppercase << std::setfill('0') <<
272
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
273
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
274
+ EXPECT_NE(fp32.lo[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
275
+ std::hex << std::uppercase << std::setfill('0') <<
276
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
277
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
278
+ EXPECT_NE(fp32.lo[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
279
+ std::hex << std::uppercase << std::setfill('0') <<
280
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
281
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
282
+ EXPECT_NE(fp32.lo[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
283
+ std::hex << std::uppercase << std::setfill('0') <<
284
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
285
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
286
+ EXPECT_NE(fp32.hi[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
287
+ std::hex << std::uppercase << std::setfill('0') <<
288
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
289
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
290
+ EXPECT_NE(fp32.hi[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
291
+ std::hex << std::uppercase << std::setfill('0') <<
292
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
293
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
294
+ EXPECT_NE(fp32.hi[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
295
+ std::hex << std::uppercase << std::setfill('0') <<
296
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
297
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
298
+ EXPECT_NE(fp32.hi[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
299
+ std::hex << std::uppercase << std::setfill('0') <<
300
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
301
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
302
+ }
303
+ }
304
+
305
+ TEST(FP16_IEEE_TO_FP32x2_PSIMD, positive_normalized_values) {
306
+ const uint32_t exponentBias = 15;
307
+ for (int32_t e = -14; e <= 15; e++) {
308
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
309
+ const psimd_u16 fp16 = {
310
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0),
311
+ (uint16_t) (h + ((e + exponentBias) << 10) + 1),
312
+ (uint16_t) (h + ((e + exponentBias) << 10) + 2),
313
+ (uint16_t) (h + ((e + exponentBias) << 10) + 3),
314
+ (uint16_t) (h + ((e + exponentBias) << 10) + 4),
315
+ (uint16_t) (h + ((e + exponentBias) << 10) + 5),
316
+ (uint16_t) (h + ((e + exponentBias) << 10) + 6),
317
+ (uint16_t) (h + ((e + exponentBias) << 10) + 7)
318
+ };
319
+ const psimd_u32x2 fp32 =
320
+ psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
321
+
322
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
323
+ std::hex << std::uppercase << std::setfill('0') <<
324
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
325
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
326
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
327
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
328
+ std::hex << std::uppercase << std::setfill('0') <<
329
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
330
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
331
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
332
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
333
+ std::hex << std::uppercase << std::setfill('0') <<
334
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
335
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
336
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
337
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
338
+ std::hex << std::uppercase << std::setfill('0') <<
339
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
340
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
341
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
342
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
343
+ std::hex << std::uppercase << std::setfill('0') <<
344
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
345
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
346
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
347
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
348
+ std::hex << std::uppercase << std::setfill('0') <<
349
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
350
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
351
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
352
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
353
+ std::hex << std::uppercase << std::setfill('0') <<
354
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
355
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
356
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
357
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
358
+ std::hex << std::uppercase << std::setfill('0') <<
359
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
360
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
361
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
362
+ }
363
+ }
364
+ }
365
+
366
+ TEST(FP16_IEEE_TO_FP32x2_PSIMD, negative_normalized_values) {
367
+ const uint32_t exponentBias = 15;
368
+ for (int32_t e = -14; e <= 15; e++) {
369
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
370
+ const psimd_u16 fp16 = {
371
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8000),
372
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8001),
373
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8002),
374
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8003),
375
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8004),
376
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8005),
377
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8006),
378
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8007)
379
+ };
380
+ const psimd_u32x2 fp32 =
381
+ psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
382
+
383
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
384
+ std::hex << std::uppercase << std::setfill('0') <<
385
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
386
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
387
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
388
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
389
+ std::hex << std::uppercase << std::setfill('0') <<
390
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
391
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
392
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
393
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
394
+ std::hex << std::uppercase << std::setfill('0') <<
395
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
396
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
397
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
398
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
399
+ std::hex << std::uppercase << std::setfill('0') <<
400
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
401
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
402
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
403
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
404
+ std::hex << std::uppercase << std::setfill('0') <<
405
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
406
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
407
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
408
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
409
+ std::hex << std::uppercase << std::setfill('0') <<
410
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
411
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
412
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
413
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
414
+ std::hex << std::uppercase << std::setfill('0') <<
415
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
416
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
417
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
418
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
419
+ std::hex << std::uppercase << std::setfill('0') <<
420
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
421
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
422
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
423
+ }
424
+ }
425
+ }
426
+
427
+ TEST(FP16_IEEE_TO_FP32x2_PSIMD, positive_denormalized_values) {
428
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
429
+ const psimd_u16 fp16 = {
430
+ (uint16_t) (h + 0),
431
+ (uint16_t) (h + 1),
432
+ (uint16_t) (h + 2),
433
+ (uint16_t) (h + 3),
434
+ (uint16_t) (h + 4),
435
+ (uint16_t) (h + 5),
436
+ (uint16_t) (h + 6),
437
+ (uint16_t) (h + 7)
438
+ };
439
+ const psimd_u32x2 fp32 =
440
+ psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
441
+
442
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
443
+ std::hex << std::uppercase << std::setfill('0') <<
444
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
445
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
446
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
447
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
448
+ std::hex << std::uppercase << std::setfill('0') <<
449
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
450
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
451
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
452
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
453
+ std::hex << std::uppercase << std::setfill('0') <<
454
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
455
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
456
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
457
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
458
+ std::hex << std::uppercase << std::setfill('0') <<
459
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
460
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
461
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
462
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
463
+ std::hex << std::uppercase << std::setfill('0') <<
464
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
465
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
466
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
467
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
468
+ std::hex << std::uppercase << std::setfill('0') <<
469
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
470
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
471
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
472
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
473
+ std::hex << std::uppercase << std::setfill('0') <<
474
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
475
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
476
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
477
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
478
+ std::hex << std::uppercase << std::setfill('0') <<
479
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
480
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
481
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
482
+ }
483
+ }
484
+
485
+ TEST(FP16_IEEE_TO_FP32x2_PSIMD, negative_denormalized_values) {
486
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
487
+ const psimd_u16 fp16 = {
488
+ (uint16_t) (h + 0x8000),
489
+ (uint16_t) (h + 0x8001),
490
+ (uint16_t) (h + 0x8002),
491
+ (uint16_t) (h + 0x8003),
492
+ (uint16_t) (h + 0x8004),
493
+ (uint16_t) (h + 0x8005),
494
+ (uint16_t) (h + 0x8006),
495
+ (uint16_t) (h + 0x8007)
496
+ };
497
+ const psimd_u32x2 fp32 =
498
+ psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
499
+
500
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
501
+ std::hex << std::uppercase << std::setfill('0') <<
502
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
503
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
504
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
505
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
506
+ std::hex << std::uppercase << std::setfill('0') <<
507
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
508
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
509
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
510
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
511
+ std::hex << std::uppercase << std::setfill('0') <<
512
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
513
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
514
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
515
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
516
+ std::hex << std::uppercase << std::setfill('0') <<
517
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
518
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
519
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
520
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
521
+ std::hex << std::uppercase << std::setfill('0') <<
522
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
523
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
524
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
525
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
526
+ std::hex << std::uppercase << std::setfill('0') <<
527
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
528
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
529
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
530
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
531
+ std::hex << std::uppercase << std::setfill('0') <<
532
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
533
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
534
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
535
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
536
+ std::hex << std::uppercase << std::setfill('0') <<
537
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
538
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
539
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
540
+ }
541
+ }
@@ -0,0 +1,96 @@
1
+ #include <gtest/gtest.h>
2
+
3
+ #include <cstdint>
4
+
5
+ #include <fp16.h>
6
+
7
+
8
+ extern "C" void fp16_alt_xmm_to_fp32_xmm_peachpy__avx(const uint16_t* fp16, uint32_t* fp32);
9
+ const size_t vector_elements = 4;
10
+
11
+
12
+ TEST(FP16_ALT_XMM_TO_FP32_XMM, positive_normalized_values) {
13
+ const uint32_t exponentBias = 15;
14
+ for (int32_t e = -14; e <= 16; e++) {
15
+ for (uint16_t h = 0; h < 0x0400; h += vector_elements) {
16
+ uint16_t fp16[vector_elements];
17
+ for (size_t i = 0; i < vector_elements; i++) {
18
+ fp16[i] = h + ((e + exponentBias) << 10) + i;
19
+ }
20
+ uint32_t fp32[vector_elements];
21
+ fp16_alt_xmm_to_fp32_xmm_peachpy__avx(fp16, fp32);
22
+
23
+ for (size_t i = 0; i < vector_elements; i++) {
24
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[i]), fp32[i]) <<
25
+ std::hex << std::uppercase << std::setfill('0') <<
26
+ "F16 = 0x" << std::setw(4) << fp16[i] << ", " <<
27
+ "F32(F16) = 0x" << std::setw(8) << fp32[i] << ", " <<
28
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[i]) <<
29
+ ", lane " << i << "/" << vector_elements;
30
+ }
31
+ }
32
+ }
33
+ }
34
+
35
+ TEST(FP16_ALT_XMM_TO_FP32_XMM, negative_normalized_values) {
36
+ const uint32_t exponentBias = 15;
37
+ for (int32_t e = -14; e <= 16; e++) {
38
+ for (uint16_t h = 0; h < 0x0400; h += vector_elements) {
39
+ uint16_t fp16[vector_elements];
40
+ for (size_t i = 0; i < vector_elements; i++) {
41
+ fp16[i] = 0x8000 + h + ((e + exponentBias) << 10) + i;
42
+ }
43
+ uint32_t fp32[vector_elements];
44
+ fp16_alt_xmm_to_fp32_xmm_peachpy__avx(fp16, fp32);
45
+
46
+ for (size_t i = 0; i < vector_elements; i++) {
47
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[i]), fp32[i]) <<
48
+ std::hex << std::uppercase << std::setfill('0') <<
49
+ "F16 = 0x" << std::setw(4) << fp16[i] << ", " <<
50
+ "F32(F16) = 0x" << std::setw(8) << fp32[i] << ", " <<
51
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[i]) <<
52
+ ", lane " << i << "/" << vector_elements;
53
+ }
54
+ }
55
+ }
56
+ }
57
+
58
+ TEST(FP16_ALT_XMM_TO_FP32_XMM, positive_denormalized_values) {
59
+ for (uint16_t h = 0; h < 0x0400; h += vector_elements) {
60
+ uint16_t fp16[vector_elements];
61
+ for (size_t i = 0; i < vector_elements; i++) {
62
+ fp16[i] = h + i;
63
+ }
64
+ uint32_t fp32[vector_elements];
65
+ fp16_alt_xmm_to_fp32_xmm_peachpy__avx(fp16, fp32);
66
+
67
+ for (size_t i = 0; i < vector_elements; i++) {
68
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[i]), fp32[i]) <<
69
+ std::hex << std::uppercase << std::setfill('0') <<
70
+ "F16 = 0x" << std::setw(4) << fp16[i] << ", " <<
71
+ "F32(F16) = 0x" << std::setw(8) << fp32[i] << ", " <<
72
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[i]) <<
73
+ ", lane " << i << "/" << vector_elements;
74
+ }
75
+ }
76
+ }
77
+
78
+ TEST(FP16_ALT_XMM_TO_FP32_XMM, negative_denormalized_values) {
79
+ for (uint16_t h = 0; h < 0x0400; h += vector_elements) {
80
+ uint16_t fp16[vector_elements];
81
+ for (size_t i = 0; i < vector_elements; i++) {
82
+ fp16[i] = 0x8000 + h + i;
83
+ }
84
+ uint32_t fp32[vector_elements];
85
+ fp16_alt_xmm_to_fp32_xmm_peachpy__avx(fp16, fp32);
86
+
87
+ for (size_t i = 0; i < vector_elements; i++) {
88
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[i]), fp32[i]) <<
89
+ std::hex << std::uppercase << std::setfill('0') <<
90
+ "F16 = 0x" << std::setw(4) << fp16[i] << ", " <<
91
+ "F32(F16) = 0x" << std::setw(8) << fp32[i] << ", " <<
92
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[i]) <<
93
+ ", lane " << i << "/" << vector_elements;
94
+ }
95
+ }
96
+ }