abseil-cpp/absl/random/internal/iostream_state_saver_test.cc
Go to the documentation of this file.
1 // Copyright 2017 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "absl/random/internal/iostream_state_saver.h"
16 
17 #include <errno.h>
18 #include <stdio.h>
19 
20 #include <sstream>
21 #include <string>
22 
23 #include "gtest/gtest.h"
24 
25 namespace {
26 
30 
31 template <typename T>
33 StreamRoundTrip(T t) {
34  std::stringstream ss;
35  {
36  auto saver = make_ostream_state_saver(ss);
37  ss.precision(stream_precision_helper<T>::kPrecision);
38  ss << t;
39  }
40  T result = 0;
41  {
42  auto saver = make_istream_state_saver(ss);
43  ss >> result;
44  }
45  EXPECT_FALSE(ss.fail()) //
46  << ss.str() << " " //
47  << (ss.good() ? "good " : "") //
48  << (ss.bad() ? "bad " : "") //
49  << (ss.eof() ? "eof " : "") //
50  << (ss.fail() ? "fail " : "");
51 
52  return result;
53 }
54 
55 template <typename T>
57 StreamRoundTrip(T t) {
58  std::stringstream ss;
59  {
60  auto saver = make_ostream_state_saver(ss);
61  ss.precision(stream_precision_helper<T>::kPrecision);
62  ss << t;
63  }
64  T result = 0;
65  {
66  auto saver = make_istream_state_saver(ss);
67  result = absl::random_internal::read_floating_point<T>(ss);
68  }
69  EXPECT_FALSE(ss.fail()) //
70  << ss.str() << " " //
71  << (ss.good() ? "good " : "") //
72  << (ss.bad() ? "bad " : "") //
73  << (ss.eof() ? "eof " : "") //
74  << (ss.fail() ? "fail " : "");
75 
76  return result;
77 }
78 
79 TEST(IOStreamStateSaver, BasicSaverState) {
80  std::stringstream ss;
81  ss.precision(2);
82  ss.fill('x');
83  ss.flags(std::ios_base::dec | std::ios_base::right);
84 
85  {
86  auto saver = make_ostream_state_saver(ss);
87  ss.precision(10);
88  EXPECT_NE('x', ss.fill());
89  EXPECT_EQ(10, ss.precision());
90  EXPECT_NE(std::ios_base::dec | std::ios_base::right, ss.flags());
91 
92  ss << 1.23;
93  }
94 
95  EXPECT_EQ('x', ss.fill());
96  EXPECT_EQ(2, ss.precision());
97  EXPECT_EQ(std::ios_base::dec | std::ios_base::right, ss.flags());
98 }
99 
100 TEST(IOStreamStateSaver, RoundTripInts) {
101  const uint64_t kUintValues[] = {
102  0,
103  1,
104  static_cast<uint64_t>(-1),
105  2,
106  static_cast<uint64_t>(-2),
107 
108  1 << 7,
109  1 << 8,
110  1 << 16,
111  1ull << 32,
112  1ull << 50,
113  1ull << 62,
114  1ull << 63,
115 
116  (1 << 7) - 1,
117  (1 << 8) - 1,
118  (1 << 16) - 1,
119  (1ull << 32) - 1,
120  (1ull << 50) - 1,
121  (1ull << 62) - 1,
122  (1ull << 63) - 1,
123 
124  static_cast<uint64_t>(-(1 << 8)),
125  static_cast<uint64_t>(-(1 << 16)),
126  static_cast<uint64_t>(-(1ll << 32)),
127  static_cast<uint64_t>(-(1ll << 50)),
128  static_cast<uint64_t>(-(1ll << 62)),
129 
130  static_cast<uint64_t>(-(1 << 8) - 1),
131  static_cast<uint64_t>(-(1 << 16) - 1),
132  static_cast<uint64_t>(-(1ll << 32) - 1),
133  static_cast<uint64_t>(-(1ll << 50) - 1),
134  static_cast<uint64_t>(-(1ll << 62) - 1),
135  };
136 
137  for (const uint64_t u : kUintValues) {
138  EXPECT_EQ(u, StreamRoundTrip<uint64_t>(u));
139 
140  int64_t x = static_cast<int64_t>(u);
141  EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
142 
143  double d = static_cast<double>(x);
144  EXPECT_EQ(d, StreamRoundTrip<double>(d));
145 
146  float f = d;
147  EXPECT_EQ(f, StreamRoundTrip<float>(f));
148  }
149 }
150 
151 TEST(IOStreamStateSaver, RoundTripFloats) {
152  static_assert(
153  stream_precision_helper<float>::kPrecision >= 9,
154  "stream_precision_helper<float>::kPrecision should be at least 9");
155 
156  const float kValues[] = {
157  1,
158  std::nextafter(1.0f, 0.0f), // 1 - epsilon
159  std::nextafter(1.0f, 2.0f), // 1 + epsilon
160 
161  1.0e+1f,
162  1.0e-1f,
163  1.0e+2f,
164  1.0e-2f,
165  1.0e+10f,
166  1.0e-10f,
167 
168  0.00000051110000111311111111f,
169  -0.00000051110000111211111111f,
170 
171  1.234678912345678912345e+6f,
172  1.234678912345678912345e-6f,
173  1.234678912345678912345e+30f,
174  1.234678912345678912345e-30f,
175  1.234678912345678912345e+38f,
176  1.0234678912345678912345e-38f,
177 
178  // Boundary cases.
180  std::numeric_limits<float>::lowest(),
181  std::numeric_limits<float>::epsilon(),
182  std::nextafter(std::numeric_limits<float>::min(),
183  1.0f), // min + epsilon
184  std::numeric_limits<float>::min(), // smallest normal
185  // There are some errors dealing with denorms on apple platforms.
186  std::numeric_limits<float>::denorm_min(), // smallest denorm
188  std::nextafter(std::numeric_limits<float>::min(),
189  0.0f), // denorm_max
190  std::nextafter(std::numeric_limits<float>::denorm_min(), 1.0f),
191  };
192 
193  for (const float f : kValues) {
194  EXPECT_EQ(f, StreamRoundTrip<float>(f));
195  EXPECT_EQ(-f, StreamRoundTrip<float>(-f));
196 
197  double d = f;
198  EXPECT_EQ(d, StreamRoundTrip<double>(d));
199  EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
200 
201  // Avoid undefined behavior (overflow/underflow).
202  if (f <= static_cast<float>(std::numeric_limits<int64_t>::max()) &&
203  f >= static_cast<float>(std::numeric_limits<int64_t>::lowest())) {
204  int64_t x = static_cast<int64_t>(f);
205  EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
206  }
207  }
208 }
209 
210 TEST(IOStreamStateSaver, RoundTripDoubles) {
211  static_assert(
212  stream_precision_helper<double>::kPrecision >= 17,
213  "stream_precision_helper<double>::kPrecision should be at least 17");
214 
215  const double kValues[] = {
216  1,
217  std::nextafter(1.0, 0.0), // 1 - epsilon
218  std::nextafter(1.0, 2.0), // 1 + epsilon
219 
220  1.0e+1,
221  1.0e-1,
222  1.0e+2,
223  1.0e-2,
224  1.0e+10,
225  1.0e-10,
226 
227  0.00000051110000111311111111,
228  -0.00000051110000111211111111,
229 
230  1.234678912345678912345e+6,
231  1.234678912345678912345e-6,
232  1.234678912345678912345e+30,
233  1.234678912345678912345e-30,
234  1.234678912345678912345e+38,
235  1.0234678912345678912345e-38,
236 
237  1.0e+100,
238  1.0e-100,
239  1.234678912345678912345e+308,
240  1.0234678912345678912345e-308,
241  2.22507385850720138e-308,
242 
243  // Boundary cases.
245  std::numeric_limits<double>::lowest(),
246  std::numeric_limits<double>::epsilon(),
247  std::nextafter(std::numeric_limits<double>::min(),
248  1.0), // min + epsilon
249  std::numeric_limits<double>::min(), // smallest normal
250  // There are some errors dealing with denorms on apple platforms.
251  std::numeric_limits<double>::denorm_min(), // smallest denorm
253  std::nextafter(std::numeric_limits<double>::min(),
254  0.0), // denorm_max
255  std::nextafter(std::numeric_limits<double>::denorm_min(), 1.0f),
256  };
257 
258  for (const double d : kValues) {
259  EXPECT_EQ(d, StreamRoundTrip<double>(d));
260  EXPECT_EQ(-d, StreamRoundTrip<double>(-d));
261 
262  // Avoid undefined behavior (overflow/underflow).
264  d >= std::numeric_limits<float>::lowest()) {
265  float f = static_cast<float>(d);
266  EXPECT_EQ(f, StreamRoundTrip<float>(f));
267  }
268 
269  // Avoid undefined behavior (overflow/underflow).
270  if (d <= static_cast<double>(std::numeric_limits<int64_t>::max()) &&
271  d >= static_cast<double>(std::numeric_limits<int64_t>::lowest())) {
272  int64_t x = static_cast<int64_t>(d);
273  EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
274  }
275  }
276 }
277 
278 TEST(IOStreamStateSaver, RoundTripLongDoubles) {
279  // Technically, C++ only guarantees that long double is at least as large as a
280  // double. Practically it varies from 64-bits to 128-bits.
281  //
282  // So it is best to consider long double a best-effort extended precision
283  // type.
284 
285  static_assert(
286  stream_precision_helper<long double>::kPrecision >= 36,
287  "stream_precision_helper<long double>::kPrecision should be at least 36");
288 
289  using real_type = long double;
290  const real_type kValues[] = {
291  1,
292  std::nextafter(1.0, 0.0), // 1 - epsilon
293  std::nextafter(1.0, 2.0), // 1 + epsilon
294 
295  1.0e+1,
296  1.0e-1,
297  1.0e+2,
298  1.0e-2,
299  1.0e+10,
300  1.0e-10,
301 
302  0.00000051110000111311111111,
303  -0.00000051110000111211111111,
304 
305  1.2346789123456789123456789123456789e+6,
306  1.2346789123456789123456789123456789e-6,
307  1.2346789123456789123456789123456789e+30,
308  1.2346789123456789123456789123456789e-30,
309  1.2346789123456789123456789123456789e+38,
310  1.2346789123456789123456789123456789e-38,
311  1.2346789123456789123456789123456789e+308,
312  1.2346789123456789123456789123456789e-308,
313 
314  1.0e+100,
315  1.0e-100,
316  1.234678912345678912345e+308,
317  1.0234678912345678912345e-308,
318 
319  // Boundary cases.
321  std::numeric_limits<real_type>::lowest(),
322  std::numeric_limits<real_type>::epsilon(),
323  std::nextafter(std::numeric_limits<real_type>::min(),
324  real_type(1)), // min + epsilon
325  std::numeric_limits<real_type>::min(), // smallest normal
326  // There are some errors dealing with denorms on apple platforms.
327  std::numeric_limits<real_type>::denorm_min(), // smallest denorm
329  std::nextafter(std::numeric_limits<real_type>::min(),
330  0.0), // denorm_max
331  std::nextafter(std::numeric_limits<real_type>::denorm_min(), 1.0f),
332  };
333 
334  int index = -1;
335  for (const long double dd : kValues) {
336  index++;
337  EXPECT_EQ(dd, StreamRoundTrip<real_type>(dd)) << index;
338  EXPECT_EQ(-dd, StreamRoundTrip<real_type>(-dd)) << index;
339 
340  // Avoid undefined behavior (overflow/underflow).
341  if (dd <= std::numeric_limits<double>::max() &&
342  dd >= std::numeric_limits<double>::lowest()) {
343  double d = static_cast<double>(dd);
344  EXPECT_EQ(d, StreamRoundTrip<double>(d));
345  }
346 
347  // Avoid undefined behavior (overflow/underflow).
348  if (dd <= std::numeric_limits<int64_t>::max() &&
349  dd >= std::numeric_limits<int64_t>::lowest()) {
350  int64_t x = static_cast<int64_t>(dd);
351  EXPECT_EQ(x, StreamRoundTrip<int64_t>(x));
352  }
353  }
354 }
355 
356 TEST(StrToDTest, DoubleMin) {
357  const char kV[] = "2.22507385850720138e-308";
358  char* end;
359  double x = std::strtod(kV, &end);
361  // errno may equal ERANGE.
362 }
363 
364 TEST(StrToDTest, DoubleDenormMin) {
365  const char kV[] = "4.94065645841246544e-324";
366  char* end;
367  double x = std::strtod(kV, &end);
368  EXPECT_EQ(std::numeric_limits<double>::denorm_min(), x);
369  // errno may equal ERANGE.
370 }
371 
372 } // namespace
EXPECT_FALSE
#define EXPECT_FALSE(condition)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:1970
_gevent_test_main.result
result
Definition: _gevent_test_main.py:96
absl::random_internal::make_istream_state_saver
istream_state_saver< std::basic_istream< CharT, Traits > > make_istream_state_saver(std::basic_istream< CharT, Traits > &is, std::ios_base::fmtflags flags=std::ios_base::dec|std::ios_base::scientific|std::ios_base::skipws)
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:149
google::protobuf.internal::real_type
FieldDescriptor::Type real_type(FieldType type)
Definition: bloaty/third_party/protobuf/src/google/protobuf/extension_set_heavy.cc:128
u
OPENSSL_EXPORT pem_password_cb void * u
Definition: pem.h:351
absl::enable_if_t
typename std::enable_if< B, T >::type enable_if_t
Definition: abseil-cpp/absl/meta/type_traits.h:631
T
#define T(upbtypeconst, upbtype, ctype, default_value)
EXPECT_EQ
#define EXPECT_EQ(a, b)
Definition: iomgr/time_averaged_stats_test.cc:27
autogen_x86imm.f
f
Definition: autogen_x86imm.py:9
end
char * end
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1008
int64_t
signed __int64 int64_t
Definition: stdint-msvc2008.h:89
TEST
#define TEST(name, init_size,...)
Definition: arena_test.cc:75
max
int max
Definition: bloaty/third_party/zlib/examples/enough.c:170
EXPECT_NE
#define EXPECT_NE(val1, val2)
Definition: bloaty/third_party/googletest/googletest/include/gtest/gtest.h:2028
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
min
#define min(a, b)
Definition: qsort.h:83
d
static const fe d
Definition: curve25519_tables.h:19
absl::random_internal::stream_precision_helper
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:107
absl::str_format_internal::LengthMod::t
@ t
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
absl::random_internal::make_ostream_state_saver
ostream_state_saver< std::basic_ostream< CharT, Traits > > make_ostream_state_saver(std::basic_ostream< CharT, Traits > &os, std::ios_base::fmtflags flags=std::ios_base::dec|std::ios_base::left|std::ios_base::scientific)
Definition: abseil-cpp/absl/random/internal/iostream_state_saver.h:82
errno.h


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:08