perl5 icon indicating copy to clipboard operation
perl5 copied to clipboard

POSIX::is*** floating-point testing functions should not return NV

Open t-a-k opened this issue 3 years ago • 10 comments

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.

t-a-k avatar Jan 06 '22 13:01 t-a-k

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

ilmari avatar Jan 06 '22 13:01 ilmari

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.

ilmari avatar Jan 06 '22 13:01 ilmari

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.

t-a-k avatar Jan 13 '22 17:01 t-a-k

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).

ilmari avatar Jan 17 '22 11:01 ilmari

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.

t-a-k avatar Jan 20 '22 14:01 t-a-k

@ilmari is it ok to merge this with you

khwilliamson avatar Feb 18 '22 01:02 khwilliamson

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

ilmari avatar Mar 04 '22 19:03 ilmari

@t-a-k Please respond

khwilliamson avatar Jun 08 '22 15:06 khwilliamson

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.

t-a-k avatar Jun 09 '22 14:06 t-a-k