]> www.ginac.de Git - cln.git/commitdiff
* src/integer/conv/cl_I_cached_power.h: New file.
authorRichard Kreckel <kreckel@ginac.de>
Sun, 20 Nov 2005 22:41:03 +0000 (22:41 +0000)
committerRichard Kreckel <kreckel@ginac.de>
Sun, 20 Nov 2005 22:41:03 +0000 (22:41 +0000)
        * src/integer/conv/cl_I_cached_power.cc: New file.
        Contains power_table and cached_power_table previously...
        * src/integer/conv/cl_I_to_digits.cc: ...here.
        * src/integer/conv/cl_I_from_digits.cc: Use cached powers.

ChangeLog
src/integer/conv/cl_I_cached_power.cc [new file with mode: 0644]
src/integer/conv/cl_I_cached_power.h [new file with mode: 0644]
src/integer/conv/cl_I_from_digits.cc
src/integer/conv/cl_I_to_digits.cc

index 18e8e19a31523c4d63f306360abb786b7544862b..d42516c97e93ebf4aed56210d99dd22df18fada3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2005-11-20  Richard B. Kreckel  <kreckel@ginac.de>
+
+       * src/integer/conv/cl_I_cached_power.h: New file.
+       * src/integer/conv/cl_I_cached_power.cc: New file.
+       Contains power_table and cached_power_table previously...
+       * src/integer/conv/cl_I_to_digits.cc: ...here.
+       * src/integer/conv/cl_I_from_digits.cc: Use cached powers.
+
 2005-11-02  Richard B. Kreckel  <kreckel@ginac.de>
 
        * src/integer/conv/cl_I_from_digits.cc: Made input of all numbers in
diff --git a/src/integer/conv/cl_I_cached_power.cc b/src/integer/conv/cl_I_cached_power.cc
new file mode 100644 (file)
index 0000000..1571d2a
--- /dev/null
@@ -0,0 +1,202 @@
+// cached_power().\r
+\r
+// Specification.\r
+#include "cl_I_cached_power.h"\r
+\r
+\r
+// Implementation.\r
+\r
+namespace cln {\r
+\r
+const power_table_entry power_table [36-2+1] = {\r
+#if (intDsize==8)\r
+       { 7, 2*2*2*2*2*2*2 },\r
+       { 5, 3*3*3*3*3 },\r
+       { 3, 4*4*4 },\r
+       { 3, 5*5*5 },\r
+       { 3, 6*6*6 },\r
+       { 2, 7*7 },\r
+       { 2, 8*8 },\r
+       { 2, 9*9 },\r
+       { 2, 10*10 },\r
+       { 2, 11*11 },\r
+       { 2, 12*12 },\r
+       { 2, 13*13 },\r
+       { 2, 14*14 },\r
+       { 2, 15*15 },\r
+       { 1, 16 },\r
+       { 1, 17 },\r
+       { 1, 18 },\r
+       { 1, 19 },\r
+       { 1, 20 },\r
+       { 1, 21 },\r
+       { 1, 22 },\r
+       { 1, 23 },\r
+       { 1, 24 },\r
+       { 1, 25 },\r
+       { 1, 26 },\r
+       { 1, 27 },\r
+       { 1, 28 },\r
+       { 1, 29 },\r
+       { 1, 30 },\r
+       { 1, 31 },\r
+       { 1, 32 },\r
+       { 1, 33 },\r
+       { 1, 34 },\r
+       { 1, 35 },\r
+       { 1, 36 },\r
+#endif\r
+#if (intDsize==16)\r
+       { 15, 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2 },\r
+       { 10, 3*3*3*3*3*3*3*3*3*3 },\r
+       {  7, 4*4*4*4*4*4*4 },\r
+       {  6, 5*5*5*5*5*5 },\r
+       {  6, 6*6*6*6*6*6 },\r
+       {  5, 7*7*7*7*7 },\r
+       {  5, 8*8*8*8*8 },\r
+       {  5, 9*9*9*9*9 },\r
+       {  4, 10*10*10*10 },\r
+       {  4, 11*11*11*11 },\r
+       {  4, 12*12*12*12 },\r
+       {  4, 13*13*13*13 },\r
+       {  4, 14*14*14*14 },\r
+       {  4, 15*15*15*15 },\r
+       {  3, 16*16*16 },\r
+       {  3, 17*17*17 },\r
+       {  3, 18*18*18 },\r
+       {  3, 19*19*19 },\r
+       {  3, 20*20*20 },\r
+       {  3, 21*21*21 },\r
+       {  3, 22*22*22 },\r
+       {  3, 23*23*23 },\r
+       {  3, 24*24*24 },\r
+       {  3, 25*25*25 },\r
+       {  3, 26*26*26 },\r
+       {  3, 27*27*27 },\r
+       {  3, 28*28*28 },\r
+       {  3, 29*29*29 },\r
+       {  3, 30*30*30 },\r
+       {  3, 31*31*31 },\r
+       {  3, 32*32*32 },\r
+       {  3, 33*33*33 },\r
+       {  3, 34*34*34 },\r
+       {  3, 35*35*35 },\r
+       {  3, 36*36*36 },\r
+#endif\r
+#if (intDsize==32)\r
+       { 31, 2UL*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2 },\r
+       { 20, 3UL*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3 },\r
+       { 15, 4UL*4*4*4*4*4*4*4*4*4*4*4*4*4*4 },\r
+       { 13, 5UL*5*5*5*5*5*5*5*5*5*5*5*5 },\r
+       { 12, 6UL*6*6*6*6*6*6*6*6*6*6*6 },\r
+       { 11, 7UL*7*7*7*7*7*7*7*7*7*7 },\r
+       { 10, 8UL*8*8*8*8*8*8*8*8*8 },\r
+       { 10, 9UL*9*9*9*9*9*9*9*9*9 },\r
+       {  9, 10UL*10*10*10*10*10*10*10*10 },\r
+       {  9, 11UL*11*11*11*11*11*11*11*11 },\r
+       {  8, 12UL*12*12*12*12*12*12*12 },\r
+       {  8, 13UL*13*13*13*13*13*13*13 },\r
+       {  8, 14UL*14*14*14*14*14*14*14 },\r
+       {  8, 15UL*15*15*15*15*15*15*15 },\r
+       {  7, 16UL*16*16*16*16*16*16 },\r
+       {  7, 17UL*17*17*17*17*17*17 },\r
+       {  7, 18UL*18*18*18*18*18*18 },\r
+       {  7, 19UL*19*19*19*19*19*19 },\r
+       {  7, 20UL*20*20*20*20*20*20 },\r
+       {  7, 21UL*21*21*21*21*21*21 },\r
+       {  7, 22UL*22*22*22*22*22*22 },\r
+       {  7, 23UL*23*23*23*23*23*23 },\r
+       {  6, 24UL*24*24*24*24*24 },\r
+       {  6, 25UL*25*25*25*25*25 },\r
+       {  6, 26UL*26*26*26*26*26 },\r
+       {  6, 27UL*27*27*27*27*27 },\r
+       {  6, 28UL*28*28*28*28*28 },\r
+       {  6, 29UL*29*29*29*29*29 },\r
+       {  6, 30UL*30*30*30*30*30 },\r
+       {  6, 31UL*31*31*31*31*31 },\r
+       {  6, 32UL*32*32*32*32*32 },\r
+       {  6, 33UL*33*33*33*33*33 },\r
+       {  6, 34UL*34*34*34*34*34 },\r
+       {  6, 35UL*35*35*35*35*35 },\r
+       {  6, 36UL*36*36*36*36*36 },\r
+#endif\r
+#if (intDsize==64)\r
+       { 63, 2ULL*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2 },\r
+       { 40, 3ULL*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3 },\r
+       { 31, 4ULL*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4 },\r
+       { 27, 5ULL*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5 },\r
+       { 24, 6ULL*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6 },\r
+       { 22, 7ULL*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7 },\r
+       { 21, 8ULL*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8 },\r
+       { 20, 9ULL*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9 },\r
+       { 19, 10ULL*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10 },\r
+       { 18, 11ULL*11*11*11*11*11*11*11*11*11*11*11*11*11*11*11*11*11 },\r
+       { 17, 12ULL*12*12*12*12*12*12*12*12*12*12*12*12*12*12*12*12 },\r
+       { 17, 13ULL*13*13*13*13*13*13*13*13*13*13*13*13*13*13*13*13 },\r
+       { 16, 14ULL*14*14*14*14*14*14*14*14*14*14*14*14*14*14*14 },\r
+       { 16, 15ULL*15*15*15*15*15*15*15*15*15*15*15*15*15*15*15 },\r
+       { 15, 16ULL*16*16*16*16*16*16*16*16*16*16*16*16*16*16 },\r
+       { 15, 17ULL*17*17*17*17*17*17*17*17*17*17*17*17*17*17 },\r
+       { 15, 18ULL*18*18*18*18*18*18*18*18*18*18*18*18*18*18 },\r
+       { 15, 19ULL*19*19*19*19*19*19*19*19*19*19*19*19*19*19 },\r
+       { 14, 20ULL*20*20*20*20*20*20*20*20*20*20*20*20*20 },\r
+       { 14, 21ULL*21*21*21*21*21*21*21*21*21*21*21*21*21 },\r
+       { 14, 22ULL*22*22*22*22*22*22*22*22*22*22*22*22*22 },\r
+       { 14, 23ULL*23*23*23*23*23*23*23*23*23*23*23*23*23 },\r
+       { 13, 24ULL*24*24*24*24*24*24*24*24*24*24*24*24 },\r
+       { 13, 25ULL*25*25*25*25*25*25*25*25*25*25*25*25 },\r
+       { 13, 26ULL*26*26*26*26*26*26*26*26*26*26*26*26 },\r
+       { 13, 27ULL*27*27*27*27*27*27*27*27*27*27*27*27 },\r
+       { 13, 28ULL*28*28*28*28*28*28*28*28*28*28*28*28 },\r
+       { 13, 29ULL*29*29*29*29*29*29*29*29*29*29*29*29 },\r
+       { 13, 30ULL*30*30*30*30*30*30*30*30*30*30*30*30 },\r
+       { 12, 31ULL*31*31*31*31*31*31*31*31*31*31*31 },\r
+       { 12, 32ULL*32*32*32*32*32*32*32*32*32*32*32 },\r
+       { 12, 33ULL*33*33*33*33*33*33*33*33*33*33*33 },\r
+       { 12, 34ULL*34*34*34*34*34*34*34*34*34*34*34 },\r
+       { 12, 35ULL*35*35*35*35*35*35*35*35*35*35*35 },\r
+       { 12, 36ULL*36*36*36*36*36*36*36*36*36*36*36 },\r
+#endif\r
+};\r
+\r
+cached_power_table* ctable [36-2+1] = {\r
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\r
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\r
+       NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,\r
+       NULL, NULL, NULL, NULL, NULL\r
+};\r
+\r
+const cached_power_table_entry * cached_power (uintD base, uintL i)\r
+{\r
+       var cached_power_table* ptr;\r
+       if (!(ptr = ctable[base-2]))\r
+        { ctable[base-2] = ptr = new cached_power_table (); }\r
+       var uintL j;\r
+       for (j = 0; j <= i; j++) {\r
+               if (zerop(ptr->element[j].base_pow)) {\r
+                       // Compute b^(k*2^j) and its inverse.\r
+                       cl_I x =\r
+                           (j==0 ? cl_I(power_table[base-2].b_to_the_k)\r
+                                 : ptr->element[j-1].base_pow * ptr->element[j-1].base_pow\r
+                            );\r
+                       ptr->element[j].base_pow = x;\r
+#ifdef MUL_REPLACES_DIV\r
+                       ptr->element[j].inv_base_pow = floor1(ash(1,2*integer_length(x)),x);\r
+#endif\r
+               }\r
+       }\r
+       return &ptr->element[i];\r
+}\r
+\r
+AT_DESTRUCTION(cached_power)\r
+{\r
+       for (var uintD base = 2; base <= 36; base++) {\r
+               var cached_power_table* ptr = ctable[base-2];\r
+               if (ptr) {\r
+                       delete ptr;\r
+                       ctable[base-2] = NULL;\r
+               }\r
+        }\r
+}\r
+\r
+}  // namespace cln\r
diff --git a/src/integer/conv/cl_I_cached_power.h b/src/integer/conv/cl_I_cached_power.h
new file mode 100644 (file)
index 0000000..1c6899a
--- /dev/null
@@ -0,0 +1,47 @@
+// cached_power().\r
+\r
+// General includes.\r
+#include "cl_sysdep.h"\r
+\r
+// Specification.\r
+#include "cl_I.h"\r
+\r
+\r
+// Implementation.\r
+\r
+namespace cln {\r
+\r
+// Table: For each base b (2 <= b <= 36), store k and b^k where k is the largest\r
+// integer such that b^k < 2^intDsize, i.e. k == floor(log(2^intDsize-1,b)).\r
+struct power_table_entry {\r
+       uintC k;\r
+       uintD b_to_the_k;\r
+};\r
+extern const power_table_entry power_table [36-2+1];\r
+\r
+// Table: contains for each base b (2 <= b <= 36) either NULL or an array of\r
+// lazily computed b^(k*2^i) and maybe 1/b^(k*2^i).\r
+//#define MUL_REPLACES_DIV\r
+struct cached_power_table_entry {\r
+       ALLOCATE_ANYWHERE(cached_power_table_entry)\r
+       cl_I base_pow; // 0 or b^(k*2^i)\r
+#ifdef MUL_REPLACES_DIV\r
+       cl_I inv_base_pow; // if base_pow: floor(2^(2*integer_length(base_pow))/base_pow)\r
+#endif\r
+};\r
+\r
+struct cached_power_table {\r
+       cached_power_table_entry element[30];\r
+       // Constructor and destructor - nothing special.\r
+       cached_power_table () {}\r
+       ~cached_power_table () {}\r
+       // Allocation and deallocation.\r
+       void* operator new (size_t size) { return malloc_hook(size); }\r
+       void operator delete (void* ptr) { free_hook(ptr); }\r
+};\r
+\r
+extern cached_power_table* ctable [36-2+1];\r
+\r
+const cached_power_table_entry * cached_power (uintD base, uintL i);\r
+\r
+}  // namespace cln\r
index 7e101ac39175e4bd9013955a5a354138675d6150..bbb1a51f9cb7f1d6cff8edb31f4979025177ed66 100644 (file)
@@ -10,6 +10,7 @@
 // Implementation.\r
 \r
 #include "cl_DS.h"\r
+#include "cl_I_cached_power.h"\r
 \r
 namespace cln {\r
 \r
@@ -57,39 +58,6 @@ static const cl_I digits_to_I_base2 (const char * MSBptr, uintL len, uintD base)
        return NUDS_to_I(erg_MSDptr,erg_len);\r
 }\r
 \r
-// For each base b in [2..36], power_table[b-2] contains the largest exponent e\r
-// such that b^e<2^intDsize, i.e. floor(log(2^intDsize-1,b)).\r
-static const uintC power_table [36-2+1] = {\r
-#if (intDsize==8)\r
-       /* base  2..7  */           7,  5,  3,  3,  3,  2,\r
-       /* base  8..15 */   2,  2,  2,  2,  2,  2,  2,  2,\r
-       /* base 16..23 */   1,  1,  1,  1,  1,  1,  1,  1,\r
-       /* base 24..31 */   1,  1,  1,  1,  1,  1,  1,  1,\r
-       /* base 32..36 */   1,  1,  1,  1,  1\r
-#endif\r
-#if (intDsize==16)\r
-       /* base  2..7  */          15, 10,  7,  6,  6,  5,\r
-       /* base  8..15 */   5,  5,  4,  4,  4,  4,  4,  4,\r
-       /* base 16..23 */   3,  3,  3,  3,  3,  3,  3,  3,\r
-       /* base 24..31 */   3,  3,  3,  3,  3,  3,  3,  3,\r
-       /* base 32..36 */   3,  3,  3,  3,  3\r
-#endif\r
-#if (intDsize==32)\r
-       /* base  2..7  */          31, 20, 15, 13, 12, 11,\r
-       /* base  8..15 */  10, 10,  9,  9,  8,  8,  8,  8,\r
-       /* base 16..23 */   7,  7,  7,  7,  7,  7,  7,  7,\r
-       /* base 24..31 */   6,  6,  6,  6,  6,  6,  6,  6,\r
-       /* base 32..36 */   6,  6,  6,  6,  6\r
-#endif\r
-#if (intDsize==64)\r
-       /* base  2..7  */          63, 40, 31, 27, 24, 22,\r
-       /* base  8..15 */  21, 20, 19, 18, 17, 17, 16, 16,\r
-       /* base 16..23 */  15, 15, 15, 15, 14, 14, 14, 14,\r
-       /* base 24..31 */  13, 13, 13, 13, 13, 13, 13, 12,\r
-       /* base 32..36 */  12, 12, 12, 12, 12\r
-#endif\r
-};\r
-\r
 static const cl_I digits_to_I_baseN (const char * MSBptr, uintL len, uintD base)\r
 {\r
        // base is not a power of two: Add digits one by one. Result nees\r
@@ -147,7 +115,7 @@ static const cl_I digits_to_I_baseN (const char * MSBptr, uintL len, uintD base)
                var uintD newdigit = 0;\r
                var uintC chx = 0;\r
                var uintD factor = 1;\r
-               while (chx < power_table[base-2] && len > 0) {\r
+               while (chx < power_table[base-2].k && len > 0) {\r
                        var uintB ch = *(const uintB *)MSBptr; MSBptr++; // next character\r
                        if (ch!='.') { // skip decimal point\r
                                // Compute value of ('0'-'9','A'-'Z','a'-'z'):\r
@@ -181,15 +149,25 @@ const cl_I digits_to_I (const char * MSBptr, uintL len, uintD base)
        } else {\r
                // This is quite insensitive to the breakeven point.\r
                // On a 1GHz Athlon I get approximately:\r
-               //   base  3: breakeven == 15000\r
-               //   base 10: breakeven ==  5000\r
-               //   base 36: breakeven ==  2000\r
-               if (len>50000/base)\r
+               //   base  3: breakeven around 25000\r
+               //   base 10: breakeven around  8000\r
+               //   base 36: breakeven around  2000\r
+               if (len>80000/base) {\r
                        // Divide-and-conquer:\r
-                       return digits_to_I(MSBptr,len/2,base)*expt_pos(base,len-len/2)\r
-                             +digits_to_I(MSBptr+len/2,len-len/2,base);\r
-               else\r
+                       // Find largest i such that B = base^(k*2^i) satisfies B <= X.\r
+                       var const cached_power_table_entry * p;\r
+                       var uintC len_B = power_table[base-2].k;\r
+                       for (uintC i = 0; ; i++) {\r
+                               p = cached_power(base, i);\r
+                               if (2*len_B >= len)\r
+                                       break;\r
+                               len_B = len_B*2;\r
+                       }\r
+                       return digits_to_I(MSBptr,len-len_B,base)*p->base_pow\r
+                             +digits_to_I(MSBptr+len-len_B,len_B,base);\r
+               } else {\r
                        return digits_to_I_baseN(MSBptr, len, base);\r
+               }\r
        }\r
 }\r
 \r
index 097d8927d63faa24640942306b7663ef7387fb93..1304b94363e4c5d06ad56544f752d0a41d1fc127 100644 (file)
 // Implementation.
 
 #include "cl_DS.h"
+#include "cl_I_cached_power.h"
 
 namespace cln {
 
-// Tabelle: enthält zu jeder Basis b (2 <= b <= 36)
-// - eine Kettenbruchapproximation num/den von intDsize*log(2)/log(b)
-//   (num/den >= intDsize*log(2)/log(b), mit num <= 2^10)
-// - k-1 und b^k mit b^k < 2^intDsize, k maximal.
-  typedef struct { /* uintW num,den; */ uintC k_1; uintD b_hoch_k; } power_table_entry;
-  static power_table_entry table [36-2+1] = {
-    #if (intDsize==8)
-      { /*    8,  1, */ 7-1, 2*2*2*2*2*2*2},
-      { /*  106, 21, */ 5-1, 3*3*3*3*3},
-      { /*    4,  1, */ 3-1, 4*4*4},
-      { /*  789,229, */ 3-1, 5*5*5},
-      { /*  359,116, */ 3-1, 6*6*6},
-      { /*  436,153, */ 2-1, 7*7},
-      { /*    8,  3, */ 2-1, 8*8},
-      { /*   53, 21, */ 2-1, 9*9},
-      { /*  525,218, */ 2-1, 10*10},
-      { /* 1006,435, */ 2-1, 11*11},
-      { /*  665,298, */ 2-1, 12*12},
-      { /*  988,457, */ 2-1, 13*13},
-      { /*  872,415, */ 2-1, 14*14},
-      { /*  987,482, */ 2-1, 15*15},
-      { /*    2,  1, */ 1-1, 16},
-      { /*  869,444, */ 1-1, 17},
-      { /*  871,454, */ 1-1, 18},
-      { /*  597,317, */ 1-1, 19},
-      { /*   87, 47, */ 1-1, 20},
-      { /*  989,543, */ 1-1, 21},
-      { /*  949,529, */ 1-1, 22},
-      { /*  191,108, */ 1-1, 23},
-      { /*  930,533, */ 1-1, 24},
-      { /*  789,458, */ 1-1, 25},
-      { /*  691,406, */ 1-1, 26},
-      { /*  461,274, */ 1-1, 27},
-      { /*  218,131, */ 1-1, 28},
-      { /*  690,419, */ 1-1, 29},
-      { /*  494,303, */ 1-1, 30},
-      { /*  633,392, */ 1-1, 31},
-      { /*    8,  5, */ 1-1, 32},
-      { /*  766,483, */ 1-1, 33},
-      { /*  629,400, */ 1-1, 34},
-      { /*  967,620, */ 1-1, 35},
-      { /*  359,232, */ 1-1, 36},
-    #endif
-    #if (intDsize==16)
-      { /*   16,  1, */ 15-1, 2*2*2*2*2*2*2*2*2*2*2*2*2*2*2},
-      { /*  212, 21, */ 10-1, 3*3*3*3*3*3*3*3*3*3},
-      { /*    8,  1, */  7-1, 4*4*4*4*4*4*4},
-      { /*  379, 55, */  6-1, 5*5*5*5*5*5},
-      { /*  359, 58, */  6-1, 6*6*6*6*6*6},
-      { /*  872,153, */  5-1, 7*7*7*7*7},
-      { /*   16,  3, */  5-1, 8*8*8*8*8},
-      { /*  106, 21, */  5-1, 9*9*9*9*9},
-      { /*  525,109, */  4-1, 10*10*10*10},
-      { /* 1013,219, */  4-1, 11*11*11*11},
-      { /*  665,149, */  4-1, 12*12*12*12},
-      { /*  761,176, */  4-1, 13*13*13*13},
-      { /*  685,163, */  4-1, 14*14*14*14},
-      { /*  987,241, */  4-1, 15*15*15*15},
-      { /*    4,  1, */  3-1, 16*16*16},
-      { /*  869,222, */  3-1, 17*17*17},
-      { /*  871,227, */  3-1, 18*18*18},
-      { /*  113, 30, */  3-1, 19*19*19},
-      { /*  174, 47, */  3-1, 20*20*20},
-      { /*   51, 14, */  3-1, 21*21*21},
-      { /*  653,182, */  3-1, 22*22*22},
-      { /*  191, 54, */  3-1, 23*23*23},
-      { /*  677,194, */  3-1, 24*24*24},
-      { /*  789,229, */  3-1, 25*25*25},
-      { /*  691,203, */  3-1, 26*26*26},
-      { /*  461,137, */  3-1, 27*27*27},
-      { /*  436,131, */  3-1, 28*28*28},
-      { /*  359,109, */  3-1, 29*29*29},
-      { /*  988,303, */  3-1, 30*30*30},
-      { /*  633,196, */  3-1, 31*31*31},
-      { /*   16,  5, */  3-1, 32*32*32},
-      { /*  203, 64, */  3-1, 33*33*33},
-      { /*  629,200, */  3-1, 34*34*34},
-      { /*  967,310, */  3-1, 35*35*35},
-      { /*  359,116, */  3-1, 36*36*36},
-    #endif
-    #if (intDsize==32)
-      { /*   32,  1, */ 31-1, 2UL*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2},
-      { /*  424, 21, */ 20-1, 3UL*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3},
-      { /*   16,  1, */ 15-1, 4UL*4*4*4*4*4*4*4*4*4*4*4*4*4*4},
-      { /*  758, 55, */ 13-1, 5UL*5*5*5*5*5*5*5*5*5*5*5*5},
-      { /*  359, 29, */ 12-1, 6UL*6*6*6*6*6*6*6*6*6*6*6},
-      { /*   57,  5, */ 11-1, 7UL*7*7*7*7*7*7*7*7*7*7},
-      { /*   32,  3, */ 10-1, 8UL*8*8*8*8*8*8*8*8*8},
-      { /*  212, 21, */ 10-1, 9UL*9*9*9*9*9*9*9*9*9},
-      { /*  289, 30, */  9-1, 10UL*10*10*10*10*10*10*10*10},
-      { /*  990,107, */  9-1, 11UL*11*11*11*11*11*11*11*11},
-      { /*  848, 95, */  8-1, 12UL*12*12*12*12*12*12*12},
-      { /*  761, 88, */  8-1, 13UL*13*13*13*13*13*13*13},
-      { /* 1017,121, */  8-1, 14UL*14*14*14*14*14*14*14},
-      { /*  901,110, */  8-1, 15UL*15*15*15*15*15*15*15},
-      { /*    8,  1, */  7-1, 16UL*16*16*16*16*16*16},
-      { /*  869,111, */  7-1, 17UL*17*17*17*17*17*17},
-      { /*  683, 89, */  7-1, 18UL*18*18*18*18*18*18},
-      { /*  113, 15, */  7-1, 19UL*19*19*19*19*19*19},
-      { /*  348, 47, */  7-1, 20UL*20*20*20*20*20*20},
-      { /*   51,  7, */  7-1, 21UL*21*21*21*21*21*21},
-      { /*  653, 91, */  7-1, 22UL*22*22*22*22*22*22},
-      { /*  191, 27, */  7-1, 23UL*23*23*23*23*23*23},
-      { /*  677, 97, */  6-1, 24UL*24*24*24*24*24},
-      { /*  379, 55, */  6-1, 25UL*25*25*25*25*25},
-      { /*  851,125, */  6-1, 26UL*26*26*26*26*26},
-      { /*  922,137, */  6-1, 27UL*27*27*27*27*27},
-      { /*  872,131, */  6-1, 28UL*28*28*28*28*28},
-      { /*  718,109, */  6-1, 29UL*29*29*29*29*29},
-      { /*  150, 23, */  6-1, 30UL*30*30*30*30*30},
-      { /*  633, 98, */  6-1, 31UL*31*31*31*31*31},
-      { /*   32,  5, */  6-1, 32UL*32*32*32*32*32},
-      { /*  203, 32, */  6-1, 33UL*33*33*33*33*33},
-      { /*  629,100, */  6-1, 34UL*34*34*34*34*34},
-      { /*  967,155, */  6-1, 35UL*35*35*35*35*35},
-      { /*  359, 58, */  6-1, 36UL*36*36*36*36*36},
-    #endif
-    #if (intDsize==64)
-      { /*   64,  1, */ 63-1, 2ULL*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2*2},
-      { /*  848, 21, */ 40-1, 3ULL*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3*3},
-      { /*   32,  1, */ 31-1, 4ULL*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4*4},
-      { /*  634, 23, */ 27-1, 5ULL*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5},
-      { /*  718, 29, */ 24-1, 6ULL*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6*6},
-      { /*  114,  5, */ 22-1, 7ULL*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7*7},
-      { /*   64,  3, */ 21-1, 8ULL*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8*8},
-      { /*  424, 21, */ 20-1, 9ULL*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9*9},
-      { /*  289, 15, */ 19-1, 10ULL*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10*10},
-      { /* 1018, 55, */ 18-1, 11ULL*11*11*11*11*11*11*11*11*11*11*11*11*11*11*11*11*11},
-      { /*  607, 34, */ 17-1, 12ULL*12*12*12*12*12*12*12*12*12*12*12*12*12*12*12*12},
-      { /*  761, 44, */ 17-1, 13ULL*13*13*13*13*13*13*13*13*13*13*13*13*13*13*13*13},
-      { /*  975, 58, */ 16-1, 14ULL*14*14*14*14*14*14*14*14*14*14*14*14*14*14*14},
-      { /*  901, 55, */ 16-1, 15ULL*15*15*15*15*15*15*15*15*15*15*15*15*15*15*15},
-      { /*   16,  1, */ 15-1, 16ULL*16*16*16*16*16*16*16*16*16*16*16*16*16*16},
-      { /*  595, 38, */ 15-1, 17ULL*17*17*17*17*17*17*17*17*17*17*17*17*17*17},
-      { /* 1013, 66, */ 15-1, 18ULL*18*18*18*18*18*18*18*18*18*18*18*18*18*18},
-      { /*  226, 15, */ 15-1, 19ULL*19*19*19*19*19*19*19*19*19*19*19*19*19*19},
-      { /*  696, 47, */ 14-1, 20ULL*20*20*20*20*20*20*20*20*20*20*20*20*20},
-      { /*  102,  7, */ 14-1, 21ULL*21*21*21*21*21*21*21*21*21*21*21*21*21},
-      { /*  775, 54, */ 14-1, 22ULL*22*22*22*22*22*22*22*22*22*22*22*22*22},
-      { /*  382, 27, */ 14-1, 23ULL*23*23*23*23*23*23*23*23*23*23*23*23*23},
-      { /* 1019, 73, */ 13-1, 24ULL*24*24*24*24*24*24*24*24*24*24*24*24},
-      { /*  758, 55, */ 13-1, 25ULL*25*25*25*25*25*25*25*25*25*25*25*25},
-      { /*  994, 73, */ 13-1, 26ULL*26*26*26*26*26*26*26*26*26*26*26*26},
-      { /*  673, 50, */ 13-1, 27ULL*27*27*27*27*27*27*27*27*27*27*27*27},
-      { /*  892, 67, */ 13-1, 28ULL*28*28*28*28*28*28*28*28*28*28*28*28},
-      { /*  830, 63, */ 13-1, 29ULL*29*29*29*29*29*29*29*29*29*29*29*29},
-      { /*  300, 23, */ 13-1, 30ULL*30*30*30*30*30*30*30*30*30*30*30*30},
-      { /*  633, 49, */ 12-1, 31ULL*31*31*31*31*31*31*31*31*31*31*31},
-      { /*   64,  5, */ 12-1, 32ULL*32*32*32*32*32*32*32*32*32*32*32},
-      { /*  203, 16, */ 12-1, 33ULL*33*33*33*33*33*33*33*33*33*33*33},
-      { /*  629, 50, */ 12-1, 34ULL*34*34*34*34*34*34*34*34*34*34*34},
-      { /*  836, 67, */ 12-1, 35ULL*35*35*35*35*35*35*35*35*35*35*35},
-      { /*  359, 29, */ 12-1, 36ULL*36*36*36*36*36*36*36*36*36*36*36},
-    #endif
-    };
-
 // Timing für Dezimal-Umwandlung einer Zahl mit N Digits = (N*32) Bits,
 // auf einem i486 33 MHz unter Linux:
 //    N      standard  dnq(div)  dnq(mul)  combined
@@ -198,60 +43,8 @@ namespace cln {
 //                call, threshold = 2050.
 // combined means divide-and-conquer as long as length >= threshold.
   const unsigned int cl_digits_div_threshold = 1015;
-  //#define MUL_REPLACES_DIV
   const int cl_digits_algo = 1;
 
-// Tabelle: enthält zu jeder Basis b (2 <= b <= 36)
-// NULL oder einen Vektor von lazy berechneten b^(k*2^i) und 1/b^(k*2^i).
-  typedef struct cached_power_table_entry {
-    ALLOCATE_ANYWHERE(cached_power_table_entry)
-    cl_I base_pow; // 0 or b^(k*2^i)
-    #ifdef MUL_REPLACES_DIV
-    cl_I inv_base_pow; // if base_pow: floor(2^(2*integer_length(base_pow))/base_pow)
-    #endif
-  } cached_power_table_entry;
-  struct cached_power_table {
-       cached_power_table_entry element[30];
-       // Constructor and destructor - nothing special.
-       cached_power_table () {}
-       ~cached_power_table () {}
-       // Allocation and deallocation.
-       void* operator new (size_t size) { return malloc_hook(size); }
-       void operator delete (void* ptr) { free_hook(ptr); }
-  };
-  static cached_power_table* ctable [36-2+1] =
-    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-      NULL, NULL, NULL, NULL, NULL
-    };
-  static const cached_power_table_entry * cached_power (uintD base, uintL i)
-    { var cached_power_table* ptr;
-      if (!(ptr = ctable[base-2]))
-        { ctable[base-2] = ptr = new cached_power_table (); }
-      var uintL j;
-      for (j = 0; j <= i; j++)
-        if (zerop(ptr->element[j].base_pow))
-          { // Compute b^(k*2^j) and its inverse.
-            cl_I x =
-              (j==0 ? (cl_I)(unsigned long)(table[base-2].b_hoch_k)
-                    : ptr->element[j-1].base_pow * ptr->element[j-1].base_pow
-              );
-            ptr->element[j].base_pow = x;
-            #ifdef MUL_REPLACES_DIV
-            ptr->element[j].inv_base_pow = floor1(ash(1,2*integer_length(x)),x);
-            #endif
-          }
-      return &ptr->element[i];
-    }
-  AT_DESTRUCTION(cached_power)
-    { for (var uintD base = 2; base <= 36; base++)
-        { var cached_power_table* ptr = ctable[base-2];
-          if (ptr)
-            { delete ptr; ctable[base-2] = NULL; }
-        }
-    }
-
 // like I_to_digits, except that the result has exactly erg_len characters.
 static inline void I_to_digits_noshrink (const cl_I& X, uintD base, uintL erg_len, cl_digits* erg)
 {
@@ -288,9 +81,9 @@ void I_to_digits (const cl_I& X, uintD base, cl_digits* erg)
 //   Dies solange bis X=0.
 //   Streiche die führenden Nullen.
       // Aufsuchen von k-1 und b^k aus der Tabelle:
-      var power_table_entry* tableptr = &table[base-2];
-      var uintC k_1 = tableptr->k_1; // k-1
-      var uintD b_hoch_k = tableptr->b_hoch_k; // b^k
+      var const power_table_entry* tableptr = &power_table[base-2];
+      var uintC k = tableptr->k;
+      var uintD b_hoch_k = tableptr->b_to_the_k; // b^k
       var uintB* erg_ptr = erg->LSBptr;
       #define next_digit(d)  { *--erg_ptr = (d<10 ? '0'+d : 'A'-10+d); }
       // Spezialfälle:
@@ -341,12 +134,12 @@ void I_to_digits (const cl_I& X, uintD base, cl_digits* erg)
               // Single-Precision-Division durch b^k:
               var uintD rest = divu_loop_msp(b_hoch_k,MSDptr,len);
               // Zerlegen des Restes in seine k Ziffern:
-              var uintC count = k_1;
+              var uintC count = k-1;
              if (fixnump(X) && count>cl_value_len-1)
                  count = cl_value_len-1;
               if ((intDsize>=11) || (count>0))
                 // (Bei intDsize>=11 ist wegen b<=36 zwangsläufig
-                // k = ceiling(intDsize*log(2)/log(b))-1 >= 2, also count = k_1 > 0.)
+                // k = ceiling(intDsize*log(2)/log(b))-1 >= 2, also count = k-1 > 0.)
                 do { var uintD d;
                      #if HAVE_DD
                        divuD((uintDD)rest,base,rest=,d=);
@@ -398,7 +191,7 @@ void I_to_digits (const cl_I& X, uintD base, cl_digits* erg)
           #endif
           var const cl_I& X1 = q;
           var const cl_I& X0 = r;
-          var uintL B_baselen = (uintL)(k_1+1)<<i;
+          var uintL B_baselen = (uintL)(k)<<i;
           I_to_digits_noshrink(X0,base,B_baselen,erg);
           erg->LSBptr -= B_baselen;
           I_to_digits(X1,base,erg);