Skip to content

Commit 319091e

Browse files
committed
Merge branch 'main' into decimal-logop-docs
2 parents f1496f8 + 4075fe1 commit 319091e

File tree

18 files changed

+174
-213
lines changed

18 files changed

+174
-213
lines changed

Doc/library/itertools.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,19 @@ which incur interpreter overhead.
866866
window.append(x)
867867
yield math.sumprod(kernel, window)
868868

869+
def polynomial_eval(coefficients, x):
870+
"""Evaluate a polynomial at a specific value.
871+
872+
Computes with better numeric stability than Horner's method.
873+
"""
874+
# Evaluate x³ -4x² -17x + 60 at x = 2.5
875+
# polynomial_eval([1, -4, -17, 60], x=2.5) --> 8.125
876+
n = len(coefficients)
877+
if n == 0:
878+
return x * 0 # coerce zero to the type of x
879+
powers = accumulate(repeat(x, n - 1), operator.mul, initial=1)
880+
return math.sumprod(reversed(coefficients), powers)
881+
869882
def polynomial_from_roots(roots):
870883
"""Compute a polynomial's coefficients from its roots.
871884

@@ -1245,6 +1258,37 @@ which incur interpreter overhead.
12451258
>>> list(convolve(data, [1, -2, 1]))
12461259
[20, 0, -36, 24, -20, 20, -20, -4, 16]
12471260

1261+
>>> from fractions import Fraction
1262+
>>> from decimal import Decimal
1263+
>>> polynomial_eval([1, -4, -17, 60], x=2)
1264+
18
1265+
>>> x = 2; x**3 - 4*x**2 -17*x + 60
1266+
18
1267+
>>> polynomial_eval([1, -4, -17, 60], x=2.5)
1268+
8.125
1269+
>>> x = 2.5; x**3 - 4*x**2 -17*x + 60
1270+
8.125
1271+
>>> polynomial_eval([1, -4, -17, 60], x=Fraction(2, 3))
1272+
Fraction(1274, 27)
1273+
>>> x = Fraction(2, 3); x**3 - 4*x**2 -17*x + 60
1274+
Fraction(1274, 27)
1275+
>>> polynomial_eval([1, -4, -17, 60], x=Decimal('1.75'))
1276+
Decimal('23.359375')
1277+
>>> x = Decimal('1.75'); x**3 - 4*x**2 -17*x + 60
1278+
Decimal('23.359375')
1279+
>>> polynomial_eval([], 2)
1280+
0
1281+
>>> polynomial_eval([], 2.5)
1282+
0.0
1283+
>>> polynomial_eval([], Fraction(2, 3))
1284+
Fraction(0, 1)
1285+
>>> polynomial_eval([], Decimal('1.75'))
1286+
Decimal('0.00')
1287+
>>> polynomial_eval([11], 7) == 11
1288+
True
1289+
>>> polynomial_eval([11, 2], 7) == 11 * 7 + 2
1290+
True
1291+
12481292
>>> polynomial_from_roots([5, -4, 3])
12491293
[1, -4, -17, 60]
12501294
>>> factored = lambda x: (x - 5) * (x + 4) * (x - 3)

Doc/whatsnew/3.12.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,11 @@ Porting to Python 3.12
10361036
functions that set the error indicator now normalize the exception
10371037
before storing it. (Contributed by Mark Shannon in :gh:`101578`.)
10381038

1039+
* ``_Py_RefTotal`` is no longer authoritative and only kept around
1040+
for ABI compabitility. Note that it is an internal global and only
1041+
available on debug builds. If you happen to be using it then you'll
1042+
need to start using ``_Py_GetGlobalRefTotal()``.
1043+
10391044
Deprecated
10401045
----------
10411046

Include/cpython/object.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ PyAPI_FUNC(void) _Py_ForgetReference(PyObject *);
1111
#endif
1212

1313
#ifdef Py_REF_DEBUG
14-
PyAPI_FUNC(Py_ssize_t) _Py_GetRefTotal(void);
14+
/* These are useful as debugging aids when chasing down refleaks. */
15+
PyAPI_FUNC(Py_ssize_t) _Py_GetGlobalRefTotal(void);
16+
# define _Py_GetRefTotal() _Py_GetGlobalRefTotal()
17+
PyAPI_FUNC(Py_ssize_t) _Py_GetLegacyRefTotal(void);
1518
#endif
1619

1720

Include/internal/pycore_object.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ PyAPI_DATA(Py_ssize_t) _Py_RefTotal;
4646
extern void _Py_AddRefTotal(Py_ssize_t);
4747
extern void _Py_IncRefTotal(void);
4848
extern void _Py_DecRefTotal(void);
49-
# define _Py_DEC_REFTOTAL() _Py_RefTotal--
49+
50+
# define _Py_DEC_REFTOTAL() _PyRuntime.object_state.reftotal--
5051
#endif
5152

5253
// Increment reference count by n
@@ -225,6 +226,7 @@ static inline void _PyObject_GC_UNTRACK(
225226
#endif
226227

227228
#ifdef Py_REF_DEBUG
229+
extern void _Py_FinalizeRefTotal(_PyRuntimeState *);
228230
extern void _PyDebug_PrintTotalRefs(void);
229231
#endif
230232

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#ifndef Py_INTERNAL_OBJECT_STATE_H
2+
#define Py_INTERNAL_OBJECT_STATE_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+
struct _py_object_runtime_state {
12+
#ifdef Py_REF_DEBUG
13+
Py_ssize_t reftotal;
14+
#else
15+
int _not_used;
16+
#endif
17+
};
18+
19+
20+
#ifdef __cplusplus
21+
}
22+
#endif
23+
#endif /* !Py_INTERNAL_OBJECT_STATE_H */

Include/internal/pycore_runtime.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ extern "C" {
1515
#include "pycore_global_objects.h" // struct _Py_global_objects
1616
#include "pycore_import.h" // struct _import_runtime_state
1717
#include "pycore_interp.h" // PyInterpreterState
18+
#include "pycore_object_state.h" // struct _py_object_runtime_state
1819
#include "pycore_parser.h" // struct _parser_runtime_state
1920
#include "pycore_pymem.h" // struct _pymem_allocators
2021
#include "pycore_pyhash.h" // struct pyhash_runtime_state
@@ -150,6 +151,7 @@ typedef struct pyruntimestate {
150151
void *open_code_userdata;
151152
_Py_AuditHookEntry *audit_hook_head;
152153

154+
struct _py_object_runtime_state object_state;
153155
struct _Py_float_runtime_state float_state;
154156
struct _Py_unicode_runtime_state unicode_state;
155157

Include/object.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -494,14 +494,9 @@ you can count such references to the type object.)
494494
extern Py_ssize_t _Py_RefTotal;
495495
# define _Py_INC_REFTOTAL() _Py_RefTotal++
496496
# define _Py_DEC_REFTOTAL() _Py_RefTotal--
497-
# elif defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
498-
extern void _Py_IncRefTotal(void);
499-
extern void _Py_DecRefTotal(void);
500-
# define _Py_INC_REFTOTAL() _Py_IncRefTotal()
501-
# define _Py_DEC_REFTOTAL() _Py_DecRefTotal()
502497
# elif !defined(Py_LIMITED_API) || Py_LIMITED_API+0 > 0x030C0000
503-
extern void _Py_IncRefTotal_DO_NOT_USE_THIS(void);
504-
extern void _Py_DecRefTotal_DO_NOT_USE_THIS(void);
498+
PyAPI_FUNC(void) _Py_IncRefTotal_DO_NOT_USE_THIS(void);
499+
PyAPI_FUNC(void) _Py_DecRefTotal_DO_NOT_USE_THIS(void);
505500
# define _Py_INC_REFTOTAL() _Py_IncRefTotal_DO_NOT_USE_THIS()
506501
# define _Py_DEC_REFTOTAL() _Py_DecRefTotal_DO_NOT_USE_THIS()
507502
# endif

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,7 @@ PYTHON_HEADERS= \
16991699
$(srcdir)/Include/internal/pycore_moduleobject.h \
17001700
$(srcdir)/Include/internal/pycore_namespace.h \
17011701
$(srcdir)/Include/internal/pycore_object.h \
1702+
$(srcdir)/Include/internal/pycore_object_state.h \
17021703
$(srcdir)/Include/internal/pycore_obmalloc.h \
17031704
$(srcdir)/Include/internal/pycore_obmalloc_init.h \
17041705
$(srcdir)/Include/internal/pycore_pathconfig.h \
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``Misc/gdbinit`` was removed.

Misc/gdbinit

Lines changed: 0 additions & 176 deletions
This file was deleted.

0 commit comments

Comments
 (0)