77#include "pycore_initconfig.h" // _PyStatus_OK()
88#include "pycore_call.h" // _PyObject_MakeTpCall
99#include "pycore_freelist.h" // _Py_FREELIST_FREE, _Py_FREELIST_POP
10+ #include "pycore_lock.h" // _PyOnceFlag_CallOnce
1011#include "pycore_long.h" // _Py_SmallInts
1112#include "pycore_object.h" // _PyObject_Init()
1213#include "pycore_runtime.h" // _PY_NSMALLPOSINTS
@@ -2732,6 +2733,36 @@ pylong_int_from_string(const char *start, const char *end, PyLongObject **res)
27322733}
27332734#endif /* WITH_PYLONG_MODULE */
27342735
2736+ static struct non_binary_base_state {
2737+ double log_base_BASE ;
2738+ twodigits convmultmax_base ;
2739+ int convwidth_base ;
2740+ _PyOnceFlag once ;
2741+ } state [37 ];
2742+
2743+ static int
2744+ init_non_binary_base (void * arg )
2745+ {
2746+ int base = * (int * )arg ;
2747+ twodigits convmax = base ;
2748+ int i = 1 ;
2749+
2750+ state [base ].log_base_BASE = (log ((double )base ) /
2751+ log ((double )PyLong_BASE ));
2752+ for (;;) {
2753+ twodigits next = convmax * base ;
2754+ if (next > PyLong_BASE ) {
2755+ break ;
2756+ }
2757+ convmax = next ;
2758+ ++ i ;
2759+ }
2760+ state [base ].convmultmax_base = convmax ;
2761+ assert (i > 0 );
2762+ state [base ].convwidth_base = i ;
2763+ return 0 ;
2764+ }
2765+
27352766/***
27362767long_from_non_binary_base: parameters and return values are the same as
27372768long_from_binary_base.
@@ -2748,26 +2779,26 @@ case number of Python digits needed to hold it is the smallest integer n s.t.
27482779 BASE**n >= B**N [taking logs to base BASE]
27492780 n >= log(B**N)/log(BASE) = N * log(B)/log(BASE)
27502781
2751- The static array log_base_BASE[base] == log(base)/log(BASE) so we can compute
2782+ The value log_base_BASE == log(base)/log(BASE) so we can compute
27522783this quickly. A Python int with that much space is reserved near the start,
27532784and the result is computed into it.
27542785
27552786The input string is actually treated as being in base base**i (i.e., i digits
2756- are processed at a time), where two more static arrays hold :
2787+ are processed at a time), where two more values :
27572788
2758- convwidth_base[base] = the largest integer i such that base**i <= BASE
2759- convmultmax_base[base] = base ** convwidth_base[base]
2789+ convwidth_base = the largest integer i such that base**i <= BASE
2790+ convmultmax_base = base ** convwidth_base
27602791
27612792The first of these is the largest i such that i consecutive input digits
27622793must fit in a single Python digit. The second is effectively the input
27632794base we're really using.
27642795
27652796Viewing the input as a sequence <c0, c1, ..., c_n-1> of digits in base
2766- convmultmax_base[base] , the result is "simply"
2797+ convmultmax_base, the result is "simply"
27672798
27682799 (((c0*B + c1)*B + c2)*B + c3)*B + ... ))) + c_n-1
27692800
2770- where B = convmultmax_base[base] .
2801+ where B = convmultmax_base.
27712802
27722803Error analysis: as above, the number of Python digits `n` needed is worst-
27732804case
@@ -2832,35 +2863,15 @@ long_from_non_binary_base(const char *start, const char *end, Py_ssize_t digits,
28322863 PyLongObject * z ;
28332864 const char * p ;
28342865
2835- static double log_base_BASE [37 ] = {0.0e0 ,};
2836- static int convwidth_base [37 ] = {0 ,};
2837- static twodigits convmultmax_base [37 ] = {0 ,};
2838-
2839- if (log_base_BASE [base ] == 0.0 ) {
2840- twodigits convmax = base ;
2841- int i = 1 ;
2842-
2843- log_base_BASE [base ] = (log ((double )base ) /
2844- log ((double )PyLong_BASE ));
2845- for (;;) {
2846- twodigits next = convmax * base ;
2847- if (next > PyLong_BASE ) {
2848- break ;
2849- }
2850- convmax = next ;
2851- ++ i ;
2852- }
2853- convmultmax_base [base ] = convmax ;
2854- assert (i > 0 );
2855- convwidth_base [base ] = i ;
2856- }
2866+ /* Initialize state[base] */
2867+ _PyOnceFlag_CallOnce (& state [base ].once , init_non_binary_base , & base );
28572868
28582869 /* Create an int object that can contain the largest possible
28592870 * integer with this base and length. Note that there's no
28602871 * need to initialize z->long_value.ob_digit -- no slot is read up before
28612872 * being stored into.
28622873 */
2863- double fsize_z = (double )digits * log_base_BASE [base ] + 1.0 ;
2874+ double fsize_z = (double )digits * state [base ]. log_base_BASE + 1.0 ;
28642875 if (fsize_z > (double )MAX_LONG_DIGITS ) {
28652876 /* The same exception as in long_alloc(). */
28662877 PyErr_SetString (PyExc_OverflowError ,
@@ -2882,8 +2893,8 @@ long_from_non_binary_base(const char *start, const char *end, Py_ssize_t digits,
28822893 /* `convwidth` consecutive input digits are treated as a single
28832894 * digit in base `convmultmax`.
28842895 */
2885- convwidth = convwidth_base [base ];
2886- convmultmax = convmultmax_base [base ];
2896+ convwidth = state [base ]. convwidth_base ;
2897+ convmultmax = state [base ]. convmultmax_base ;
28872898
28882899 /* Work ;-) */
28892900 p = start ;
0 commit comments