1

I am writing a Python extension in C/C++ that works with numeric values. When a user passes in a value that is too large to fit into a float, I want to return the value that is represented in Python code as inf. How can I do that in C/C++? The Floating Point Objects page in the official documentation lists PyFloat_GetMax(), but nothing for inf. I searched the Python 3.9 source code for this function and found the following:

SetDblFlag(DBL_MAX);
SetIntFlag(DBL_MAX_EXP);
SetIntFlag(DBL_MAX_10_EXP);
SetDblFlag(DBL_MIN);
SetIntFlag(DBL_MIN_EXP);
SetIntFlag(DBL_MIN_10_EXP);
SetIntFlag(DBL_DIG);
SetIntFlag(DBL_MANT_DIG);
SetDblFlag(DBL_EPSILON);
SetIntFlag(FLT_RADIX);
SetIntFlag(FLT_ROUNDS);

But none of those seems to be what I'm looking for. Theoretically, I could add 1 to DBL_MAX, but that doesn't seem very clean. Any suggestions?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Alan
  • 1,889
  • 2
  • 18
  • 30
  • 4
    I see that `math.h` provides an `INFINITY` macro; I suspect that would be a valid argument for `PyFloat_FromDouble`. IEEE 754 defines infinity as a float/double with all ones in the exponent field and 0 for the significand. – chepner May 27 '21 at 15:03
  • @chepner, that solved my problem, thanks! If you post it as an answer, I'll select it. – Alan May 27 '21 at 19:12

1 Answers1

3

PyFloat_FromDouble returns a float object given a double value. math.h provides a macro for IEEE 754 infinity (which, FYI, is a float with a 0 significand and all ones in the exponent) which you can use as the argument.

#include <math.h>

...

    return PyFloat_FromDouble(INFINITY)

As an aside, you can see this value for infinity in Python itself:

>>> import struct
>>> >>> struct.pack("!f", float('inf'))
b'\x7f\x80\x00\x00'
>>> struct.pack("!d", float('inf'))
b'\x7f\xf0\x00\x00\x00\x00\x00\x00'

In both cases you can see (if you mentally convert hex to binary) the 0 sign bit, the 1 exponent bits, and the 0 signifiant bits. You can also see negative infinity:

>>> struct.pack("!f", -float('inf'))
b'\xff\x80\x00\x00'
>>> struct.pack("!d", -float('inf'))
b'\xff\xf0\x00\x00\x00\x00\x00\x00'

Same as positive infinity, but with the leading 1 sign bit.


Strictly speaking, Python doesn't assume any particular floating-point format; it uses whatever the underlying platform provides. The behavior may be different on systems not using IEEE 754 floating-point values. In particular, I don't know if the presence of INFINITY (or math.h itself) is dependent on IEEE 754, or if there is a relevant C standard that mandates it.

chepner
  • 497,756
  • 71
  • 530
  • 681