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,348 @@
1
+ #include <gtest/gtest.h>
2
+
3
+ #include <cstdint>
4
+ #include <cmath>
5
+
6
+ #include <fp16.h>
7
+ #include <tables.h>
8
+
9
+
10
+ TEST(FP16_ALT_TO_FP32_VALUE, normalized_powers_of_2) {
11
+ const uint16_t min_po2_f16 = UINT16_C(0x0400);
12
+ const uint16_t eighths_f16 = UINT16_C(0x3000);
13
+ const uint16_t quarter_f16 = UINT16_C(0x3400);
14
+ const uint16_t half_f16 = UINT16_C(0x3800);
15
+ const uint16_t one_f16 = UINT16_C(0x3C00);
16
+ const uint16_t two_f16 = UINT16_C(0x4000);
17
+ const uint16_t four_f16 = UINT16_C(0x4400);
18
+ const uint16_t eight_f16 = UINT16_C(0x4800);
19
+ const uint16_t sixteen_f16 = UINT16_C(0x4C00);
20
+ const uint16_t thirtytwo_f16 = UINT16_C(0x5000);
21
+ const uint16_t sixtyfour_f16 = UINT16_C(0x5400);
22
+ const uint16_t max_po2_f16 = UINT16_C(0x7C00);
23
+
24
+ const uint32_t min_po2_f32 = UINT32_C(0x38800000);
25
+ const uint32_t eighths_f32 = UINT32_C(0x3E000000);
26
+ const uint32_t quarter_f32 = UINT32_C(0x3E800000);
27
+ const uint32_t half_f32 = UINT32_C(0x3F000000);
28
+ const uint32_t one_f32 = UINT32_C(0x3F800000);
29
+ const uint32_t two_f32 = UINT32_C(0x40000000);
30
+ const uint32_t four_f32 = UINT32_C(0x40800000);
31
+ const uint32_t eight_f32 = UINT32_C(0x41000000);
32
+ const uint32_t sixteen_f32 = UINT32_C(0x41800000);
33
+ const uint32_t thirtytwo_f32 = UINT32_C(0x42000000);
34
+ const uint32_t sixtyfour_f32 = UINT32_C(0x42800000);
35
+ const uint32_t max_po2_f32 = UINT32_C(0x47800000);
36
+
37
+ const float min_po2_value = fp16_alt_to_fp32_value(min_po2_f16);
38
+ uint32_t min_po2_bits;
39
+ memcpy(&min_po2_bits, &min_po2_value, sizeof(min_po2_bits));
40
+ EXPECT_EQ(min_po2_f32, min_po2_bits) <<
41
+ std::hex << std::uppercase << std::setfill('0') <<
42
+ "F16 = 0x" << std::setw(4) << min_po2_f16 << ", " <<
43
+ "F32(F16) = 0x" << std::setw(8) << min_po2_bits << ", " <<
44
+ "F32 = 0x" << std::setw(8) << min_po2_f32;
45
+
46
+ const float eighths_value = fp16_alt_to_fp32_value(eighths_f16);
47
+ uint32_t eighths_bits;
48
+ memcpy(&eighths_bits, &eighths_value, sizeof(eighths_bits));
49
+ EXPECT_EQ(eighths_f32, eighths_bits) <<
50
+ std::hex << std::uppercase << std::setfill('0') <<
51
+ "F16 = 0x" << std::setw(4) << eighths_f16 << ", " <<
52
+ "F32(F16) = 0x" << std::setw(8) << eighths_bits << ", " <<
53
+ "F32 = 0x" << std::setw(8) << eighths_f32;
54
+
55
+ const float quarter_value = fp16_alt_to_fp32_value(quarter_f16);
56
+ uint32_t quarter_bits;
57
+ memcpy(&quarter_bits, &quarter_value, sizeof(quarter_bits));
58
+ EXPECT_EQ(quarter_f32, quarter_bits) <<
59
+ std::hex << std::uppercase << std::setfill('0') <<
60
+ "F16 = 0x" << std::setw(4) << quarter_f16 << ", " <<
61
+ "F32(F16) = 0x" << std::setw(8) << quarter_bits << ", " <<
62
+ "F32 = 0x" << std::setw(8) << quarter_f32;
63
+
64
+ const float half_value = fp16_alt_to_fp32_value(half_f16);
65
+ uint32_t half_bits;
66
+ memcpy(&half_bits, &half_value, sizeof(half_bits));
67
+ EXPECT_EQ(half_f32, half_bits) <<
68
+ std::hex << std::uppercase << std::setfill('0') <<
69
+ "F16 = 0x" << std::setw(4) << half_f16 << ", " <<
70
+ "F32(F16) = 0x" << std::setw(8) << half_bits << ", " <<
71
+ "F32 = 0x" << std::setw(8) << half_f32;
72
+
73
+ const float one_value = fp16_alt_to_fp32_value(one_f16);
74
+ uint32_t one_bits;
75
+ memcpy(&one_bits, &one_value, sizeof(one_bits));
76
+ EXPECT_EQ(one_f32, one_bits) <<
77
+ std::hex << std::uppercase << std::setfill('0') <<
78
+ "F16 = 0x" << std::setw(4) << one_f16 << ", " <<
79
+ "F32(F16) = 0x" << std::setw(8) << one_bits << ", " <<
80
+ "F32 = 0x" << std::setw(8) << one_f32;
81
+
82
+ const float two_value = fp16_alt_to_fp32_value(two_f16);
83
+ uint32_t two_bits;
84
+ memcpy(&two_bits, &two_value, sizeof(two_bits));
85
+ EXPECT_EQ(two_f32, two_bits) <<
86
+ std::hex << std::uppercase << std::setfill('0') <<
87
+ "F16 = 0x" << std::setw(4) << two_f16 << ", " <<
88
+ "F32(F16) = 0x" << std::setw(8) << two_bits << ", " <<
89
+ "F32 = 0x" << std::setw(8) << two_f32;
90
+
91
+ const float four_value = fp16_alt_to_fp32_value(four_f16);
92
+ uint32_t four_bits;
93
+ memcpy(&four_bits, &four_value, sizeof(four_bits));
94
+ EXPECT_EQ(four_f32, four_bits) <<
95
+ std::hex << std::uppercase << std::setfill('0') <<
96
+ "F16 = 0x" << std::setw(4) << four_f16 << ", " <<
97
+ "F32(F16) = 0x" << std::setw(8) << four_bits << ", " <<
98
+ "F32 = 0x" << std::setw(8) << four_f32;
99
+
100
+ const float eight_value = fp16_alt_to_fp32_value(eight_f16);
101
+ uint32_t eight_bits;
102
+ memcpy(&eight_bits, &eight_value, sizeof(eight_bits));
103
+ EXPECT_EQ(eight_f32, eight_bits) <<
104
+ std::hex << std::uppercase << std::setfill('0') <<
105
+ "F16 = 0x" << std::setw(4) << eight_f16 << ", " <<
106
+ "F32(F16) = 0x" << std::setw(8) << eight_bits << ", " <<
107
+ "F32 = 0x" << std::setw(8) << eight_f32;
108
+
109
+ const float sixteen_value = fp16_alt_to_fp32_value(sixteen_f16);
110
+ uint32_t sixteen_bits;
111
+ memcpy(&sixteen_bits, &sixteen_value, sizeof(sixteen_bits));
112
+ EXPECT_EQ(sixteen_f32, sixteen_bits) <<
113
+ std::hex << std::uppercase << std::setfill('0') <<
114
+ "F16 = 0x" << std::setw(4) << sixteen_f16 << ", " <<
115
+ "F32(F16) = 0x" << std::setw(8) << sixteen_bits << ", " <<
116
+ "F32 = 0x" << std::setw(8) << sixteen_f32;
117
+
118
+ const float thirtytwo_value = fp16_alt_to_fp32_value(thirtytwo_f16);
119
+ uint32_t thirtytwo_bits;
120
+ memcpy(&thirtytwo_bits, &thirtytwo_value, sizeof(thirtytwo_bits));
121
+ EXPECT_EQ(thirtytwo_f32, thirtytwo_bits) <<
122
+ std::hex << std::uppercase << std::setfill('0') <<
123
+ "F16 = 0x" << std::setw(4) << thirtytwo_f16 << ", " <<
124
+ "F32(F16) = 0x" << std::setw(8) << thirtytwo_bits << ", " <<
125
+ "F32 = 0x" << std::setw(8) << thirtytwo_f32;
126
+
127
+ const float sixtyfour_value = fp16_alt_to_fp32_value(sixtyfour_f16);
128
+ uint32_t sixtyfour_bits;
129
+ memcpy(&sixtyfour_bits, &sixtyfour_value, sizeof(sixtyfour_bits));
130
+ EXPECT_EQ(sixtyfour_f32, sixtyfour_bits) <<
131
+ std::hex << std::uppercase << std::setfill('0') <<
132
+ "F16 = 0x" << std::setw(4) << sixtyfour_f16 << ", " <<
133
+ "F32(F16) = 0x" << std::setw(8) << sixtyfour_bits << ", " <<
134
+ "F32 = 0x" << std::setw(8) << sixtyfour_f32;
135
+
136
+ const float max_po2_value = fp16_alt_to_fp32_value(max_po2_f16);
137
+ uint32_t max_po2_bits;
138
+ memcpy(&max_po2_bits, &max_po2_value, sizeof(max_po2_bits));
139
+ EXPECT_EQ(max_po2_f32, max_po2_bits) <<
140
+ std::hex << std::uppercase << std::setfill('0') <<
141
+ "F16 = 0x" << std::setw(4) << max_po2_f16 << ", " <<
142
+ "F32(F16) = 0x" << std::setw(8) << max_po2_bits << ", " <<
143
+ "F32 = 0x" << std::setw(8) << max_po2_f32;
144
+ }
145
+
146
+ TEST(FP16_ALT_TO_FP32_VALUE, denormalized_powers_of_2) {
147
+ const uint16_t exp2_minus_15_f16 = UINT16_C(0x0200);
148
+ const uint16_t exp2_minus_16_f16 = UINT16_C(0x0100);
149
+ const uint16_t exp2_minus_17_f16 = UINT16_C(0x0080);
150
+ const uint16_t exp2_minus_18_f16 = UINT16_C(0x0040);
151
+ const uint16_t exp2_minus_19_f16 = UINT16_C(0x0020);
152
+ const uint16_t exp2_minus_20_f16 = UINT16_C(0x0010);
153
+ const uint16_t exp2_minus_21_f16 = UINT16_C(0x0008);
154
+ const uint16_t exp2_minus_22_f16 = UINT16_C(0x0004);
155
+ const uint16_t exp2_minus_23_f16 = UINT16_C(0x0002);
156
+ const uint16_t exp2_minus_24_f16 = UINT16_C(0x0001);
157
+
158
+ const uint32_t exp2_minus_15_f32 = UINT32_C(0x38000000);
159
+ const uint32_t exp2_minus_16_f32 = UINT32_C(0x37800000);
160
+ const uint32_t exp2_minus_17_f32 = UINT32_C(0x37000000);
161
+ const uint32_t exp2_minus_18_f32 = UINT32_C(0x36800000);
162
+ const uint32_t exp2_minus_19_f32 = UINT32_C(0x36000000);
163
+ const uint32_t exp2_minus_20_f32 = UINT32_C(0x35800000);
164
+ const uint32_t exp2_minus_21_f32 = UINT32_C(0x35000000);
165
+ const uint32_t exp2_minus_22_f32 = UINT32_C(0x34800000);
166
+ const uint32_t exp2_minus_23_f32 = UINT32_C(0x34000000);
167
+ const uint32_t exp2_minus_24_f32 = UINT32_C(0x33800000);
168
+
169
+ const float exp2_minus_15_value = fp16_alt_to_fp32_value(exp2_minus_15_f16);
170
+ uint32_t exp2_minus_15_bits;
171
+ memcpy(&exp2_minus_15_bits, &exp2_minus_15_value, sizeof(exp2_minus_15_bits));
172
+ EXPECT_EQ(exp2_minus_15_f32, exp2_minus_15_bits) <<
173
+ std::hex << std::uppercase << std::setfill('0') <<
174
+ "F16 = 0x" << std::setw(4) << exp2_minus_15_f16 << ", " <<
175
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_15_bits << ", " <<
176
+ "F32 = 0x" << std::setw(8) << exp2_minus_15_f32;
177
+
178
+ const float exp2_minus_16_value = fp16_alt_to_fp32_value(exp2_minus_16_f16);
179
+ uint32_t exp2_minus_16_bits;
180
+ memcpy(&exp2_minus_16_bits, &exp2_minus_16_value, sizeof(exp2_minus_16_bits));
181
+ EXPECT_EQ(exp2_minus_16_f32, exp2_minus_16_bits) <<
182
+ std::hex << std::uppercase << std::setfill('0') <<
183
+ "F16 = 0x" << std::setw(4) << exp2_minus_16_f16 << ", " <<
184
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_16_bits << ", " <<
185
+ "F32 = 0x" << std::setw(8) << exp2_minus_16_f32;
186
+
187
+ const float exp2_minus_17_value = fp16_alt_to_fp32_value(exp2_minus_17_f16);
188
+ uint32_t exp2_minus_17_bits;
189
+ memcpy(&exp2_minus_17_bits, &exp2_minus_17_value, sizeof(exp2_minus_17_bits));
190
+ EXPECT_EQ(exp2_minus_17_f32, exp2_minus_17_bits) <<
191
+ std::hex << std::uppercase << std::setfill('0') <<
192
+ "F16 = 0x" << std::setw(4) << exp2_minus_17_f16 << ", " <<
193
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_17_bits << ", " <<
194
+ "F32 = 0x" << std::setw(8) << exp2_minus_17_f32;
195
+
196
+ const float exp2_minus_18_value = fp16_alt_to_fp32_value(exp2_minus_18_f16);
197
+ uint32_t exp2_minus_18_bits;
198
+ memcpy(&exp2_minus_18_bits, &exp2_minus_18_value, sizeof(exp2_minus_18_bits));
199
+ EXPECT_EQ(exp2_minus_18_f32, exp2_minus_18_bits) <<
200
+ std::hex << std::uppercase << std::setfill('0') <<
201
+ "F16 = 0x" << std::setw(4) << exp2_minus_18_f16 << ", " <<
202
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_18_bits << ", " <<
203
+ "F32 = 0x" << std::setw(8) << exp2_minus_18_f32;
204
+
205
+ const float exp2_minus_19_value = fp16_alt_to_fp32_value(exp2_minus_19_f16);
206
+ uint32_t exp2_minus_19_bits;
207
+ memcpy(&exp2_minus_19_bits, &exp2_minus_19_value, sizeof(exp2_minus_19_bits));
208
+ EXPECT_EQ(exp2_minus_19_f32, exp2_minus_19_bits) <<
209
+ std::hex << std::uppercase << std::setfill('0') <<
210
+ "F16 = 0x" << std::setw(4) << exp2_minus_19_f16 << ", " <<
211
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_19_bits << ", " <<
212
+ "F32 = 0x" << std::setw(8) << exp2_minus_19_f32;
213
+
214
+ const float exp2_minus_20_value = fp16_alt_to_fp32_value(exp2_minus_20_f16);
215
+ uint32_t exp2_minus_20_bits;
216
+ memcpy(&exp2_minus_20_bits, &exp2_minus_20_value, sizeof(exp2_minus_20_bits));
217
+ EXPECT_EQ(exp2_minus_20_f32, exp2_minus_20_bits) <<
218
+ std::hex << std::uppercase << std::setfill('0') <<
219
+ "F16 = 0x" << std::setw(4) << exp2_minus_20_f16 << ", " <<
220
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_20_bits << ", " <<
221
+ "F32 = 0x" << std::setw(8) << exp2_minus_20_f32;
222
+
223
+ const float exp2_minus_21_value = fp16_alt_to_fp32_value(exp2_minus_21_f16);
224
+ uint32_t exp2_minus_21_bits;
225
+ memcpy(&exp2_minus_21_bits, &exp2_minus_21_value, sizeof(exp2_minus_21_bits));
226
+ EXPECT_EQ(exp2_minus_21_f32, exp2_minus_21_bits) <<
227
+ std::hex << std::uppercase << std::setfill('0') <<
228
+ "F16 = 0x" << std::setw(4) << exp2_minus_21_f16 << ", " <<
229
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_21_bits << ", " <<
230
+ "F32 = 0x" << std::setw(8) << exp2_minus_21_f32;
231
+
232
+ const float exp2_minus_22_value = fp16_alt_to_fp32_value(exp2_minus_22_f16);
233
+ uint32_t exp2_minus_22_bits;
234
+ memcpy(&exp2_minus_22_bits, &exp2_minus_22_value, sizeof(exp2_minus_22_bits));
235
+ EXPECT_EQ(exp2_minus_22_f32, exp2_minus_22_bits) <<
236
+ std::hex << std::uppercase << std::setfill('0') <<
237
+ "F16 = 0x" << std::setw(4) << exp2_minus_22_f16 << ", " <<
238
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_22_bits << ", " <<
239
+ "F32 = 0x" << std::setw(8) << exp2_minus_22_f32;
240
+
241
+ const float exp2_minus_23_value = fp16_alt_to_fp32_value(exp2_minus_23_f16);
242
+ uint32_t exp2_minus_23_bits;
243
+ memcpy(&exp2_minus_23_bits, &exp2_minus_23_value, sizeof(exp2_minus_23_bits));
244
+ EXPECT_EQ(exp2_minus_23_f32, exp2_minus_23_bits) <<
245
+ std::hex << std::uppercase << std::setfill('0') <<
246
+ "F16 = 0x" << std::setw(4) << exp2_minus_23_f16 << ", " <<
247
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_23_bits << ", " <<
248
+ "F32 = 0x" << std::setw(8) << exp2_minus_23_f32;
249
+
250
+ const float exp2_minus_24_value = fp16_alt_to_fp32_value(exp2_minus_24_f16);
251
+ uint32_t exp2_minus_24_bits;
252
+ memcpy(&exp2_minus_24_bits, &exp2_minus_24_value, sizeof(exp2_minus_24_bits));
253
+ EXPECT_EQ(exp2_minus_24_f32, exp2_minus_24_bits) <<
254
+ std::hex << std::uppercase << std::setfill('0') <<
255
+ "F16 = 0x" << std::setw(4) << exp2_minus_24_f16 << ", " <<
256
+ "F32(F16) = 0x" << std::setw(8) << exp2_minus_24_bits << ", " <<
257
+ "F32 = 0x" << std::setw(8) << exp2_minus_24_f32;
258
+ }
259
+
260
+ TEST(FP16_ALT_TO_FP32_VALUE, zero) {
261
+ const uint16_t positive_zero_f16 = UINT16_C(0x0000);
262
+ const uint16_t negative_zero_f16 = UINT16_C(0x8000);
263
+
264
+ const uint32_t positive_zero_f32 = UINT32_C(0x00000000);
265
+ const uint32_t negative_zero_f32 = UINT32_C(0x80000000);
266
+
267
+ const float positive_zero_value = fp16_alt_to_fp32_value(positive_zero_f16);
268
+ uint32_t positive_zero_bits;
269
+ memcpy(&positive_zero_bits, &positive_zero_value, sizeof(positive_zero_bits));
270
+ EXPECT_EQ(positive_zero_f32, positive_zero_bits) <<
271
+ std::hex << std::uppercase << std::setfill('0') <<
272
+ "F16 = 0x" << std::setw(4) << positive_zero_f16 << ", " <<
273
+ "F32(F16) = 0x" << std::setw(8) << positive_zero_bits << ", " <<
274
+ "F32 = 0x" << std::setw(8) << positive_zero_f32;
275
+
276
+ const float negative_zero_value = fp16_alt_to_fp32_value(negative_zero_f16);
277
+ uint32_t negative_zero_bits;
278
+ memcpy(&negative_zero_bits, &negative_zero_value, sizeof(negative_zero_bits));
279
+ EXPECT_EQ(negative_zero_f32, negative_zero_bits) <<
280
+ std::hex << std::uppercase << std::setfill('0') <<
281
+ "F16 = 0x" << std::setw(4) << negative_zero_f16 << ", " <<
282
+ "F32(F16) = 0x" << std::setw(8) << negative_zero_bits << ", " <<
283
+ "F32 = 0x" << std::setw(8) << negative_zero_f32;
284
+ }
285
+
286
+ TEST(FP16_ALT_TO_FP32_VALUE, positive_normalized_values) {
287
+ const uint32_t exponentBias = 15;
288
+ for (int32_t e = -14; e <= 16; e++) {
289
+ for (uint16_t h = 0; h < 0x0400; h++) {
290
+ const uint16_t fp16 = h + ((uint16_t) (e + exponentBias) << 10);
291
+ const uint32_t fp32 = fp16::normalizedValues[h] + ((uint32_t) e << 23);
292
+ const float value = fp16_alt_to_fp32_value(fp16);
293
+ uint32_t bits;
294
+ memcpy(&bits, &value, sizeof(bits));
295
+ EXPECT_EQ(fp32, bits) <<
296
+ std::hex << std::uppercase << std::setfill('0') <<
297
+ "F16 = 0x" << std::setw(4) << fp16 << ", " <<
298
+ "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
299
+ "F32 = 0x" << std::setw(8) << fp32;
300
+ }
301
+ }
302
+ }
303
+
304
+ TEST(FP16_ALT_TO_FP32_VALUE, negative_normalized_values) {
305
+ const uint32_t exponentBias = 15;
306
+ for (int32_t e = -14; e <= 16; e++) {
307
+ for (uint16_t h = 0; h < 0x0400; h++) {
308
+ const uint16_t fp16 = (h + ((uint16_t) (e + exponentBias) << 10)) ^ UINT16_C(0x8000);
309
+ const uint32_t fp32 = (fp16::normalizedValues[h] + ((uint32_t) e << 23)) ^ UINT32_C(0x80000000);
310
+ const float value = fp16_alt_to_fp32_value(fp16);
311
+ uint32_t bits;
312
+ memcpy(&bits, &value, sizeof(bits));
313
+ EXPECT_EQ(fp32, bits) <<
314
+ std::hex << std::uppercase << std::setfill('0') <<
315
+ "F16 = 0x" << std::setw(4) << fp16 << ", " <<
316
+ "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
317
+ "F32 = 0x" << std::setw(8) << fp32;
318
+ }
319
+ }
320
+ }
321
+
322
+ TEST(FP16_ALT_TO_FP32_VALUE, positive_denormalized_values) {
323
+ for (uint16_t h = 0; h < 0x0400; h++) {
324
+ const float value = fp16_alt_to_fp32_value(h);
325
+ uint32_t bits;
326
+ memcpy(&bits, &value, sizeof(bits));
327
+ EXPECT_EQ(fp16::denormalizedValues[h], bits) <<
328
+ std::hex << std::uppercase << std::setfill('0') <<
329
+ "F16 = 0x" << std::setw(4) << h << ", " <<
330
+ "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
331
+ "F32 = 0x" << std::setw(8) << fp16::denormalizedValues[h];
332
+ }
333
+ }
334
+
335
+ TEST(FP16_ALT_TO_FP32_VALUE, negative_denormalized_values) {
336
+ for (uint16_t h = 0; h < 0x0400; h++) {
337
+ const uint16_t fp16 = h ^ UINT16_C(0x8000);
338
+ const uint32_t fp32 = fp16::denormalizedValues[h] ^ UINT32_C(0x80000000);
339
+ const float value = fp16_alt_to_fp32_value(fp16);
340
+ uint32_t bits;
341
+ memcpy(&bits, &value, sizeof(bits));
342
+ EXPECT_EQ(fp32, bits) <<
343
+ std::hex << std::uppercase << std::setfill('0') <<
344
+ "F16 = 0x" << std::setw(4) << fp16 << ", " <<
345
+ "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
346
+ "F32 = 0x" << std::setw(8) << fp32;
347
+ }
348
+ }
@@ -0,0 +1,245 @@
1
+ #include <gtest/gtest.h>
2
+
3
+ #include <cstdint>
4
+
5
+ #include <fp16.h>
6
+ #include <fp16/psimd.h>
7
+
8
+
9
+ TEST(FP16_ALT_TO_FP32x2_PSIMD, positive_normalized_values) {
10
+ const uint32_t exponentBias = 15;
11
+ for (int32_t e = -14; e <= 16; e++) {
12
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
13
+ const psimd_u16 fp16 = {
14
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0),
15
+ (uint16_t) (h + ((e + exponentBias) << 10) + 1),
16
+ (uint16_t) (h + ((e + exponentBias) << 10) + 2),
17
+ (uint16_t) (h + ((e + exponentBias) << 10) + 3),
18
+ (uint16_t) (h + ((e + exponentBias) << 10) + 4),
19
+ (uint16_t) (h + ((e + exponentBias) << 10) + 5),
20
+ (uint16_t) (h + ((e + exponentBias) << 10) + 6),
21
+ (uint16_t) (h + ((e + exponentBias) << 10) + 7)
22
+ };
23
+ const psimd_u32x2 fp32 =
24
+ psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
25
+
26
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
27
+ std::hex << std::uppercase << std::setfill('0') <<
28
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
29
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
30
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
31
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
32
+ std::hex << std::uppercase << std::setfill('0') <<
33
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
34
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
35
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
36
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
37
+ std::hex << std::uppercase << std::setfill('0') <<
38
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
39
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
40
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
41
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
42
+ std::hex << std::uppercase << std::setfill('0') <<
43
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
44
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
45
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
46
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
47
+ std::hex << std::uppercase << std::setfill('0') <<
48
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
49
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
50
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
51
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
52
+ std::hex << std::uppercase << std::setfill('0') <<
53
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
54
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
55
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
56
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
57
+ std::hex << std::uppercase << std::setfill('0') <<
58
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
59
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
60
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
61
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
62
+ std::hex << std::uppercase << std::setfill('0') <<
63
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
64
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
65
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
66
+ }
67
+ }
68
+ }
69
+
70
+ TEST(FP16_ALT_TO_FP32x2_PSIMD, negative_normalized_values) {
71
+ const uint32_t exponentBias = 15;
72
+ for (int32_t e = -14; e <= 16; e++) {
73
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
74
+ const psimd_u16 fp16 = {
75
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8000),
76
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8001),
77
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8002),
78
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8003),
79
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8004),
80
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8005),
81
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8006),
82
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8007)
83
+ };
84
+ const psimd_u32x2 fp32 =
85
+ psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
86
+
87
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
88
+ std::hex << std::uppercase << std::setfill('0') <<
89
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
90
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
91
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
92
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
93
+ std::hex << std::uppercase << std::setfill('0') <<
94
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
95
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
96
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
97
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
98
+ std::hex << std::uppercase << std::setfill('0') <<
99
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
100
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
101
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
102
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
103
+ std::hex << std::uppercase << std::setfill('0') <<
104
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
105
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
106
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
107
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
108
+ std::hex << std::uppercase << std::setfill('0') <<
109
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
110
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
111
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
112
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
113
+ std::hex << std::uppercase << std::setfill('0') <<
114
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
115
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
116
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
117
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
118
+ std::hex << std::uppercase << std::setfill('0') <<
119
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
120
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
121
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
122
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
123
+ std::hex << std::uppercase << std::setfill('0') <<
124
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
125
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
126
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
127
+ }
128
+ }
129
+ }
130
+
131
+ TEST(FP16_ALT_TO_FP32x2_PSIMD, positive_denormalized_values) {
132
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
133
+ const psimd_u16 fp16 = {
134
+ (uint16_t) (h + 0),
135
+ (uint16_t) (h + 1),
136
+ (uint16_t) (h + 2),
137
+ (uint16_t) (h + 3),
138
+ (uint16_t) (h + 4),
139
+ (uint16_t) (h + 5),
140
+ (uint16_t) (h + 6),
141
+ (uint16_t) (h + 7)
142
+ };
143
+ const psimd_u32x2 fp32 =
144
+ psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
145
+
146
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
147
+ std::hex << std::uppercase << std::setfill('0') <<
148
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
149
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
150
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
151
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
152
+ std::hex << std::uppercase << std::setfill('0') <<
153
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
154
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
155
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
156
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
157
+ std::hex << std::uppercase << std::setfill('0') <<
158
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
159
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
160
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
161
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
162
+ std::hex << std::uppercase << std::setfill('0') <<
163
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
164
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
165
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
166
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
167
+ std::hex << std::uppercase << std::setfill('0') <<
168
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
169
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
170
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
171
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
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
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
176
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
177
+ std::hex << std::uppercase << std::setfill('0') <<
178
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
179
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
180
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
181
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
182
+ std::hex << std::uppercase << std::setfill('0') <<
183
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
184
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
185
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
186
+ }
187
+ }
188
+
189
+ TEST(FP16_ALT_TO_FP32x2_PSIMD, negative_denormalized_values) {
190
+ for (uint16_t h = 0; h < 0x0400; h += 8) {
191
+ const psimd_u16 fp16 = {
192
+ (uint16_t) (h + 0x8000),
193
+ (uint16_t) (h + 0x8001),
194
+ (uint16_t) (h + 0x8002),
195
+ (uint16_t) (h + 0x8003),
196
+ (uint16_t) (h + 0x8004),
197
+ (uint16_t) (h + 0x8005),
198
+ (uint16_t) (h + 0x8006),
199
+ (uint16_t) (h + 0x8007)
200
+ };
201
+ const psimd_u32x2 fp32 =
202
+ psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
203
+
204
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
205
+ std::hex << std::uppercase << std::setfill('0') <<
206
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
207
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
208
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
209
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
210
+ std::hex << std::uppercase << std::setfill('0') <<
211
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
212
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
213
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
214
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
215
+ std::hex << std::uppercase << std::setfill('0') <<
216
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
217
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
218
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
219
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
220
+ std::hex << std::uppercase << std::setfill('0') <<
221
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
222
+ "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
223
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
224
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
225
+ std::hex << std::uppercase << std::setfill('0') <<
226
+ "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
227
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
228
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
229
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
230
+ std::hex << std::uppercase << std::setfill('0') <<
231
+ "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
232
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
233
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
234
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
235
+ std::hex << std::uppercase << std::setfill('0') <<
236
+ "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
237
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
238
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
239
+ EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
240
+ std::hex << std::uppercase << std::setfill('0') <<
241
+ "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
242
+ "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
243
+ "F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
244
+ }
245
+ }
@@ -0,0 +1,56 @@
1
+ #include <gtest/gtest.h>
2
+
3
+ #include <cstdint>
4
+
5
+ #include <fp16.h>
6
+
7
+
8
+ TEST(FP32_TO_BITS, positive) {
9
+ for (uint32_t bits = UINT32_C(0x00000000); bits <= UINT32_C(0x7FFFFFFF); bits++) {
10
+ float value;
11
+ memcpy(&value, &bits, sizeof(value));
12
+
13
+ ASSERT_EQ(bits, fp32_to_bits(value)) <<
14
+ std::hex << std::uppercase << std::setfill('0') <<
15
+ "BITS = 0x" << std::setw(8) << bits << ", " <<
16
+ "BITCAST(VALUE) = 0x" << std::setw(8) << fp32_to_bits(value);
17
+ }
18
+ }
19
+
20
+ TEST(FP32_TO_BITS, negative) {
21
+ for (uint32_t bits = UINT32_C(0xFFFFFFFF); bits >= UINT32_C(0x80000000); bits--) {
22
+ float value;
23
+ memcpy(&value, &bits, sizeof(value));
24
+
25
+ ASSERT_EQ(bits, fp32_to_bits(value)) <<
26
+ std::hex << std::uppercase << std::setfill('0') <<
27
+ "BITS = 0x" << std::setw(8) << bits << ", " <<
28
+ "BITCAST(VALUE) = 0x" << std::setw(8) << fp32_to_bits(value);
29
+ }
30
+ }
31
+
32
+ TEST(FP32_FROM_BITS, positive) {
33
+ for (uint32_t bits = UINT32_C(0x00000000); bits <= UINT32_C(0x7FFFFFFF); bits++) {
34
+ const float value = fp32_from_bits(bits);
35
+ uint32_t bitcast;
36
+ memcpy(&bitcast, &value, sizeof(bitcast));
37
+
38
+ ASSERT_EQ(bits, bitcast) <<
39
+ std::hex << std::uppercase << std::setfill('0') <<
40
+ "BITS = 0x" << std::setw(8) << bits << ", " <<
41
+ "VALUE = 0x" << std::setw(8) << bitcast;
42
+ }
43
+ }
44
+
45
+ TEST(FP32_FROM_BITS, negative) {
46
+ for (uint32_t bits = UINT32_C(0xFFFFFFFF); bits >= UINT32_C(0x80000000); bits--) {
47
+ const float value = fp32_from_bits(bits);
48
+ uint32_t bitcast;
49
+ memcpy(&bitcast, &value, sizeof(bitcast));
50
+
51
+ ASSERT_EQ(bits, bitcast) <<
52
+ std::hex << std::uppercase << std::setfill('0') <<
53
+ "BITS = 0x" << std::setw(8) << bits << ", " <<
54
+ "VALUE = 0x" << std::setw(8) << bitcast;
55
+ }
56
+ }