xref: /aosp_15_r20/external/XNNPACK/eval/f32-f16-cvt.cc (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1*4bdc9457SAndroid Build Coastguard Worker // Copyright 2021 Google LLC
2*4bdc9457SAndroid Build Coastguard Worker //
3*4bdc9457SAndroid Build Coastguard Worker // This source code is licensed under the BSD-style license found in the
4*4bdc9457SAndroid Build Coastguard Worker // LICENSE file in the root directory of this source tree.
5*4bdc9457SAndroid Build Coastguard Worker 
6*4bdc9457SAndroid Build Coastguard Worker #include <algorithm>
7*4bdc9457SAndroid Build Coastguard Worker #include <cmath>
8*4bdc9457SAndroid Build Coastguard Worker #include <cstddef>
9*4bdc9457SAndroid Build Coastguard Worker #include <cstdint>
10*4bdc9457SAndroid Build Coastguard Worker #include <cstdlib>
11*4bdc9457SAndroid Build Coastguard Worker #include <iomanip>
12*4bdc9457SAndroid Build Coastguard Worker #include <ios>
13*4bdc9457SAndroid Build Coastguard Worker #include <vector>
14*4bdc9457SAndroid Build Coastguard Worker 
15*4bdc9457SAndroid Build Coastguard Worker #include <gtest/gtest.h>
16*4bdc9457SAndroid Build Coastguard Worker 
17*4bdc9457SAndroid Build Coastguard Worker #include <fp16.h>
18*4bdc9457SAndroid Build Coastguard Worker 
19*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/aligned-allocator.h>
20*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/common.h>
21*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/isa-checks.h>
22*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/math.h>
23*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/math-stubs.h>
24*4bdc9457SAndroid Build Coastguard Worker 
25*4bdc9457SAndroid Build Coastguard Worker 
26*4bdc9457SAndroid Build Coastguard Worker constexpr int kBlockSize = 1024;
27*4bdc9457SAndroid Build Coastguard Worker 
28*4bdc9457SAndroid Build Coastguard Worker #if XNN_ARCH_X86 || XNN_ARCH_X86_64
TEST(CVT__SSE2,positive_normal)29*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, positive_normal) {
30*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
31*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
32*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
33*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
34*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
35*4bdc9457SAndroid Build Coastguard Worker       }
36*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
37*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
38*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
39*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
40*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
41*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
42*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
43*4bdc9457SAndroid Build Coastguard Worker       }
44*4bdc9457SAndroid Build Coastguard Worker     }
45*4bdc9457SAndroid Build Coastguard Worker   }
46*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,negative_normal)47*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, negative_normal) {
48*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
49*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
50*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
51*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
52*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
53*4bdc9457SAndroid Build Coastguard Worker       }
54*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
55*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
56*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
57*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
58*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
59*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
60*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
61*4bdc9457SAndroid Build Coastguard Worker       }
62*4bdc9457SAndroid Build Coastguard Worker     }
63*4bdc9457SAndroid Build Coastguard Worker   }
64*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,positive_subnormal)65*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, positive_subnormal) {
66*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
67*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
68*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
69*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
70*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
71*4bdc9457SAndroid Build Coastguard Worker       }
72*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
73*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
74*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
75*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
76*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
77*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
78*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
79*4bdc9457SAndroid Build Coastguard Worker       }
80*4bdc9457SAndroid Build Coastguard Worker     }
81*4bdc9457SAndroid Build Coastguard Worker   }
82*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,negative_subnormal)83*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, negative_subnormal) {
84*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
85*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
86*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
87*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
88*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
89*4bdc9457SAndroid Build Coastguard Worker       }
90*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
91*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
92*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
93*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
94*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
95*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
96*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
97*4bdc9457SAndroid Build Coastguard Worker       }
98*4bdc9457SAndroid Build Coastguard Worker     }
99*4bdc9457SAndroid Build Coastguard Worker   }
100*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,positive_underflow)101*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, positive_underflow) {
102*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
103*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
104*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
105*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
106*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
107*4bdc9457SAndroid Build Coastguard Worker       }
108*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
109*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
110*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x0000);
111*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
112*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
113*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
114*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
115*4bdc9457SAndroid Build Coastguard Worker       }
116*4bdc9457SAndroid Build Coastguard Worker     }
117*4bdc9457SAndroid Build Coastguard Worker   }
118*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,negative_underflow)119*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, negative_underflow) {
120*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
121*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
122*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
123*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
124*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
125*4bdc9457SAndroid Build Coastguard Worker       }
126*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
127*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
128*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x8000);
129*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
130*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
131*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
132*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
133*4bdc9457SAndroid Build Coastguard Worker       }
134*4bdc9457SAndroid Build Coastguard Worker     }
135*4bdc9457SAndroid Build Coastguard Worker   }
136*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,positive_zero)137*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, positive_zero) {
138*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
139*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
140*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +0.0f);
141*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
142*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x0000);
143*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
144*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
145*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
146*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
147*4bdc9457SAndroid Build Coastguard Worker   }
148*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,negative_zero)149*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, negative_zero) {
150*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
151*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
152*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -0.0f);
153*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
154*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x8000);
155*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
156*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
157*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
158*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
159*4bdc9457SAndroid Build Coastguard Worker   }
160*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,positive_overflow)161*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, positive_overflow) {
162*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
163*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
164*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
165*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
166*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
167*4bdc9457SAndroid Build Coastguard Worker       }
168*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
169*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
170*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x7C00);
171*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
172*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
173*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
174*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
175*4bdc9457SAndroid Build Coastguard Worker       }
176*4bdc9457SAndroid Build Coastguard Worker     }
177*4bdc9457SAndroid Build Coastguard Worker   }
178*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,negative_overflow)179*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, negative_overflow) {
180*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
181*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
182*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
183*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
184*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
185*4bdc9457SAndroid Build Coastguard Worker       }
186*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
187*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
188*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0xFC00);
189*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
190*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
191*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
192*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
193*4bdc9457SAndroid Build Coastguard Worker       }
194*4bdc9457SAndroid Build Coastguard Worker     }
195*4bdc9457SAndroid Build Coastguard Worker   }
196*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,positive_infinity)197*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, positive_infinity) {
198*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
199*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
200*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
201*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
202*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x7C00);
203*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
204*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
205*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
206*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
207*4bdc9457SAndroid Build Coastguard Worker   }
208*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,negative_infinity)209*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, negative_infinity) {
210*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
211*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
212*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
213*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
214*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0xFC00);
215*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
216*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
217*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
218*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
219*4bdc9457SAndroid Build Coastguard Worker   }
220*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,positive_nan)221*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, positive_nan) {
222*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
223*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
224*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
225*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
226*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
227*4bdc9457SAndroid Build Coastguard Worker       }
228*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
229*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
230*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0x7C00))
231*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
232*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
233*4bdc9457SAndroid Build Coastguard Worker         ASSERT_LT(outputs[i], UINT16_C(0x8000))
234*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
235*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
236*4bdc9457SAndroid Build Coastguard Worker       }
237*4bdc9457SAndroid Build Coastguard Worker     }
238*4bdc9457SAndroid Build Coastguard Worker   }
239*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE2,negative_nan)240*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE2, negative_nan) {
241*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
242*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
243*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
244*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
245*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
246*4bdc9457SAndroid Build Coastguard Worker       }
247*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse2(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
248*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
249*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0xFC00))
250*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
251*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
252*4bdc9457SAndroid Build Coastguard Worker       }
253*4bdc9457SAndroid Build Coastguard Worker     }
254*4bdc9457SAndroid Build Coastguard Worker   }
255*4bdc9457SAndroid Build Coastguard Worker #endif  // XNN_ARCH_X86 || XNN_ARCH_X86_64
256*4bdc9457SAndroid Build Coastguard Worker 
257*4bdc9457SAndroid Build Coastguard Worker #if XNN_ARCH_X86 || XNN_ARCH_X86_64
TEST(CVT__SSE41,positive_normal)258*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, positive_normal) {
259*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
260*4bdc9457SAndroid Build Coastguard Worker 
261*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
262*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
263*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
264*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
265*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
266*4bdc9457SAndroid Build Coastguard Worker       }
267*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
268*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
269*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
270*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
271*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
272*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
273*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
274*4bdc9457SAndroid Build Coastguard Worker       }
275*4bdc9457SAndroid Build Coastguard Worker     }
276*4bdc9457SAndroid Build Coastguard Worker   }
277*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,negative_normal)278*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, negative_normal) {
279*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
280*4bdc9457SAndroid Build Coastguard Worker 
281*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
282*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
283*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
284*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
285*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
286*4bdc9457SAndroid Build Coastguard Worker       }
287*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
288*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
289*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
290*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
291*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
292*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
293*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
294*4bdc9457SAndroid Build Coastguard Worker       }
295*4bdc9457SAndroid Build Coastguard Worker     }
296*4bdc9457SAndroid Build Coastguard Worker   }
297*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,positive_subnormal)298*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, positive_subnormal) {
299*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
300*4bdc9457SAndroid Build Coastguard Worker 
301*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
302*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
303*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
304*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
305*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
306*4bdc9457SAndroid Build Coastguard Worker       }
307*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
308*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
309*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
310*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
311*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
312*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
313*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
314*4bdc9457SAndroid Build Coastguard Worker       }
315*4bdc9457SAndroid Build Coastguard Worker     }
316*4bdc9457SAndroid Build Coastguard Worker   }
317*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,negative_subnormal)318*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, negative_subnormal) {
319*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
320*4bdc9457SAndroid Build Coastguard Worker 
321*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
322*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
323*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
324*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
325*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
326*4bdc9457SAndroid Build Coastguard Worker       }
327*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
328*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
329*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
330*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
331*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
332*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
333*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
334*4bdc9457SAndroid Build Coastguard Worker       }
335*4bdc9457SAndroid Build Coastguard Worker     }
336*4bdc9457SAndroid Build Coastguard Worker   }
337*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,positive_underflow)338*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, positive_underflow) {
339*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
340*4bdc9457SAndroid Build Coastguard Worker 
341*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
342*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
343*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
344*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
345*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
346*4bdc9457SAndroid Build Coastguard Worker       }
347*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
348*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
349*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x0000);
350*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
351*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
352*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
353*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
354*4bdc9457SAndroid Build Coastguard Worker       }
355*4bdc9457SAndroid Build Coastguard Worker     }
356*4bdc9457SAndroid Build Coastguard Worker   }
357*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,negative_underflow)358*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, negative_underflow) {
359*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
360*4bdc9457SAndroid Build Coastguard Worker 
361*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
362*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
363*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
364*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
365*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
366*4bdc9457SAndroid Build Coastguard Worker       }
367*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
368*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
369*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x8000);
370*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
371*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
372*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
373*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
374*4bdc9457SAndroid Build Coastguard Worker       }
375*4bdc9457SAndroid Build Coastguard Worker     }
376*4bdc9457SAndroid Build Coastguard Worker   }
377*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,positive_zero)378*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, positive_zero) {
379*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
380*4bdc9457SAndroid Build Coastguard Worker 
381*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
382*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
383*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +0.0f);
384*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
385*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x0000);
386*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
387*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
388*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
389*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
390*4bdc9457SAndroid Build Coastguard Worker   }
391*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,negative_zero)392*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, negative_zero) {
393*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
394*4bdc9457SAndroid Build Coastguard Worker 
395*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
396*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
397*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -0.0f);
398*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
399*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x8000);
400*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
401*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
402*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
403*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
404*4bdc9457SAndroid Build Coastguard Worker   }
405*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,positive_overflow)406*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, positive_overflow) {
407*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
408*4bdc9457SAndroid Build Coastguard Worker 
409*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
410*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
411*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
412*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
413*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
414*4bdc9457SAndroid Build Coastguard Worker       }
415*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
416*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
417*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x7C00);
418*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
419*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
420*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
421*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
422*4bdc9457SAndroid Build Coastguard Worker       }
423*4bdc9457SAndroid Build Coastguard Worker     }
424*4bdc9457SAndroid Build Coastguard Worker   }
425*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,negative_overflow)426*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, negative_overflow) {
427*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
428*4bdc9457SAndroid Build Coastguard Worker 
429*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
430*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
431*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
432*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
433*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
434*4bdc9457SAndroid Build Coastguard Worker       }
435*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
436*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
437*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0xFC00);
438*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
439*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
440*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
441*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
442*4bdc9457SAndroid Build Coastguard Worker       }
443*4bdc9457SAndroid Build Coastguard Worker     }
444*4bdc9457SAndroid Build Coastguard Worker   }
445*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,positive_infinity)446*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, positive_infinity) {
447*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
448*4bdc9457SAndroid Build Coastguard Worker 
449*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
450*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
451*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
452*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
453*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x7C00);
454*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
455*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
456*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
457*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
458*4bdc9457SAndroid Build Coastguard Worker   }
459*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,negative_infinity)460*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, negative_infinity) {
461*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
462*4bdc9457SAndroid Build Coastguard Worker 
463*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
464*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
465*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
466*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
467*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0xFC00);
468*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
469*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
470*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
471*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
472*4bdc9457SAndroid Build Coastguard Worker   }
473*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,positive_nan)474*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, positive_nan) {
475*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
476*4bdc9457SAndroid Build Coastguard Worker 
477*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
478*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
479*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
480*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
481*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
482*4bdc9457SAndroid Build Coastguard Worker       }
483*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
484*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
485*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0x7C00))
486*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
487*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
488*4bdc9457SAndroid Build Coastguard Worker         ASSERT_LT(outputs[i], UINT16_C(0x8000))
489*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
490*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
491*4bdc9457SAndroid Build Coastguard Worker       }
492*4bdc9457SAndroid Build Coastguard Worker     }
493*4bdc9457SAndroid Build Coastguard Worker   }
494*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SSE41,negative_nan)495*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__SSE41, negative_nan) {
496*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_SSE41;
497*4bdc9457SAndroid Build Coastguard Worker 
498*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
499*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
500*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
501*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
502*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
503*4bdc9457SAndroid Build Coastguard Worker       }
504*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__sse41(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
505*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
506*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0xFC00))
507*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
508*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
509*4bdc9457SAndroid Build Coastguard Worker       }
510*4bdc9457SAndroid Build Coastguard Worker     }
511*4bdc9457SAndroid Build Coastguard Worker   }
512*4bdc9457SAndroid Build Coastguard Worker #endif  // XNN_ARCH_X86 || XNN_ARCH_X86_64
513*4bdc9457SAndroid Build Coastguard Worker 
514*4bdc9457SAndroid Build Coastguard Worker #if XNN_ARCH_X86 || XNN_ARCH_X86_64
TEST(CVT__F16C,positive_normal)515*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, positive_normal) {
516*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
517*4bdc9457SAndroid Build Coastguard Worker 
518*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
519*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
520*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
521*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
522*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
523*4bdc9457SAndroid Build Coastguard Worker       }
524*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
525*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
526*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
527*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
528*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
529*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
530*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
531*4bdc9457SAndroid Build Coastguard Worker       }
532*4bdc9457SAndroid Build Coastguard Worker     }
533*4bdc9457SAndroid Build Coastguard Worker   }
534*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,negative_normal)535*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, negative_normal) {
536*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
537*4bdc9457SAndroid Build Coastguard Worker 
538*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
539*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
540*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
541*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
542*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
543*4bdc9457SAndroid Build Coastguard Worker       }
544*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
545*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
546*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
547*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
548*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
549*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
550*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
551*4bdc9457SAndroid Build Coastguard Worker       }
552*4bdc9457SAndroid Build Coastguard Worker     }
553*4bdc9457SAndroid Build Coastguard Worker   }
554*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,positive_subnormal)555*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, positive_subnormal) {
556*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
557*4bdc9457SAndroid Build Coastguard Worker 
558*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
559*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
560*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
561*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
562*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
563*4bdc9457SAndroid Build Coastguard Worker       }
564*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
565*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
566*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
567*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
568*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
569*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
570*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
571*4bdc9457SAndroid Build Coastguard Worker       }
572*4bdc9457SAndroid Build Coastguard Worker     }
573*4bdc9457SAndroid Build Coastguard Worker   }
574*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,negative_subnormal)575*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, negative_subnormal) {
576*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
577*4bdc9457SAndroid Build Coastguard Worker 
578*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
579*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
580*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
581*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
582*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
583*4bdc9457SAndroid Build Coastguard Worker       }
584*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
585*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
586*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
587*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
588*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
589*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
590*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
591*4bdc9457SAndroid Build Coastguard Worker       }
592*4bdc9457SAndroid Build Coastguard Worker     }
593*4bdc9457SAndroid Build Coastguard Worker   }
594*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,positive_underflow)595*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, positive_underflow) {
596*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
597*4bdc9457SAndroid Build Coastguard Worker 
598*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
599*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
600*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
601*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
602*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
603*4bdc9457SAndroid Build Coastguard Worker       }
604*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
605*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
606*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x0000);
607*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
608*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
609*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
610*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
611*4bdc9457SAndroid Build Coastguard Worker       }
612*4bdc9457SAndroid Build Coastguard Worker     }
613*4bdc9457SAndroid Build Coastguard Worker   }
614*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,negative_underflow)615*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, negative_underflow) {
616*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
617*4bdc9457SAndroid Build Coastguard Worker 
618*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
619*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
620*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
621*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
622*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
623*4bdc9457SAndroid Build Coastguard Worker       }
624*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
625*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
626*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x8000);
627*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
628*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
629*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
630*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
631*4bdc9457SAndroid Build Coastguard Worker       }
632*4bdc9457SAndroid Build Coastguard Worker     }
633*4bdc9457SAndroid Build Coastguard Worker   }
634*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,positive_zero)635*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, positive_zero) {
636*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
637*4bdc9457SAndroid Build Coastguard Worker 
638*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
639*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
640*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +0.0f);
641*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
642*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x0000);
643*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
644*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
645*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
646*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
647*4bdc9457SAndroid Build Coastguard Worker   }
648*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,negative_zero)649*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, negative_zero) {
650*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
651*4bdc9457SAndroid Build Coastguard Worker 
652*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
653*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
654*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -0.0f);
655*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
656*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x8000);
657*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
658*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
659*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
660*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
661*4bdc9457SAndroid Build Coastguard Worker   }
662*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,positive_overflow)663*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, positive_overflow) {
664*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
665*4bdc9457SAndroid Build Coastguard Worker 
666*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
667*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
668*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
669*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
670*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
671*4bdc9457SAndroid Build Coastguard Worker       }
672*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
673*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
674*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x7C00);
675*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
676*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
677*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
678*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
679*4bdc9457SAndroid Build Coastguard Worker       }
680*4bdc9457SAndroid Build Coastguard Worker     }
681*4bdc9457SAndroid Build Coastguard Worker   }
682*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,negative_overflow)683*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, negative_overflow) {
684*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
685*4bdc9457SAndroid Build Coastguard Worker 
686*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
687*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
688*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
689*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
690*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
691*4bdc9457SAndroid Build Coastguard Worker       }
692*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
693*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
694*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0xFC00);
695*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
696*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
697*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
698*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
699*4bdc9457SAndroid Build Coastguard Worker       }
700*4bdc9457SAndroid Build Coastguard Worker     }
701*4bdc9457SAndroid Build Coastguard Worker   }
702*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,positive_infinity)703*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, positive_infinity) {
704*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
705*4bdc9457SAndroid Build Coastguard Worker 
706*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
707*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
708*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
709*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
710*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x7C00);
711*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
712*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
713*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
714*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
715*4bdc9457SAndroid Build Coastguard Worker   }
716*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,negative_infinity)717*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, negative_infinity) {
718*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
719*4bdc9457SAndroid Build Coastguard Worker 
720*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
721*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
722*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
723*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
724*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0xFC00);
725*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
726*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
727*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
728*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
729*4bdc9457SAndroid Build Coastguard Worker   }
730*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,positive_nan)731*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, positive_nan) {
732*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
733*4bdc9457SAndroid Build Coastguard Worker 
734*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
735*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
736*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
737*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
738*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
739*4bdc9457SAndroid Build Coastguard Worker       }
740*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
741*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
742*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0x7C00))
743*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
744*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
745*4bdc9457SAndroid Build Coastguard Worker         ASSERT_LT(outputs[i], UINT16_C(0x8000))
746*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
747*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
748*4bdc9457SAndroid Build Coastguard Worker       }
749*4bdc9457SAndroid Build Coastguard Worker     }
750*4bdc9457SAndroid Build Coastguard Worker   }
751*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__F16C,negative_nan)752*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__F16C, negative_nan) {
753*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_X86_F16C;
754*4bdc9457SAndroid Build Coastguard Worker 
755*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
756*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
757*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
758*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
759*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
760*4bdc9457SAndroid Build Coastguard Worker       }
761*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__f16c(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
762*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
763*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0xFC00))
764*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
765*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
766*4bdc9457SAndroid Build Coastguard Worker       }
767*4bdc9457SAndroid Build Coastguard Worker     }
768*4bdc9457SAndroid Build Coastguard Worker   }
769*4bdc9457SAndroid Build Coastguard Worker #endif  // XNN_ARCH_X86 || XNN_ARCH_X86_64
770*4bdc9457SAndroid Build Coastguard Worker 
771*4bdc9457SAndroid Build Coastguard Worker #if XNN_ARCH_ARM || XNN_ARCH_ARM64
TEST(CVT__NEON,positive_normal)772*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, positive_normal) {
773*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
774*4bdc9457SAndroid Build Coastguard Worker 
775*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
776*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
777*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
778*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
779*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
780*4bdc9457SAndroid Build Coastguard Worker       }
781*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
782*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
783*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
784*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
785*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
786*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
787*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
788*4bdc9457SAndroid Build Coastguard Worker       }
789*4bdc9457SAndroid Build Coastguard Worker     }
790*4bdc9457SAndroid Build Coastguard Worker   }
791*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,negative_normal)792*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, negative_normal) {
793*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
794*4bdc9457SAndroid Build Coastguard Worker 
795*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
796*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
797*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
798*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
799*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
800*4bdc9457SAndroid Build Coastguard Worker       }
801*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
802*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
803*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
804*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
805*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
806*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
807*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
808*4bdc9457SAndroid Build Coastguard Worker       }
809*4bdc9457SAndroid Build Coastguard Worker     }
810*4bdc9457SAndroid Build Coastguard Worker   }
811*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,positive_subnormal)812*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, positive_subnormal) {
813*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
814*4bdc9457SAndroid Build Coastguard Worker 
815*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
816*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
817*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
818*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
819*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
820*4bdc9457SAndroid Build Coastguard Worker       }
821*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
822*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
823*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
824*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
825*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
826*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
827*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
828*4bdc9457SAndroid Build Coastguard Worker       }
829*4bdc9457SAndroid Build Coastguard Worker     }
830*4bdc9457SAndroid Build Coastguard Worker   }
831*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,negative_subnormal)832*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, negative_subnormal) {
833*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
834*4bdc9457SAndroid Build Coastguard Worker 
835*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
836*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
837*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
838*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
839*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
840*4bdc9457SAndroid Build Coastguard Worker       }
841*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
842*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
843*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
844*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
845*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
846*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
847*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
848*4bdc9457SAndroid Build Coastguard Worker       }
849*4bdc9457SAndroid Build Coastguard Worker     }
850*4bdc9457SAndroid Build Coastguard Worker   }
851*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,positive_underflow)852*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, positive_underflow) {
853*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
854*4bdc9457SAndroid Build Coastguard Worker 
855*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
856*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
857*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
858*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
859*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
860*4bdc9457SAndroid Build Coastguard Worker       }
861*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
862*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
863*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x0000);
864*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
865*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
866*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
867*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
868*4bdc9457SAndroid Build Coastguard Worker       }
869*4bdc9457SAndroid Build Coastguard Worker     }
870*4bdc9457SAndroid Build Coastguard Worker   }
871*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,negative_underflow)872*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, negative_underflow) {
873*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
874*4bdc9457SAndroid Build Coastguard Worker 
875*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
876*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
877*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
878*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
879*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
880*4bdc9457SAndroid Build Coastguard Worker       }
881*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
882*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
883*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x8000);
884*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
885*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
886*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
887*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
888*4bdc9457SAndroid Build Coastguard Worker       }
889*4bdc9457SAndroid Build Coastguard Worker     }
890*4bdc9457SAndroid Build Coastguard Worker   }
891*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,positive_zero)892*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, positive_zero) {
893*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
894*4bdc9457SAndroid Build Coastguard Worker 
895*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
896*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
897*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +0.0f);
898*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
899*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x0000);
900*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
901*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
902*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
903*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
904*4bdc9457SAndroid Build Coastguard Worker   }
905*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,negative_zero)906*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, negative_zero) {
907*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
908*4bdc9457SAndroid Build Coastguard Worker 
909*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
910*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
911*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -0.0f);
912*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
913*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x8000);
914*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
915*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
916*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
917*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
918*4bdc9457SAndroid Build Coastguard Worker   }
919*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,positive_overflow)920*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, positive_overflow) {
921*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
922*4bdc9457SAndroid Build Coastguard Worker 
923*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
924*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
925*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
926*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
927*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
928*4bdc9457SAndroid Build Coastguard Worker       }
929*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
930*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
931*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x7C00);
932*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
933*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
934*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
935*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
936*4bdc9457SAndroid Build Coastguard Worker       }
937*4bdc9457SAndroid Build Coastguard Worker     }
938*4bdc9457SAndroid Build Coastguard Worker   }
939*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,negative_overflow)940*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, negative_overflow) {
941*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
942*4bdc9457SAndroid Build Coastguard Worker 
943*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
944*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
945*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
946*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
947*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
948*4bdc9457SAndroid Build Coastguard Worker       }
949*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
950*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
951*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0xFC00);
952*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
953*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
954*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
955*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
956*4bdc9457SAndroid Build Coastguard Worker       }
957*4bdc9457SAndroid Build Coastguard Worker     }
958*4bdc9457SAndroid Build Coastguard Worker   }
959*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,positive_infinity)960*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, positive_infinity) {
961*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
962*4bdc9457SAndroid Build Coastguard Worker 
963*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
964*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
965*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
966*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
967*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x7C00);
968*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
969*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
970*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
971*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
972*4bdc9457SAndroid Build Coastguard Worker   }
973*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,negative_infinity)974*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, negative_infinity) {
975*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
976*4bdc9457SAndroid Build Coastguard Worker 
977*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
978*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
979*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
980*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
981*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0xFC00);
982*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
983*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
984*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
985*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
986*4bdc9457SAndroid Build Coastguard Worker   }
987*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,positive_nan)988*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, positive_nan) {
989*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
990*4bdc9457SAndroid Build Coastguard Worker 
991*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
992*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
993*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
994*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
995*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
996*4bdc9457SAndroid Build Coastguard Worker       }
997*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
998*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
999*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0x7C00))
1000*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1001*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1002*4bdc9457SAndroid Build Coastguard Worker         ASSERT_LT(outputs[i], UINT16_C(0x8000))
1003*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1004*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1005*4bdc9457SAndroid Build Coastguard Worker       }
1006*4bdc9457SAndroid Build Coastguard Worker     }
1007*4bdc9457SAndroid Build Coastguard Worker   }
1008*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEON,negative_nan)1009*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEON, negative_nan) {
1010*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON;
1011*4bdc9457SAndroid Build Coastguard Worker 
1012*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1013*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1014*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1015*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1016*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1017*4bdc9457SAndroid Build Coastguard Worker       }
1018*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neon(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1019*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1020*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0xFC00))
1021*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1022*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1023*4bdc9457SAndroid Build Coastguard Worker       }
1024*4bdc9457SAndroid Build Coastguard Worker     }
1025*4bdc9457SAndroid Build Coastguard Worker   }
1026*4bdc9457SAndroid Build Coastguard Worker #endif  // XNN_ARCH_ARM || XNN_ARCH_ARM64
1027*4bdc9457SAndroid Build Coastguard Worker 
1028*4bdc9457SAndroid Build Coastguard Worker #if XNN_ARCH_ARM || XNN_ARCH_ARM64
TEST(CVT__NEONFP16,positive_normal)1029*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, positive_normal) {
1030*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1031*4bdc9457SAndroid Build Coastguard Worker 
1032*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1033*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1034*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
1035*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1036*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1037*4bdc9457SAndroid Build Coastguard Worker       }
1038*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1039*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1040*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1041*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1042*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1043*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1044*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1045*4bdc9457SAndroid Build Coastguard Worker       }
1046*4bdc9457SAndroid Build Coastguard Worker     }
1047*4bdc9457SAndroid Build Coastguard Worker   }
1048*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,negative_normal)1049*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, negative_normal) {
1050*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1051*4bdc9457SAndroid Build Coastguard Worker 
1052*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1053*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1054*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
1055*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1056*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1057*4bdc9457SAndroid Build Coastguard Worker       }
1058*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1059*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1060*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1061*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1062*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1063*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1064*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1065*4bdc9457SAndroid Build Coastguard Worker       }
1066*4bdc9457SAndroid Build Coastguard Worker     }
1067*4bdc9457SAndroid Build Coastguard Worker   }
1068*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,positive_subnormal)1069*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, positive_subnormal) {
1070*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1071*4bdc9457SAndroid Build Coastguard Worker 
1072*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1073*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1074*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
1075*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1076*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
1077*4bdc9457SAndroid Build Coastguard Worker       }
1078*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1079*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1080*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1081*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1082*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1083*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1084*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1085*4bdc9457SAndroid Build Coastguard Worker       }
1086*4bdc9457SAndroid Build Coastguard Worker     }
1087*4bdc9457SAndroid Build Coastguard Worker   }
1088*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,negative_subnormal)1089*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, negative_subnormal) {
1090*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1091*4bdc9457SAndroid Build Coastguard Worker 
1092*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1093*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1094*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
1095*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1096*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
1097*4bdc9457SAndroid Build Coastguard Worker       }
1098*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1099*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1100*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1101*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1102*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1103*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1104*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1105*4bdc9457SAndroid Build Coastguard Worker       }
1106*4bdc9457SAndroid Build Coastguard Worker     }
1107*4bdc9457SAndroid Build Coastguard Worker   }
1108*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,positive_underflow)1109*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, positive_underflow) {
1110*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1111*4bdc9457SAndroid Build Coastguard Worker 
1112*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1113*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1114*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
1115*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1116*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1117*4bdc9457SAndroid Build Coastguard Worker       }
1118*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1119*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1120*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x0000);
1121*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1122*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1123*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1124*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1125*4bdc9457SAndroid Build Coastguard Worker       }
1126*4bdc9457SAndroid Build Coastguard Worker     }
1127*4bdc9457SAndroid Build Coastguard Worker   }
1128*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,negative_underflow)1129*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, negative_underflow) {
1130*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1131*4bdc9457SAndroid Build Coastguard Worker 
1132*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1133*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1134*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
1135*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1136*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1137*4bdc9457SAndroid Build Coastguard Worker       }
1138*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1139*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1140*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x8000);
1141*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1142*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1143*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1144*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1145*4bdc9457SAndroid Build Coastguard Worker       }
1146*4bdc9457SAndroid Build Coastguard Worker     }
1147*4bdc9457SAndroid Build Coastguard Worker   }
1148*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,positive_zero)1149*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, positive_zero) {
1150*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1151*4bdc9457SAndroid Build Coastguard Worker 
1152*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1153*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1154*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +0.0f);
1155*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1156*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x0000);
1157*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1158*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1159*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1160*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1161*4bdc9457SAndroid Build Coastguard Worker   }
1162*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,negative_zero)1163*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, negative_zero) {
1164*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1165*4bdc9457SAndroid Build Coastguard Worker 
1166*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1167*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1168*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -0.0f);
1169*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1170*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x8000);
1171*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1172*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1173*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1174*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1175*4bdc9457SAndroid Build Coastguard Worker   }
1176*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,positive_overflow)1177*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, positive_overflow) {
1178*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1179*4bdc9457SAndroid Build Coastguard Worker 
1180*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1181*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1182*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
1183*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1184*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1185*4bdc9457SAndroid Build Coastguard Worker       }
1186*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1187*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1188*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x7C00);
1189*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1190*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1191*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1192*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1193*4bdc9457SAndroid Build Coastguard Worker       }
1194*4bdc9457SAndroid Build Coastguard Worker     }
1195*4bdc9457SAndroid Build Coastguard Worker   }
1196*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,negative_overflow)1197*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, negative_overflow) {
1198*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1199*4bdc9457SAndroid Build Coastguard Worker 
1200*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1201*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1202*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
1203*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1204*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1205*4bdc9457SAndroid Build Coastguard Worker       }
1206*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1207*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1208*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0xFC00);
1209*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1210*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1211*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1212*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1213*4bdc9457SAndroid Build Coastguard Worker       }
1214*4bdc9457SAndroid Build Coastguard Worker     }
1215*4bdc9457SAndroid Build Coastguard Worker   }
1216*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,positive_infinity)1217*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, positive_infinity) {
1218*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1219*4bdc9457SAndroid Build Coastguard Worker 
1220*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1221*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1222*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
1223*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1224*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x7C00);
1225*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1226*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1227*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1228*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1229*4bdc9457SAndroid Build Coastguard Worker   }
1230*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,negative_infinity)1231*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, negative_infinity) {
1232*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1233*4bdc9457SAndroid Build Coastguard Worker 
1234*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1235*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1236*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
1237*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1238*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0xFC00);
1239*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1240*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1241*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1242*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1243*4bdc9457SAndroid Build Coastguard Worker   }
1244*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,positive_nan)1245*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, positive_nan) {
1246*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1247*4bdc9457SAndroid Build Coastguard Worker 
1248*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1249*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1250*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1251*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1252*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1253*4bdc9457SAndroid Build Coastguard Worker       }
1254*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1255*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1256*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0x7C00))
1257*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1258*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1259*4bdc9457SAndroid Build Coastguard Worker         ASSERT_LT(outputs[i], UINT16_C(0x8000))
1260*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1261*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1262*4bdc9457SAndroid Build Coastguard Worker       }
1263*4bdc9457SAndroid Build Coastguard Worker     }
1264*4bdc9457SAndroid Build Coastguard Worker   }
1265*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__NEONFP16,negative_nan)1266*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__NEONFP16, negative_nan) {
1267*4bdc9457SAndroid Build Coastguard Worker     TEST_REQUIRES_ARM_NEON_FP16;
1268*4bdc9457SAndroid Build Coastguard Worker 
1269*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1270*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1271*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1272*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1273*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1274*4bdc9457SAndroid Build Coastguard Worker       }
1275*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__neonfp16(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1276*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1277*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0xFC00))
1278*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1279*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1280*4bdc9457SAndroid Build Coastguard Worker       }
1281*4bdc9457SAndroid Build Coastguard Worker     }
1282*4bdc9457SAndroid Build Coastguard Worker   }
1283*4bdc9457SAndroid Build Coastguard Worker #endif  // XNN_ARCH_ARM || XNN_ARCH_ARM64
1284*4bdc9457SAndroid Build Coastguard Worker 
1285*4bdc9457SAndroid Build Coastguard Worker #if XNN_ARCH_WASMSIMD || XNN_ARCH_WASMRELAXEDSIMD
TEST(CVT__WASMSIMD,positive_normal)1286*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, positive_normal) {
1287*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1288*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1289*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
1290*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1291*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1292*4bdc9457SAndroid Build Coastguard Worker       }
1293*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1294*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1295*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1296*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1297*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1298*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1299*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1300*4bdc9457SAndroid Build Coastguard Worker       }
1301*4bdc9457SAndroid Build Coastguard Worker     }
1302*4bdc9457SAndroid Build Coastguard Worker   }
1303*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,negative_normal)1304*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, negative_normal) {
1305*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1306*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1307*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
1308*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1309*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1310*4bdc9457SAndroid Build Coastguard Worker       }
1311*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1312*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1313*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1314*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1315*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1316*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1317*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1318*4bdc9457SAndroid Build Coastguard Worker       }
1319*4bdc9457SAndroid Build Coastguard Worker     }
1320*4bdc9457SAndroid Build Coastguard Worker   }
1321*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,positive_subnormal)1322*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, positive_subnormal) {
1323*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1324*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1325*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
1326*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1327*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
1328*4bdc9457SAndroid Build Coastguard Worker       }
1329*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1330*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1331*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1332*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1333*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1334*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1335*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1336*4bdc9457SAndroid Build Coastguard Worker       }
1337*4bdc9457SAndroid Build Coastguard Worker     }
1338*4bdc9457SAndroid Build Coastguard Worker   }
1339*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,negative_subnormal)1340*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, negative_subnormal) {
1341*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1342*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1343*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
1344*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1345*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
1346*4bdc9457SAndroid Build Coastguard Worker       }
1347*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1348*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1349*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1350*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1351*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1352*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1353*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1354*4bdc9457SAndroid Build Coastguard Worker       }
1355*4bdc9457SAndroid Build Coastguard Worker     }
1356*4bdc9457SAndroid Build Coastguard Worker   }
1357*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,positive_underflow)1358*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, positive_underflow) {
1359*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1360*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1361*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
1362*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1363*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1364*4bdc9457SAndroid Build Coastguard Worker       }
1365*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1366*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1367*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x0000);
1368*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1369*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1370*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1371*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1372*4bdc9457SAndroid Build Coastguard Worker       }
1373*4bdc9457SAndroid Build Coastguard Worker     }
1374*4bdc9457SAndroid Build Coastguard Worker   }
1375*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,negative_underflow)1376*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, negative_underflow) {
1377*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1378*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1379*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
1380*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1381*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1382*4bdc9457SAndroid Build Coastguard Worker       }
1383*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1384*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1385*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x8000);
1386*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1387*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1388*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1389*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1390*4bdc9457SAndroid Build Coastguard Worker       }
1391*4bdc9457SAndroid Build Coastguard Worker     }
1392*4bdc9457SAndroid Build Coastguard Worker   }
1393*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,positive_zero)1394*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, positive_zero) {
1395*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1396*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1397*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +0.0f);
1398*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1399*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x0000);
1400*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1401*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1402*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1403*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1404*4bdc9457SAndroid Build Coastguard Worker   }
1405*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,negative_zero)1406*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, negative_zero) {
1407*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1408*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1409*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -0.0f);
1410*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1411*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x8000);
1412*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1413*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1414*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1415*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1416*4bdc9457SAndroid Build Coastguard Worker   }
1417*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,positive_overflow)1418*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, positive_overflow) {
1419*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1420*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1421*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
1422*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1423*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1424*4bdc9457SAndroid Build Coastguard Worker       }
1425*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1426*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1427*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0x7C00);
1428*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1429*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1430*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1431*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1432*4bdc9457SAndroid Build Coastguard Worker       }
1433*4bdc9457SAndroid Build Coastguard Worker     }
1434*4bdc9457SAndroid Build Coastguard Worker   }
1435*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,negative_overflow)1436*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, negative_overflow) {
1437*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1438*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1439*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
1440*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1441*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(n + i);
1442*4bdc9457SAndroid Build Coastguard Worker       }
1443*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1444*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1445*4bdc9457SAndroid Build Coastguard Worker         const uint16_t reference_output = UINT16_C(0xFC00);
1446*4bdc9457SAndroid Build Coastguard Worker         ASSERT_EQ(reference_output, outputs[i])
1447*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1448*4bdc9457SAndroid Build Coastguard Worker           << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1449*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1450*4bdc9457SAndroid Build Coastguard Worker       }
1451*4bdc9457SAndroid Build Coastguard Worker     }
1452*4bdc9457SAndroid Build Coastguard Worker   }
1453*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,positive_infinity)1454*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, positive_infinity) {
1455*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1456*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1457*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
1458*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1459*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0x7C00);
1460*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1461*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1462*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1463*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1464*4bdc9457SAndroid Build Coastguard Worker   }
1465*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,negative_infinity)1466*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, negative_infinity) {
1467*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1468*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1469*4bdc9457SAndroid Build Coastguard Worker     std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
1470*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1471*4bdc9457SAndroid Build Coastguard Worker     const uint16_t reference_output = UINT16_C(0xFC00);
1472*4bdc9457SAndroid Build Coastguard Worker     ASSERT_EQ(reference_output, outputs[0])
1473*4bdc9457SAndroid Build Coastguard Worker       << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1474*4bdc9457SAndroid Build Coastguard Worker       << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1475*4bdc9457SAndroid Build Coastguard Worker       << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1476*4bdc9457SAndroid Build Coastguard Worker   }
1477*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,positive_nan)1478*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, positive_nan) {
1479*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1480*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1481*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1482*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1483*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1484*4bdc9457SAndroid Build Coastguard Worker       }
1485*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1486*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1487*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0x7C00))
1488*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1489*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1490*4bdc9457SAndroid Build Coastguard Worker         ASSERT_LT(outputs[i], UINT16_C(0x8000))
1491*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1492*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1493*4bdc9457SAndroid Build Coastguard Worker       }
1494*4bdc9457SAndroid Build Coastguard Worker     }
1495*4bdc9457SAndroid Build Coastguard Worker   }
1496*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__WASMSIMD,negative_nan)1497*4bdc9457SAndroid Build Coastguard Worker   TEST(CVT__WASMSIMD, negative_nan) {
1498*4bdc9457SAndroid Build Coastguard Worker     std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1499*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1500*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1501*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1502*4bdc9457SAndroid Build Coastguard Worker         inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1503*4bdc9457SAndroid Build Coastguard Worker       }
1504*4bdc9457SAndroid Build Coastguard Worker       xnn_math_f32_f16_cvt__wasmsimd(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1505*4bdc9457SAndroid Build Coastguard Worker       for (uint32_t i = 0; i < kBlockSize; i++) {
1506*4bdc9457SAndroid Build Coastguard Worker         ASSERT_GT(outputs[i], UINT16_C(0xFC00))
1507*4bdc9457SAndroid Build Coastguard Worker           << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1508*4bdc9457SAndroid Build Coastguard Worker           << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1509*4bdc9457SAndroid Build Coastguard Worker       }
1510*4bdc9457SAndroid Build Coastguard Worker     }
1511*4bdc9457SAndroid Build Coastguard Worker   }
1512*4bdc9457SAndroid Build Coastguard Worker #endif  // XNN_ARCH_WASMSIMD || XNN_ARCH_WASMRELAXEDSIMD
1513*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,positive_normal)1514*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, positive_normal) {
1515*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1516*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1517*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
1518*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1519*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1520*4bdc9457SAndroid Build Coastguard Worker     }
1521*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1522*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1523*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1524*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1525*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1526*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1527*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1528*4bdc9457SAndroid Build Coastguard Worker     }
1529*4bdc9457SAndroid Build Coastguard Worker   }
1530*4bdc9457SAndroid Build Coastguard Worker }
1531*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,negative_normal)1532*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, negative_normal) {
1533*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1534*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1535*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
1536*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1537*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1538*4bdc9457SAndroid Build Coastguard Worker     }
1539*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1540*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1541*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1542*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1543*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1544*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1545*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1546*4bdc9457SAndroid Build Coastguard Worker     }
1547*4bdc9457SAndroid Build Coastguard Worker   }
1548*4bdc9457SAndroid Build Coastguard Worker }
1549*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,positive_subnormal)1550*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, positive_subnormal) {
1551*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1552*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1553*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
1554*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1555*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
1556*4bdc9457SAndroid Build Coastguard Worker     }
1557*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1558*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1559*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1560*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1561*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1562*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1563*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1564*4bdc9457SAndroid Build Coastguard Worker     }
1565*4bdc9457SAndroid Build Coastguard Worker   }
1566*4bdc9457SAndroid Build Coastguard Worker }
1567*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,negative_subnormal)1568*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, negative_subnormal) {
1569*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1570*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1571*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
1572*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1573*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
1574*4bdc9457SAndroid Build Coastguard Worker     }
1575*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1576*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1577*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1578*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1579*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1580*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1581*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1582*4bdc9457SAndroid Build Coastguard Worker     }
1583*4bdc9457SAndroid Build Coastguard Worker   }
1584*4bdc9457SAndroid Build Coastguard Worker }
1585*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,positive_underflow)1586*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, positive_underflow) {
1587*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1588*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1589*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
1590*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1591*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1592*4bdc9457SAndroid Build Coastguard Worker     }
1593*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1594*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1595*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0x0000);
1596*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1597*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1598*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1599*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1600*4bdc9457SAndroid Build Coastguard Worker     }
1601*4bdc9457SAndroid Build Coastguard Worker   }
1602*4bdc9457SAndroid Build Coastguard Worker }
1603*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,negative_underflow)1604*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, negative_underflow) {
1605*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1606*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1607*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
1608*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1609*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1610*4bdc9457SAndroid Build Coastguard Worker     }
1611*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1612*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1613*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0x8000);
1614*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1615*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1616*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1617*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1618*4bdc9457SAndroid Build Coastguard Worker     }
1619*4bdc9457SAndroid Build Coastguard Worker   }
1620*4bdc9457SAndroid Build Coastguard Worker }
1621*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,positive_zero)1622*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, positive_zero) {
1623*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1624*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1625*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), +0.0f);
1626*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1627*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0x0000);
1628*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1629*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1630*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1631*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1632*4bdc9457SAndroid Build Coastguard Worker }
1633*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,negative_zero)1634*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, negative_zero) {
1635*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1636*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1637*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), -0.0f);
1638*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1639*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0x8000);
1640*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1641*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1642*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1643*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1644*4bdc9457SAndroid Build Coastguard Worker }
1645*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,positive_overflow)1646*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, positive_overflow) {
1647*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1648*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1649*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
1650*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1651*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1652*4bdc9457SAndroid Build Coastguard Worker     }
1653*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1654*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1655*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0x7C00);
1656*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1657*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1658*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1659*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1660*4bdc9457SAndroid Build Coastguard Worker     }
1661*4bdc9457SAndroid Build Coastguard Worker   }
1662*4bdc9457SAndroid Build Coastguard Worker }
1663*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,negative_overflow)1664*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, negative_overflow) {
1665*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1666*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1667*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
1668*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1669*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1670*4bdc9457SAndroid Build Coastguard Worker     }
1671*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1672*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1673*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0xFC00);
1674*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1675*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1676*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1677*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1678*4bdc9457SAndroid Build Coastguard Worker     }
1679*4bdc9457SAndroid Build Coastguard Worker   }
1680*4bdc9457SAndroid Build Coastguard Worker }
1681*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,positive_infinity)1682*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, positive_infinity) {
1683*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1684*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1685*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
1686*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1687*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0x7C00);
1688*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1689*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1690*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1691*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1692*4bdc9457SAndroid Build Coastguard Worker }
1693*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,negative_infinity)1694*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, negative_infinity) {
1695*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1696*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1697*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
1698*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1699*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0xFC00);
1700*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1701*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1702*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1703*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1704*4bdc9457SAndroid Build Coastguard Worker }
1705*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,positive_nan)1706*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, positive_nan) {
1707*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1708*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1709*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1710*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1711*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1712*4bdc9457SAndroid Build Coastguard Worker     }
1713*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1714*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1715*4bdc9457SAndroid Build Coastguard Worker       ASSERT_GT(outputs[i], UINT16_C(0x7C00))
1716*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1717*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1718*4bdc9457SAndroid Build Coastguard Worker       ASSERT_LT(outputs[i], UINT16_C(0x8000))
1719*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1720*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1721*4bdc9457SAndroid Build Coastguard Worker     }
1722*4bdc9457SAndroid Build Coastguard Worker   }
1723*4bdc9457SAndroid Build Coastguard Worker }
1724*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_BITCAST,negative_nan)1725*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_BITCAST, negative_nan) {
1726*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1727*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1728*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1729*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1730*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1731*4bdc9457SAndroid Build Coastguard Worker     }
1732*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_bitcast(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1733*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1734*4bdc9457SAndroid Build Coastguard Worker       ASSERT_GT(outputs[i], UINT16_C(0xFC00))
1735*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1736*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1737*4bdc9457SAndroid Build Coastguard Worker     }
1738*4bdc9457SAndroid Build Coastguard Worker   }
1739*4bdc9457SAndroid Build Coastguard Worker }
1740*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,positive_normal)1741*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, positive_normal) {
1742*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1743*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1744*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x387FE000); n < UINT32_C(0x477FF000); n += kBlockSize) {
1745*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1746*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1747*4bdc9457SAndroid Build Coastguard Worker     }
1748*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1749*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1750*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1751*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1752*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1753*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1754*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1755*4bdc9457SAndroid Build Coastguard Worker     }
1756*4bdc9457SAndroid Build Coastguard Worker   }
1757*4bdc9457SAndroid Build Coastguard Worker }
1758*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,negative_normal)1759*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, negative_normal) {
1760*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1761*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1762*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0xB87FE000); n < UINT32_C(0xC77FF000); n += kBlockSize) {
1763*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1764*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1765*4bdc9457SAndroid Build Coastguard Worker     }
1766*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1767*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1768*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1769*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1770*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1771*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1772*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1773*4bdc9457SAndroid Build Coastguard Worker     }
1774*4bdc9457SAndroid Build Coastguard Worker   }
1775*4bdc9457SAndroid Build Coastguard Worker }
1776*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,positive_subnormal)1777*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, positive_subnormal) {
1778*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1779*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1780*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x33000001); n < UINT32_C(0x387FE000); n += kBlockSize) {
1781*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1782*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x387FDFFF)));
1783*4bdc9457SAndroid Build Coastguard Worker     }
1784*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1785*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1786*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1787*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1788*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1789*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1790*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1791*4bdc9457SAndroid Build Coastguard Worker     }
1792*4bdc9457SAndroid Build Coastguard Worker   }
1793*4bdc9457SAndroid Build Coastguard Worker }
1794*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,negative_subnormal)1795*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, negative_subnormal) {
1796*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1797*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1798*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0xB3000001); n < UINT32_C(0xB87FE000); n += kBlockSize) {
1799*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1800*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0xB87FDFFF)));
1801*4bdc9457SAndroid Build Coastguard Worker     }
1802*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1803*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1804*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = fp16_ieee_from_fp32_value(inputs[i]);
1805*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1806*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1807*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1808*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1809*4bdc9457SAndroid Build Coastguard Worker     }
1810*4bdc9457SAndroid Build Coastguard Worker   }
1811*4bdc9457SAndroid Build Coastguard Worker }
1812*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,positive_underflow)1813*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, positive_underflow) {
1814*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1815*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1816*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x00000001); n < UINT32_C(0x33000001); n += kBlockSize) {
1817*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1818*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1819*4bdc9457SAndroid Build Coastguard Worker     }
1820*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1821*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1822*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0x0000);
1823*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1824*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1825*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1826*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1827*4bdc9457SAndroid Build Coastguard Worker     }
1828*4bdc9457SAndroid Build Coastguard Worker   }
1829*4bdc9457SAndroid Build Coastguard Worker }
1830*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,negative_underflow)1831*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, negative_underflow) {
1832*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1833*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1834*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x80000001); n < UINT32_C(0xB3000001); n += kBlockSize) {
1835*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1836*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1837*4bdc9457SAndroid Build Coastguard Worker     }
1838*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1839*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1840*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0x8000);
1841*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1842*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1843*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1844*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1845*4bdc9457SAndroid Build Coastguard Worker     }
1846*4bdc9457SAndroid Build Coastguard Worker   }
1847*4bdc9457SAndroid Build Coastguard Worker }
1848*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,positive_zero)1849*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, positive_zero) {
1850*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1851*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1852*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), +0.0f);
1853*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1854*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0x0000);
1855*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1856*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1857*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1858*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1859*4bdc9457SAndroid Build Coastguard Worker }
1860*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,negative_zero)1861*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, negative_zero) {
1862*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1863*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1864*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), -0.0f);
1865*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1866*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0x8000);
1867*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1868*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1869*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1870*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1871*4bdc9457SAndroid Build Coastguard Worker }
1872*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,positive_overflow)1873*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, positive_overflow) {
1874*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1875*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1876*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x477FF000); n < UINT32_C(0x7F800000); n += kBlockSize) {
1877*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1878*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1879*4bdc9457SAndroid Build Coastguard Worker     }
1880*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1881*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1882*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0x7C00);
1883*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1884*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1885*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1886*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1887*4bdc9457SAndroid Build Coastguard Worker     }
1888*4bdc9457SAndroid Build Coastguard Worker   }
1889*4bdc9457SAndroid Build Coastguard Worker }
1890*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,negative_overflow)1891*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, negative_overflow) {
1892*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1893*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1894*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0xC77FF000); n < UINT32_C(0xFF800000); n += kBlockSize) {
1895*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1896*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(n + i);
1897*4bdc9457SAndroid Build Coastguard Worker     }
1898*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1899*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1900*4bdc9457SAndroid Build Coastguard Worker       const uint16_t reference_output = UINT16_C(0xFC00);
1901*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(reference_output, outputs[i])
1902*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1903*4bdc9457SAndroid Build Coastguard Worker         << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1904*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1905*4bdc9457SAndroid Build Coastguard Worker     }
1906*4bdc9457SAndroid Build Coastguard Worker   }
1907*4bdc9457SAndroid Build Coastguard Worker }
1908*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,positive_infinity)1909*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, positive_infinity) {
1910*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1911*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1912*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), +std::numeric_limits<float>::infinity());
1913*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1914*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0x7C00);
1915*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1916*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1917*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1918*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1919*4bdc9457SAndroid Build Coastguard Worker }
1920*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,negative_infinity)1921*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, negative_infinity) {
1922*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1923*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1924*4bdc9457SAndroid Build Coastguard Worker   std::fill(inputs.begin(), inputs.end(), -std::numeric_limits<float>::infinity());
1925*4bdc9457SAndroid Build Coastguard Worker   xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1926*4bdc9457SAndroid Build Coastguard Worker   const uint16_t reference_output = UINT16_C(0xFC00);
1927*4bdc9457SAndroid Build Coastguard Worker   ASSERT_EQ(reference_output, outputs[0])
1928*4bdc9457SAndroid Build Coastguard Worker     << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[0])
1929*4bdc9457SAndroid Build Coastguard Worker     << ", reference = 0x" << std::hex << std::setw(4) << std::setfill('0') << reference_output
1930*4bdc9457SAndroid Build Coastguard Worker     << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[0];
1931*4bdc9457SAndroid Build Coastguard Worker }
1932*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,positive_nan)1933*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, positive_nan) {
1934*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1935*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1936*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1937*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1938*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1939*4bdc9457SAndroid Build Coastguard Worker     }
1940*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1941*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1942*4bdc9457SAndroid Build Coastguard Worker       ASSERT_GT(outputs[i], UINT16_C(0x7C00))
1943*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1944*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1945*4bdc9457SAndroid Build Coastguard Worker       ASSERT_LT(outputs[i], UINT16_C(0x8000))
1946*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1947*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1948*4bdc9457SAndroid Build Coastguard Worker     }
1949*4bdc9457SAndroid Build Coastguard Worker   }
1950*4bdc9457SAndroid Build Coastguard Worker }
1951*4bdc9457SAndroid Build Coastguard Worker 
TEST(CVT__SCALAR_FABSF,negative_nan)1952*4bdc9457SAndroid Build Coastguard Worker TEST(CVT__SCALAR_FABSF, negative_nan) {
1953*4bdc9457SAndroid Build Coastguard Worker   std::vector<float, AlignedAllocator<float, 64>> inputs(kBlockSize);
1954*4bdc9457SAndroid Build Coastguard Worker   std::vector<uint16_t, AlignedAllocator<uint16_t, 64>> outputs(kBlockSize);
1955*4bdc9457SAndroid Build Coastguard Worker   for (uint32_t n = UINT32_C(0x7F800001); n < UINT32_C(0x80000000); n += kBlockSize) {
1956*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1957*4bdc9457SAndroid Build Coastguard Worker       inputs[i] = uint32_as_float(UINT32_C(0x80000000) | std::min<uint32_t>(n + i, UINT32_C(0x7FFFFFFF)));
1958*4bdc9457SAndroid Build Coastguard Worker     }
1959*4bdc9457SAndroid Build Coastguard Worker     xnn_math_f32_f16_cvt__scalar_fabsf(kBlockSize * sizeof(uint16_t), inputs.data(), outputs.data());
1960*4bdc9457SAndroid Build Coastguard Worker     for (uint32_t i = 0; i < kBlockSize; i++) {
1961*4bdc9457SAndroid Build Coastguard Worker       ASSERT_GT(outputs[i], UINT16_C(0xFC00))
1962*4bdc9457SAndroid Build Coastguard Worker         << "input = 0x" << std::hex << std::setw(8) << std::setfill('0') << float_as_uint32(inputs[i])
1963*4bdc9457SAndroid Build Coastguard Worker         << ", optimized = 0x" << std::hex << std::setw(4) << std::setfill('0') << outputs[i];
1964*4bdc9457SAndroid Build Coastguard Worker     }
1965*4bdc9457SAndroid Build Coastguard Worker   }
1966*4bdc9457SAndroid Build Coastguard Worker }
1967