Cast from double to int64_t/uint64_t : +/- inf handling ?

X

Xavier Roche

Hi folks,

Are there any rules regarding cast result from double to
int64_t/uint64_t for positive/negative infinity, or is the result
totally undefined ?

Typically, playing with cast on x86-64 arch (Linux/gcc) leads to the
following observations:
(uint64_t) -inf == 9223372036854775808 (8000000000000000)
(uint64_t) inf == 0 (0)
(int64_t) -inf == -9223372036854775808 (8000000000000000)
(int64_t) inf == -9223372036854775808 (8000000000000000)

(I was expecting (uint64_t) inf to give 0xffffffffffffffff for example)

[ I could play with finite()/isinf(), but I was wondering if a fast
method would be available/documented. ]
 
J

James Kuyper

Hi folks,

Are there any rules regarding cast result from double to
int64_t/uint64_t for positive/negative infinity, or is the result
totally undefined ?

6.3.1.4p1 defines the behavior when a finite value of real floating type
is converted to an integer type; the behavior is undefined if the value
cannot be represented in the integer type. Nothing defines the result
when infinite values are converted, so the behavior is undefined "by
omission of any explicit definition of behavior" (4p2). The same
argument applies to NaNs.

This fits into the general scheme of C conversions; they are
value-preserving, to the extent that they can be, when the value being
converted is within the representable range of the destination type, and
usually have undefined behavior when it is not. The special handling of
_Bool, and the modulo results when converting from integer values to
unsigned types are the two main exceptions to that rule.

C integer types don't have representations of infinities or NaNs (though
it would be perfectly feasible to implement an integer-like type which did).
Typically, playing with cast on x86-64 arch (Linux/gcc) leads to the
following observations:
(uint64_t) -inf == 9223372036854775808 (8000000000000000)
(uint64_t) inf == 0 (0)
(int64_t) -inf == -9223372036854775808 (8000000000000000)
(int64_t) inf == -9223372036854775808 (8000000000000000)

(I was expecting (uint64_t) inf to give 0xffffffffffffffff for example)

[ I could play with finite()/isinf(), but I was wondering if a fast
method would be available/documented. ]

To avoid undefined behavior, it is necessary to avoid converting any
value that is greater than INT64_MAX, or less than INT64_MIN (or less
than 0 for uint64_t). Infinities will be captured by such checks, so
there's no need for a separate check of isfinite() or isinf(). On the
other hand, if NaNs are a possibility, you will need to check isnan().
 
X

Xavier Roche

To avoid undefined behavior, it is necessary to avoid converting any
value that is greater than INT64_MAX, or less than INT64_MIN (or less
than 0 for uint64_t).


Makes sense, thanks for the exhaustive reply!

[ I was hoping (at least on x86-64 archs) that the corresponding
conversion would handle that, but this is not the case obviously ; the
0x8000000000000000 value returned is "the indefinite integer value" as
per x86-64 convention BTW. ]
 
F

Fred J. Tydeman

Are there any rules regarding cast result from double to
int64_t/uint64_t for positive/negative infinity, or is the result
totally undefined ?

If Annex F is being followed, the requirements are:

F.4 Floating to integer conversion

If the integer type is _Bool, 6.3.1.2 applies and no floating-point
exceptions are raised (even for NaN). Otherwise, if the floating value
is infinite or NaN or if the integral part of the floating value
exceeds the range of the integer type, then the ''invalid'' floating-
point exception is raised and the resulting value is
unspecified. Otherwise, the resulting value is determined by
6.3.1.4. Conversion of an integral floating value that does not exceed
the range of the integer type raises no floating-point exceptions;
whether conversion of a non-integral floating value raises the
''inexact'' floating-point exception is unspecified.360)

The public test case:
http://www.tybor.com/tflt2int.c
shows how bad compilers do for that kind of conversion.
---
Fred J. Tydeman Tydeman Consulting
(e-mail address removed) Testing, numerics, programming
+1 (775) 358-9748 Vice-chair of PL22.11 (ANSI "C")
Sample C99+FPCE tests: http://www.tybor.com
Savers sleep well, investors eat well, spenders work forever.
 
T

Tim Rentsch

James Kuyper said:
Hi folks,

Are there any rules regarding cast result from double to
int64_t/uint64_t for positive/negative infinity, or is the result
totally undefined ?

6.3.1.4p1 defines the behavior when a finite value of real floating type
is converted to an integer type; the behavior is undefined if the value
cannot be represented in the integer type. [snip..snip..snip]

To avoid undefined behavior, it is necessary to avoid converting any
value that is greater than INT64_MAX, or less than INT64_MIN (or less
than 0 for uint64_t). [snip]


Actually the values to avoid are >= INT64_MAX + 1, or <= INT64_MIN-1,
or <= -1 for uint64_t, because of such conversions doing truncation
toward zero.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top