From: Gero Peterhoff (g.peterhoff_at_[hidden])
Date: 2023-04-14 18:39:04


Am 14.04.23 um 15:37 schrieb Matt Borland:
>
>> Hi Matt,
>> Thanks for your comments. But I don't want to go that far, since the rest of the math functions will hopefully be constexpr with C++26 (https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p1383r1.pdf). An implementation in ccmath would be very elaborate.
>> My questions were related to how I can now provide additional math functions without much effort; to stay with the cot example (simplified):
>>
>> 1) without constexpr
>> template <typename Type> inline auto cot(const Type x) noexcept { return 1/std::tan(x); }
>> This would have the disadvantage that performance might be wasted if the compiler already provides std::tan constexpr (e.g. gcc).
>>
>> 2) "optimistic" with constexpr
>> template <typename Type> inline constexpr auto cot ...
>> constexpr auto y = cot(2); // gcc ok else error "not constexpr"
>> This may give a CT error. The question is if this would be acceptable from your side.
>>
>> 3) additional macro e.g. BOOST_MATH_CONSTEXPR
>> #if (BOOST_GCC && __cplusplus >= 201103L) || (defined(__cpp_lib_constexpr_cmath) && __cpp_lib_constexpr_cmath >= 202202L)
>> #define BOOST_MATH_CONSTEXPR constexpr
>> #else
>> #define BOOST_MATH_CONSTEXPR
>> #endif
>> template <typename Type> inline BOOST_MATH_CONSTEXPR auto cot ...
>> BOOST_MATH_CONSTEXPR auto y = cot(2);
>> Disadvantage: the macro must always be kept up to date (maintenance effort).
>>
>>
>> Which would be the best solution?
>>
>> thx
>> Gero
>
> Gero,
>
> For seemingly trivial functions like cot = 1 / tan having an accurate implementation is non-trivial. You will want to implement this using a minmax polynomial instead https://en.wikipedia.org/wiki/Remez_algorithm <https://en.wikipedia.org/wiki/Remez_algorithm>. If you look in various standard library implementations they use these polynomials instead of trigonometric identities (e.g. sin = cos(pi/2 - theta)) for accuracy*. These are certainly more elaborate to implement. The current ccmath functions are all cross-platform so we do not have a dependency on GCC. I would recommend that if you want to proceed that you follow the way we implement functions we already ship in ccmath.
>
> Matt
>
>
> *https://github.com/bpowers/musl/blob/master/src/math/__sin.c <https://github.com/bpowers/musl/blob/master/src/math/__sin.c> and https://github.com/bpowers/musl/blob/master/src/math/__cos.c <https://github.com/bpowers/musl/blob/master/src/math/__cos.c>

Hi Matt,
I see, and these would also have to be provided for std::complex and multiprecision+octonion+quaternion. Nevertheless, a start has to be made.
For functions that are not based on series, however, your reasoning does not apply. How can/should I handle constexpr there (1, 2 or 3)?

In addition your ccmath functions are buggy. The problem is that you make incomplete nan-checks. You check for isnan (limits::quiet_NaN), but not for limits::signaling_NaN. These are different values - https://godbolt.org/z/4YWMWbabz. But for e.g. copysign you have to ensure that *only* the sign is changed, which is not the case with your implementation (based on abs).
Maybe it would even make sense to remove ccmath completely.

cu
Gero