Patchwork abs(long long)

login
register
mail settings
Submitter Marc Glisse
Date Oct. 2, 2012, 8:45 a.m.
Message ID <alpine.DEB.2.02.1210021018570.5523@stedding.saclay.inria.fr>
Download mbox | patch
Permalink /patch/188428/
State New
Headers show

Comments

Marc Glisse - Oct. 2, 2012, 8:45 a.m.
Hello,

here is the patch from PR54686. Several notes:

* I'll have to ask experts if std::abs(unsigned) (yes, a weird thing to 
do, but still) is meant to return a double...
* I still don't like the configure-time _GLIBCXX_USE_INT128, I think it 
should use defined(__SIZEOF_INT128__), which would help other compilers.
* newlib has llabs, according to the doc. It would be good to know what 
newlib is missing for libstdc++ to detect it as C99-ready.

I tested a previous version (without __STRICT_ANSI__) on x86_64-linux-gnu 
and Oleg Endo did a basic check on sh/newlib. I'll do a last check after 
the review (no point if the patch needs changing again).

2012-10-02  Marc Glisse  <marc.glisse@inria.fr>

 	PR libstdc++/54686
 	* include/c_std/cstdlib (abs(long long)): Define fallback whenever
 	we have long long but possibly not llabs.
 	(abs(long long)): Use llabs when available.
 	(abs(__int128)): Define when we have __int128.
 	(div(long long, long long)): Use lldiv.
 	* testsuite/26_numerics/headers/cstdlib/54686.c: New file.

Patch

Index: include/c_std/cstdlib

===================================================================
--- include/c_std/cstdlib	(revision 191941)

+++ include/c_std/cstdlib	(working copy)

@@ -130,20 +130,32 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION

   using ::strtoul;
   using ::system;
 #ifdef _GLIBCXX_USE_WCHAR_T
   using ::wcstombs;
   using ::wctomb;
 #endif // _GLIBCXX_USE_WCHAR_T
 
   inline long
   abs(long __i) { return labs(__i); }
 
+#if defined (_GLIBCXX_USE_LONG_LONG) \

+    && (!_GLIBCXX_USE_C99 || _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC)

+  // Fallback version if we don't have llabs but still allow long long.

+  inline long long

+  abs(long long __x) { return __x >= 0 ? __x : -__x; }

+#endif

+

+#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_INT128)

+  inline __int128

+  abs(__int128 __x) { return __x >= 0 ? __x : -__x; }

+#endif

+

   inline ldiv_t
   div(long __i, long __j) { return ldiv(__i, __j); }
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
 #if _GLIBCXX_USE_C99
 
 #undef _Exit
 #undef llabs
@@ -161,29 +173,29 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION

 #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
   using ::lldiv_t;
 #endif
 #if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC
   extern "C" void (_Exit)(int) throw () _GLIBCXX_NORETURN;
 #endif
 #if !_GLIBCXX_USE_C99_DYNAMIC
   using ::_Exit;
 #endif
 
+#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC

   inline long long
-  abs(long long __x) { return __x >= 0 ? __x : -__x; }

+  abs(long long __x) { return ::llabs (__x); }

 
-#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC

   using ::llabs;
 
   inline lldiv_t
   div(long long __n, long long __d)
-  { lldiv_t __q; __q.quot = __n / __d; __q.rem = __n % __d; return __q; }

+  { return ::lldiv (__n, __d); }

 
   using ::lldiv;
 #endif
 
 #if _GLIBCXX_USE_C99_LONG_LONG_CHECK || _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
   extern "C" long long int (atoll)(const char *) throw ();
   extern "C" long long int
     (strtoll)(const char * __restrict, char ** __restrict, int) throw ();
   extern "C" unsigned long long int
     (strtoull)(const char * __restrict, char ** __restrict, int) throw ();
@@ -198,22 +210,22 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION

 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace __gnu_cxx
 
 namespace std
 {
 #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
   using ::__gnu_cxx::lldiv_t;
 #endif
   using ::__gnu_cxx::_Exit;
-  using ::__gnu_cxx::abs;

 #if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC
+  using ::__gnu_cxx::abs;

   using ::__gnu_cxx::llabs;
   using ::__gnu_cxx::div;
   using ::__gnu_cxx::lldiv;
 #endif
   using ::__gnu_cxx::atoll;
   using ::__gnu_cxx::strtof;
   using ::__gnu_cxx::strtoll;
   using ::__gnu_cxx::strtoull;
   using ::__gnu_cxx::strtold;
 } // namespace std
Index: testsuite/26_numerics/headers/cstdlib/54686.c

===================================================================
--- testsuite/26_numerics/headers/cstdlib/54686.c	(revision 0)

+++ testsuite/26_numerics/headers/cstdlib/54686.c	(revision 0)

@@ -0,0 +1,32 @@ 

+// { dg-do compile }

+// { dg-options "-std=c++11" }

+

+// Copyright (C) 2012 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/>.

+

+#include <cmath>

+#include <cstdlib>

+#include <type_traits>

+#include <utility>

+

+#ifdef _GLIBCXX_USE_LONG_LONG

+void test01()

+{

+  static_assert (std::is_same<decltype (std::abs (std::declval<long long> ())),

+			      long long>::value, "Missing abs(long long)");

+}

+#endif