usearch 2.10.3 → 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,333 @@
1
+ #include <gtest/gtest.h>
2
+
3
+ #include <cstdint>
4
+
5
+ #include <fp16.h>
6
+ #include <tables.h>
7
+
8
+
9
+ TEST(FP16_IEEE_TO_FP32_BITS, normalized_powers_of_2) {
10
+ const uint16_t min_po2_f16 = UINT16_C(0x0400);
11
+ const uint16_t eighths_f16 = UINT16_C(0x3000);
12
+ const uint16_t quarter_f16 = UINT16_C(0x3400);
13
+ const uint16_t half_f16 = UINT16_C(0x3800);
14
+ const uint16_t one_f16 = UINT16_C(0x3C00);
15
+ const uint16_t two_f16 = UINT16_C(0x4000);
16
+ const uint16_t four_f16 = UINT16_C(0x4400);
17
+ const uint16_t eight_f16 = UINT16_C(0x4800);
18
+ const uint16_t sixteen_f16 = UINT16_C(0x4C00);
19
+ const uint16_t thirtytwo_f16 = UINT16_C(0x5000);
20
+ const uint16_t sixtyfour_f16 = UINT16_C(0x5400);
21
+ const uint16_t max_po2_f16 = UINT16_C(0x7800);
22
+
23
+ const uint32_t min_po2_f32 = UINT32_C(0x38800000);
24
+ const uint32_t eighths_f32 = UINT32_C(0x3E000000);
25
+ const uint32_t quarter_f32 = UINT32_C(0x3E800000);
26
+ const uint32_t half_f32 = UINT32_C(0x3F000000);
27
+ const uint32_t one_f32 = UINT32_C(0x3F800000);
28
+ const uint32_t two_f32 = UINT32_C(0x40000000);
29
+ const uint32_t four_f32 = UINT32_C(0x40800000);
30
+ const uint32_t eight_f32 = UINT32_C(0x41000000);
31
+ const uint32_t sixteen_f32 = UINT32_C(0x41800000);
32
+ const uint32_t thirtytwo_f32 = UINT32_C(0x42000000);
33
+ const uint32_t sixtyfour_f32 = UINT32_C(0x42800000);
34
+ const uint32_t max_po2_f32 = UINT32_C(0x47000000);
35
+
36
+ EXPECT_EQ(min_po2_f32, fp16_ieee_to_fp32_bits(min_po2_f16)) <<
37
+ std::hex << std::uppercase << std::setfill('0') <<
38
+ "F16 = 0x" << std::setw(4) << min_po2_f16 << ", " <<
39
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(min_po2_f16) << ", " <<
40
+ "F32 = 0x" << std::setw(8) << min_po2_f32;
41
+
42
+ EXPECT_EQ(eighths_f32, fp16_ieee_to_fp32_bits(eighths_f16)) <<
43
+ std::hex << std::uppercase << std::setfill('0') <<
44
+ "F16 = 0x" << std::setw(4) << eighths_f16 << ", " <<
45
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(eighths_f16) << ", " <<
46
+ "F32 = 0x" << std::setw(8) << eighths_f32;
47
+
48
+ EXPECT_EQ(quarter_f32, fp16_ieee_to_fp32_bits(quarter_f16)) <<
49
+ std::hex << std::uppercase << std::setfill('0') <<
50
+ "F16 = 0x" << std::setw(4) << quarter_f16 << ", " <<
51
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(quarter_f16) << ", " <<
52
+ "F32 = 0x" << std::setw(8) << quarter_f32;
53
+
54
+ EXPECT_EQ(half_f32, fp16_ieee_to_fp32_bits(half_f16)) <<
55
+ std::hex << std::uppercase << std::setfill('0') <<
56
+ "F16 = 0x" << std::setw(4) << half_f16 << ", " <<
57
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(half_f16) << ", " <<
58
+ "F32 = 0x" << std::setw(8) << half_f32;
59
+
60
+ EXPECT_EQ(one_f32, fp16_ieee_to_fp32_bits(one_f16)) <<
61
+ std::hex << std::uppercase << std::setfill('0') <<
62
+ "F16 = 0x" << std::setw(4) << one_f16 << ", " <<
63
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(one_f16) << ", " <<
64
+ "F32 = 0x" << std::setw(8) << one_f32;
65
+
66
+ EXPECT_EQ(two_f32, fp16_ieee_to_fp32_bits(two_f16)) <<
67
+ std::hex << std::uppercase << std::setfill('0') <<
68
+ "F16 = 0x" << std::setw(4) << two_f16 << ", " <<
69
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(two_f16) << ", " <<
70
+ "F32 = 0x" << std::setw(8) << two_f32;
71
+
72
+ EXPECT_EQ(four_f32, fp16_ieee_to_fp32_bits(four_f16)) <<
73
+ std::hex << std::uppercase << std::setfill('0') <<
74
+ "F16 = 0x" << std::setw(4) << four_f16 << ", " <<
75
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(four_f16) << ", " <<
76
+ "F32 = 0x" << std::setw(8) << four_f32;
77
+
78
+ EXPECT_EQ(eight_f32, fp16_ieee_to_fp32_bits(eight_f16)) <<
79
+ std::hex << std::uppercase << std::setfill('0') <<
80
+ "F16 = 0x" << std::setw(4) << eight_f16 << ", " <<
81
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(eight_f16) << ", " <<
82
+ "F32 = 0x" << std::setw(8) << eight_f32;
83
+
84
+ EXPECT_EQ(sixteen_f32, fp16_ieee_to_fp32_bits(sixteen_f16)) <<
85
+ std::hex << std::uppercase << std::setfill('0') <<
86
+ "F16 = 0x" << std::setw(4) << sixteen_f16 << ", " <<
87
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(sixteen_f16) << ", " <<
88
+ "F32 = 0x" << std::setw(8) << sixteen_f32;
89
+
90
+ EXPECT_EQ(thirtytwo_f32, fp16_ieee_to_fp32_bits(thirtytwo_f16)) <<
91
+ std::hex << std::uppercase << std::setfill('0') <<
92
+ "F16 = 0x" << std::setw(4) << thirtytwo_f16 << ", " <<
93
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(thirtytwo_f16) << ", " <<
94
+ "F32 = 0x" << std::setw(8) << thirtytwo_f32;
95
+
96
+ EXPECT_EQ(sixtyfour_f32, fp16_ieee_to_fp32_bits(sixtyfour_f16)) <<
97
+ std::hex << std::uppercase << std::setfill('0') <<
98
+ "F16 = 0x" << std::setw(4) << sixtyfour_f16 << ", " <<
99
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(sixtyfour_f16) << ", " <<
100
+ "F32 = 0x" << std::setw(8) << sixtyfour_f32;
101
+
102
+ EXPECT_EQ(max_po2_f32, fp16_ieee_to_fp32_bits(max_po2_f16)) <<
103
+ std::hex << std::uppercase << std::setfill('0') <<
104
+ "F16 = 0x" << std::setw(4) << max_po2_f16 << ", " <<
105
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(max_po2_f16) << ", " <<
106
+ "F32 = 0x" << std::setw(8) << max_po2_f32;
107
+ }
108
+
109
+ TEST(FP16_IEEE_TO_FP32_BITS, denormalized_powers_of_2) {
110
+ const uint16_t exp2_minus_15_f16 = UINT16_C(0x0200);
111
+ const uint16_t exp2_minus_16_f16 = UINT16_C(0x0100);
112
+ const uint16_t exp2_minus_17_f16 = UINT16_C(0x0080);
113
+ const uint16_t exp2_minus_18_f16 = UINT16_C(0x0040);
114
+ const uint16_t exp2_minus_19_f16 = UINT16_C(0x0020);
115
+ const uint16_t exp2_minus_20_f16 = UINT16_C(0x0010);
116
+ const uint16_t exp2_minus_21_f16 = UINT16_C(0x0008);
117
+ const uint16_t exp2_minus_22_f16 = UINT16_C(0x0004);
118
+ const uint16_t exp2_minus_23_f16 = UINT16_C(0x0002);
119
+ const uint16_t exp2_minus_24_f16 = UINT16_C(0x0001);
120
+
121
+ const uint32_t exp2_minus_15_f32 = UINT32_C(0x38000000);
122
+ const uint32_t exp2_minus_16_f32 = UINT32_C(0x37800000);
123
+ const uint32_t exp2_minus_17_f32 = UINT32_C(0x37000000);
124
+ const uint32_t exp2_minus_18_f32 = UINT32_C(0x36800000);
125
+ const uint32_t exp2_minus_19_f32 = UINT32_C(0x36000000);
126
+ const uint32_t exp2_minus_20_f32 = UINT32_C(0x35800000);
127
+ const uint32_t exp2_minus_21_f32 = UINT32_C(0x35000000);
128
+ const uint32_t exp2_minus_22_f32 = UINT32_C(0x34800000);
129
+ const uint32_t exp2_minus_23_f32 = UINT32_C(0x34000000);
130
+ const uint32_t exp2_minus_24_f32 = UINT32_C(0x33800000);
131
+
132
+ EXPECT_EQ(exp2_minus_15_f32, fp16_ieee_to_fp32_bits(exp2_minus_15_f16)) <<
133
+ std::hex << std::uppercase << std::setfill('0') <<
134
+ "F16 = 0x" << std::setw(4) << exp2_minus_15_f16 << ", " <<
135
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_15_f16) << ", " <<
136
+ "F32 = 0x" << std::setw(8) << exp2_minus_15_f32;
137
+
138
+ EXPECT_EQ(exp2_minus_16_f32, fp16_ieee_to_fp32_bits(exp2_minus_16_f16)) <<
139
+ std::hex << std::uppercase << std::setfill('0') <<
140
+ "F16 = 0x" << std::setw(4) << exp2_minus_16_f16 << ", " <<
141
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_16_f16) << ", " <<
142
+ "F32 = 0x" << std::setw(8) << exp2_minus_16_f32;
143
+
144
+ EXPECT_EQ(exp2_minus_17_f32, fp16_ieee_to_fp32_bits(exp2_minus_17_f16)) <<
145
+ std::hex << std::uppercase << std::setfill('0') <<
146
+ "F16 = 0x" << std::setw(4) << exp2_minus_17_f16 << ", " <<
147
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_17_f16) << ", " <<
148
+ "F32 = 0x" << std::setw(8) << exp2_minus_17_f32;
149
+
150
+ EXPECT_EQ(exp2_minus_18_f32, fp16_ieee_to_fp32_bits(exp2_minus_18_f16)) <<
151
+ std::hex << std::uppercase << std::setfill('0') <<
152
+ "F16 = 0x" << std::setw(4) << exp2_minus_18_f16 << ", " <<
153
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_18_f16) << ", " <<
154
+ "F32 = 0x" << std::setw(8) << exp2_minus_18_f32;
155
+
156
+ EXPECT_EQ(exp2_minus_19_f32, fp16_ieee_to_fp32_bits(exp2_minus_19_f16)) <<
157
+ std::hex << std::uppercase << std::setfill('0') <<
158
+ "F16 = 0x" << std::setw(4) << exp2_minus_19_f16 << ", " <<
159
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_19_f16) << ", " <<
160
+ "F32 = 0x" << std::setw(8) << exp2_minus_19_f32;
161
+
162
+ EXPECT_EQ(exp2_minus_20_f32, fp16_ieee_to_fp32_bits(exp2_minus_20_f16)) <<
163
+ std::hex << std::uppercase << std::setfill('0') <<
164
+ "F16 = 0x" << std::setw(4) << exp2_minus_20_f16 << ", " <<
165
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_20_f16) << ", " <<
166
+ "F32 = 0x" << std::setw(8) << exp2_minus_20_f32;
167
+
168
+ EXPECT_EQ(exp2_minus_21_f32, fp16_ieee_to_fp32_bits(exp2_minus_21_f16)) <<
169
+ std::hex << std::uppercase << std::setfill('0') <<
170
+ "F16 = 0x" << std::setw(4) << exp2_minus_21_f16 << ", " <<
171
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_21_f16) << ", " <<
172
+ "F32 = 0x" << std::setw(8) << exp2_minus_21_f32;
173
+
174
+ EXPECT_EQ(exp2_minus_22_f32, fp16_ieee_to_fp32_bits(exp2_minus_22_f16)) <<
175
+ std::hex << std::uppercase << std::setfill('0') <<
176
+ "F16 = 0x" << std::setw(4) << exp2_minus_22_f16 << ", " <<
177
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_22_f16) << ", " <<
178
+ "F32 = 0x" << std::setw(8) << exp2_minus_22_f32;
179
+
180
+ EXPECT_EQ(exp2_minus_23_f32, fp16_ieee_to_fp32_bits(exp2_minus_23_f16)) <<
181
+ std::hex << std::uppercase << std::setfill('0') <<
182
+ "F16 = 0x" << std::setw(4) << exp2_minus_23_f16 << ", " <<
183
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_23_f16) << ", " <<
184
+ "F32 = 0x" << std::setw(8) << exp2_minus_23_f32;
185
+
186
+ EXPECT_EQ(exp2_minus_24_f32, fp16_ieee_to_fp32_bits(exp2_minus_24_f16)) <<
187
+ std::hex << std::uppercase << std::setfill('0') <<
188
+ "F16 = 0x" << std::setw(4) << exp2_minus_24_f16 << ", " <<
189
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(exp2_minus_24_f16) << ", " <<
190
+ "F32 = 0x" << std::setw(8) << exp2_minus_24_f32;
191
+ }
192
+
193
+ TEST(FP16_IEEE_TO_FP32_BITS, zero) {
194
+ const uint16_t positive_zero_f16 = UINT16_C(0x0000);
195
+ const uint16_t negative_zero_f16 = UINT16_C(0x8000);
196
+
197
+ const uint32_t positive_zero_f32 = UINT32_C(0x00000000);
198
+ const uint32_t negative_zero_f32 = UINT32_C(0x80000000);
199
+
200
+ EXPECT_EQ(positive_zero_f32, fp16_ieee_to_fp32_bits(positive_zero_f16)) <<
201
+ std::hex << std::uppercase << std::setfill('0') <<
202
+ "F16 = 0x" << std::setw(4) << positive_zero_f16 << ", " <<
203
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(positive_zero_f16) << ", " <<
204
+ "F32 = 0x" << std::setw(8) << positive_zero_f32;
205
+
206
+ EXPECT_EQ(negative_zero_f32, fp16_ieee_to_fp32_bits(negative_zero_f16)) <<
207
+ std::hex << std::uppercase << std::setfill('0') <<
208
+ "F16 = 0x" << std::setw(4) << negative_zero_f16 << ", " <<
209
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(negative_zero_f16) << ", " <<
210
+ "F32 = 0x" << std::setw(8) << negative_zero_f32;
211
+ }
212
+
213
+ TEST(FP16_IEEE_TO_FP32_BITS, infinity) {
214
+ const uint16_t positive_infinity_f16 = UINT16_C(0x7C00);
215
+ const uint16_t negative_infinity_f16 = UINT16_C(0xFC00);
216
+
217
+ const uint32_t positive_infinity_f32 = UINT32_C(0x7F800000);
218
+ const uint32_t negative_infinity_f32 = UINT32_C(0xFF800000);
219
+
220
+ EXPECT_EQ(positive_infinity_f32, fp16_ieee_to_fp32_bits(positive_infinity_f16)) <<
221
+ std::hex << std::uppercase << std::setfill('0') <<
222
+ "F16 = 0x" << std::setw(4) << positive_infinity_f16 << ", " <<
223
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(positive_infinity_f16) << ", " <<
224
+ "F32 = 0x" << std::setw(8) << positive_infinity_f32;
225
+
226
+ EXPECT_EQ(negative_infinity_f32, fp16_ieee_to_fp32_bits(negative_infinity_f16)) <<
227
+ std::hex << std::uppercase << std::setfill('0') <<
228
+ "F16 = 0x" << std::setw(4) << negative_infinity_f16 << ", " <<
229
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(negative_infinity_f16) << ", " <<
230
+ "F32 = 0x" << std::setw(8) << negative_infinity_f32;
231
+ }
232
+
233
+ TEST(FP16_IEEE_TO_FP32_BITS, positive_nan) {
234
+ for (uint16_t m = UINT16_C(1); m < UINT16_C(0x0400); m++) {
235
+ const uint16_t nan_f16 = UINT16_C(0x7C00) | m;
236
+ const uint32_t nan_f32 = fp16_ieee_to_fp32_bits(nan_f16);
237
+
238
+ /* Check sign */
239
+ EXPECT_EQ(nan_f32 & UINT32_C(0x80000000), 0) <<
240
+ std::hex << std::uppercase << std::setfill('0') <<
241
+ "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
242
+ "F32(F16) = 0x" << std::setw(8) << nan_f32;
243
+
244
+ /* Check exponent */
245
+ EXPECT_EQ(nan_f32 & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
246
+ std::hex << std::uppercase << std::setfill('0') <<
247
+ "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
248
+ "F32(F16) = 0x" << std::setw(8) << nan_f32;
249
+
250
+ /* Check mantissa */
251
+ EXPECT_NE(nan_f32 & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
252
+ std::hex << std::uppercase << std::setfill('0') <<
253
+ "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
254
+ "F32(F16) = 0x" << std::setw(8) << nan_f32;
255
+ }
256
+ }
257
+
258
+ TEST(FP16_IEEE_TO_FP32_BITS, negative_nan) {
259
+ for (uint16_t m = UINT16_C(1); m < UINT16_C(0x0400); m++) {
260
+ const uint16_t nan_f16 = UINT16_C(0xFC00) | m;
261
+ const uint32_t nan_f32 = fp16_ieee_to_fp32_bits(nan_f16);
262
+
263
+ /* Check sign */
264
+ EXPECT_NE(nan_f32 & UINT32_C(0x80000000), UINT32_C(0)) <<
265
+ std::hex << std::uppercase << std::setfill('0') <<
266
+ "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
267
+ "F32(F16) = 0x" << std::setw(8) << nan_f32;
268
+
269
+ /* Check exponent */
270
+ EXPECT_EQ(nan_f32 & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
271
+ std::hex << std::uppercase << std::setfill('0') <<
272
+ "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
273
+ "F32(F16) = 0x" << std::setw(8) << nan_f32;
274
+
275
+ /* Check mantissa */
276
+ EXPECT_NE(nan_f32 & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
277
+ std::hex << std::uppercase << std::setfill('0') <<
278
+ "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
279
+ "F32(F16) = 0x" << std::setw(8) << nan_f32;
280
+ }
281
+ }
282
+
283
+ TEST(FP16_IEEE_TO_FP32_BITS, positive_normalized_values) {
284
+ const uint32_t exponentBias = 15;
285
+ for (int32_t e = -14; e <= 15; e++) {
286
+ for (uint16_t h = 0; h < 0x0400; h++) {
287
+ const uint16_t fp16 = h + ((uint16_t) (e + exponentBias) << 10);
288
+ const uint32_t fp32 = fp16::normalizedValues[h] + ((uint32_t) e << 23);
289
+ EXPECT_EQ(fp32, fp16_ieee_to_fp32_bits(fp16)) <<
290
+ std::hex << std::uppercase << std::setfill('0') <<
291
+ "F16 = 0x" << std::setw(4) << fp16 << ", " <<
292
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16) << ", " <<
293
+ "F32 = 0x" << std::setw(8) << fp32;
294
+ }
295
+ }
296
+ }
297
+
298
+ TEST(FP16_IEEE_TO_FP32_BITS, negative_normalized_values) {
299
+ const uint32_t exponentBias = 15;
300
+ for (int32_t e = -14; e <= 15; e++) {
301
+ for (uint16_t h = 0; h < 0x0400; h++) {
302
+ const uint16_t fp16 = (h + ((uint16_t) (e + exponentBias) << 10)) ^ UINT16_C(0x8000);
303
+ const uint32_t fp32 = (fp16::normalizedValues[h] + ((uint32_t) e << 23)) ^ UINT32_C(0x80000000);
304
+ EXPECT_EQ(fp32, fp16_ieee_to_fp32_bits(fp16)) <<
305
+ std::hex << std::uppercase << std::setfill('0') <<
306
+ "F16 = 0x" << std::setw(4) << fp16 << ", " <<
307
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16) << ", " <<
308
+ "F32 = 0x" << std::setw(8) << fp32;
309
+ }
310
+ }
311
+ }
312
+
313
+ TEST(FP16_IEEE_TO_FP32_BITS, positive_denormalized_values) {
314
+ for (uint16_t h = 0; h < 0x0400; h++) {
315
+ EXPECT_EQ(fp16::denormalizedValues[h], fp16_ieee_to_fp32_bits(h)) <<
316
+ std::hex << std::uppercase << std::setfill('0') <<
317
+ "F16 = 0x" << std::setw(4) << h << ", " <<
318
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(h) << ", " <<
319
+ "F32 = 0x" << std::setw(8) << fp16::denormalizedValues[h];
320
+ }
321
+ }
322
+
323
+ TEST(FP16_IEEE_TO_FP32_BITS, negative_denormalized_values) {
324
+ for (uint16_t h = 0; h < 0x0400; h++) {
325
+ const uint16_t fp16 = h ^ UINT16_C(0x8000);
326
+ const uint32_t fp32 = fp16::denormalizedValues[h] ^ UINT32_C(0x80000000);
327
+ EXPECT_EQ(fp32, fp16_ieee_to_fp32_bits(fp16)) <<
328
+ std::hex << std::uppercase << std::setfill('0') <<
329
+ "F16 = 0x" << std::setw(4) << fp16 << ", " <<
330
+ "F32(F16) = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16) << ", " <<
331
+ "F32 = 0x" << std::setw(8) << fp32;
332
+ }
333
+ }
@@ -0,0 +1,312 @@
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_FP32_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
+ };
20
+ const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
21
+
22
+ EXPECT_EQ(positive_infinity_f32, fp32[0]) <<
23
+ std::hex << std::uppercase << std::setfill('0') <<
24
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
25
+ "F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
26
+ "F32 = 0x" << std::setw(8) << positive_infinity_f32;
27
+ EXPECT_EQ(negative_infinity_f32, fp32[1]) <<
28
+ std::hex << std::uppercase << std::setfill('0') <<
29
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
30
+ "F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
31
+ "F32 = 0x" << std::setw(8) << negative_infinity_f32;
32
+ EXPECT_EQ(negative_infinity_f32, fp32[2]) <<
33
+ std::hex << std::uppercase << std::setfill('0') <<
34
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
35
+ "F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
36
+ "F32 = 0x" << std::setw(8) << negative_infinity_f32;
37
+ EXPECT_EQ(positive_infinity_f32, fp32[3]) <<
38
+ std::hex << std::uppercase << std::setfill('0') <<
39
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
40
+ "F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
41
+ "F32 = 0x" << std::setw(8) << positive_infinity_f32;
42
+ }
43
+
44
+ TEST(FP16_IEEE_TO_FP32_PSIMD, positive_nan) {
45
+ for (uint16_t h = 0; h < 0x0400; h += 4) {
46
+ const psimd_u16 fp16 = {
47
+ (uint16_t) (h + 0x7C00 + (h == 0)) /* Avoid infinity */,
48
+ (uint16_t) (h + 0x7C01),
49
+ (uint16_t) (h + 0x7C02),
50
+ (uint16_t) (h + 0x7C03),
51
+ };
52
+ const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
53
+
54
+ /* Check sign */
55
+ EXPECT_EQ(fp32[0] & UINT32_C(0x80000000), 0) <<
56
+ std::hex << std::uppercase << std::setfill('0') <<
57
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
58
+ "F32(F16) = 0x" << std::setw(8) << fp32[0];
59
+ EXPECT_EQ(fp32[1] & UINT32_C(0x80000000), 0) <<
60
+ std::hex << std::uppercase << std::setfill('0') <<
61
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
62
+ "F32(F16) = 0x" << std::setw(8) << fp32[1];
63
+ EXPECT_EQ(fp32[2] & UINT32_C(0x80000000), 0) <<
64
+ std::hex << std::uppercase << std::setfill('0') <<
65
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
66
+ "F32(F16) = 0x" << std::setw(8) << fp32[2];
67
+ EXPECT_EQ(fp32[3] & UINT32_C(0x80000000), 0) <<
68
+ std::hex << std::uppercase << std::setfill('0') <<
69
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
70
+ "F32(F16) = 0x" << std::setw(8) << fp32[3];
71
+
72
+ /* Check exponent */
73
+ EXPECT_EQ(fp32[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
74
+ std::hex << std::uppercase << std::setfill('0') <<
75
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
76
+ "F32(F16) = 0x" << std::setw(8) << fp32[0];
77
+ EXPECT_EQ(fp32[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
78
+ std::hex << std::uppercase << std::setfill('0') <<
79
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
80
+ "F32(F16) = 0x" << std::setw(8) << fp32[1];
81
+ EXPECT_EQ(fp32[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
82
+ std::hex << std::uppercase << std::setfill('0') <<
83
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
84
+ "F32(F16) = 0x" << std::setw(8) << fp32[2];
85
+ EXPECT_EQ(fp32[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
86
+ std::hex << std::uppercase << std::setfill('0') <<
87
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
88
+ "F32(F16) = 0x" << std::setw(8) << fp32[3];
89
+
90
+ /* Check mantissa */
91
+ EXPECT_NE(fp32[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
92
+ std::hex << std::uppercase << std::setfill('0') <<
93
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
94
+ "F32(F16) = 0x" << std::setw(8) << fp32[0];
95
+ EXPECT_NE(fp32[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
96
+ std::hex << std::uppercase << std::setfill('0') <<
97
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
98
+ "F32(F16) = 0x" << std::setw(8) << fp32[1];
99
+ EXPECT_NE(fp32[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
100
+ std::hex << std::uppercase << std::setfill('0') <<
101
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
102
+ "F32(F16) = 0x" << std::setw(8) << fp32[2];
103
+ EXPECT_NE(fp32[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
104
+ std::hex << std::uppercase << std::setfill('0') <<
105
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
106
+ "F32(F16) = 0x" << std::setw(8) << fp32[3];
107
+ }
108
+ }
109
+
110
+ TEST(FP16_IEEE_TO_FP32_PSIMD, negative_nan) {
111
+ for (uint16_t h = 0; h < 0x0400; h += 4) {
112
+ const psimd_u16 fp16 = {
113
+ (uint16_t) (h + 0xFC00 + (h == 0)) /* Avoid infinity */,
114
+ (uint16_t) (h + 0xFC01),
115
+ (uint16_t) (h + 0xFC02),
116
+ (uint16_t) (h + 0xFC03),
117
+ };
118
+ const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
119
+
120
+ /* Check sign */
121
+ EXPECT_EQ(fp32[0] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
122
+ std::hex << std::uppercase << std::setfill('0') <<
123
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
124
+ "F32(F16) = 0x" << std::setw(8) << fp32[0];
125
+ EXPECT_EQ(fp32[1] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
126
+ std::hex << std::uppercase << std::setfill('0') <<
127
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
128
+ "F32(F16) = 0x" << std::setw(8) << fp32[1];
129
+ EXPECT_EQ(fp32[2] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
130
+ std::hex << std::uppercase << std::setfill('0') <<
131
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
132
+ "F32(F16) = 0x" << std::setw(8) << fp32[2];
133
+ EXPECT_EQ(fp32[3] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
134
+ std::hex << std::uppercase << std::setfill('0') <<
135
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
136
+ "F32(F16) = 0x" << std::setw(8) << fp32[3];
137
+
138
+ /* Check exponent */
139
+ EXPECT_EQ(fp32[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
140
+ std::hex << std::uppercase << std::setfill('0') <<
141
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
142
+ "F32(F16) = 0x" << std::setw(8) << fp32[0];
143
+ EXPECT_EQ(fp32[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
144
+ std::hex << std::uppercase << std::setfill('0') <<
145
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
146
+ "F32(F16) = 0x" << std::setw(8) << fp32[1];
147
+ EXPECT_EQ(fp32[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
148
+ std::hex << std::uppercase << std::setfill('0') <<
149
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
150
+ "F32(F16) = 0x" << std::setw(8) << fp32[2];
151
+ EXPECT_EQ(fp32[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
152
+ std::hex << std::uppercase << std::setfill('0') <<
153
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
154
+ "F32(F16) = 0x" << std::setw(8) << fp32[3];
155
+
156
+ /* Check mantissa */
157
+ EXPECT_NE(fp32[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
158
+ std::hex << std::uppercase << std::setfill('0') <<
159
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
160
+ "F32(F16) = 0x" << std::setw(8) << fp32[0];
161
+ EXPECT_NE(fp32[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
162
+ std::hex << std::uppercase << std::setfill('0') <<
163
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
164
+ "F32(F16) = 0x" << std::setw(8) << fp32[1];
165
+ EXPECT_NE(fp32[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
166
+ std::hex << std::uppercase << std::setfill('0') <<
167
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
168
+ "F32(F16) = 0x" << std::setw(8) << fp32[2];
169
+ EXPECT_NE(fp32[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
170
+ std::hex << std::uppercase << std::setfill('0') <<
171
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
172
+ "F32(F16) = 0x" << std::setw(8) << fp32[3];
173
+ }
174
+ }
175
+
176
+ TEST(FP16_IEEE_TO_FP32_PSIMD, positive_normalized_values) {
177
+ const uint32_t exponentBias = 15;
178
+ for (int32_t e = -14; e <= 15; e++) {
179
+ for (uint16_t h = 0; h < 0x0400; h += 4) {
180
+ const psimd_u16 fp16 = {
181
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0),
182
+ (uint16_t) (h + ((e + exponentBias) << 10) + 1),
183
+ (uint16_t) (h + ((e + exponentBias) << 10) + 2),
184
+ (uint16_t) (h + ((e + exponentBias) << 10) + 3),
185
+ };
186
+ const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
187
+
188
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
189
+ std::hex << std::uppercase << std::setfill('0') <<
190
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
191
+ "F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
192
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
193
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
194
+ std::hex << std::uppercase << std::setfill('0') <<
195
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
196
+ "F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
197
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
198
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
199
+ std::hex << std::uppercase << std::setfill('0') <<
200
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
201
+ "F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
202
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
203
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
204
+ std::hex << std::uppercase << std::setfill('0') <<
205
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
206
+ "F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
207
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
208
+ }
209
+ }
210
+ }
211
+
212
+ TEST(FP16_IEEE_TO_FP32_PSIMD, negative_normalized_values) {
213
+ const uint32_t exponentBias = 15;
214
+ for (int32_t e = -14; e <= 15; e++) {
215
+ for (uint16_t h = 0; h < 0x0400; h += 4) {
216
+ const psimd_u16 fp16 = {
217
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8000),
218
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8001),
219
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8002),
220
+ (uint16_t) (h + ((e + exponentBias) << 10) + 0x8003),
221
+ };
222
+ const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
223
+
224
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
225
+ std::hex << std::uppercase << std::setfill('0') <<
226
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
227
+ "F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
228
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
229
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
230
+ std::hex << std::uppercase << std::setfill('0') <<
231
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
232
+ "F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
233
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
234
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
235
+ std::hex << std::uppercase << std::setfill('0') <<
236
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
237
+ "F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
238
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
239
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
240
+ std::hex << std::uppercase << std::setfill('0') <<
241
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
242
+ "F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
243
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
244
+ }
245
+ }
246
+ }
247
+
248
+ TEST(FP16_IEEE_TO_FP32_PSIMD, positive_denormalized_values) {
249
+ for (uint16_t h = 0; h < 0x0400; h += 4) {
250
+ const psimd_u16 fp16 = {
251
+ (uint16_t) (h + 0),
252
+ (uint16_t) (h + 1),
253
+ (uint16_t) (h + 2),
254
+ (uint16_t) (h + 3),
255
+ };
256
+ const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
257
+
258
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
259
+ std::hex << std::uppercase << std::setfill('0') <<
260
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
261
+ "F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
262
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
263
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
264
+ std::hex << std::uppercase << std::setfill('0') <<
265
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
266
+ "F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
267
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
268
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
269
+ std::hex << std::uppercase << std::setfill('0') <<
270
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
271
+ "F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
272
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
273
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
274
+ std::hex << std::uppercase << std::setfill('0') <<
275
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
276
+ "F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
277
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
278
+ }
279
+ }
280
+
281
+ TEST(FP16_IEEE_TO_FP32_PSIMD, negative_denormalized_values) {
282
+ for (uint16_t h = 0; h < 0x0400; h += 4) {
283
+ const psimd_u16 fp16 = {
284
+ (uint16_t) (h + 0x8000),
285
+ (uint16_t) (h + 0x8001),
286
+ (uint16_t) (h + 0x8002),
287
+ (uint16_t) (h + 0x8003),
288
+ };
289
+ const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
290
+
291
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
292
+ std::hex << std::uppercase << std::setfill('0') <<
293
+ "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
294
+ "F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
295
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
296
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
297
+ std::hex << std::uppercase << std::setfill('0') <<
298
+ "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
299
+ "F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
300
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
301
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
302
+ std::hex << std::uppercase << std::setfill('0') <<
303
+ "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
304
+ "F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
305
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
306
+ EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
307
+ std::hex << std::uppercase << std::setfill('0') <<
308
+ "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
309
+ "F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
310
+ "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
311
+ }
312
+ }