15 // We observe the following timings:
16 // Time for dividing 2*N digits by N digits, on a i486 33 MHz running Linux:
28 // -----> Newton faster for N >= 550.
29 // Time for dividing 3*N digits by N digits, on a i486 33 MHz running Linux:
41 // -----> Newton faster for N >= 740.
42 // Time for dividing m digits by n digits:
43 // n = 2,3,5,10,25,50,100,250: Newton never faster.
44 // n = 400: Newton faster for m >= 440, m < 600
45 // n = 500: Newton faster for m >= 530, m < 900
46 // n = 600: Newton faster for m >= 630, m < 1250
47 // n = 700: Newton faster for m >= 730, m < 1530
48 // n = 800: Newton faster for m >= 825, m < 2600 or m >= 5300
49 // n = 900: Newton faster for m >= 925, m < 2700 or m >= 3400
50 // n = 1000: Newton faster for m >= 1020
51 // n = 1500: Newton faster for m >= 1520
52 // n = 2000: Newton faster for m >= 2020
53 // n = 2500: Newton faster for m >= 2520
54 // n = 5000: Newton faster for m >= 5020
55 // Break-even-point. When in doubt, prefer to choose the standard algorithm.
56 static inline cl_boolean cl_recip_suitable (uintL m, uintL n) // m > n
61 return (cl_boolean)((m >= n+30) && (m < 3*n-600));
63 return (cl_boolean)(m >= n+20);
66 // Dividiert zwei Unsigned Digit sequences durcheinander.
67 // UDS_divide(a_MSDptr,a_len,a_LSDptr, b_MSDptr,b_len,b_LSDptr, &q,&r);
68 // Die UDS a = a_MSDptr/a_len/a_LSDptr (a>=0) wird durch
69 // die UDS b = b_MSDptr/b_len/b_LSDptr (b>=0) dividiert:
70 // a = q * b + r mit 0 <= r < b. Bei b=0 Error.
71 // q der Quotient, r der Rest.
72 // q = q_MSDptr/q_len/q_LSDptr, r = r_MSDptr/r_len/r_LSDptr beides
73 // Normalized Unsigned Digit sequences.
74 // Vorsicht: q_LSDptr <= r_MSDptr,
75 // Vorzeichenerweiterung von r kann q zerstören!
76 // Vorzeichenerweiterung von q ist erlaubt.
77 // a und b werden nicht modifiziert.
80 // erst a und b normalisieren: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
81 // mit m>=0 und n>0 (Stellensystem der Basis beta=2^intDsize).
82 // Falls m<n, ist q:=0 und r:=a.
83 // Falls m>=n=1, Single-Precision-Division:
86 // {Hier (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
87 // = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
88 // j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
89 // Normalisiere [q[m-1],...,q[0]], liefert q.
90 // Falls m>=n>1, Multiple-Precision-Division:
91 // Es gilt a/b < beta^(m-n+1).
92 // s:=intDsize-1-(Nummer des höchsten Bits in b[n-1]), 0<=s<intDsize.
93 // Schiebe a und b um s Bits nach links und kopiere sie dabei. r:=a.
94 // r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] mit b[n-1]>=beta/2.
95 // Für j=m-n,...,0: {Hier 0 <= r < b*beta^(j+1).}
97 // q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
98 // Bei Überlauf (q* >= beta) setze q* := beta-1.
99 // Berechne c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
100 // und c3 := b[n-2] * q*.
101 // {Es ist 0 <= c2 < 2*beta^2, sogar 0 <= c2 < beta^2 falls kein
102 // Überlauf aufgetreten war. Ferner 0 <= c3 < beta^2.
103 // Bei Überlauf und r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta,
104 // das heißt c2 >= beta^2, kann man die nächste Abfrage überspringen.}
105 // Solange c3 > c2, {hier 0 <= c2 < c3 < beta^2} setze
106 // q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
108 // Setze r := r - b * q* * beta^j, im einzelnen:
109 // [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
110 // also: u:=0, for i:=0 to n-1 do
111 // u := u + q* * b[i],
112 // r[j+i]:=r[j+i]-(u mod beta) (+ beta, falls Carry),
113 // u:=u div beta (+ 1, falls bei der Subtraktion Carry)
115 // {Da stets u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
116 // < q* + 1 <= beta, läuft der Übertrag u nicht über.}
117 // Tritt dabei ein negativer Übertrag auf, so setze q* := q* - 1
118 // und [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
120 // Normalisiere [q[m-n],..,q[0]] und erhalte den Quotienten q,
121 // Schiebe [r[n-1],...,r[0]] um s Bits nach rechts, normalisiere und
122 // erhalte den Rest r.
123 // Dabei kann q[j] auf dem Platz von r[n+j] liegen.
124 void cl_UDS_divide (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr,
125 const uintD* b_MSDptr, uintC b_len, const uintD* b_LSDptr,
126 uintD* roomptr, // ab roomptr kommen a_len+1 freie Digits
128 { // a normalisieren (a_MSDptr erhöhen, a_len erniedrigen):
129 while ((a_len>0) && (mspref(a_MSDptr,0)==0)) { msshrink(a_MSDptr); a_len--; }
130 // b normalisieren (b_MSDptr erhöhen, b_len erniedrigen):
132 { if (b_len==0) { cl_error_division_by_0(); }
133 if (mspref(b_MSDptr,0)==0) { msshrink(b_MSDptr); b_len--; }
136 // jetzt m=a_len >=0 und n=b_len >0.
138 // m<n: Trivialfall, q=0, r:= Kopie von a.
139 { var uintD* r_MSDptr = roomptr;
140 var uintD* r_LSDptr = roomptr mspop a_len;
141 // Speicheraufbau: r_MSDptr/0/r_MSDptr/a_len/r_LSDptr
143 copy_loop_lsp(a_LSDptr,r_LSDptr,a_len);
144 q_->MSDptr = r_MSDptr; q_->len = 0; q_->LSDptr = r_MSDptr; // q = 0, eine NUDS
145 r_->MSDptr = r_MSDptr; r_->len = a_len; r_->LSDptr = r_LSDptr; // r = Kopie von a, eine NUDS
149 // n=1: Single-Precision-Division
150 { // beta^(m-1) <= a < beta^m ==> beta^(m-2) <= a/b < beta^m
151 var uintD* q_MSDptr = roomptr;
152 var uintD* q_LSDptr = q_MSDptr mspop a_len;
153 var uintD* r_MSDptr = q_LSDptr;
154 var uintD* r_LSDptr = r_MSDptr mspop 1;
155 // Speicheraufbau: q_MSDptr/a_len/q_LSDptr r_MSDptr/1/r_LSDptr
157 {var uintD rest = divucopy_loop_msp(mspref(b_MSDptr,0),a_MSDptr,q_MSDptr,a_len); // Division durch b[0]
160 { mspref(r_MSDptr,0) = rest; r_len=1; } // Rest als r ablegen
162 { r_MSDptr = r_LSDptr; r_len=0; } // Rest auf 0 normalisieren
163 if (mspref(q_MSDptr,0)==0)
164 { msshrink(q_MSDptr); a_len--; } // q normalisieren
165 q_->MSDptr = q_MSDptr; q_->len = a_len; q_->LSDptr = q_LSDptr; // q ablegen
166 r_->MSDptr = r_MSDptr; r_->len = r_len; r_->LSDptr = r_LSDptr; // r ablegen
170 // n>1: Multiple-Precision-Division
171 { // beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n ==>
172 // beta^(m-n-1) <= a/b < beta^(m-n+1).
176 { var uintD msd = mspref(b_MSDptr,0); // b[n-1]
179 while ((sintD)msd >= 0) { msd = msd<<1; s++; }
180 #else // ein wenig effizienter, Abfrage auf s=0 vorwegnehmen
182 { s = 0; goto shift_ok; }
184 { integerlengthD(msd, s = intDsize - ); goto shift; }
187 // 0 <= s < intDsize.
188 // Kopiere b und schiebe es dabei um s Bits nach links:
191 { var uintD* new_b_MSDptr;
192 var uintD* new_b_LSDptr;
193 num_stack_alloc(b_len,new_b_MSDptr=,new_b_LSDptr=);
194 shiftleftcopy_loop_lsp(b_LSDptr,new_b_LSDptr,b_len,s);
195 b_MSDptr = new_b_MSDptr; b_LSDptr = new_b_LSDptr;
198 // Wieder b = b_MSDptr/b_len/b_LSDptr.
199 // Kopiere a und schiebe es dabei um s Bits nach links, erhalte r:
200 {var uintD* r_MSDptr = roomptr;
201 var uintD* r_LSDptr = roomptr mspop (a_len+1);
202 // Speicheraufbau: r_MSDptr/ a_len+1 /r_LSDptr
204 // später: q_MSDptr/a_len-b_len+1/r_MSDptr/b_len/r_LSDptr
207 { copy_loop_lsp(a_LSDptr,r_LSDptr,a_len); mspref(r_MSDptr,0) = 0; }
209 { mspref(r_MSDptr,0) = shiftleftcopy_loop_lsp(a_LSDptr,r_LSDptr,a_len,s); }
210 // Nun r = r_MSDptr/a_len+1/r_LSDptr.
211 var uintC j = a_len-b_len; // m-n
212 var uintD* q_MSDptr = r_MSDptr;
213 var uintC q_len = j+1; // q wird m-n+1 Digits haben
214 if (cl_recip_suitable(a_len,b_len))
215 { // Bestimme Kehrwert c von b.
218 num_stack_alloc(j+3,c_MSDptr=,c_LSDptr=);
219 cl_UDS_recip(b_MSDptr,b_len,c_MSDptr,j+1);
220 // c hat j+3 Digits, | beta^(m+2)/b - c | < beta.
221 // Mit a' = floor(a/beta^n) multiplizieren, liefert d':
223 UDS_UDS_mul_UDS(j+1,r_MSDptr mspop (j+1), j+3,c_MSDptr mspop (j+3),
225 // d' has 2*j+4 digits, d := floor(d'/beta^(j+2)) has j+2 digits.
226 // | beta^(m+2)/b - c | < beta ==> (since a < beta^(m+1))
227 // | beta^(m+2)*a/b - a*c | < beta^(m+2),
228 // 0 <= a - a'*beta^n < beta^n ==> (since c <= 2*beta^(j+2))
229 // 0 <= a*c - a'*c*beta^n < 2*beta^(m+2) ==>
230 // -beta^(m+2) < beta^(m+2)*a/b - a'*c*beta^n < 3*beta^(m+2) ==>
231 // -1 < a/b - a'*c*beta^(-j-2) < 3 ==>
232 // -1 < a/b - d'*beta^(-j-2) < 3,
233 // -1 < d'*beta^(-j-2) - d <= 0 ==>
234 // -2 < a/b - d < 3 ==>
235 // -2 <= q - d < 3 ==> |q-d| <= 2.
236 var uintD* d_LSDptr = d_MSDptr mspop (j+2);
237 // Zur Bestimmung des Restes wieder mit b multiplizieren:
240 UDS_UDS_mul_UDS(j+2,d_LSDptr, b_len,b_LSDptr, p_MSDptr=,,p_LSDptr=);
241 // d ist um höchstens 2 zu groß, muß also evtl. zweimal um 1
242 // decrementieren, bis das Produkt <= a wird.
243 if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
244 { dec_loop_lsp(d_LSDptr,j+2);
245 if (subfrom_loop_lsp(b_LSDptr,p_LSDptr,b_len))
246 dec_loop_lsp(p_LSDptr lspop b_len,j+2);
247 if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
248 { dec_loop_lsp(d_LSDptr,j+2);
249 if (subfrom_loop_lsp(b_LSDptr,p_LSDptr,b_len))
250 dec_loop_lsp(p_LSDptr lspop b_len,j+2);
251 if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
255 subfrom_loop_lsp(p_LSDptr,r_LSDptr,a_len+1);
256 if (test_loop_msp(r_MSDptr,j)) cl_abort();
257 r_MSDptr = r_LSDptr lspop b_len; // = r_MSDptr mspop (j+1);
258 // d ist um höchstens 2 zu klein, muß also evtl. zweimal um 1
259 // incrementieren, bis der Rest < b wird.
260 if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
261 { inc_loop_lsp(d_LSDptr,j+2);
262 if (subfrom_loop_lsp(b_LSDptr,r_LSDptr,b_len))
263 lspref(r_LSDptr,b_len) -= 1;
264 if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
265 { inc_loop_lsp(d_LSDptr,j+2);
266 if (subfrom_loop_lsp(b_LSDptr,r_LSDptr,b_len))
267 lspref(r_LSDptr,b_len) -= 1;
268 if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
271 // r ist fertig, q := d.
272 if (mspref(d_MSDptr,0) > 0) cl_abort();
273 q_len = j+1; copy_loop_msp(d_MSDptr mspop 1,q_MSDptr,q_len);
276 { var uintD* r_ptr = r_LSDptr lspop j; // Pointer oberhalb von r[j]
278 var uintD b_msd = mspref(b_MSDptr,0); // b[n-1]
279 var uintD b_2msd = mspref(b_MSDptr,1); // b[n-2]
281 var uintDD b_msdd = highlowDD(b_msd,b_2msd); // b[n-1]*beta+b[n-2]
283 // Divisions-Schleife: (wird m-n+1 mal durchlaufen)
284 // j = Herabzähler, b_MSDptr/b_len/b_LSDptr = [b[n-1],...,b[0]], b_len=n,
285 // r_MSDptr = Pointer auf r[n+j] = Pointer auf q[j],
286 // r_ptr = Pointer oberhalb von r[j].
287 do { var uintD q_stern;
289 if (mspref(r_MSDptr,0) < b_msd) // r[j+n] < b[n-1] ?
290 { // Dividiere r[j+n]*beta+r[j+n-1] durch b[n-1], ohne Überlauf:
292 divuD(highlowDD(mspref(r_MSDptr,0),mspref(r_MSDptr,1)),b_msd, q_stern=,c1=);
294 divuD(mspref(r_MSDptr,0),mspref(r_MSDptr,1),b_msd, q_stern=,c1=);
298 { // Überlauf, also r[j+n]*beta+r[j+n-1] >= beta*b[n-1]
299 q_stern = bitm(intDsize)-1; // q* = beta-1
300 // Teste ob r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
301 // <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
302 // <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) {<= beta !} ist.
303 // Wenn ja, direkt zur Subtraktionschleife.
304 // (Andernfalls ist r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
305 // <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ).
306 if ((mspref(r_MSDptr,0) > b_msd) || ((c1 = mspref(r_MSDptr,1)+b_msd) < b_msd))
307 // r[j+n] >= b[n-1]+1 oder
308 // r[j+n] = b[n-1] und Addition r[j+n-1]+b[n-1] gibt Carry ?
309 { goto subtract; } // ja -> direkt in die Subtraktion
312 // c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta).
314 { var uintDD c2 = highlowDD(c1,mspref(r_MSDptr,2)); // c1*beta+r[j+n-2]
315 var uintDD c3 = muluD(b_2msd,q_stern); // b[n-2] * q*
316 // Solange c2 < c3, c2 erhöhen, c3 erniedrigen:
317 // Rechne dabei mit c3-c2:
318 // solange >0, um b[n-1]*beta+b[n-2] erniedrigen.
319 // Dies kann wegen b[n-1]*beta+b[n-2] >= beta^2/2
320 // höchstens zwei mal auftreten.
322 { q_stern = q_stern-1; // q* := q* - 1
324 { q_stern = q_stern-1; } // q* := q* - 1
327 // Wie oben, nur mit zweigeteilten c2=[c2hi|c2lo] und c3=[c3hi|c3lo]:
329 { var uintD c2lo = mspref(r_MSDptr,2); // c2hi*beta+c2lo = c1*beta+r[j+n-2]
332 muluD(b_2msd,q_stern, c3hi=,c3lo=); // c3hi*beta+c3lo = b[n-2] * q*
333 if ((c3hi > c2hi) || ((c3hi == c2hi) && (c3lo > c2lo)))
334 { q_stern = q_stern-1; // q* := q* - 1
335 c3hi -= c2hi; if (c3lo < c2lo) { c3hi--; }; c3lo -= c2lo; // c3 := c3-c2
336 if ((c3hi > b_msd) || ((c3hi == b_msd) && (c3lo > b_2msd)))
337 { q_stern = q_stern-1; } // q* := q* - 1
343 { // Subtraktionsschleife: r := r - b * q* * beta^j
344 var uintD carry = mulusub_loop_lsp(q_stern,b_LSDptr,r_ptr,b_len);
345 // Noch r_ptr[-b_len-1] -= carry, d.h. r_MSDptr[0] -= carry
346 // durchführen und danach r_MSDptr[0] vergessen:
347 if (carry > mspref(r_MSDptr,0))
348 // Subtraktion ergab Übertrag
349 { q_stern = q_stern-1; // q* := q* - 1
350 addto_loop_lsp(b_LSDptr,r_ptr,b_len); // Additionsschleife
351 // r[n+j] samt Carry kann vergessen werden...
353 // Berechnung von q* ist fertig.
354 msprefnext(r_MSDptr) = q_stern; // als q[j] ablegen
355 r_ptr = r_ptr mspop 1;
359 // Nun ist q = [q[m-n],..,q[0]] = q_MSDptr/q_len/r_MSDptr
360 // und r = [r[n-1],...,r[0]] = r_MSDptr/b_len/r_LSDptr.
361 // q normalisieren und ablegen:
362 if (mspref(q_MSDptr,0)==0)
363 { msshrink(q_MSDptr); q_len--; }
364 q_->MSDptr = q_MSDptr; q_->len = q_len; q_->LSDptr = r_MSDptr;
365 // Schiebe [r[n-1],...,r[0]] um s Bits nach rechts:
367 { shiftright_loop_msp(r_MSDptr,b_len,s); }
368 // r normalisieren und ablegen:
369 while ((b_len>0) && (mspref(r_MSDptr,0)==0))
370 { msshrink(r_MSDptr); b_len--; }
371 r_->MSDptr = r_MSDptr; r_->len = b_len; r_->LSDptr = r_LSDptr;
375 // Bit complexity (N = a_len): O(M(N)).