1 # Hilfsfunktion zur Eingabe von Integers
2 
3 # Wandelt eine Ziffernfolge in ein Integer >=0 um.
4 # DIGITS_to_I(MSBptr,len,base)
5 # > base: Stellenwertsystem-Basis, >=2, <=36
6 # > MSBptr/len/..: Ziffernfolge, bestehend aus Punkten (werden überlesen)
7 #     und Ziffern/Buchstaben mit Wert < base.
8 # < result: der dargestellte Integer >=0
9 # can trigger GC
DIGITS_to_I(const chart * MSBptr,uintL len,uintD base)10   local maygc object DIGITS_to_I (const chart* MSBptr, uintL len, uintD base)
11   {
12     SAVE_NUM_STACK # num_stack retten
13     var uintD* erg_MSDptr;
14     var uintC erg_len;
15     var uintD* erg_LSDptr;
16     while (len && as_cint(*MSBptr) == '0')
17       { len--; MSBptr++; } /* drop leading 0s */
18     # Platz fürs Ergebnis:
19     # 1+ceiling(len*log(base)/(intDsize*log(2))) oder etwas mehr Digits
20     var uintL need = 1+floor(len,intDsize*256); # > len/(intDsize*256) >=0
21     switch (base) { # need mit ceiling(256*log(base)/log(2)) multiplizieren:
22       case 2: need = 256*need; break;
23       case 3: need = 406*need; break;
24       case 4: need = 512*need; break;
25       case 5: need = 595*need; break;
26       case 6: need = 662*need; break;
27       case 7: need = 719*need; break;
28       case 8: need = 768*need; break;
29       case 9: need = 812*need; break;
30       case 10: need = 851*need; break;
31       case 11: need = 886*need; break;
32       case 12: need = 918*need; break;
33       case 13: need = 948*need; break;
34       case 14: need = 975*need; break;
35       case 15: need = 1001*need; break;
36       case 16: need = 1024*need; break;
37       case 17: need = 1047*need; break;
38       case 18: need = 1068*need; break;
39       case 19: need = 1088*need; break;
40       case 20: need = 1107*need; break;
41       case 21: need = 1125*need; break;
42       case 22: need = 1142*need; break;
43       case 23: need = 1159*need; break;
44       case 24: need = 1174*need; break;
45       case 25: need = 1189*need; break;
46       case 26: need = 1204*need; break;
47       case 27: need = 1218*need; break;
48       case 28: need = 1231*need; break;
49       case 29: need = 1244*need; break;
50       case 30: need = 1257*need; break;
51       case 31: need = 1269*need; break;
52       case 32: need = 1280*need; break;
53       case 33: need = 1292*need; break;
54       case 34: need = 1303*need; break;
55       case 35: need = 1314*need; break;
56       case 36: need = 1324*need; break;
57       default: NOTREACHED;
58     }
59     # Nun gilt need >= len*log(base)/(intDsize*log(2)).
60     need += 1;
61     /* there is another check below, so be VERY lenient here.
62        the test here is to avoid doing the unnecessary work if we KNOW
63        that the number is too big. see https://sourceforge.net/p/clisp/bugs/455/ */
64     if ((intWCsize < 32) && (need > (uintL)(bitc(intWCsize+1))))
65       BN_ueberlauf();
66     num_stack_need(need,_EMA_,erg_LSDptr=);
67     erg_MSDptr = erg_LSDptr; erg_len = 0;
68     if (len > 0) {
69       begin_arith_call();
70       # Ziffern einzeln draufaddieren:
71       dotimespL(len,len, {
72         # erg_MSDptr/erg_len/erg_LSDptr ist eine NUDS, erg_len < need.
73         var chart ch = *MSBptr++; # nächstes Character
74         var cint c = as_cint(ch);
75         if (!(c=='.')) { # Punkt überlesen
76           # Wert von c ('0'-'9','A'-'Z','a'-'z') bilden:
77           c = c - '0';
78           if (c > '9'-'0') { # keine Ziffer?
79             c = c+'0'-'A'+10;
80             if (c > 'Z'-'A'+10) # kein Großbuchstabe?
81               c = c+'A'-'a'; # dann ein Kleinbuchstabe
82           }
83           # multipliziere erg mit base und addiere ch:
84           var uintD carry = mulusmall_loop_down(base,erg_LSDptr,erg_len,c);
85           if (!(carry==0)) {
86             # muss NUDS vergrößern:
87             *--erg_MSDptr = carry; erg_len++;
88 	    if (uintWCoverflow(erg_len)) /* overflow of the length? */
89 	      BN_ueberlauf();
90           }
91         }
92       });
93       end_arith_call();
94     }
95     var object result = NUDS_to_I(erg_MSDptr,erg_len);
96     RESTORE_NUM_STACK # num_stack zurück
97     return result;
98   }
99