Bug 113770 - _Float64x support on g++ 13.2.0
Summary: _Float64x support on g++ 13.2.0
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 13.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2024-02-05 14:17 UTC by Masahide Kashiwagi
Modified: 2024-02-06 11:14 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Masahide Kashiwagi 2024-02-05 14:17:14 UTC
I have noticed that the following simple program will not complie
with g++ 13.2.0 on ubuntu 23.04 .

#include <iostream>

int main()
{
        _Float64x a;

        std::cin >> a;
}

It compiles fine with long double and __float80.
Also no problem with clang++ 16.0.6.

I also noticed that with _Float64x, the numeric_limits<_Float64x> return 0,
as shown below.

#include <iostream>
#include <limits>

int main()
{
        std::cout << std::numeric_limits<_Float64x>::epsilon() << std::endl;
        std::cout << std::numeric_limits<_Float64x>::max() << std::endl;
        std::cout << std::numeric_limits<_Float64x>::min() << std::endl;
        std::cout << std::numeric_limits<_Float64x>::infinity() << std::endl;
}

This program returns 0:

0
0
0
0

With long double and __float80, the program returns correct values:

1.0842e-19
1.18973e+4932
3.3621e-4932
inf

It seems to me that g++ 13 cannot handle _Float64 correctly.
Is there any way to deal with this?
Comment 1 Jonathan Wakely 2024-02-05 14:29:29 UTC
(In reply to Masahide Kashiwagi from comment #0)
> I have noticed that the following simple program will not complie
> with g++ 13.2.0 on ubuntu 23.04 .
> 
> #include <iostream>
> 
> int main()
> {
>         _Float64x a;
> 
>         std::cin >> a;

This is expected, _Float64x is not defined in any C++ standard, and there is no support for it in the standard library.

> }
> 
> It compiles fine with long double and __float80.

Of course, because long double is a standard type, and __float80 is a typedef for long double on x86_64.

> Also no problem with clang++ 16.0.6.
> 
> I also noticed that with _Float64x, the numeric_limits<_Float64x> return 0,

That's also expected. It's not a standard type, and the standard library doesn't know anything about it.

> as shown below.
> 
> #include <iostream>
> #include <limits>
> 
> int main()
> {
>         std::cout << std::numeric_limits<_Float64x>::epsilon() << std::endl;
>         std::cout << std::numeric_limits<_Float64x>::max() << std::endl;
>         std::cout << std::numeric_limits<_Float64x>::min() << std::endl;
>         std::cout << std::numeric_limits<_Float64x>::infinity() << std::endl;
> }
> 
> This program returns 0:
> 
> 0
> 0
> 0
> 0
> 
> With long double and __float80, the program returns correct values:
> 
> 1.0842e-19
> 1.18973e+4932
> 3.3621e-4932
> inf

For the same reason given above.
 
> It seems to me that g++ 13 cannot handle _Float64 correctly.

I assume that's a typo, as it handles _Float64 properly, because that's std::float64_t which is a standard type.

> Is there any way to deal with this?

Don't use _Float64x in C++?
Comment 2 Jonathan Wakely 2024-02-05 14:32:17 UTC
(In reply to Masahide Kashiwagi from comment #0)
> Also no problem with clang++ 16.0.6.

That's because Clang doesn't support _Float64x or _Float64 at all.

Those names get defined as typedefs by libc:

# 214 "/usr/include/bits/floatn-common.h" 3 4
typedef float _Float32;
# 251 "/usr/include/bits/floatn-common.h" 3 4
typedef double _Float64;
# 268 "/usr/include/bits/floatn-common.h" 3 4
typedef double _Float32x;
# 285 "/usr/include/bits/floatn-common.h" 3 4
typedef long double _Float64x;

So when you use Clang, _Float64x is just another typedef for long double.

If you are happy to just use long double, then use long double. Don't try to use extended floating point types that are not part of the C++ standard.
Comment 3 Masahide Kashiwagi 2024-02-05 14:47:23 UTC
I forgot to mention in my earlier post that these two programs work fine in g++ 12.

Also, at https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html it says that __float80 and _Float64x are 80-bit extended floating point numbers and are available on x86. Has support for _Float64x been stopped?
Comment 4 Jakub Jelinek 2024-02-05 14:52:32 UTC
(In reply to Masahide Kashiwagi from comment #3)
> I forgot to mention in my earlier post that these two programs work fine in
> g++ 12.

Because same thing as for clang applies there, _Float64 or _Float64x types
aren't supported there in C++.  gcc 12 and earlier only supports them in C.
In GCC 13 and later, they are supported in C++ as well as distinct types,
_Float{16,32,64,128} as underlying types for std::float{16,32,64,128}_t, 
and the x suffixed types just with minimal support (the compiler can mangle them among other things).
But because they aren't standard C++, the library doesn't know about them and because they are distinct from long double etc. (again, intentional, because they should mangle differently), the long double etc. support in the STL headers doesn't work for those.

> Also, at https://gcc.gnu.org/onlinedocs/gcc/Floating-Types.html it says that
> __float80 and _Float64x are 80-bit extended floating point numbers and are
> available on x86. Has support for _Float64x been stopped?

No, it has been added, but just in very limited way.
Comment 5 Masahide Kashiwagi 2024-02-05 15:08:58 UTC
Thank you very much.

I understand that g++ 13 no longer supports _Float64x in a very limited way.

Does this mean that if I want to use 80-bit extended floating point numbers in g++ 13 or later, is it best to use long double?

Since long double may not be 80-bit on non-x86 architectures, I wanted to use _Float64x or __float80, which are clearly 80-bit, if possible.
Comment 6 Jonathan Wakely 2024-02-05 15:15:08 UTC
(In reply to Masahide Kashiwagi from comment #5)
> I understand that g++ 13 no longer supports _Float64x in a very limited way.

No, that's incorrect.

In GCC 12, there was no C++ support for that type, it was just a typedef for long double.

In GCC 13 there is limited support for a distinct _Float64x type in the compiler, but you can't use it with the standard library (iostreams, numeric_limits, etc.)

> Does this mean that if I want to use 80-bit extended floating point numbers
> in g++ 13 or later, is it best to use long double?

If you use long double then you get exactly the same code as you would get using _Float64x with GCC 12.

> Since long double may not be 80-bit on non-x86 architectures, I wanted to
> use _Float64x or __float80, which are clearly 80-bit, if possible.

You can use them, but you can't use _Float64x with the standard library. You need to convert to/from another  type like long double to use standard APIs.
Comment 7 Jakub Jelinek 2024-02-05 15:16:51 UTC
(In reply to Masahide Kashiwagi from comment #5)
> Thank you very much.
> 
> I understand that g++ 13 no longer supports _Float64x in a very limited way.

You understand it wrong.  _Float64x wasn't supported at all in GCC 12 and earlier.
The reason you don't get an error is because of glibc typedefs.
Now it is supported in a limited way.

> Does this mean that if I want to use 80-bit extended floating point numbers
> in g++ 13 or later, is it best to use long double?
> 
> Since long double may not be 80-bit on non-x86 architectures, I wanted to
> use _Float64x or __float80, which are clearly 80-bit, if possible.

_Float64x certainly doesn't mean 80-bit.  In C, it doesn't have to be supported at all (such as when IEEE double is the largest type supported by hw and/or emulation), or can be IEEE quad, 80-bit extended or whatever else.
So, if you need only 80-bit and want an error otherwise, use __float80.
Comment 8 Masahide Kashiwagi 2024-02-05 15:34:40 UTC
(In reply to Jakub Jelinek from comment #7)
> _Float64x certainly doesn't mean 80-bit.  In C, it doesn't have to be
> supported at all (such as when IEEE double is the largest type supported by
> hw and/or emulation), or can be IEEE quad, 80-bit extended or whatever else.
> So, if you need only 80-bit and want an error otherwise, use __float80.

Thank you very much. This information was very important to me. I will stop using _Float64x and consider using __float80 or long double.
Comment 9 Andrew Pinski 2024-02-05 16:54:48 UTC
As described, this is not a bug.