Browse Source

* src/integer/conv/cl_I_from_digits.cc (digits_to_I): Speedup when

the base is a power of two.
master
Richard Kreckel 21 years ago
parent
commit
ac82f8ef8b
  1. 5
      ChangeLog
  2. 218
      src/integer/conv/cl_I_from_digits.cc

5
ChangeLog

@ -1,3 +1,8 @@
2004-10-12 Richard B. Kreckel <kreckel@ginac.de>
* src/integer/conv/cl_I_from_digits.cc (digits_to_I): Speedup when
the base is a power of two.
2004-10-05 Richard B. Kreckel <kreckel@ginac.de> 2004-10-05 Richard B. Kreckel <kreckel@ginac.de>
* src/integer/conv/cl_I_to_digits.cc (I_to_digits): Fix bug in base 32. * src/integer/conv/cl_I_to_digits.cc (I_to_digits): Fix bug in base 32.

218
src/integer/conv/cl_I_from_digits.cc

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