Skip to content

Commit 0a883a7

Browse files
authored
bpo-35134: Add Include/cpython/floatobject.h (GH-28957)
Split Include/floatobject.h into sub-files: add Include/cpython/floatobject.h and Include/internal/pycore_floatobject.h.
1 parent 79cf20e commit 0a883a7

14 files changed

+123
-79
lines changed

Include/cpython/floatobject.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef Py_CPYTHON_FLOATOBJECT_H
2+
# error "this header file must not be included directly"
3+
#endif
4+
5+
typedef struct {
6+
PyObject_HEAD
7+
double ob_fval;
8+
} PyFloatObject;
9+
10+
// Macro version of PyFloat_AsDouble() trading safety for speed.
11+
// It doesn't check if op is a double object.
12+
#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval)

Include/floatobject.h

+17-79
Original file line numberDiff line numberDiff line change
@@ -11,106 +11,44 @@ PyFloatObject represents a (double precision) floating point number.
1111
extern "C" {
1212
#endif
1313

14-
#ifndef Py_LIMITED_API
15-
typedef struct {
16-
PyObject_HEAD
17-
double ob_fval;
18-
} PyFloatObject;
19-
#endif
20-
2114
PyAPI_DATA(PyTypeObject) PyFloat_Type;
2215

2316
#define PyFloat_Check(op) PyObject_TypeCheck(op, &PyFloat_Type)
2417
#define PyFloat_CheckExact(op) Py_IS_TYPE(op, &PyFloat_Type)
2518

2619
#ifdef Py_NAN
27-
#define Py_RETURN_NAN return PyFloat_FromDouble(Py_NAN)
20+
# define Py_RETURN_NAN return PyFloat_FromDouble(Py_NAN)
2821
#endif
2922

30-
#define Py_RETURN_INF(sign) do \
31-
if (copysign(1., sign) == 1.) { \
32-
return PyFloat_FromDouble(Py_HUGE_VAL); \
33-
} else { \
34-
return PyFloat_FromDouble(-Py_HUGE_VAL); \
23+
#define Py_RETURN_INF(sign) \
24+
do { \
25+
if (copysign(1., sign) == 1.) { \
26+
return PyFloat_FromDouble(Py_HUGE_VAL); \
27+
} \
28+
else { \
29+
return PyFloat_FromDouble(-Py_HUGE_VAL); \
30+
} \
3531
} while(0)
3632

3733
PyAPI_FUNC(double) PyFloat_GetMax(void);
3834
PyAPI_FUNC(double) PyFloat_GetMin(void);
39-
PyAPI_FUNC(PyObject *) PyFloat_GetInfo(void);
35+
PyAPI_FUNC(PyObject*) PyFloat_GetInfo(void);
4036

4137
/* Return Python float from string PyObject. */
42-
PyAPI_FUNC(PyObject *) PyFloat_FromString(PyObject*);
38+
PyAPI_FUNC(PyObject*) PyFloat_FromString(PyObject*);
4339

4440
/* Return Python float from C double. */
45-
PyAPI_FUNC(PyObject *) PyFloat_FromDouble(double);
41+
PyAPI_FUNC(PyObject*) PyFloat_FromDouble(double);
4642

4743
/* Extract C double from Python float. The macro version trades safety for
4844
speed. */
49-
PyAPI_FUNC(double) PyFloat_AsDouble(PyObject *);
50-
#ifndef Py_LIMITED_API
51-
#define PyFloat_AS_DOUBLE(op) (((PyFloatObject *)(op))->ob_fval)
52-
#endif
45+
PyAPI_FUNC(double) PyFloat_AsDouble(PyObject*);
5346

5447
#ifndef Py_LIMITED_API
55-
/* _PyFloat_{Pack,Unpack}{4,8}
56-
*
57-
* The struct and pickle (at least) modules need an efficient platform-
58-
* independent way to store floating-point values as byte strings.
59-
* The Pack routines produce a string from a C double, and the Unpack
60-
* routines produce a C double from such a string. The suffix (4 or 8)
61-
* specifies the number of bytes in the string.
62-
*
63-
* On platforms that appear to use (see _PyFloat_Init()) IEEE-754 formats
64-
* these functions work by copying bits. On other platforms, the formats the
65-
* 4- byte format is identical to the IEEE-754 single precision format, and
66-
* the 8-byte format to the IEEE-754 double precision format, although the
67-
* packing of INFs and NaNs (if such things exist on the platform) isn't
68-
* handled correctly, and attempting to unpack a string containing an IEEE
69-
* INF or NaN will raise an exception.
70-
*
71-
* On non-IEEE platforms with more precision, or larger dynamic range, than
72-
* 754 supports, not all values can be packed; on non-IEEE platforms with less
73-
* precision, or smaller dynamic range, not all values can be unpacked. What
74-
* happens in such cases is partly accidental (alas).
75-
*/
76-
77-
/* The pack routines write 2, 4 or 8 bytes, starting at p. le is a bool
78-
* argument, true if you want the string in little-endian format (exponent
79-
* last, at p+1, p+3 or p+7), false if you want big-endian format (exponent
80-
* first, at p).
81-
* Return value: 0 if all is OK, -1 if error (and an exception is
82-
* set, most likely OverflowError).
83-
* There are two problems on non-IEEE platforms:
84-
* 1): What this does is undefined if x is a NaN or infinity.
85-
* 2): -0.0 and +0.0 produce the same string.
86-
*/
87-
PyAPI_FUNC(int) _PyFloat_Pack2(double x, unsigned char *p, int le);
88-
PyAPI_FUNC(int) _PyFloat_Pack4(double x, unsigned char *p, int le);
89-
PyAPI_FUNC(int) _PyFloat_Pack8(double x, unsigned char *p, int le);
90-
91-
/* The unpack routines read 2, 4 or 8 bytes, starting at p. le is a bool
92-
* argument, true if the string is in little-endian format (exponent
93-
* last, at p+1, p+3 or p+7), false if big-endian (exponent first, at p).
94-
* Return value: The unpacked double. On error, this is -1.0 and
95-
* PyErr_Occurred() is true (and an exception is set, most likely
96-
* OverflowError). Note that on a non-IEEE platform this will refuse
97-
* to unpack a string that represents a NaN or infinity.
98-
*/
99-
PyAPI_FUNC(double) _PyFloat_Unpack2(const unsigned char *p, int le);
100-
PyAPI_FUNC(double) _PyFloat_Unpack4(const unsigned char *p, int le);
101-
PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le);
102-
103-
PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
104-
105-
/* Format the object based on the format_spec, as defined in PEP 3101
106-
(Advanced String Formatting). */
107-
PyAPI_FUNC(int) _PyFloat_FormatAdvancedWriter(
108-
_PyUnicodeWriter *writer,
109-
PyObject *obj,
110-
PyObject *format_spec,
111-
Py_ssize_t start,
112-
Py_ssize_t end);
113-
#endif /* Py_LIMITED_API */
48+
# define Py_CPYTHON_FLOATOBJECT_H
49+
# include "cpython/floatobject.h"
50+
# undef Py_CPYTHON_FLOATOBJECT_H
51+
#endif
11452

11553
#ifdef __cplusplus
11654
}

Include/internal/pycore_floatobject.h

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#ifndef Py_INTERNAL_FLOATOBJECT_H
2+
#define Py_INTERNAL_FLOATOBJECT_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
/* _PyFloat_{Pack,Unpack}{4,8}
12+
*
13+
* The struct and pickle (at least) modules need an efficient platform-
14+
* independent way to store floating-point values as byte strings.
15+
* The Pack routines produce a string from a C double, and the Unpack
16+
* routines produce a C double from such a string. The suffix (4 or 8)
17+
* specifies the number of bytes in the string.
18+
*
19+
* On platforms that appear to use (see _PyFloat_Init()) IEEE-754 formats
20+
* these functions work by copying bits. On other platforms, the formats the
21+
* 4- byte format is identical to the IEEE-754 single precision format, and
22+
* the 8-byte format to the IEEE-754 double precision format, although the
23+
* packing of INFs and NaNs (if such things exist on the platform) isn't
24+
* handled correctly, and attempting to unpack a string containing an IEEE
25+
* INF or NaN will raise an exception.
26+
*
27+
* On non-IEEE platforms with more precision, or larger dynamic range, than
28+
* 754 supports, not all values can be packed; on non-IEEE platforms with less
29+
* precision, or smaller dynamic range, not all values can be unpacked. What
30+
* happens in such cases is partly accidental (alas).
31+
*/
32+
33+
/* The pack routines write 2, 4 or 8 bytes, starting at p. le is a bool
34+
* argument, true if you want the string in little-endian format (exponent
35+
* last, at p+1, p+3 or p+7), false if you want big-endian format (exponent
36+
* first, at p).
37+
* Return value: 0 if all is OK, -1 if error (and an exception is
38+
* set, most likely OverflowError).
39+
* There are two problems on non-IEEE platforms:
40+
* 1): What this does is undefined if x is a NaN or infinity.
41+
* 2): -0.0 and +0.0 produce the same string.
42+
*/
43+
PyAPI_FUNC(int) _PyFloat_Pack2(double x, unsigned char *p, int le);
44+
PyAPI_FUNC(int) _PyFloat_Pack4(double x, unsigned char *p, int le);
45+
PyAPI_FUNC(int) _PyFloat_Pack8(double x, unsigned char *p, int le);
46+
47+
/* The unpack routines read 2, 4 or 8 bytes, starting at p. le is a bool
48+
* argument, true if the string is in little-endian format (exponent
49+
* last, at p+1, p+3 or p+7), false if big-endian (exponent first, at p).
50+
* Return value: The unpacked double. On error, this is -1.0 and
51+
* PyErr_Occurred() is true (and an exception is set, most likely
52+
* OverflowError). Note that on a non-IEEE platform this will refuse
53+
* to unpack a string that represents a NaN or infinity.
54+
*/
55+
PyAPI_FUNC(double) _PyFloat_Unpack2(const unsigned char *p, int le);
56+
PyAPI_FUNC(double) _PyFloat_Unpack4(const unsigned char *p, int le);
57+
PyAPI_FUNC(double) _PyFloat_Unpack8(const unsigned char *p, int le);
58+
59+
60+
PyAPI_FUNC(void) _PyFloat_DebugMallocStats(FILE* out);
61+
62+
63+
/* Format the object based on the format_spec, as defined in PEP 3101
64+
(Advanced String Formatting). */
65+
PyAPI_FUNC(int) _PyFloat_FormatAdvancedWriter(
66+
_PyUnicodeWriter *writer,
67+
PyObject *obj,
68+
PyObject *format_spec,
69+
Py_ssize_t start,
70+
Py_ssize_t end);
71+
72+
#ifdef __cplusplus
73+
}
74+
#endif
75+
#endif /* !Py_INTERNAL_FLOATOBJECT_H */

Makefile.pre.in

+2
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,7 @@ PYTHON_HEADERS= \
12081208
$(srcdir)/Include/cpython/dictobject.h \
12091209
$(srcdir)/Include/cpython/fileobject.h \
12101210
$(srcdir)/Include/cpython/fileutils.h \
1211+
$(srcdir)/Include/cpython/floatobject.h \
12111212
$(srcdir)/Include/cpython/frameobject.h \
12121213
$(srcdir)/Include/cpython/import.h \
12131214
$(srcdir)/Include/cpython/initconfig.h \
@@ -1250,6 +1251,7 @@ PYTHON_HEADERS= \
12501251
$(srcdir)/Include/internal/pycore_dict.h \
12511252
$(srcdir)/Include/internal/pycore_dtoa.h \
12521253
$(srcdir)/Include/internal/pycore_fileutils.h \
1254+
$(srcdir)/Include/internal/pycore_floatobject.h \
12531255
$(srcdir)/Include/internal/pycore_format.h \
12541256
$(srcdir)/Include/internal/pycore_getopt.h \
12551257
$(srcdir)/Include/internal/pycore_gil.h \

Modules/_ctypes/cfield.c

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "pycore_bitutils.h" // _Py_bswap32()
88
#include "pycore_call.h" // _PyObject_CallNoArgs()
9+
#include "pycore_floatobject.h" // _PyFloat_Pack8()
910

1011
#include <ffi.h>
1112
#include "ctypes.h"

Modules/_pickle.c

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#endif
1010

1111
#include "Python.h"
12+
#include "pycore_floatobject.h" // _PyFloat_Pack8()
1213
#include "pycore_moduleobject.h" // _PyModule_GetState()
1314
#include "structmember.h" // PyMemberDef
1415

Modules/_struct.c

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define PY_SSIZE_T_CLEAN
77

88
#include "Python.h"
9+
#include "pycore_floatobject.h" // _PyFloat_Unpack2()
910
#include "pycore_moduleobject.h" // _PyModule_GetState()
1011
#include "structmember.h" // PyMemberDef
1112
#include <ctype.h>

Modules/arraymodule.c

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#define PY_SSIZE_T_CLEAN
77
#include "Python.h"
8+
#include "pycore_floatobject.h" // _PyFloat_Unpack4()
89
#include "pycore_moduleobject.h" // _PyModule_GetState()
910
#include "structmember.h" // PyMemberDef
1011
#include <stddef.h> // offsetof()

Objects/floatobject.c

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "Python.h"
77
#include "pycore_dtoa.h" // _Py_dg_dtoa()
8+
#include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter()
89
#include "pycore_interp.h" // _PyInterpreterState.float_state
910
#include "pycore_long.h" // _PyLong_GetOne()
1011
#include "pycore_object.h" // _PyObject_Init()

Objects/object.c

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "pycore_ceval.h" // _Py_EnterRecursiveCall()
77
#include "pycore_context.h"
88
#include "pycore_dict.h"
9+
#include "pycore_floatobject.h" // _PyFloat_DebugMallocStats()
910
#include "pycore_initconfig.h" // _PyStatus_EXCEPTION()
1011
#include "pycore_object.h" // _PyType_CheckConsistency()
1112
#include "pycore_pyerrors.h" // _PyErr_Occurred()

Objects/stringlib/unicode_format.h

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
unicode_format.h -- implementation of str.format().
33
*/
44

5+
#include "pycore_floatobject.h" // _PyFloat_FormatAdvancedWriter()
6+
57
/************************************************************************/
68
/*********** Global data structures and forward declarations *********/
79
/************************************************************************/

PCbuild/pythoncore.vcxproj

+2
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
<ClInclude Include="..\Include\cpython\dictobject.h" />
133133
<ClInclude Include="..\Include\cpython\fileobject.h" />
134134
<ClInclude Include="..\Include\cpython\fileutils.h" />
135+
<ClInclude Include="..\Include\cpython\floatobject.h" />
135136
<ClInclude Include="..\Include\cpython\frameobject.h" />
136137
<ClInclude Include="..\Include\cpython\import.h" />
137138
<ClInclude Include="..\Include\cpython\initconfig.h" />
@@ -188,6 +189,7 @@
188189
<ClInclude Include="..\Include\internal\pycore_context.h" />
189190
<ClInclude Include="..\Include\internal\pycore_dtoa.h" />
190191
<ClInclude Include="..\Include\internal\pycore_fileutils.h" />
192+
<ClInclude Include="..\Include\internal\pycore_floatobject.h" />
191193
<ClInclude Include="..\Include\internal\pycore_format.h" />
192194
<ClInclude Include="..\Include\internal\pycore_gc.h" />
193195
<ClInclude Include="..\Include\internal\pycore_getopt.h" />

PCbuild/pythoncore.vcxproj.filters

+6
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,9 @@
393393
<ClInclude Include="..\Include\cpython\fileutils.h">
394394
<Filter>Include\cpython</Filter>
395395
</ClInclude>
396+
<ClInclude Include="..\Include\cpython\floatobject.h">
397+
<Filter>Include\cpython</Filter>
398+
</ClInclude>
396399
<ClInclude Include="..\Include\cpython\import.h">
397400
<Filter>Include\cpython</Filter>
398401
</ClInclude>
@@ -522,6 +525,9 @@
522525
<ClInclude Include="..\Include\internal\pycore_fileutils.h">
523526
<Filter>Include\internal</Filter>
524527
</ClInclude>
528+
<ClInclude Include="..\Include\internal\pycore_floatobject.h">
529+
<Filter>Include\internal</Filter>
530+
</ClInclude>
525531
<ClInclude Include="..\Include\internal\pycore_format.h">
526532
<Filter>Include\internal</Filter>
527533
</ClInclude>

Python/marshal.c

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "Python.h"
1212
#include "pycore_call.h" // _PyObject_CallNoArgs()
1313
#include "pycore_code.h" // _PyCode_New()
14+
#include "pycore_floatobject.h" // _PyFloat_Pack8()
1415
#include "pycore_hashtable.h" // _Py_hashtable_t
1516
#include "longintrepr.h"
1617
#include "code.h"

0 commit comments

Comments
 (0)