|
|
@ -19,17 +19,54 @@ const cl_I digits_to_I (const char * MSBptr, uintL len, uintD base) |
|
|
|
var uintD* erg_MSDptr; |
|
|
|
var uintC erg_len; |
|
|
|
var uintD* erg_LSDptr; |
|
|
|
if ((base & (base-1)) == 0) { |
|
|
|
// Fast path for powers of two: write the digits from least
|
|
|
|
// significant to most significant into the result NUDS.
|
|
|
|
var int b = (base==2 ? 1 : base==4 ? 2 : base==8 ? 3 : base==16 ? 4 : /*base==32*/ 5); |
|
|
|
num_stack_alloc(1+(len*b-1)/intDsize,,erg_LSDptr=); |
|
|
|
erg_MSDptr = erg_LSDptr; erg_len = 0; |
|
|
|
var uintD d = 0; // resulting digit
|
|
|
|
var int ch_where = 0; // position of ch inside d
|
|
|
|
while (len > 0) |
|
|
|
{ var uintB ch = *(const uintB *)(MSBptr+len-1); // next character
|
|
|
|
if (!(ch=='.')) // skip decimal point
|
|
|
|
{ // Compute value of ch ('0'-'9','A'-'Z','a'-'z'):
|
|
|
|
ch = ch - '0'; |
|
|
|
if (ch > '9'-'0') // not a digit?
|
|
|
|
{ ch = ch+'0'-'A'+10; |
|
|
|
if (ch > 'Z'-'A'+10) // not an uppercase letter?
|
|
|
|
{ ch = ch+'A'-'a'; } // must be lowercase!
|
|
|
|
} |
|
|
|
d = d | (uintD)ch<<ch_where; |
|
|
|
ch_where = ch_where+b; |
|
|
|
if (ch_where >= intDsize) { |
|
|
|
// d is ready to be written into the NUDS:
|
|
|
|
lsprefnext(erg_MSDptr) = d; |
|
|
|
ch_where = ch_where-intDsize; |
|
|
|
d = (uintD)ch >> b-ch_where; // carry
|
|
|
|
erg_len++; |
|
|
|
} |
|
|
|
} |
|
|
|
len--; |
|
|
|
} |
|
|
|
if (d != 0) { // is there anything left over?
|
|
|
|
lsprefnext(erg_MSDptr) = d; |
|
|
|
++erg_len; |
|
|
|
} |
|
|
|
} else { |
|
|
|
// Slow path: Add digits one by one for non-powers of two.
|
|
|
|
// Platz fürs Ergebnis:
|
|
|
|
// 1+ceiling(len*log(base)/(intDsize*log(2))) oder etwas mehr Digits
|
|
|
|
// 1+ceiling(len*log(base)/(intDsize*log(2))) or some more digits
|
|
|
|
var uintL need = 1+floor(len,intDsize*256); // > len/(intDsize*256) >=0
|
|
|
|
switch (base) // need mit ceiling(256*log(base)/log(2)) multiplizieren:
|
|
|
|
{ case 2: need = 256*need; break; |
|
|
|
switch (base) // multiply need with ceiling(256*log(base)/log(2)):
|
|
|
|
{ |
|
|
|
//case 2: need = 256*need; break;
|
|
|
|
case 3: need = 406*need; break; |
|
|
|
case 4: need = 512*need; break; |
|
|
|
//case 4: need = 512*need; break;
|
|
|
|
case 5: need = 595*need; break; |
|
|
|
case 6: need = 662*need; break; |
|
|
|
case 7: need = 719*need; break; |
|
|
|
case 8: need = 768*need; break; |
|
|
|
//case 8: need = 768*need; break;
|
|
|
|
case 9: need = 812*need; break; |
|
|
|
case 10: need = 851*need; break; |
|
|
|
case 11: need = 886*need; break; |
|
|
@ -37,7 +74,7 @@ const cl_I digits_to_I (const char * MSBptr, uintL len, uintD base) |
|
|
|
case 13: need = 948*need; break; |
|
|
|
case 14: need = 975*need; break; |
|
|
|
case 15: need = 1001*need; break; |
|
|
|
case 16: need = 1024*need; break; |
|
|
|
//case 16: need = 1024*need; break;
|
|
|
|
case 17: need = 1047*need; break; |
|
|
|
case 18: need = 1068*need; break; |
|
|
|
case 19: need = 1088*need; break; |
|
|
@ -53,37 +90,38 @@ const cl_I digits_to_I (const char * MSBptr, uintL len, uintD base) |
|
|
|
case 29: need = 1244*need; break; |
|
|
|
case 30: need = 1257*need; break; |
|
|
|
case 31: need = 1269*need; break; |
|
|
|
case 32: need = 1280*need; break; |
|
|
|
//case 32: need = 1280*need; break;
|
|
|
|
case 33: need = 1292*need; break; |
|
|
|
case 34: need = 1303*need; break; |
|
|
|
case 35: need = 1314*need; break; |
|
|
|
case 36: need = 1324*need; break; |
|
|
|
default: NOTREACHED |
|
|
|
} |
|
|
|
// Nun gilt need >= len*log(base)/(intDsize*log(2)).
|
|
|
|
// Now we have need >= len*log(base)/(intDsize*log(2)).
|
|
|
|
need += 1; |
|
|
|
// Add digits one by one:
|
|
|
|
num_stack_alloc(need,,erg_LSDptr=); |
|
|
|
erg_MSDptr = erg_LSDptr; erg_len = 0; |
|
|
|
// Ziffern einzeln draufaddieren:
|
|
|
|
while (len > 0) |
|
|
|
{ // erg_MSDptr/erg_len/erg_LSDptr ist eine NUDS, erg_len < need.
|
|
|
|
var uintB ch = *(const uintB *)MSBptr; MSBptr++; // nächstes Character
|
|
|
|
if (!(ch=='.')) // Punkt überlesen
|
|
|
|
{ // Wert von ch ('0'-'9','A'-'Z','a'-'z') bilden:
|
|
|
|
{ // erg_MSDptr/erg_len/erg_LSDptr is a NUDS, erg_len < need.
|
|
|
|
var uintB ch = *(const uintB *)MSBptr; MSBptr++; // next character
|
|
|
|
if (!(ch=='.')) // skip decimal point
|
|
|
|
{ // Compute value of ('0'-'9','A'-'Z','a'-'z'):
|
|
|
|
ch = ch - '0'; |
|
|
|
if (ch > '9'-'0') // keine Ziffer?
|
|
|
|
if (ch > '9'-'0') // not a digit?
|
|
|
|
{ ch = ch+'0'-'A'+10; |
|
|
|
if (ch > 'Z'-'A'+10) // kein Großbuchstabe?
|
|
|
|
{ ch = ch+'A'-'a'; } // dann ein Kleinbuchstabe
|
|
|
|
if (ch > 'Z'-'A'+10) // not an uppercase letter?
|
|
|
|
{ ch = ch+'A'-'a'; } // must be lowercase!
|
|
|
|
} |
|
|
|
// multipliziere erg mit base und addiere ch:
|
|
|
|
// multiply erg with base and add ch:
|
|
|
|
{var uintD carry = mulusmall_loop_lsp(base,erg_LSDptr,erg_len,ch); |
|
|
|
if (!(carry==0)) |
|
|
|
// muß NUDS vergrößern:
|
|
|
|
// need to extend NUDS:
|
|
|
|
{ lsprefnext(erg_MSDptr) = carry; erg_len++; } |
|
|
|
}} |
|
|
|
len--; |
|
|
|
} |
|
|
|
} |
|
|
|
return NUDS_to_I(erg_MSDptr,erg_len); |
|
|
|
} |
|
|
|
|
|
|
|