libm lacks C99 functions -> no c++11 cmath in libstdc++

From: Dmitry Marakasov <amdmi3_at_amdmi3.ru>
Date: Wed, 29 Jan 2014 20:41:36 +0400
Hi!

Gerald haven't responded yet, so I though I'd better post in on the
list as well for wider discussion.

In short:
- our libm lacks some C99 functions: erfl erfcl lgammal tgammal
- bad enough by itself, it affects libstdc++ from ports' gcc in such a
  way that it disables C++11 math completely (along with a lot more
  other more widely used math functions)
- we may probably implement these by calling less-precise
  erf erfc lgamma tgamma as we do with other functions as we alredy
  do with some others

----- Forwarded message from Dmitry Marakasov <amdmi3_at_hades.panopticon> -----

Date: Tue, 21 Jan 2014 19:13:07 +0400
From: Dmitry Marakasov <amdmi3_at_hades.panopticon>
To: gerald_at_FreeBSD.org
Subject: libstdc++ from ports' gcc's and cmath

Hi!

I've was just curious why one of my ports doesn't build on < 10.x and
found the following:

This code:

---
#include <cmath>
int main() { std::hypot(3.0, 4.0); }
---

won't build even with latest gcc:

---
% g++49 -std=c++11 2.cc
2.cc: In function 'int main()':
2.cc:2:14: error: 'hypot' is not a member of 'std'
 int main() { std::hypot(3.0, 4.0); }
              ^
2.cc:2:14: note: suggested alternative:
In file included from /usr/local/lib/gcc49/include/c++/cmath:44:0,
                 from 2.cc:1:
/usr/include/math.h:276:8: note:   'hypot'
 double hypot(double, double);
        ^
---

Why's std::hypot not defined?

--- /usr/local/lib/gcc49/include/c++/cmath
...

#ifdef _GLIBCXX_USE_C99_MATH_TR1

...

namespace std _GLIBCXX_VISIBILITY(default)
{

  ...

  constexpr float
  hypot(float __x, float __y)
  { return __builtin_hypotf(__x, __y); }

  constexpr long double
  hypot(long double __x, long double __y)
  { return __builtin_hypotl(__x, __y); }

  template<typename _Tp, typename _Up>
    constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
    hypot(_Tp __x, _Up __y)
    {
      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
      return hypot(__type(__x), __type(__y));
    }
---

As you can see, it's hidden under _GLIBCXX_USE_C99_MATH_TR1.
What if I define _GLIBCXX_USE_C99_MATH_TR1?

---
% g++49 -std=c++11 2.cc
In file included from 2.cc:1:0:
/usr/local/lib/gcc49/include/c++/cmath:1064:11: error: '::erfl' has not been declared
   using ::erfl;
           ^
/usr/local/lib/gcc49/include/c++/cmath:1068:11: error: '::erfcl' has not been declared
   using ::erfcl;
           ^
/usr/local/lib/gcc49/include/c++/cmath:1104:11: error: '::lgammal' has not been declared
   using ::lgammal;
           ^
/usr/local/lib/gcc49/include/c++/cmath:1176:11: error: '::tgammal' has not been declared
   using ::tgammal;
           ^
---

That's the very reason _GLIBCXX_USE_C99_MATH_TR1 is not defined:
libstdc++ configure checks for availability of all C99 math functions in
our math library, doesn't find these four and disable whole C99 math
set.

libstdc++ works this around by using lower-precision variants (e.g.
erf instead of erfl) and issues a warning on linking.

So I wonder: could libstdc++ be made more usable for C++11 code in some
way? That's crucial for pre-clang FreeBSD branches which will live for
quite some time, and this is useful for gcc users on post-clang world.

The simple solution would be to disable named 4 functions, but make all
others available. The better would be to do what libc++ does, with
corresponding warnings.

What do you think?

-- 
Dmitry Marakasov   .   55B5 0596 FF1E 8D84 5F56  9510 D35A 80DD F9D2 F77D
amdmi3_at_amdmi3.ru  ..:  jabber: amdmi3_at_jabber.ru    http://www.amdmi3.ru

----- End forwarded message -----

-- 
Dmitry Marakasov   .   55B5 0596 FF1E 8D84 5F56  9510 D35A 80DD F9D2 F77D
amdmi3_at_amdmi3.ru  ..:  jabber: amdmi3_at_jabber.ru    http://www.amdmi3.ru
Received on Wed Jan 29 2014 - 15:41:40 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:46 UTC