[boost] bug - boost::math::ccmath::copysign not work

9 views
Skip to first unread message

Gero Peterhoff via Boost

unread,
Aug 17, 2022, 7:12:11 PM8/17/22
to bo...@lists.boost.org, Gero Peterhoff
Hi,
I just see that boost::math::ccmath::copysign doesn't work.
https://godbolt.org/z/9af1ME9fT

cu
Gero
OpenPGP_signature

Proton via Boost

unread,
Aug 17, 2022, 10:25:35 PM8/17/22
to John Maddock via Boost, Proton
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
> <OpenPGP_signature.sig>

Gero,

The typical implementation of copysign and signbit involve type-punning which is not allowed in constexpr contexts. An example can be found here: https://android.googlesource.com/platform/bionic.git/+/brillo-m7-dev/libm/signbit.c. Due to this limitation we do not provide support for signed zero or analyzing the sign of NAN.

Matt

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Mathias Gaunard via Boost

unread,
Aug 18, 2022, 2:29:48 AM8/18/22
to Boost mailing list, Mathias Gaunard
bit_cast is constexpr.

John Maddock via Boost

unread,
Aug 18, 2022, 6:13:53 AM8/18/22
to Mathias Gaunard via Boost, John Maddock
On 18/08/2022 07:23, Mathias Gaunard via Boost wrote:
> bit_cast is constexpr.

Good catch!

Matt and I discussed this ages ago and decided it was basically
impossible, it's a shame that fix is C++20 but it's certainly better
than nothing.

Matt, here's a thought: if we can detect NaN's (and obviously zeros),
can/should we static_assert in those cases that this is known not to work?

Best, John.

Andrey Semashev via Boost

unread,
Aug 18, 2022, 8:27:01 AM8/18/22
to bo...@lists.boost.org, Andrey Semashev
On 8/18/22 13:13, John Maddock via Boost wrote:
> On 18/08/2022 07:23, Mathias Gaunard via Boost wrote:
>> bit_cast is constexpr.
>
> Good catch!
>
> Matt and I discussed this ages ago and decided it was basically
> impossible, it's a shame that fix is C++20 but it's certainly better
> than nothing.

__builtin_bit_cast is available regardless of the C++ level. Though
you're still limited to compilers that support it.

Proton via Boost

unread,
Aug 18, 2022, 9:54:04 PM8/18/22
to John Maddock via Boost, Proton

Using __builtin_bit_cast should be fine for conditional C++17 support since we already rely on __builtin_is_constant_evaluated. I’ll play with it this weekend and see where it get us. Worst case is we static_assert unsupported cases like John suggested.

Matt

Gero Peterhoff via Boost

unread,
Aug 21, 2022, 4:26:53 PM8/21/22
to bo...@lists.boost.org, Gero Peterhoff
Am 19.08.22 um 03:53 schrieb Proton via Boost:
> Using __builtin_bit_cast should be fine for conditional C++17 support since we already rely on __builtin_is_constant_evaluated. I’ll play with it this weekend and see where it get us. Worst case is we static_assert unsupported cases like John suggested.

Hi Matt,
I see that you have started work on ccmath::signbit/copysign/etc. I also. Our basic problem is that std::bit_cast is only available with C++20. You are already trying to provide this for C++17 (BOOST_MATH_BIT_CAST). My questions:
- can you *guarantee* that BOOST_MATH_BIT_CAST works on/with all platforms/compilers ?
- if not: does it make sense to upgrade ccmath to C++20 so that std::bit_cast is available ?

Otherwise I can only oracle and provide code to the best of my knowledge - without guarantee that it works on/with all platforms/compilers :-(

regards
Gero

OpenPGP_signature

Proton via Boost

unread,
Aug 21, 2022, 5:26:03 PM8/21/22
to John Maddock via Boost, Proton

> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

> <OpenPGP_signature.sig>


Gero,

I can make no such guarantees. I do not think it makes sense to upgrade to C++20 because BOOST_MATH_BIT_CAST macro enables C++17 support. If you look at the comments even with a move to C++20 Clang does not yet support constexpr std::bit_cast/__builtin_bit_cast with bit-fields. I have provided layouts for 64, 80, and 128 bit long doubles so most platforms should be covered if the toolchain supports it.

Gero Peterhoff via Boost

unread,
Aug 21, 2022, 7:53:07 PM8/21/22
to Proton, John Maddock via Boost, Gero Peterhoff
Am 21.08.22 um 23:25 schrieb Proton:
Hi Matt,
I haven't tried whether clang's bit_cast supports bit fields. There is a problem with your simple implementation:
Memory size for long double/float80 can be 10/12/16 bytes depending on platform or compiler option. You didn't take that into account, so bit_cast then fails.

That's why I'm working on extended structures for the bitrepresentation for float-types, so that unusual or machine-specific types can also be mapped. These then also include manipulating the individual components and/or checking for special values. For the concrete implementations it would be advantageous to have a stable bit_cast; otherwise I can only use explicit bitpatterns and hope they are (ieee) compatible.

This approach has other advantages. These extended structures always deliver correct results, even if the compiler option fast-math/finite-math or something similar is set. This can be used to implement various requirements, e.g. isnan/isinf:
- isnan/isinf -> default
- isnan_stable/isinf_stable -> correct results also with fast/finite-math etc

This can be very useful when implementing math functions.

Best, Gero
OpenPGP_signature

Proton via Boost

unread,
Aug 21, 2022, 8:12:13 PM8/21/22
to Gero Peterhoff, Proton, John Maddock via Boost
> Hi Matt,
> I haven't tried whether clang's bit_cast supports bit fields. There is a problem with your simple implementation:
> Memory size for long double/float80 can be 10/12/16 bytes depending on platform or compiler option. You didn't take that into account, so bit_cast then fails.
>
> That's why I'm working on extended structures for the bitrepresentation for float-types, so that unusual or machine-specific types can also be mapped. These then also include manipulating the individual components and/or checking for special values. For the concrete implementations it would be advantageous to have a stable bit_cast; otherwise I can only use explicit bitpatterns and hope they are (ieee) compatible.
>
> This approach has other advantages. These extended structures always deliver correct results, even if the compiler option fast-math/finite-math or something similar is set. This can be used to implement various requirements, e.g. isnan/isinf:
> - isnan/isinf -> default
> - isnan_stable/isinf_stable -> correct results also with fast/finite-math etc
>
> This can be very useful when implementing math functions.
>
> Best, Gero

Gero,

What platform does this fail on? I have provided multiple macro enabled definitions for the bit patterns of long doubles on major architectures.

Have you run into issues with the implementations of isnan or isinf? We provide a version of fpclassify (https://www.boost.org/doc/libs/1_80_0/boost/math/special_functions/fpclassify.hpp) that yields stable results regardless of the compiler flag like you are looking for.

Matt

Gero Peterhoff via Boost

unread,
Aug 21, 2022, 9:06:00 PM8/21/22
to Proton, Gero Peterhoff, John Maddock via Boost
Am 22.08.22 um 02:11 schrieb Proton:
>
>>
>> Hi Matt,
>> I haven't tried whether clang's bit_cast supports bit fields. There is a problem with your simple implementation:
>> Memory size for long double/float80 can be 10/12/16 bytes depending on platform or compiler option. You didn't take that into account, so bit_cast then fails.
>>
>> That's why I'm working on extended structures for the bitrepresentation for float-types, so that unusual or machine-specific types can also be mapped. These then also include manipulating the individual components and/or checking for special values. For the concrete implementations it would be advantageous to have a stable bit_cast; otherwise I can only use explicit bitpatterns and hope they are (ieee) compatible.
>>
>> This approach has other advantages. These extended structures always deliver correct results, even if the compiler option fast-math/finite-math or something similar is set. This can be used to implement various requirements, e.g. isnan/isinf:
>> - isnan/isinf -> default
>> - isnan_stable/isinf_stable -> correct results also with fast/finite-math etc
>>
>> This can be very useful when implementing math functions.
>>
>> Best, Gero
>
> Gero,
>
> What platform does this fail on? I have provided multiple macro enabled definitions for the bit patterns of long doubles on major architectures.
>

e.g. on x86 gcc (https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/x86-Options.html#x86-Options):
x86_64 sizeof(long double) == 16
x86_32 sizeof(long double) == 12
This can also be changed with compiler flags, eg with gcc
-m96bit-long-double
-m128bit-long-double
and/or
-mlong-double-64
-mlong-double-80
-mlong-double-128

> Have you run into issues with the implementations of isnan or isinf? We provide a version of fpclassify (https://www.boost.org/doc/libs/1_80_0/boost/math/special_functions/fpclassify.hpp <https://www.boost.org/doc/libs/1_80_0/boost/math/special_functions/fpclassify.hpp>)  that yields stable results regardless of the compiler flag like you are looking for.

But fpclassify is an if-else-cascade and not a direct and therefore fast test.
>
> Matt
>
Gero




OpenPGP_signature

Proton via Boost

unread,
Aug 21, 2022, 9:42:23 PM8/21/22
to Gero Peterhoff, Proton, John Maddock via Boost
> e.g. on x86 gcc (https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/x86-Options.html#x86-Options):
> x86_64 sizeof(long double) == 16
> x86_32 sizeof(long double) == 12
> This can also be changed with compiler flags, eg with gcc
> -m96bit-long-double
> -m128bit-long-double
> and/or
> -mlong-double-64
> -mlong-double-80
> -mlong-double-128

None of those fail on the PR branch. The appropriate representation of long double is macro enabled based on LDBL_MANT_DIG and LDBL_MAX_EXP.
Reply all
Reply to author
Forward
0 new messages