Export of internal Abseil changes

--
f34cd235a12ad0ee1fea3a1ee5a427272dc2b285 by Abseil Team <absl-team@google.com>:

Migrates uses of deprecated map types to recommended types.

PiperOrigin-RevId: 309945156

--
e3410a47ad32c0775b6911610bc47b22938decad by Matthew Brown <matthewbr@google.com>:

Internal Change

PiperOrigin-RevId: 309856021

--
a58cfa25e0bb59e7fa9647ac1aae65eaccff0086 by Greg Falcon <gfalcon@google.com>:

Internal change.

PiperOrigin-RevId: 309804612

--
cdc5ec310035fbe25f496bda283fe655d94d7769 by Mark Barolak <mbar@google.com>:

Standardize the header comments for friend functions in cord.h

PiperOrigin-RevId: 309779073

--
fe61602701be795e54477b0fdbf5ffc1df12a6b7 by Samuel Benzaquen <sbenza@google.com>:

Implement %f natively for any input.
It evaluates the input at runtime and allocates stack space accordingly.

This removes a potential fallback into snprintf, improves performance, and removes all memory allocations in this formatting path.

PiperOrigin-RevId: 309752501

--
79e2a24f3f959e8b06ddf1d440bbabbd5f89b5b7 by Greg Falcon <gfalcon@google.com>:

Add a Cord::swap() method.  Many other Abseil types already provide this, but it was missing here.

We already provided a two-argument free function form of `swap()`, but that API is better suited for generic code.  The swap member function is a better API when the types are known.

PiperOrigin-RevId: 309751740

--
85cdf60024f153fb4fcb7fe68ed2b14b9faf119d by Derek Mauro <dmauro@google.com>:

Cleanup uses of "linker initialized" SpinLocks

PiperOrigin-RevId: 309581867

--
9e5443bfcec4b94056b13c75326576e987ab88fb by Matt Kulukundis <kfm@google.com>:

Clarify intended mixing properties of `absl::Hash`

PiperOrigin-RevId: 309520174

--
a0630f0827b67f217aaeae68a448fe4c1101e17d by Greg Falcon <gfalcon@google.com>:

Comment out a test in Emscripten to sidestep `long double` issues.

PiperOrigin-RevId: 309482953
GitOrigin-RevId: f34cd235a12ad0ee1fea3a1ee5a427272dc2b285
Change-Id: Icce0c9d547117374d596b9d684e4054ddd118669
This commit is contained in:
Abseil Team 2020-05-05 07:54:14 -07:00 committed by vslashg
parent a1d6689907
commit d85783fd0b
24 changed files with 1112 additions and 197 deletions

View file

@ -1,14 +1,18 @@
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <cctype>
#include <cmath>
#include <limits>
#include <string>
#include <thread> // NOLINT
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/base/internal/raw_logging.h"
#include "absl/strings/internal/str_format/bind.h"
#include "absl/types/optional.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@ -57,7 +61,7 @@ std::string Esc(const T &v) {
return oss.str();
}
void StrAppend(std::string *dst, const char *format, va_list ap) {
void StrAppendV(std::string *dst, const char *format, va_list ap) {
// First try with a small fixed size buffer
static const int kSpaceLength = 1024;
char space[kSpaceLength];
@ -98,11 +102,18 @@ void StrAppend(std::string *dst, const char *format, va_list ap) {
delete[] buf;
}
void StrAppend(std::string *out, const char *format, ...) {
va_list ap;
va_start(ap, format);
StrAppendV(out, format, ap);
va_end(ap);
}
std::string StrPrint(const char *format, ...) {
va_list ap;
va_start(ap, format);
std::string result;
StrAppend(&result, format, ap);
StrAppendV(&result, format, ap);
va_end(ap);
return result;
}
@ -471,8 +482,8 @@ TEST_F(FormatConvertTest, Float) {
#endif // _MSC_VER
const char *const kFormats[] = {
"%", "%.3", "%8.5", "%9", "%.60", "%.30", "%03", "%+",
"% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"};
"%", "%.3", "%8.5", "%500", "%.5000", "%.60", "%.30", "%03",
"%+", "% ", "%-10", "%#15.3", "%#.0", "%.0", "%1$*2$", "%1$.*2$"};
std::vector<double> doubles = {0.0,
-0.0,
@ -489,11 +500,6 @@ TEST_F(FormatConvertTest, Float) {
std::numeric_limits<double>::infinity(),
-std::numeric_limits<double>::infinity()};
#ifndef __APPLE__
// Apple formats NaN differently (+nan) vs. (nan)
doubles.push_back(std::nan(""));
#endif
// Some regression tests.
doubles.push_back(0.99999999999999989);
@ -512,43 +518,204 @@ TEST_F(FormatConvertTest, Float) {
}
}
// Workaround libc bug.
// https://sourceware.org/bugzilla/show_bug.cgi?id=22142
const bool gcc_bug_22142 =
StrPrint("%f", std::numeric_limits<double>::max()) !=
"1797693134862315708145274237317043567980705675258449965989174768031"
"5726078002853876058955863276687817154045895351438246423432132688946"
"4182768467546703537516986049910576551282076245490090389328944075868"
"5084551339423045832369032229481658085593321233482747978262041447231"
"68738177180919299881250404026184124858368.000000";
if (!gcc_bug_22142) {
for (int exp = -300; exp <= 300; ++exp) {
const double all_ones_mantissa = 0x1fffffffffffff;
doubles.push_back(std::ldexp(all_ones_mantissa, exp));
}
}
if (gcc_bug_22142) {
for (auto &d : doubles) {
using L = std::numeric_limits<double>;
double d2 = std::abs(d);
if (d2 == L::max() || d2 == L::min() || d2 == L::denorm_min()) {
d = 0;
}
}
}
// Remove duplicates to speed up the logic below.
std::sort(doubles.begin(), doubles.end());
doubles.erase(std::unique(doubles.begin(), doubles.end()), doubles.end());
#ifndef __APPLE__
// Apple formats NaN differently (+nan) vs. (nan)
doubles.push_back(std::nan(""));
#endif
// Reserve the space to ensure we don't allocate memory in the output itself.
std::string str_format_result;
str_format_result.reserve(1 << 20);
std::string string_printf_result;
string_printf_result.reserve(1 << 20);
for (const char *fmt : kFormats) {
for (char f : {'f', 'F', //
'g', 'G', //
'a', 'A', //
'e', 'E'}) {
std::string fmt_str = std::string(fmt) + f;
if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') {
// This particular test takes way too long with snprintf.
// Disable for the case we are not implementing natively.
continue;
}
for (double d : doubles) {
int i = -10;
FormatArgImpl args[2] = {FormatArgImpl(d), FormatArgImpl(i)};
UntypedFormatSpecImpl format(fmt_str);
// We use ASSERT_EQ here because failures are usually correlated and a
// bug would print way too many failed expectations causing the test to
// time out.
ASSERT_EQ(StrPrint(fmt_str.c_str(), d, i),
FormatPack(format, absl::MakeSpan(args)))
<< fmt_str << " " << StrPrint("%.18g", d) << " "
<< StrPrint("%.999f", d);
string_printf_result.clear();
StrAppend(&string_printf_result, fmt_str.c_str(), d, i);
str_format_result.clear();
{
AppendPack(&str_format_result, format, absl::MakeSpan(args));
}
if (string_printf_result != str_format_result) {
// We use ASSERT_EQ here because failures are usually correlated and a
// bug would print way too many failed expectations causing the test
// to time out.
ASSERT_EQ(string_printf_result, str_format_result)
<< fmt_str << " " << StrPrint("%.18g", d) << " "
<< StrPrint("%a", d) << " " << StrPrint("%.1080f", d);
}
}
}
}
}
TEST_F(FormatConvertTest, LongDouble) {
const char *const kFormats[] = {"%", "%.3", "%8.5", "%9",
"%.60", "%+", "% ", "%-10"};
TEST_F(FormatConvertTest, FloatRound) {
std::string s;
const auto format = [&](const char *fmt, double d) -> std::string & {
s.clear();
FormatArgImpl args[1] = {FormatArgImpl(d)};
AppendPack(&s, UntypedFormatSpecImpl(fmt), absl::MakeSpan(args));
#if !defined(_MSC_VER)
// MSVC has a different rounding policy than us so we can't test our
// implementation against the native one there.
EXPECT_EQ(StrPrint(fmt, d), s);
#endif // _MSC_VER
// This value is not representable in double, but it is in long double that
// uses the extended format.
// This is to verify that we are not truncating the value mistakenly through a
// double.
long double very_precise = 10000000000000000.25L;
return s;
};
// All of these values have to be exactly represented.
// Otherwise we might not be testing what we think we are testing.
// These values can fit in a 64bit "fast" representation.
const double exact_value = 0.00000000000005684341886080801486968994140625;
assert(exact_value == std::pow(2, -44));
// Round up at a 5xx.
EXPECT_EQ(format("%.13f", exact_value), "0.0000000000001");
// Round up at a >5
EXPECT_EQ(format("%.14f", exact_value), "0.00000000000006");
// Round down at a <5
EXPECT_EQ(format("%.16f", exact_value), "0.0000000000000568");
// Nine handling
EXPECT_EQ(format("%.35f", exact_value),
"0.00000000000005684341886080801486969");
EXPECT_EQ(format("%.36f", exact_value),
"0.000000000000056843418860808014869690");
// Round down the last nine.
EXPECT_EQ(format("%.37f", exact_value),
"0.0000000000000568434188608080148696899");
EXPECT_EQ(format("%.10f", 0.000003814697265625), "0.0000038147");
// Round up the last nine
EXPECT_EQ(format("%.11f", 0.000003814697265625), "0.00000381470");
EXPECT_EQ(format("%.12f", 0.000003814697265625), "0.000003814697");
// Round to even (down)
EXPECT_EQ(format("%.43f", exact_value),
"0.0000000000000568434188608080148696899414062");
// Exact
EXPECT_EQ(format("%.44f", exact_value),
"0.00000000000005684341886080801486968994140625");
// Round to even (up), let make the last digits 75 instead of 25
EXPECT_EQ(format("%.43f", exact_value + std::pow(2, -43)),
"0.0000000000001705302565824240446090698242188");
// Exact, just to check.
EXPECT_EQ(format("%.44f", exact_value + std::pow(2, -43)),
"0.00000000000017053025658242404460906982421875");
// This value has to be small enough that it won't fit in the uint128
// representation for printing.
const double small_exact_value =
0.000000000000000000000000000000000000752316384526264005099991383822237233803945956334136013765601092018187046051025390625; // NOLINT
assert(small_exact_value == std::pow(2, -120));
// Round up at a 5xx.
EXPECT_EQ(format("%.37f", small_exact_value),
"0.0000000000000000000000000000000000008");
// Round down at a <5
EXPECT_EQ(format("%.38f", small_exact_value),
"0.00000000000000000000000000000000000075");
// Round up at a >5
EXPECT_EQ(format("%.41f", small_exact_value),
"0.00000000000000000000000000000000000075232");
// Nine handling
EXPECT_EQ(format("%.55f", small_exact_value),
"0.0000000000000000000000000000000000007523163845262640051");
EXPECT_EQ(format("%.56f", small_exact_value),
"0.00000000000000000000000000000000000075231638452626400510");
EXPECT_EQ(format("%.57f", small_exact_value),
"0.000000000000000000000000000000000000752316384526264005100");
EXPECT_EQ(format("%.58f", small_exact_value),
"0.0000000000000000000000000000000000007523163845262640051000");
// Round down the last nine
EXPECT_EQ(format("%.59f", small_exact_value),
"0.00000000000000000000000000000000000075231638452626400509999");
// Round up the last nine
EXPECT_EQ(format("%.79f", small_exact_value),
"0.000000000000000000000000000000000000"
"7523163845262640050999913838222372338039460");
// Round to even (down)
EXPECT_EQ(format("%.119f", small_exact_value),
"0.000000000000000000000000000000000000"
"75231638452626400509999138382223723380"
"394595633413601376560109201818704605102539062");
// Exact
EXPECT_EQ(format("%.120f", small_exact_value),
"0.000000000000000000000000000000000000"
"75231638452626400509999138382223723380"
"3945956334136013765601092018187046051025390625");
// Round to even (up), let make the last digits 75 instead of 25
EXPECT_EQ(format("%.119f", small_exact_value + std::pow(2, -119)),
"0.000000000000000000000000000000000002"
"25694915357879201529997415146671170141"
"183786900240804129680327605456113815307617188");
// Exact, just to check.
EXPECT_EQ(format("%.120f", small_exact_value + std::pow(2, -119)),
"0.000000000000000000000000000000000002"
"25694915357879201529997415146671170141"
"1837869002408041296803276054561138153076171875");
}
TEST_F(FormatConvertTest, LongDouble) {
#ifdef _MSC_VER
// MSVC has a different rounding policy than us so we can't test our
// implementation against the native one there.
return;
#endif // _MSC_VER
const char *const kFormats[] = {"%", "%.3", "%8.5", "%9", "%.5000",
"%.60", "%+", "% ", "%-10"};
std::vector<long double> doubles = {
0.0,
-0.0,
very_precise,
1 / very_precise,
std::numeric_limits<long double>::max(),
-std::numeric_limits<long double>::max(),
std::numeric_limits<long double>::min(),
@ -556,22 +723,44 @@ TEST_F(FormatConvertTest, LongDouble) {
std::numeric_limits<long double>::infinity(),
-std::numeric_limits<long double>::infinity()};
for (long double base : {1.L, 12.L, 123.L, 1234.L, 12345.L, 123456.L,
1234567.L, 12345678.L, 123456789.L, 1234567890.L,
12345678901.L, 123456789012.L, 1234567890123.L,
// This value is not representable in double, but it
// is in long double that uses the extended format.
// This is to verify that we are not truncating the
// value mistakenly through a double.
10000000000000000.25L}) {
for (int exp : {-1000, -500, 0, 500, 1000}) {
for (int sign : {1, -1}) {
doubles.push_back(sign * std::ldexp(base, exp));
doubles.push_back(sign / std::ldexp(base, exp));
}
}
}
for (const char *fmt : kFormats) {
for (char f : {'f', 'F', //
'g', 'G', //
'a', 'A', //
'e', 'E'}) {
std::string fmt_str = std::string(fmt) + 'L' + f;
if (fmt == absl::string_view("%.5000") && f != 'f' && f != 'F') {
// This particular test takes way too long with snprintf.
// Disable for the case we are not implementing natively.
continue;
}
for (auto d : doubles) {
FormatArgImpl arg(d);
UntypedFormatSpecImpl format(fmt_str);
// We use ASSERT_EQ here because failures are usually correlated and a
// bug would print way too many failed expectations causing the test to
// time out.
ASSERT_EQ(StrPrint(fmt_str.c_str(), d),
FormatPack(format, {&arg, 1}))
ASSERT_EQ(StrPrint(fmt_str.c_str(), d), FormatPack(format, {&arg, 1}))
<< fmt_str << " " << StrPrint("%.18Lg", d) << " "
<< StrPrint("%.999Lf", d);
<< StrPrint("%La", d) << " " << StrPrint("%.1080Lf", d);
}
}
}