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