]> www.ginac.de Git - cln.git/blob - src/base/digitseq/cl_DS_div.cc
- Rearranged break-even points to better match present-day CPUs whenever
[cln.git] / src / base / digitseq / cl_DS_div.cc
1 // cl_UDS_divide().
2
3 // General includes.
4 #include "cl_sysdep.h"
5
6 // Specification.
7 #include "cl_DS.h"
8
9
10 // Implementation.
11
12 #include "cl_N.h"
13 #include "cl_abort.h"
14
15 // We observe the following timings in seconds:
16 // Time for dividing a 2*n word number by a n word number:
17 // OS: Linux 2.2, intDsize==32,        OS: TRU64/4.0, intDsize==64,
18 // Machine: P-III/450MHz               Machine: EV5/300MHz:
19 //      n   standard  Newton               standard  Newton
20 //      10   0.000010  0.000024             0.000036  0.000058
21 //      30   0.000026  0.000080             0.00012   0.00027
22 //     100   0.00018   0.00048              0.00084   0.0016
23 //     300   0.0013    0.0028               0.0062    0.0090
24 //    1000   0.014     0.019                0.064     0.066  <-(~2200)
25 //    2000   0.058     0.058  <-(~2000)     0.26      0.20
26 //    3000   0.20      0.11                 0.57      0.24
27 //   10000   2.3       0.50                 6.7       1.2
28 //   30000  24.4       1.2                 62.0       2.8
29 // Time for dividing a 3*n word number by a n word number:
30 // OS: Linux 2.2, intDsize==32,        OS: TRU64/4.0, intDsize==64,
31 // Machine: P-III/450MHz               Machine: EV5/300MHz:
32 //      n   standard  Newton               standard  Newton
33 //      10   0.000013  0.000040             0.000063   0.00011
34 //      30   0.000046  0.00018              0.00024    0.00062
35 //     100   0.00035   0.0012               0.0016     0.0040
36 //     300   0.0027    0.0071               0.012      0.021
37 //    1000   0.029     0.047                0.13       0.16
38 //    2000   0.12      0.14  <-(~2200)      0.51       0.45  <-(~1600)
39 //    3000   0.40      0.22                 1.1        0.52
40 //   10000   4.5       0.76                13.2        2.0
41 //   30000  42.0       2.8                123.0        6.0
42 // Time for dividing m digits by n digits:
43 // OS: Linux 2.2, intDsize==32,        OS: TRU64/4.0, intDsize==64,
44 // Machine: P-III/450MHz               Machine: EV5/300MHz:
45 //      n   Newton faster for:         Newton faster for:
46 //    2-400 never                      never
47 //    600   never                       670<m<900 (definitly negligible)
48 //    800   never                       850<m<1500
49 //   1000   never                      1030<m<2000
50 //   1200   1400<m<1700                1230<m<2700
51 //   1500   1590<m<2500                1530<m<5100, 6600<m (ridge negligible)
52 //   2000   2060<m<3600                2030<m
53 //   3000   3040<m                     3030<m
54 //   4000   4030<m                     4030<m
55 //   5000   5030<m                     5030<m
56 //   8000   8030<m                     8030<m
57 // Break-even-point, should be acceptable for both architectures.
58 // When in doubt, prefer to choose the standard algorithm.
59 #if CL_USE_GMP
60   static inline cl_boolean cl_recip_suitable (uintL m, uintL n) // m > n
61     { if (n < 900)
62         return cl_false;
63       else
64         if (n < 2200)
65           return (cl_boolean)((m >= n+50) && (m < 2*n-600));
66         else
67           return (cl_boolean)(m >= n+30);
68     }
69 #else
70 // Use the old default values from CLN version <= 1.0.3 as a crude estimate.
71 // They came from the timings for dividing m digits by n digits on an i486/33:
72 // Dividing 2*N digits by N digits:    Dividing 3*N digits by N digits:
73 //      N   standard  Newton           standard  Newton
74 //      10    0.0003  0.0012             0.0006  0.0025
75 //      25    0.0013  0.0044             0.0026  0.0103
76 //      50    0.0047  0.0125             0.0092  0.030
77 //     100    0.017   0.037              0.035   0.089
78 //     250    0.108   0.146              0.215   0.362
79 //     500    0.43    0.44  <-(~550)     0.85    1.10
80 //    1000    1.72    1.32               3.44    3.21  <-(~740)
81 //    2500   11.2     4.1               23.3     7.9
82 //    5000   44.3     9.5               89.0    15.6
83 //   10000  187      20.6              362      33.1
84 // Time for dividing m digits by n digits:
85 //   n = 2,3,5,10,25,50,100,250: Newton never faster.
86 //   n = 400: Newton faster for m >= 440, m < 600
87 //   n = 500: Newton faster for m >= 530, m < 900
88 //   n = 600: Newton faster for m >= 630, m < 1250
89 //   n = 700: Newton faster for m >= 730, m < 1530
90 //   n = 800: Newton faster for m >= 825, m < 2600 or m >= 5300
91 //   n = 900: Newton faster for m >= 925, m < 2700 or m >= 3400
92 //   n = 1000: Newton faster for m >= 1020
93 //   n = 1500: Newton faster for m >= 1520
94 //   n = 2000: Newton faster for m >= 2020
95 //   n = 2500: Newton faster for m >= 2520
96 //   n = 5000: Newton faster for m >= 5020
97   static inline cl_boolean cl_recip_suitable (uintL m, uintL n) // m > n
98     { if (n < 500)
99         return cl_false;
100       else
101         if (n < 1000)
102           return (cl_boolean)((m >= n+30) && (m < 3*n-600));
103         else
104           return (cl_boolean)(m >= n+20);
105     }
106 #endif
107
108 // Dividiert zwei Unsigned Digit sequences durcheinander.
109 // UDS_divide(a_MSDptr,a_len,a_LSDptr, b_MSDptr,b_len,b_LSDptr, &q,&r);
110 // Die UDS a = a_MSDptr/a_len/a_LSDptr (a>=0) wird durch
111 // die UDS b = b_MSDptr/b_len/b_LSDptr (b>=0) dividiert:
112 // a = q * b + r mit 0 <= r < b. Bei b=0 Error.
113 // q der Quotient, r der Rest.
114 // q = q_MSDptr/q_len/q_LSDptr, r = r_MSDptr/r_len/r_LSDptr beides
115 // Normalized Unsigned Digit sequences.
116 // Vorsicht: q_LSDptr <= r_MSDptr,
117 //           Vorzeichenerweiterung von r kann q zerstören!
118 //           Vorzeichenerweiterung von q ist erlaubt.
119 // a und b werden nicht modifiziert.
120 //
121 // Methode:
122 // erst a und b normalisieren: a=[a[m-1],...,a[0]], b=[b[n-1],...,b[0]]
123 // mit m>=0 und n>0 (Stellensystem der Basis beta=2^intDsize).
124 // Falls m<n, ist q:=0 und r:=a.
125 // Falls m>=n=1, Single-Precision-Division:
126 //   r:=0, j:=m,
127 //   while j>0 do
128 //     {Hier (q[m-1]*beta^(m-1)+...+q[j]*beta^j) * b[0] + r*beta^j =
129 //           = a[m-1]*beta^(m-1)+...+a[j]*beta^j und 0<=r<b[0]<beta}
130 //     j:=j-1, r:=r*beta+a[j], q[j]:=floor(r/b[0]), r:=r-b[0]*q[j].
131 //   Normalisiere [q[m-1],...,q[0]], liefert q.
132 // Falls m>=n>1, Multiple-Precision-Division:
133 //   Es gilt a/b < beta^(m-n+1).
134 //   s:=intDsize-1-(Nummer des höchsten Bits in b[n-1]), 0<=s<intDsize.
135 //   Schiebe a und b um s Bits nach links und kopiere sie dabei. r:=a.
136 //   r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] mit b[n-1]>=beta/2.
137 //   Für j=m-n,...,0: {Hier 0 <= r < b*beta^(j+1).}
138 //     Berechne q* :
139 //       q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
140 //       Bei Überlauf (q* >= beta) setze q* := beta-1.
141 //       Berechne c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
142 //       und c3 := b[n-2] * q*.
143 //       {Es ist 0 <= c2 < 2*beta^2, sogar 0 <= c2 < beta^2 falls kein
144 //        Überlauf aufgetreten war. Ferner 0 <= c3 < beta^2.
145 //        Bei Überlauf und r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta,
146 //        das heißt c2 >= beta^2, kann man die nächste Abfrage überspringen.}
147 //       Solange c3 > c2, {hier 0 <= c2 < c3 < beta^2} setze
148 //         q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
149 //       Falls q* > 0:
150 //         Setze r := r - b * q* * beta^j, im einzelnen:
151 //           [r[n+j],...,r[j]] := [r[n+j],...,r[j]] - q* * [b[n-1],...,b[0]].
152 //           also: u:=0, for i:=0 to n-1 do
153 //                         u := u + q* * b[i],
154 //                         r[j+i]:=r[j+i]-(u mod beta) (+ beta, falls Carry),
155 //                         u:=u div beta (+ 1, falls bei der Subtraktion Carry)
156 //                 r[n+j]:=r[n+j]-u.
157 //           {Da stets u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
158 //                       < q* + 1 <= beta, läuft der Übertrag u nicht über.}
159 //         Tritt dabei ein negativer Übertrag auf, so setze q* := q* - 1
160 //           und [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
161 //     Setze q[j] := q*.
162 //   Normalisiere [q[m-n],..,q[0]] und erhalte den Quotienten q,
163 //   Schiebe [r[n-1],...,r[0]] um s Bits nach rechts, normalisiere und
164 //   erhalte den Rest r.
165 //   Dabei kann q[j] auf dem Platz von r[n+j] liegen.
166   void cl_UDS_divide (const uintD* a_MSDptr, uintC a_len, const uintD* a_LSDptr,
167                       const uintD* b_MSDptr, uintC b_len, const uintD* b_LSDptr,
168                       uintD* roomptr, // ab roomptr kommen a_len+1 freie Digits
169                       DS* q_, DS* r_)
170     { // a normalisieren (a_MSDptr erhöhen, a_len erniedrigen):
171       while ((a_len>0) && (mspref(a_MSDptr,0)==0)) { msshrink(a_MSDptr); a_len--; }
172       // b normalisieren (b_MSDptr erhöhen, b_len erniedrigen):
173       loop
174         { if (b_len==0) { cl_error_division_by_0(); }
175           if (mspref(b_MSDptr,0)==0) { msshrink(b_MSDptr); b_len--; }
176           else break;
177         }
178       // jetzt m=a_len >=0 und n=b_len >0.
179       if (a_len < b_len)
180         // m<n: Trivialfall, q=0, r:= Kopie von a.
181         { var uintD* r_MSDptr = roomptr;
182           var uintD* r_LSDptr = roomptr mspop a_len;
183           // Speicheraufbau: r_MSDptr/0/r_MSDptr/a_len/r_LSDptr
184           //                    |     q    |       r      |
185           copy_loop_lsp(a_LSDptr,r_LSDptr,a_len);
186           q_->MSDptr = r_MSDptr; q_->len = 0; q_->LSDptr = r_MSDptr; // q = 0, eine NUDS
187           r_->MSDptr = r_MSDptr; r_->len = a_len; r_->LSDptr = r_LSDptr; // r = Kopie von a, eine NUDS
188           return;
189         }
190       elif (b_len==1)
191         // n=1: Single-Precision-Division
192         { // beta^(m-1) <= a < beta^m  ==>  beta^(m-2) <= a/b < beta^m
193           var uintD* q_MSDptr = roomptr;
194           var uintD* q_LSDptr = q_MSDptr mspop a_len;
195           var uintD* r_MSDptr = q_LSDptr;
196           var uintD* r_LSDptr = r_MSDptr mspop 1;
197           // Speicheraufbau: q_MSDptr/a_len/q_LSDptr    r_MSDptr/1/r_LSDptr
198           //                     |      q      |           |     r    |
199          {var uintD rest = divucopy_loop_msp(mspref(b_MSDptr,0),a_MSDptr,q_MSDptr,a_len); // Division durch b[0]
200           var uintC r_len;
201           if (!(rest==0))
202             { mspref(r_MSDptr,0) = rest; r_len=1; } // Rest als r ablegen
203             else
204             { r_MSDptr = r_LSDptr; r_len=0; } // Rest auf 0 normalisieren
205           if (mspref(q_MSDptr,0)==0)
206             { msshrink(q_MSDptr); a_len--; } // q normalisieren
207           q_->MSDptr = q_MSDptr; q_->len = a_len; q_->LSDptr = q_LSDptr; // q ablegen
208           r_->MSDptr = r_MSDptr; r_->len = r_len; r_->LSDptr = r_LSDptr; // r ablegen
209           return;
210         }}
211       else
212         // n>1: Multiple-Precision-Division
213         { // beta^(m-1) <= a < beta^m, beta^(n-1) <= b < beta^n  ==>
214           // beta^(m-n-1) <= a/b < beta^(m-n+1).
215           var uintL s;
216           CL_ALLOCA_STACK;
217           // s bestimmen:
218           { var uintD msd = mspref(b_MSDptr,0); // b[n-1]
219             #if 0
220             s = 0;
221             while ((sintD)msd >= 0) { msd = msd<<1; s++; }
222             #else // ein wenig effizienter, Abfrage auf s=0 vorwegnehmen
223             if ((sintD)msd < 0)
224               { s = 0; goto shift_ok; }
225               else
226               { integerlengthD(msd, s = intDsize - ); goto shift; }
227             #endif
228           }
229           // 0 <= s < intDsize.
230           // Kopiere b und schiebe es dabei um s Bits nach links:
231           if (!(s==0))
232             shift:
233             { var uintD* new_b_MSDptr;
234               var uintD* new_b_LSDptr;
235               num_stack_alloc(b_len,new_b_MSDptr=,new_b_LSDptr=);
236               shiftleftcopy_loop_lsp(b_LSDptr,new_b_LSDptr,b_len,s);
237               b_MSDptr = new_b_MSDptr; b_LSDptr = new_b_LSDptr;
238             }
239           shift_ok:
240           // Wieder b = b_MSDptr/b_len/b_LSDptr.
241           // Kopiere a und schiebe es dabei um s Bits nach links, erhalte r:
242          {var uintD* r_MSDptr = roomptr;
243           var uintD* r_LSDptr = roomptr mspop (a_len+1);
244           // Speicheraufbau:  r_MSDptr/          a_len+1           /r_LSDptr
245           //                     |                  r                  |
246           // später:          q_MSDptr/a_len-b_len+1/r_MSDptr/b_len/r_LSDptr
247           //                     |           q          |       r      |
248           if (s==0)
249             { copy_loop_lsp(a_LSDptr,r_LSDptr,a_len); mspref(r_MSDptr,0) = 0; }
250             else
251             { mspref(r_MSDptr,0) = shiftleftcopy_loop_lsp(a_LSDptr,r_LSDptr,a_len,s); }
252           // Nun r = r_MSDptr/a_len+1/r_LSDptr.
253           var uintC j = a_len-b_len; // m-n
254           var uintD* q_MSDptr = r_MSDptr;
255           var uintC q_len = j+1; // q wird m-n+1 Digits haben
256           if (cl_recip_suitable(a_len,b_len))
257             { // Bestimme Kehrwert c von b.
258               var uintD* c_MSDptr;
259               var uintD* c_LSDptr;
260               num_stack_alloc(j+3,c_MSDptr=,c_LSDptr=);
261               cl_UDS_recip(b_MSDptr,b_len,c_MSDptr,j+1);
262               // c hat j+3 Digits, | beta^(m+2)/b - c | < beta.
263               // Mit a' = floor(a/beta^n) multiplizieren, liefert d':
264               var uintD* d_MSDptr;
265               UDS_UDS_mul_UDS(j+1,r_MSDptr mspop (j+1), j+3,c_MSDptr mspop (j+3),
266                               d_MSDptr=,,);
267               // d' has 2*j+4 digits, d := floor(d'/beta^(j+2)) has j+2 digits.
268               // | beta^(m+2)/b - c | < beta  ==> (since a < beta^(m+1))
269               // | beta^(m+2)*a/b - a*c | < beta^(m+2),
270               // 0 <= a - a'*beta^n < beta^n ==> (since c <= 2*beta^(j+2))
271               // 0 <= a*c - a'*c*beta^n < 2*beta^(m+2) ==>
272               // -beta^(m+2) < beta^(m+2)*a/b - a'*c*beta^n < 3*beta^(m+2) ==>
273               // -1 < a/b - a'*c*beta^(-j-2) < 3 ==>
274               // -1 < a/b - d'*beta^(-j-2) < 3,
275               // -1 < d'*beta^(-j-2) - d <= 0 ==>
276               // -2 < a/b - d < 3 ==>
277               // -2 <= q - d < 3 ==> |q-d| <= 2.
278               var uintD* d_LSDptr = d_MSDptr mspop (j+2);
279               // Zur Bestimmung des Restes wieder mit b multiplizieren:
280               var uintD* p_MSDptr;
281               var uintD* p_LSDptr;
282               UDS_UDS_mul_UDS(j+2,d_LSDptr, b_len,b_LSDptr, p_MSDptr=,,p_LSDptr=);
283               // d ist um höchstens 2 zu groß, muß also evtl. zweimal um 1
284               // decrementieren, bis das Produkt <= a wird.
285               if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
286                 { dec_loop_lsp(d_LSDptr,j+2);
287                   if (subfrom_loop_lsp(b_LSDptr,p_LSDptr,b_len))
288                     dec_loop_lsp(p_LSDptr lspop b_len,j+2);
289                   if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
290                     { dec_loop_lsp(d_LSDptr,j+2);
291                       if (subfrom_loop_lsp(b_LSDptr,p_LSDptr,b_len))
292                         dec_loop_lsp(p_LSDptr lspop b_len,j+2);
293                       if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
294                         cl_abort();
295                 }   }
296               // Rest bestimmen:
297               subfrom_loop_lsp(p_LSDptr,r_LSDptr,a_len+1);
298               if (test_loop_msp(r_MSDptr,j)) cl_abort();
299               r_MSDptr = r_LSDptr lspop b_len; // = r_MSDptr mspop (j+1);
300               // d ist um höchstens 2 zu klein, muß also evtl. zweimal um 1
301               // incrementieren, bis der Rest < b wird.
302               if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
303                 { inc_loop_lsp(d_LSDptr,j+2);
304                   if (subfrom_loop_lsp(b_LSDptr,r_LSDptr,b_len))
305                     lspref(r_LSDptr,b_len) -= 1;
306                   if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
307                     { inc_loop_lsp(d_LSDptr,j+2);
308                       if (subfrom_loop_lsp(b_LSDptr,r_LSDptr,b_len))
309                         lspref(r_LSDptr,b_len) -= 1;
310                       if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
311                         cl_abort();
312                 }   }
313               // r ist fertig, q := d.
314               if (mspref(d_MSDptr,0) > 0) cl_abort();
315               q_len = j+1; copy_loop_msp(d_MSDptr mspop 1,q_MSDptr,q_len);
316             }
317             else
318             { var uintD* r_ptr = r_LSDptr lspop j; // Pointer oberhalb von r[j]
319               j = j+1;
320               var uintD b_msd = mspref(b_MSDptr,0); // b[n-1]
321               var uintD b_2msd = mspref(b_MSDptr,1); // b[n-2]
322               #if HAVE_DD
323               var uintDD b_msdd = highlowDD(b_msd,b_2msd); // b[n-1]*beta+b[n-2]
324               #endif
325               // Divisions-Schleife: (wird m-n+1 mal durchlaufen)
326               // j = Herabzähler, b_MSDptr/b_len/b_LSDptr = [b[n-1],...,b[0]], b_len=n,
327               // r_MSDptr = Pointer auf r[n+j] = Pointer auf q[j],
328               // r_ptr = Pointer oberhalb von r[j].
329               do { var uintD q_stern;
330                    var uintD c1;
331                    if (mspref(r_MSDptr,0) < b_msd) // r[j+n] < b[n-1] ?
332                      { // Dividiere r[j+n]*beta+r[j+n-1] durch b[n-1], ohne Überlauf:
333                        #if HAVE_DD
334                          divuD(highlowDD(mspref(r_MSDptr,0),mspref(r_MSDptr,1)),b_msd, q_stern=,c1=);
335                        #else
336                          divuD(mspref(r_MSDptr,0),mspref(r_MSDptr,1),b_msd, q_stern=,c1=);
337                        #endif
338                      }
339                      else
340                      { // Überlauf, also r[j+n]*beta+r[j+n-1] >= beta*b[n-1]
341                        q_stern = bitm(intDsize)-1; // q* = beta-1
342                        // Teste ob r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
343                        // <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
344                        // <==> b[n-1] < floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) {<= beta !} ist.
345                        // Wenn ja, direkt zur Subtraktionschleife.
346                        // (Andernfalls ist r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] < beta
347                        //  <==> floor((r[j+n]*beta+r[j+n-1]+b[n-1])/beta) = b[n-1] ).
348                        if ((mspref(r_MSDptr,0) > b_msd) || ((c1 = mspref(r_MSDptr,1)+b_msd) < b_msd))
349                          // r[j+n] >= b[n-1]+1 oder
350                          // r[j+n] = b[n-1] und Addition r[j+n-1]+b[n-1] gibt Carry ?
351                          { goto subtract; } // ja -> direkt in die Subtraktion
352                      }
353                    // q_stern = q*,
354                    // c1 = (r[j+n]*beta+r[j+n-1]) - q* * b[n-1] (>=0, <beta).
355                    #if HAVE_DD
356                      { var uintDD c2 = highlowDD(c1,mspref(r_MSDptr,2)); // c1*beta+r[j+n-2]
357                        var uintDD c3 = muluD(b_2msd,q_stern); // b[n-2] * q*
358                        // Solange c2 < c3, c2 erhöhen, c3 erniedrigen:
359                        // Rechne dabei mit c3-c2:
360                        // solange >0, um b[n-1]*beta+b[n-2] erniedrigen.
361                        // Dies kann wegen b[n-1]*beta+b[n-2] >= beta^2/2
362                        // höchstens zwei mal auftreten.
363                        if (c3 > c2)
364                          { q_stern = q_stern-1; // q* := q* - 1
365                            if (c3-c2 > b_msdd)
366                              { q_stern = q_stern-1; } // q* := q* - 1
367                      }   }
368                    #else
369                      // Wie oben, nur mit zweigeteilten c2=[c2hi|c2lo] und c3=[c3hi|c3lo]:
370                      #define c2hi c1
371                      { var uintD c2lo = mspref(r_MSDptr,2); // c2hi*beta+c2lo = c1*beta+r[j+n-2]
372                        var uintD c3hi;
373                        var uintD c3lo;
374                        muluD(b_2msd,q_stern, c3hi=,c3lo=); // c3hi*beta+c3lo = b[n-2] * q*
375                        if ((c3hi > c2hi) || ((c3hi == c2hi) && (c3lo > c2lo)))
376                          { q_stern = q_stern-1; // q* := q* - 1
377                            c3hi -= c2hi; if (c3lo < c2lo) { c3hi--; }; c3lo -= c2lo; // c3 := c3-c2
378                            if ((c3hi > b_msd) || ((c3hi == b_msd) && (c3lo > b_2msd)))
379                              { q_stern = q_stern-1; } // q* := q* - 1
380                      }   }
381                      #undef c2hi
382                    #endif
383                    if (!(q_stern==0))
384                      subtract:
385                      { // Subtraktionsschleife: r := r - b * q* * beta^j
386                        var uintD carry = mulusub_loop_lsp(q_stern,b_LSDptr,r_ptr,b_len);
387                        // Noch r_ptr[-b_len-1] -= carry, d.h. r_MSDptr[0] -= carry
388                        // durchführen und danach r_MSDptr[0] vergessen:
389                        if (carry > mspref(r_MSDptr,0))
390                          // Subtraktion ergab Übertrag
391                          { q_stern = q_stern-1; // q* := q* - 1
392                            addto_loop_lsp(b_LSDptr,r_ptr,b_len); // Additionsschleife
393                            // r[n+j] samt Carry kann vergessen werden...
394                      }   }
395                    // Berechnung von q* ist fertig.
396                    msprefnext(r_MSDptr) = q_stern; // als q[j] ablegen
397                    r_ptr = r_ptr mspop 1;
398                  }
399                  until (--j == 0);
400             }
401           // Nun ist q = [q[m-n],..,q[0]] = q_MSDptr/q_len/r_MSDptr
402           // und r = [r[n-1],...,r[0]] = r_MSDptr/b_len/r_LSDptr.
403           // q normalisieren und ablegen:
404           if (mspref(q_MSDptr,0)==0)
405             { msshrink(q_MSDptr); q_len--; }
406           q_->MSDptr = q_MSDptr; q_->len = q_len; q_->LSDptr = r_MSDptr;
407           // Schiebe [r[n-1],...,r[0]] um s Bits nach rechts:
408           if (!(s==0))
409             { shiftright_loop_msp(r_MSDptr,b_len,s); }
410           // r normalisieren und ablegen:
411           while ((b_len>0) && (mspref(r_MSDptr,0)==0))
412             { msshrink(r_MSDptr); b_len--; }
413           r_->MSDptr = r_MSDptr; r_->len = b_len; r_->LSDptr = r_LSDptr;
414           return;
415         }}
416     }
417 // Bit complexity (N = a_len): O(M(N)).
418