Bug 1882714 [wpt PR 44850] - Update wpt metadata, a=testonly
[gecko.git] / third_party / wasm2c / src / test-hexfloat.cc
blobd732c99202ed7eb36cec50ec6e36888c6d5dd8c2
1 /*
2 * Copyright 2016 WebAssembly Community Group participants
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.
17 #include <cstdio>
18 #include <thread>
19 #include <vector>
21 #include "gtest/gtest.h"
23 #include "wabt/literal.h"
25 #define FOREACH_UINT32_MULTIPLIER 1
27 #define FOREACH_UINT32(bits) \
28 uint32_t last_bits = 0; \
29 uint32_t bits = shard; \
30 int last_top_byte = -1; \
31 for (; bits >= last_bits; \
32 last_bits = bits, bits += num_threads_ * FOREACH_UINT32_MULTIPLIER)
34 #define LOG_COMPLETION(bits) \
35 if (shard == 0) { \
36 int top_byte = bits >> 24; \
37 if (top_byte != last_top_byte) { \
38 printf("value: 0x%08x (%d%%)\r", bits, \
39 static_cast<int>(static_cast<double>(bits) * 100 / UINT32_MAX)); \
40 fflush(stdout); \
41 last_top_byte = top_byte; \
42 } \
45 #define LOG_DONE() \
46 if (shard == 0) { \
47 printf("done.\n"); \
48 fflush(stdout); \
51 using namespace wabt;
53 template <typename T, typename F>
54 T bit_cast(F value) {
55 T result;
56 memcpy(&result, &value, sizeof(result));
57 return result;
60 static bool is_infinity_or_nan(uint32_t float_bits) {
61 return ((float_bits >> 23) & 0xff) == 0xff;
64 static bool is_infinity_or_nan(uint64_t double_bits) {
65 return ((double_bits >> 52) & 0x7ff) == 0x7ff;
68 class ThreadedTest : public ::testing::Test {
69 protected:
70 static constexpr int kDefaultNumThreads = 2;
72 virtual void SetUp() {
73 num_threads_ = std::thread::hardware_concurrency();
74 if (num_threads_ == 0)
75 num_threads_ = kDefaultNumThreads;
78 virtual void RunShard(int shard) = 0;
80 void RunThreads() {
81 std::vector<std::thread> threads;
83 for (int i = 0; i < num_threads_; ++i) {
84 threads.emplace_back(&ThreadedTest::RunShard, this, i);
87 for (std::thread& thread : threads) {
88 thread.join();
92 int num_threads_;
95 /* floats */
96 class AllFloatsParseTest : public ThreadedTest {
97 protected:
98 virtual void RunShard(int shard) {
99 char buffer[100];
100 FOREACH_UINT32(bits) {
101 LOG_COMPLETION(bits);
102 if (is_infinity_or_nan(bits))
103 continue;
105 float value = bit_cast<float>(bits);
106 int len = snprintf(buffer, sizeof(buffer), "%a", value);
108 uint32_t me;
109 ASSERT_EQ(Result::Ok,
110 ParseFloat(LiteralType::Hexfloat, buffer, buffer + len, &me));
111 ASSERT_EQ(me, bits);
113 LOG_DONE();
117 TEST_F(AllFloatsParseTest, Run) {
118 RunThreads();
121 class AllFloatsWriteTest : public ThreadedTest {
122 protected:
123 virtual void RunShard(int shard) {
124 char buffer[100];
125 FOREACH_UINT32(bits) {
126 LOG_COMPLETION(bits);
127 if (is_infinity_or_nan(bits))
128 continue;
130 WriteFloatHex(buffer, sizeof(buffer), bits);
132 char* endptr;
133 float them_float = strtof(buffer, &endptr);
134 uint32_t them_bits = bit_cast<uint32_t>(them_float);
135 ASSERT_EQ(bits, them_bits);
137 LOG_DONE();
141 TEST_F(AllFloatsWriteTest, Run) {
142 RunThreads();
145 class AllFloatsRoundtripTest : public ThreadedTest {
146 protected:
147 static LiteralType ClassifyFloat(uint32_t float_bits) {
148 if (is_infinity_or_nan(float_bits)) {
149 if (float_bits & 0x7fffff) {
150 return LiteralType::Nan;
151 } else {
152 return LiteralType::Infinity;
154 } else {
155 return LiteralType::Hexfloat;
159 virtual void RunShard(int shard) {
160 char buffer[100];
161 FOREACH_UINT32(bits) {
162 LOG_COMPLETION(bits);
163 WriteFloatHex(buffer, sizeof(buffer), bits);
164 int len = strlen(buffer);
166 uint32_t new_bits;
167 ASSERT_EQ(Result::Ok, ParseFloat(ClassifyFloat(bits), buffer,
168 buffer + len, &new_bits));
169 ASSERT_EQ(new_bits, bits);
171 LOG_DONE();
175 TEST_F(AllFloatsRoundtripTest, Run) {
176 RunThreads();
179 /* doubles */
180 class ManyDoublesParseTest : public ThreadedTest {
181 protected:
182 virtual void RunShard(int shard) {
183 char buffer[100];
184 FOREACH_UINT32(halfbits) {
185 LOG_COMPLETION(halfbits);
186 uint64_t bits = (static_cast<uint64_t>(halfbits) << 32) | halfbits;
187 if (is_infinity_or_nan(bits))
188 continue;
190 double value = bit_cast<double>(bits);
191 int len = snprintf(buffer, sizeof(buffer), "%a", value);
193 uint64_t me;
194 ASSERT_EQ(Result::Ok,
195 ParseDouble(LiteralType::Hexfloat, buffer, buffer + len, &me));
196 ASSERT_EQ(me, bits);
198 LOG_DONE();
202 TEST_F(ManyDoublesParseTest, Run) {
203 RunThreads();
206 class ManyDoublesWriteTest : public ThreadedTest {
207 protected:
208 virtual void RunShard(int shard) {
209 char buffer[100];
210 FOREACH_UINT32(halfbits) {
211 LOG_COMPLETION(halfbits);
212 uint64_t bits = (static_cast<uint64_t>(halfbits) << 32) | halfbits;
213 if (is_infinity_or_nan(bits))
214 continue;
216 WriteDoubleHex(buffer, sizeof(buffer), bits);
218 char* endptr;
219 double them_double = strtod(buffer, &endptr);
220 uint64_t them_bits = bit_cast<uint64_t>(them_double);
221 ASSERT_EQ(bits, them_bits);
223 LOG_DONE();
227 TEST_F(ManyDoublesWriteTest, Run) {
228 RunThreads();
231 class ManyDoublesRoundtripTest : public ThreadedTest {
232 protected:
233 static LiteralType ClassifyDouble(uint64_t double_bits) {
234 if (is_infinity_or_nan(double_bits)) {
235 if (double_bits & 0xfffffffffffffULL) {
236 return LiteralType::Nan;
237 } else {
238 return LiteralType::Infinity;
240 } else {
241 return LiteralType::Hexfloat;
245 virtual void RunShard(int shard) {
246 char buffer[100];
247 FOREACH_UINT32(halfbits) {
248 LOG_COMPLETION(halfbits);
249 uint64_t bits = (static_cast<uint64_t>(halfbits) << 32) | halfbits;
250 WriteDoubleHex(buffer, sizeof(buffer), bits);
251 int len = strlen(buffer);
253 uint64_t new_bits;
254 ASSERT_EQ(Result::Ok, ParseDouble(ClassifyDouble(bits), buffer,
255 buffer + len, &new_bits));
256 ASSERT_EQ(new_bits, bits);
258 LOG_DONE();
262 TEST_F(ManyDoublesRoundtripTest, Run) {
263 RunThreads();