summaryrefslogtreecommitdiff
path: root/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-06-12 15:52:02 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2019-06-12 15:52:02 +0100
commitcd0b94e650a880b2ab04922e476aa28007277d5c (patch)
tree392d0abf2fbedc380e69b203ddb9b74c775d072d /libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions
parentff7b3aa51f8edd24fdc599d9f95a5cbf61aeb76e (diff)
Replace std::to_string for integers with optimized version
The std::to_chars functions from C++17 can be used to implement std::to_string with much better performance than calling snprintf. Only the __detail::__to_chars_len and __detail::__to_chars_10 functions are needed for to_string, because it always outputs base 10 representations. The return type of __detail::__to_chars_10 should not be declared before C++17, so the function body is extracted into a new function that can be reused by to_string and __detail::__to_chars_10. The existing tests for to_chars rely on to_string to check for correct answers. Now that they use the same code that doesn't actually ensure correctness, so add new tests for std::to_string that compare against printf output. * include/Makefile.am: Add new <bits/charconv.h> header. * include/Makefile.in: Regenerate. * include/bits/basic_string.h (to_string(int), to_string(unsigned)) (to_string(long), to_string(unsigned long), to_string(long long)) (to_string(unsigned long long)): Rewrite to use __to_chars_10_impl. * include/bits/charconv.h: New header. (__detail::__to_chars_len): Move here from <charconv>. (__detail::__to_chars_10_impl): New function extracted from __detail::__to_chars_10. * include/std/charconv (__cpp_lib_to_chars): Add, but comment out. (__to_chars_unsigned_type): New class template that reuses __make_unsigned_selector_base::__select to pick a type. (__unsigned_least_t): Redefine as __to_chars_unsigned_type<T>::type. (__detail::__to_chars_len): Move to new header. (__detail::__to_chars_10): Add inline specifier. Move code doing the output to __detail::__to_chars_10_impl and call that. * include/std/version (__cpp_lib_to_chars): Add, but comment out. * testsuite/21_strings/basic_string/numeric_conversions/char/ to_string.cc: Fix reference in comment. Remove unused variable. * testsuite/21_strings/basic_string/numeric_conversions/char/ to_string_int.cc: New test. From-SVN: r272186
Diffstat (limited to 'libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions')
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string.cc4
-rw-r--r--libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_int.cc164
2 files changed, 165 insertions, 3 deletions
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string.cc b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string.cc
index 11cb7c8a451..a3dab3e54ac 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string.cc
@@ -20,7 +20,7 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-// 21.4 Numeric Conversions [string.conversions]
+// C++11 21.5 Numeric Conversions [string.conversions]
#include <string>
#include <testsuite_hooks.h>
@@ -28,7 +28,6 @@
void
test01()
{
- bool test = true;
using namespace std;
long long ll1 = -2;
@@ -59,5 +58,4 @@ test01()
int main()
{
test01();
- return 0;
}
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_int.cc b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_int.cc
new file mode 100644
index 00000000000..8eb2a48bd30
--- /dev/null
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/numeric_conversions/char/to_string_int.cc
@@ -0,0 +1,164 @@
+// { dg-options "-DSIMULATOR_TEST" { target simulator } }
+// { dg-do run { target c++11 } }
+
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// C++11 21.5 Numeric Conversions [string.conversions]
+
+#include <string>
+#include <limits>
+#include <cstdint>
+#include <cstdio>
+#include <testsuite_hooks.h>
+
+namespace test
+{
+static char buf[100];
+
+// Canonical version of std::to_string(int) as specified in the standard.
+static std::string to_string(int val)
+{
+ std::string str;
+ const int len = std::snprintf(buf, sizeof(buf), "%d", val);
+ VERIFY( len < (int)sizeof(buf) );
+ return std::string(buf, len);
+}
+
+static std::string to_string(unsigned int val)
+{
+ std::string str;
+ const int len = std::snprintf(buf, sizeof(buf), "%u", val);
+ VERIFY( len < (int)sizeof(buf) );
+ return std::string(buf, len);
+}
+
+static std::string to_string(long val)
+{
+ std::string str;
+ const int len = std::snprintf(buf, sizeof(buf), "%ld", val);
+ VERIFY( len < (int)sizeof(buf) );
+ return std::string(buf, len);
+}
+
+static std::string to_string(unsigned long val)
+{
+ std::string str;
+ const int len = std::snprintf(buf, sizeof(buf), "%lu", val);
+ VERIFY( len < (int)sizeof(buf) );
+ return std::string(buf, len);
+}
+
+static std::string to_string(long long val)
+{
+ std::string str;
+ const int len = std::snprintf(buf, sizeof(buf), "%lld", val);
+ VERIFY( len < (int)sizeof(buf) );
+ return std::string(buf, len);
+}
+
+static std::string to_string(unsigned long long val)
+{
+ std::string str;
+ const int len = std::snprintf(buf, sizeof(buf), "%llu", val);
+ VERIFY( len < (int)sizeof(buf) );
+ return std::string(buf, len);
+}
+
+} // namespace test
+
+const std::uint_least32_t values[] = {
+ 0x10, 0x30, 0x50, 0x80, 0xc0,
+ 0x100, 0x180, 0x1c0, 0x200, 0x400, 0x800, 0xc00,
+ 0x1000, 0x1800, 0x2000, 0x4000, 0x8000, 0xc000,
+ 0x10000, 0x10101, 0x80000, 0x80706, 0xc0000, 0xccccc,
+ 0x100000, 0x101010, 0x800000, 0x807060, 0xc0fefe, 0xc1d2e3f,
+ 0x1000000, 0x1001000, 0x1008000, 0x1010000, 0x1080000, 0x1100000, 0x1234567,
+ 0x10000000, 0x10101010, 0x12345678, 0x80000010, 0x87654321, 0xaaaaaaaa,
+ 0xf0000000, 0xf0101010, 0xf0f00000, 0xf0f0f0f0, 0xf0ff0ff0, 0xff0ff00f,
+ 0xffff0000, 0xffff00f0, 0xffff0ff0, 0xffffff00
+};
+
+const std::size_t empty_string_capacity = std::string().capacity();
+
+#include <set>
+
+template<typename T>
+ void check_value(T val)
+ {
+ const std::string s = std::to_string(val);
+ const std::string expected = test::to_string(val);
+ VERIFY( s == expected );
+ VERIFY( s[s.size()] == '\0' ); // null-terminator not overwritten!
+ if (s.size() > empty_string_capacity)
+ VERIFY( s.capacity() == s.size() ); // GNU-specific guarantee
+ }
+
+#ifdef SIMULATOR_TEST
+const int width = 3;
+#else
+const int width = 16;
+#endif
+
+template<typename T>
+ void check_values()
+ {
+#ifdef SIMULATOR_TEST
+ check_value((T)-1);
+ check_value((T)0);
+ check_value((T)+1);
+#endif
+
+ for (auto v : values)
+ {
+ for (int i = -width; i < +width; ++i)
+ {
+ const T val = (T)v + i;
+ check_value(val);
+ }
+
+ if (std::numeric_limits<T>::digits > 32)
+ {
+ for (auto v2 : values)
+ {
+ for (int i = -width; i < +width; ++i)
+ {
+ typename std::make_unsigned<T>::type hi = v2;
+ hi += i;
+ hi <<= 32;
+ const T val = T(hi) | v;
+ check_value(val);
+ }
+ }
+ }
+ }
+ }
+
+void test02()
+{
+ check_values<int>();
+ check_values<unsigned int>();
+ check_values<long>();
+ check_values<unsigned long>();
+ check_values<long long>();
+ check_values<unsigned long long>();
+}
+
+int main()
+{
+ test02();
+}