Skip to content

Conversation

@t-a-k
Copy link
Contributor

@t-a-k t-a-k commented Jan 6, 2022

C99 floating-point comparison (isgreater, isunordered, ...), classification (isinf, isfinite, ...) and signbit macros are semantically boolean functions returning int, but their corresponding XSUBs in POSIX.xs used to return NV.

This PR will change them to return integers, and actually return immortal "1" when underlying C macro/functions returned nonzero value, because these nonzero value might be C library/compiler dependent.

C99 floating-point comparison (isgreater, isunordered, ...), classification (isinf, isfinite, ...) and signbit macros are semantically boolean functions returning int, but their corresponding XSUBs in POSIX.xs used to return NV. They now return integers, and acutually return immortal "1" when underlying C macro/functions returned nonzero value.
@ilmari
Copy link
Member

ilmari commented Jan 6, 2022

Now that we have stable boolean values, should these functions not return those?

@ilmari
Copy link
Member

ilmari commented Jan 6, 2022

Now that we have stable boolean values, should these functions not return those?

Oh, actually looking at the code I see they do for true, but not for false.
I'm not sure I agree with the backwards-compatibility argument enough to justify the mixed-type return.

@t-a-k
Copy link
Contributor Author

t-a-k commented Jan 13, 2022

Oh, actually looking at the code I see they do for true, but not for false.

I have once tried to make them return &PL_sv_no for false, but this broke existing tests like is(signbit(2), 0, ...) (found in ext/POSIX/t/math.t).

Because these functions used to return numeric value for long times, I think that there might already exist perl programs which expect these functions to return "0" for false, not a zero-length string.

@ilmari
Copy link
Member

ilmari commented Jan 17, 2022

I have once tried to make them return &PL_sv_no for false, but this broke existing tests like is(signbit(2), 0, ...) (found in ext/POSIX/t/math.t).

Because these functions used to return numeric value for long times, I think that there might already exist perl programs which expect these functions to return "0" for false, not a zero-length string.

On further thought, unlike is*, signbit is not a predicate, it returns the value of the sign bit, so that should be returning zero or one as an IV, not a boolean (even in the 1 case).

@t-a-k
Copy link
Contributor Author

t-a-k commented Jan 20, 2022

On further thought, unlike is*, signbit is not a predicate, it returns the value of the sign bit, so that should be returning zero or one as an IV, not a boolean (even in the 1 case).

C99 (and POSIX) seem to say that the signbit macro returns some nonzero value if its argument is negative, not the value of the sign bit.
(For example, on x86 with x87 FPU, GCC's signbit might return 512.)
So I think it should be treated as a predicate like other is* macros, despite its name.

@khwilliamson
Copy link
Contributor

@ilmari is it ok to merge this with you

@ilmari
Copy link
Member

ilmari commented Mar 4, 2022

I remain of the opinion that is* should return booleans always, and signbit should return a plain IV.

@khwilliamson
Copy link
Contributor

@t-a-k Please respond

@t-a-k
Copy link
Contributor Author

t-a-k commented Jun 9, 2022

I still think that signbit should be treated as a boolean function, because:

  • POSIX says

    The signbit() macro shall return a non-zero value if and only if the sign of its argument value is negative.

    (C99 seems to describe signbit similarly.)
    This is the same wording with other is*** semantically-boolean function/macros such as isfinite. "Non-zero" value is not specified, so a (portable) program has no other way than to treat its return value as a boolean by examining whether the value is zero or non-zero.

  • C and POSIX seems not to define "sign bit" for floating types in any way (they do not assume any binary format for floating types; neither the exact meaning of sign bit nor even its existence is assumed). So, despite its name, I think it unreasonable to interpret signbit as returning "the value of the sign bit".

  • In C++, its counterpart (signbit overloaded function) is defined to return bool.

@jkeenan
Copy link
Contributor

jkeenan commented Aug 27, 2024

I still think that signbit should be treated as a boolean function, because:

* [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signbit.html) says > The _signbit_() macro shall return a non-zero value if and only if the sign of its argument value is negative. (C99 seems to describe `signbit` similarly.) This is the same wording with other `is***` semantically-boolean function/macros such as `isfinite`. "Non-zero" value is not specified, so a (portable) program has no other way than to treat its return value as a boolean by examining whether the value is zero or non-zero. * C and POSIX seems not to define "sign bit" for floating types in any way (they do not assume any binary format for floating types; neither the exact meaning of sign bit nor even its existence is assumed). So, despite its name, I think it unreasonable to interpret `signbit` as returning "the value of the sign bit". * In C++, its counterpart (`signbit` overloaded function) is defined to return `bool`. 

@ilmari , @khwilliamson ... could you respond to @t-a-k's comments from two years ago? Thanks.

@jkeenan
Copy link
Contributor

jkeenan commented Oct 1, 2025

I still think that signbit should be treated as a boolean function, because:

* [POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/functions/signbit.html) says > The _signbit_() macro shall return a non-zero value if and only if the sign of its argument value is negative. (C99 seems to describe `signbit` similarly.) This is the same wording with other `is***` semantically-boolean function/macros such as `isfinite`. "Non-zero" value is not specified, so a (portable) program has no other way than to treat its return value as a boolean by examining whether the value is zero or non-zero. * C and POSIX seems not to define "sign bit" for floating types in any way (they do not assume any binary format for floating types; neither the exact meaning of sign bit nor even its existence is assumed). So, despite its name, I think it unreasonable to interpret `signbit` as returning "the value of the sign bit". * In C++, its counterpart (`signbit` overloaded function) is defined to return `bool`. 

@ilmari , @khwilliamson ... could you respond to @t-a-k's comments from two years ago? Thanks.

@ilmari, @khwilliamson could you respond to @t-a-k's comments from three years ago? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

5 participants