1 // Copyright 2019 Google LLC
2 // SPDX-License-Identifier: Apache-2.0
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
18 #undef HWY_TARGET_INCLUDE
19 #define HWY_TARGET_INCLUDE "base_test.cc"
20 #include "hwy/foreach_target.h" // IWYU pragma: keep
21 #include "hwy/highway.h"
22 #include "hwy/tests/test_util-inl.h"
24 HWY_BEFORE_NAMESPACE();
26 namespace HWY_NAMESPACE
{
28 HWY_NOINLINE
void TestAllLimits() {
29 HWY_ASSERT_EQ(uint8_t{0}, LimitsMin
<uint8_t>());
30 HWY_ASSERT_EQ(uint16_t{0}, LimitsMin
<uint16_t>());
31 HWY_ASSERT_EQ(uint32_t{0}, LimitsMin
<uint32_t>());
32 HWY_ASSERT_EQ(uint64_t{0}, LimitsMin
<uint64_t>());
34 HWY_ASSERT_EQ(int8_t{-128}, LimitsMin
<int8_t>());
35 HWY_ASSERT_EQ(int16_t{-32768}, LimitsMin
<int16_t>());
36 HWY_ASSERT_EQ(static_cast<int32_t>(0x80000000u
), LimitsMin
<int32_t>());
37 HWY_ASSERT_EQ(static_cast<int64_t>(0x8000000000000000ull
),
38 LimitsMin
<int64_t>());
40 HWY_ASSERT_EQ(uint8_t{0xFF}, LimitsMax
<uint8_t>());
41 HWY_ASSERT_EQ(uint16_t{0xFFFF}, LimitsMax
<uint16_t>());
42 HWY_ASSERT_EQ(uint32_t{0xFFFFFFFFu
}, LimitsMax
<uint32_t>());
43 HWY_ASSERT_EQ(uint64_t{0xFFFFFFFFFFFFFFFFull
}, LimitsMax
<uint64_t>());
45 HWY_ASSERT_EQ(int8_t{0x7F}, LimitsMax
<int8_t>());
46 HWY_ASSERT_EQ(int16_t{0x7FFF}, LimitsMax
<int16_t>());
47 HWY_ASSERT_EQ(int32_t{0x7FFFFFFFu
}, LimitsMax
<int32_t>());
48 HWY_ASSERT_EQ(int64_t{0x7FFFFFFFFFFFFFFFull
}, LimitsMax
<int64_t>());
51 struct TestLowestHighest
{
53 HWY_NOINLINE
void operator()(T
/*unused*/) const {
54 HWY_ASSERT_EQ(std::numeric_limits
<T
>::lowest(), LowestValue
<T
>());
55 HWY_ASSERT_EQ(std::numeric_limits
<T
>::max(), HighestValue
<T
>());
59 HWY_NOINLINE
void TestAllLowestHighest() { ForAllTypes(TestLowestHighest()); }
60 struct TestIsUnsigned
{
62 HWY_NOINLINE
void operator()(T
/*unused*/) const {
63 static_assert(!IsFloat
<T
>(), "Expected !IsFloat");
64 static_assert(!IsSigned
<T
>(), "Expected !IsSigned");
70 HWY_NOINLINE
void operator()(T
/*unused*/) const {
71 static_assert(!IsFloat
<T
>(), "Expected !IsFloat");
72 static_assert(IsSigned
<T
>(), "Expected IsSigned");
78 HWY_NOINLINE
void operator()(T
/*unused*/) const {
79 static_assert(IsFloat
<T
>(), "Expected IsFloat");
80 static_assert(IsSigned
<T
>(), "Floats are also considered signed");
84 HWY_NOINLINE
void TestAllType() {
85 ForUnsignedTypes(TestIsUnsigned());
86 ForSignedTypes(TestIsSigned());
87 ForFloatTypes(TestIsFloat());
89 static_assert(sizeof(MakeUnsigned
<hwy::uint128_t
>) == 16, "");
90 static_assert(sizeof(MakeWide
<uint64_t>) == 16, "Expected uint128_t");
91 static_assert(sizeof(MakeNarrow
<hwy::uint128_t
>) == 8, "Expected uint64_t");
96 HWY_NOINLINE
void operator()(T
/*unused*/) const {
97 static_assert(IsSame
<T
, T
>(), "T == T");
98 static_assert(!IsSame
<MakeSigned
<T
>, MakeUnsigned
<T
>>(), "S != U");
99 static_assert(!IsSame
<MakeUnsigned
<T
>, MakeSigned
<T
>>(), "U != S");
103 HWY_NOINLINE
void TestAllIsSame() { ForAllTypes(TestIsSame()); }
105 HWY_NOINLINE
void TestAllBitScan() {
106 HWY_ASSERT_EQ(size_t{0}, Num0BitsAboveMS1Bit_Nonzero32(0x80000000u
));
107 HWY_ASSERT_EQ(size_t{0}, Num0BitsAboveMS1Bit_Nonzero32(0xFFFFFFFFu
));
108 HWY_ASSERT_EQ(size_t{1}, Num0BitsAboveMS1Bit_Nonzero32(0x40000000u
));
109 HWY_ASSERT_EQ(size_t{1}, Num0BitsAboveMS1Bit_Nonzero32(0x40108210u
));
110 HWY_ASSERT_EQ(size_t{30}, Num0BitsAboveMS1Bit_Nonzero32(2u));
111 HWY_ASSERT_EQ(size_t{30}, Num0BitsAboveMS1Bit_Nonzero32(3u));
112 HWY_ASSERT_EQ(size_t{31}, Num0BitsAboveMS1Bit_Nonzero32(1u));
114 HWY_ASSERT_EQ(size_t{0},
115 Num0BitsAboveMS1Bit_Nonzero64(0x8000000000000000ull
));
116 HWY_ASSERT_EQ(size_t{0},
117 Num0BitsAboveMS1Bit_Nonzero64(0xFFFFFFFFFFFFFFFFull
));
118 HWY_ASSERT_EQ(size_t{1},
119 Num0BitsAboveMS1Bit_Nonzero64(0x4000000000000000ull
));
120 HWY_ASSERT_EQ(size_t{1},
121 Num0BitsAboveMS1Bit_Nonzero64(0x4010821004200011ull
));
122 HWY_ASSERT_EQ(size_t{62}, Num0BitsAboveMS1Bit_Nonzero64(2ull));
123 HWY_ASSERT_EQ(size_t{62}, Num0BitsAboveMS1Bit_Nonzero64(3ull));
124 HWY_ASSERT_EQ(size_t{63}, Num0BitsAboveMS1Bit_Nonzero64(1ull));
126 HWY_ASSERT_EQ(size_t{0}, Num0BitsBelowLS1Bit_Nonzero32(1u));
127 HWY_ASSERT_EQ(size_t{1}, Num0BitsBelowLS1Bit_Nonzero32(2u));
128 HWY_ASSERT_EQ(size_t{30}, Num0BitsBelowLS1Bit_Nonzero32(0xC0000000u
));
129 HWY_ASSERT_EQ(size_t{31}, Num0BitsBelowLS1Bit_Nonzero32(0x80000000u
));
131 HWY_ASSERT_EQ(size_t{0}, Num0BitsBelowLS1Bit_Nonzero64(1ull));
132 HWY_ASSERT_EQ(size_t{1}, Num0BitsBelowLS1Bit_Nonzero64(2ull));
133 HWY_ASSERT_EQ(size_t{62},
134 Num0BitsBelowLS1Bit_Nonzero64(0xC000000000000000ull
));
135 HWY_ASSERT_EQ(size_t{63},
136 Num0BitsBelowLS1Bit_Nonzero64(0x8000000000000000ull
));
139 HWY_NOINLINE
void TestAllPopCount() {
140 HWY_ASSERT_EQ(size_t{0}, PopCount(0u));
141 HWY_ASSERT_EQ(size_t{1}, PopCount(1u));
142 HWY_ASSERT_EQ(size_t{1}, PopCount(2u));
143 HWY_ASSERT_EQ(size_t{2}, PopCount(3u));
144 HWY_ASSERT_EQ(size_t{1}, PopCount(0x80000000u
));
145 HWY_ASSERT_EQ(size_t{31}, PopCount(0x7FFFFFFFu
));
146 HWY_ASSERT_EQ(size_t{32}, PopCount(0xFFFFFFFFu
));
148 HWY_ASSERT_EQ(size_t{1}, PopCount(0x80000000ull
));
149 HWY_ASSERT_EQ(size_t{31}, PopCount(0x7FFFFFFFull
));
150 HWY_ASSERT_EQ(size_t{32}, PopCount(0xFFFFFFFFull
));
151 HWY_ASSERT_EQ(size_t{33}, PopCount(0x10FFFFFFFFull
));
152 HWY_ASSERT_EQ(size_t{63}, PopCount(0xFFFEFFFFFFFFFFFFull
));
153 HWY_ASSERT_EQ(size_t{64}, PopCount(0xFFFFFFFFFFFFFFFFull
));
157 static HWY_INLINE T
TestEndianGetIntegerVal(T val
) {
158 static_assert(!IsFloat
<T
>() && !IsSpecialFloat
<T
>(),
159 "T must not be a floating-point type");
160 using TU
= MakeUnsigned
<T
>;
161 static_assert(sizeof(T
) == sizeof(TU
),
162 "sizeof(T) == sizeof(TU) must be true");
164 uint8_t result_bytes
[sizeof(T
)];
165 const TU val_u
= static_cast<TU
>(val
);
167 for (size_t i
= 0; i
< sizeof(T
); i
++) {
168 #if HWY_IS_BIG_ENDIAN
169 const size_t shift_amt
= (sizeof(T
) - 1 - i
) * 8;
171 const size_t shift_amt
= i
* 8;
173 result_bytes
[i
] = static_cast<uint8_t>((val_u
>> shift_amt
) & 0xFF);
177 CopyBytes
<sizeof(T
)>(result_bytes
, &result
);
181 template <class T
, class... Bytes
>
182 static HWY_INLINE T
TestEndianCreateValueFromBytes(Bytes
&&... bytes
) {
183 static_assert(sizeof(T
) > 0, "sizeof(T) > 0 must be true");
184 static_assert(sizeof...(Bytes
) == sizeof(T
),
185 "sizeof...(Bytes) == sizeof(T) must be true");
187 const uint8_t src_bytes
[sizeof(T
)]{static_cast<uint8_t>(bytes
)...};
190 CopyBytes
<sizeof(T
)>(src_bytes
, &result
);
194 #define HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(val) \
195 HWY_ASSERT_EQ(val, TestEndianGetIntegerVal(val))
197 HWY_NOINLINE
void TestAllEndian() {
198 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int8_t{0x01});
199 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint8_t{0x01});
200 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int16_t{0x0102});
201 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint16_t{0x0102});
202 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int32_t{0x01020304});
203 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint32_t{0x01020304});
204 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int64_t{0x0102030405060708});
205 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint64_t{0x0102030405060708});
207 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int16_t{0x0201});
208 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint16_t{0x0201});
209 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int32_t{0x04030201});
210 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint32_t{0x04030201});
211 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(int64_t{0x0807060504030201});
212 HWY_TEST_ENDIAN_CHECK_INTEGER_VAL(uint64_t{0x0807060504030201});
214 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN
? int16_t{0x0102} : int16_t{0x0201},
215 TestEndianCreateValueFromBytes
<int16_t>(0x01, 0x02));
216 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN
? uint16_t{0x0102} : uint16_t{0x0201},
217 TestEndianCreateValueFromBytes
<uint16_t>(0x01, 0x02));
219 HWY_IS_BIG_ENDIAN
? int32_t{0x01020304} : int32_t{0x04030201},
220 TestEndianCreateValueFromBytes
<int32_t>(0x01, 0x02, 0x03, 0x04));
222 HWY_IS_BIG_ENDIAN
? uint32_t{0x01020304} : uint32_t{0x04030201},
223 TestEndianCreateValueFromBytes
<uint32_t>(0x01, 0x02, 0x03, 0x04));
224 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN
? int64_t{0x0102030405060708}
225 : int64_t{0x0807060504030201},
226 TestEndianCreateValueFromBytes
<int64_t>(
227 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08));
228 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN
? uint64_t{0x0102030405060708}
229 : uint64_t{0x0807060504030201},
230 TestEndianCreateValueFromBytes
<uint64_t>(
231 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08));
233 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN
? int16_t{-0x5EFE} : int16_t{0x02A1},
234 TestEndianCreateValueFromBytes
<int16_t>(0xA1, 0x02));
236 HWY_IS_BIG_ENDIAN
? int32_t{-0x5E4D3CFC} : int32_t{0x04C3B2A1},
237 TestEndianCreateValueFromBytes
<int32_t>(0xA1, 0xB2, 0xC3, 0x04));
238 HWY_ASSERT_EQ(HWY_IS_BIG_ENDIAN
? int64_t{-0x6E5D4C3B2A1908F8}
239 : int64_t{0x08F7E6D5C4B3A291},
240 TestEndianCreateValueFromBytes
<int64_t>(
241 0x91, 0xA2, 0xB3, 0xC4, 0xD5, 0xE6, 0xF7, 0x08));
243 HWY_ASSERT_EQ(HWY_IS_LITTLE_ENDIAN
? int16_t{-0x5DFF} : int16_t{0x01A2},
244 TestEndianCreateValueFromBytes
<int16_t>(0x01, 0xA2));
246 HWY_IS_LITTLE_ENDIAN
? int32_t{-0x3B4C5DFF} : int32_t{0x01A2B3C4},
247 TestEndianCreateValueFromBytes
<int32_t>(0x01, 0xA2, 0xB3, 0xC4));
248 HWY_ASSERT_EQ(HWY_IS_LITTLE_ENDIAN
? int64_t{-0x0718293A4B5C6DFF}
249 : int64_t{0x0192A3B4C5D6E7F8},
250 TestEndianCreateValueFromBytes
<int64_t>(
251 0x01, 0x92, 0xA3, 0xB4, 0xC5, 0xD6, 0xE7, 0xF8));
253 #if HWY_IS_BIG_ENDIAN
255 TestEndianCreateValueFromBytes
<float>(0x3F, 0x80, 0x00, 0x00));
256 HWY_ASSERT_EQ(15922433.0f
,
257 TestEndianCreateValueFromBytes
<float>(0x4B, 0x72, 0xF5, 0x01));
258 HWY_ASSERT_EQ(-12357485.0f
,
259 TestEndianCreateValueFromBytes
<float>(0xCB, 0x3C, 0x8F, 0x6D));
262 TestEndianCreateValueFromBytes
<float>(0x00, 0x00, 0x80, 0x3F));
263 HWY_ASSERT_EQ(15922433.0f
,
264 TestEndianCreateValueFromBytes
<float>(0x01, 0xF5, 0x72, 0x4B));
265 HWY_ASSERT_EQ(-12357485.0f
,
266 TestEndianCreateValueFromBytes
<float>(0x6D, 0x8F, 0x3C, 0xCB));
270 #if HWY_IS_BIG_ENDIAN
271 HWY_ASSERT_EQ(1.0, TestEndianCreateValueFromBytes
<double>(
272 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
273 HWY_ASSERT_EQ(8707235690688195.0,
274 TestEndianCreateValueFromBytes
<double>(0x43, 0x3E, 0xEF, 0x2F,
275 0x4A, 0x51, 0xAE, 0xC3));
276 HWY_ASSERT_EQ(-6815854340348452.0,
277 TestEndianCreateValueFromBytes
<double>(0xC3, 0x38, 0x36, 0xFB,
278 0xC0, 0xCC, 0x1A, 0x24));
280 HWY_ASSERT_EQ(1.0, TestEndianCreateValueFromBytes
<double>(
281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F));
282 HWY_ASSERT_EQ(8707235690688195.0,
283 TestEndianCreateValueFromBytes
<double>(0xC3, 0xAE, 0x51, 0x4A,
284 0x2F, 0xEF, 0x3E, 0x43));
285 HWY_ASSERT_EQ(-6815854340348452.0,
286 TestEndianCreateValueFromBytes
<double>(0x24, 0x1A, 0xCC, 0xC0,
287 0xFB, 0x36, 0x38, 0xC3));
288 #endif // HWY_IS_BIG_ENDIAN
289 #endif // HWY_HAVE_FLOAT64
292 // NOLINTNEXTLINE(google-readability-namespace-comments)
293 } // namespace HWY_NAMESPACE
295 HWY_AFTER_NAMESPACE();
300 HWY_BEFORE_TEST(BaseTest
);
301 HWY_EXPORT_AND_TEST_P(BaseTest
, TestAllLimits
);
302 HWY_EXPORT_AND_TEST_P(BaseTest
, TestAllLowestHighest
);
303 HWY_EXPORT_AND_TEST_P(BaseTest
, TestAllType
);
304 HWY_EXPORT_AND_TEST_P(BaseTest
, TestAllIsSame
);
305 HWY_EXPORT_AND_TEST_P(BaseTest
, TestAllBitScan
);
306 HWY_EXPORT_AND_TEST_P(BaseTest
, TestAllPopCount
);
307 HWY_EXPORT_AND_TEST_P(BaseTest
, TestAllEndian
);