Namespaces
Variants

Talk:cpp/numeric/math/frexp

From cppreference.com

There doesn't seem to be any explanation of what happens for negative input. I think the statement that x is always in [0.5, 1) is wrong - I think this is the range of abs(x), and x takes the sign of the input. But I'm not sure.

You're right, both C and POSIX wording is "magnitude in the interval [1/2, 1)". It can even be demonstrated right on this page: click Run this code, change the compiler to clang so that it compiles, and change the test value to negative. I'll update. --Cubbi (talk) 06:56, 19 December 2014 (PST)

What do we mean by "it" is returned?

In several of the Floating Point Manipulation Functions we have "it", but what is returned is inconsistent.

For example (highlights are mine):

frexp

If the implementation supports IEEE floating-point arithmetic (IEC 60559),

  • If arg is ±0, it is returned, unmodified, and 0 is stored in *exp.
  • If arg is ±∞, it is returned, and an unspecified value is stored in *exp.
  • If arg is NaN, NaN is returned, and an unspecified value is stored in *exp.
modf

If the implementation supports IEEE floating-point arithmetic (IEC 60559),

  • If x is ±0, ±0 is returned, and ±0 is stored in *iptr.
  • If x is ±∞, ±0 is returned, and ±∞ is stored in *iptr. <-- Seems like ±∞ should be returned
  • If x is NaN, NaN is returned, and NaN is stored in *iptr.


Although it is equivalent, seems to me that we should be using a form like:

  • If arg is ±0, arg is returned, unmodified, and 0 is stored in *exp.


ticotico (talk) 08:41, 2 April 2022 (PDT)

there is a bit of a shorthand here that is probably obscure: "If x is ±∞, ±0 is returned, and ±∞ is stored" covers two special cases:
  • the argument is positive infinity: return value is positive zero, and positive infinity is written to *ptr
  • the argument is negative infinity: return value is negative zero, and negative infinity is written to *ptr
likewise, where it says "If the argument is ±0, it is returned, unmodified", there are two special cases:
  • the argument is +0: return value is +0
  • the argument is -0: return value is -0
(I think I wrote those but I don't remember why sometimes it's "unmodified" and sometimes it's repeating the "±" expression)
There are cases where these pairs fold "If the argument is ±0, -∞ is returned" in cpp/numeric/math/log2 covers two special cases with identical result.
It's probably a good idea to split every single "±" special case line into two lines, one for + and one for - --Cubbi (talk) 19:49, 2 April 2022 (PDT)

I think there's more to it. If you try:

#include <cmath>
#include <iostream>
int main()
{
    std::cout << std::fixed
              << "floor(+2.7) = " << std::floor(+2.7) << '\n'
              << "floor(-2.7) = " << std::floor(-2.7) << '\n'
              << "floor(+0)   = " << std::floor(0) << '\n'
              << "floor(+0.0) = " << std::floor(0.0) << '\n'
              << "floor(-0.0) = " << std::floor(-0.0) << '\n'
              << "floor(-0)   = " << std::floor(-0) << '\n'
              << "floor(NAN)  = " << std::floor(NAN) << '\n'
              << "floor(+Inf) = " << std::floor(INFINITY) << '\n'
              << "floor(-Inf) = " << std::floor(-INFINITY) << '\n';
}

Output:

floor(+2.7) = 2.000000
floor(-2.7) = -3.000000
floor(+0)   = 0.000000
floor(+0.0) = 0.000000
floor(-0.0) = -0.000000
floor(-0)   = 0.000000
floor(NAN)  = nan
floor(+Inf) = inf
floor(-Inf) = -inf

You'll notice that the output for -0 is positive zero.

ticotico (talk) 07:43, 3 April 2022 (PDT)

Furthermore, I've seen some functions that state:

If arg is not a floating-point number, the behavior is unspecified.

However, shouldn't -0 be subject to floating-point to integral conversion, and yield 0.0000? From Integral Conversions:

  • If the destination type is signed, the value does not change if the source integer can be represented in the destination type. Otherwise the result is implementation-defined(until C++20)the unique value of the destination type equal to the source value modulo 2n
    where n is the number of bits used to represent the destination type.
    (since C++20)
    . (Note that this is different from signed integer arithmetic overflow, which is undefined).

ticotico (talk) 08:43, 3 April 2022 (PDT)

I think you're overthinking: floor(-0.0) gives -0.0 as described. If we are to undo the shortcuts and rewrite "If arg is ±0, it is returned, unmodified" as two lines "If arg is +0.0, +0.0 is returned" and "if arg is -0.0, -0.0 is returned", it should be unambiguous. floor(-0) is floor of the integer zero (minus does nothing) and is covered by the overload/template (6) that converts it to +0.0 double.
I made modifications and I can use this as a model for other functions. Check it out and make corrections or suggestions and I'll modify them as I translate onto Spanish. One more question, with the function template does it make sense to have the UB if arg is not a floating-point number? I'm assuming that anything that can go through std::is_integral would work, so what else would be there that wouldn't be rejected by the compiler? ticotico (talk) 07:27, 4 April 2022 (PDT)
I disagree with the conversion of maths notation to teletype. INFINITY is a implementation defined float and 0.0 is a double, but the overload set supports float, double and long double. The maths notation isn't tied down to the specifics of C++, so it's more appropriate IMO. (As for the splitting of ± into both cases, I'm neither here nor there). --Ybab321 (talk) 08:51, 4 April 2022 (PDT)
Re "the results are unspecified", that seems to be a copy paste bug from C. In C it's unspecified, in C++ we have the catch-all template/overload https://eel.is/c++draft/c.math#cmath.syn-2 . And linking "infinity" (specific binary IEEE FP value) to INFINITY (preprocessor constant) might be confusing:
* reader would spin some extra cycles reconciling "implementation supports floating-point infinities" from cpp/numeric/math/INFINITY with "the implementation supports IEEE floating-point" here in cpp/numeric/math/frexp
* worse yet, INFINITY actually says "positive or negative infinity" (which is what the C standard says), but the sign very much matters here. --Cubbi (talk) 09:12, 4 April 2022 (PDT)