// cl_UDS_divide().
// General includes.
-#include "cl_sysdep.h"
+#include "base/cl_sysdep.h"
// Specification.
-#include "cl_DS.h"
+#include "base/digitseq/cl_DS.h"
// Implementation.
-#include "cl_N.h"
-#include "cl_abort.h"
+#include "cln/exception.h"
+
+namespace cln {
// We observe the following timings in seconds:
// Time for dividing a 2*n word number by a n word number:
// Break-even-point, should be acceptable for both architectures.
// When in doubt, prefer to choose the standard algorithm.
#if CL_USE_GMP
- static inline cl_boolean cl_recip_suitable (uintL m, uintL n) // m > n
+ static inline bool cl_recip_suitable (uintC m, uintC n) // m > n
{ if (n < 900)
- return cl_false;
+ return false;
else
if (n < 2200)
- return (cl_boolean)((m >= n+50) && (m < 2*n-600));
+ return (m >= n+50) && (m < 2*n-600);
else
- return (cl_boolean)(m >= n+30);
+ return m >= n+30;
}
#else
// Use the old default values from CLN version <= 1.0.3 as a crude estimate.
// n = 2000: Newton faster for m >= 2020
// n = 2500: Newton faster for m >= 2520
// n = 5000: Newton faster for m >= 5020
- static inline cl_boolean cl_recip_suitable (uintL m, uintL n) // m > n
+ static inline bool cl_recip_suitable (uintC m, uintC n) // m > n
{ if (n < 500)
- return cl_false;
+ return false;
else
if (n < 1000)
- return (cl_boolean)((m >= n+30) && (m < 3*n-600));
+ return (m >= n+30) && (m < 3*n-600);
else
- return (cl_boolean)(m >= n+20);
+ return m >= n+20;
}
#endif
// q = q_MSDptr/q_len/q_LSDptr, r = r_MSDptr/r_len/r_LSDptr beides
// Normalized Unsigned Digit sequences.
// Vorsicht: q_LSDptr <= r_MSDptr,
-// Vorzeichenerweiterung von r kann q zerstören!
+// Vorzeichenerweiterung von r kann q zerstören!
// Vorzeichenerweiterung von q ist erlaubt.
// a und b werden nicht modifiziert.
//
// Normalisiere [q[m-1],...,q[0]], liefert q.
// Falls m>=n>1, Multiple-Precision-Division:
// Es gilt a/b < beta^(m-n+1).
-// s:=intDsize-1-(Nummer des höchsten Bits in b[n-1]), 0<=s<intDsize.
+// s:=intDsize-1-(Nummer des höchsten Bits in b[n-1]), 0<=s<intDsize.
// Schiebe a und b um s Bits nach links und kopiere sie dabei. r:=a.
// r=[r[m],...,r[0]], b=[b[n-1],...,b[0]] mit b[n-1]>=beta/2.
-// Für j=m-n,...,0: {Hier 0 <= r < b*beta^(j+1).}
+// Für j=m-n,...,0: {Hier 0 <= r < b*beta^(j+1).}
// Berechne q* :
// q* := floor((r[j+n]*beta+r[j+n-1])/b[n-1]).
-// Bei Überlauf (q* >= beta) setze q* := beta-1.
+// Bei Überlauf (q* >= beta) setze q* := beta-1.
// Berechne c2 := ((r[j+n]*beta+r[j+n-1]) - q* * b[n-1])*beta + r[j+n-2]
// und c3 := b[n-2] * q*.
// {Es ist 0 <= c2 < 2*beta^2, sogar 0 <= c2 < beta^2 falls kein
-// Überlauf aufgetreten war. Ferner 0 <= c3 < beta^2.
-// Bei Überlauf und r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta,
-// das heißt c2 >= beta^2, kann man die nächste Abfrage überspringen.}
+// Überlauf aufgetreten war. Ferner 0 <= c3 < beta^2.
+// Bei Überlauf und r[j+n]*beta+r[j+n-1] - q* * b[n-1] >= beta,
+// das heißt c2 >= beta^2, kann man die nächste Abfrage überspringen.}
// Solange c3 > c2, {hier 0 <= c2 < c3 < beta^2} setze
// q* := q* - 1, c2 := c2 + b[n-1]*beta, c3 := c3 - b[n-2].
// Falls q* > 0:
// u:=u div beta (+ 1, falls bei der Subtraktion Carry)
// r[n+j]:=r[n+j]-u.
// {Da stets u = (q* * [b[i-1],...,b[0]] div beta^i) + 1
-// < q* + 1 <= beta, läuft der Übertrag u nicht über.}
-// Tritt dabei ein negativer Übertrag auf, so setze q* := q* - 1
+// < q* + 1 <= beta, läuft der Übertrag u nicht über.}
+// Tritt dabei ein negativer Übertrag auf, so setze q* := q* - 1
// und [r[n+j],...,r[j]] := [r[n+j],...,r[j]] + [0,b[n-1],...,b[0]].
// Setze q[j] := q*.
// Normalisiere [q[m-n],..,q[0]] und erhalte den Quotienten q,
const uintD* b_MSDptr, uintC b_len, const uintD* b_LSDptr,
uintD* roomptr, // ab roomptr kommen a_len+1 freie Digits
DS* q_, DS* r_)
- { // a normalisieren (a_MSDptr erhöhen, a_len erniedrigen):
+ { // a normalisieren (a_MSDptr erhöhen, a_len erniedrigen):
while ((a_len>0) && (mspref(a_MSDptr,0)==0)) { msshrink(a_MSDptr); a_len--; }
- // b normalisieren (b_MSDptr erhöhen, b_len erniedrigen):
+ // b normalisieren (b_MSDptr erhöhen, b_len erniedrigen):
loop
- { if (b_len==0) { cl_error_division_by_0(); }
+ { if (b_len==0) { throw division_by_0_exception(); }
if (mspref(b_MSDptr,0)==0) { msshrink(b_MSDptr); b_len--; }
else break;
}
var uintD* r_LSDptr = roomptr mspop (a_len+1);
// Speicheraufbau: r_MSDptr/ a_len+1 /r_LSDptr
// | r |
- // später: q_MSDptr/a_len-b_len+1/r_MSDptr/b_len/r_LSDptr
+ // später: q_MSDptr/a_len-b_len+1/r_MSDptr/b_len/r_LSDptr
// | q | r |
if (s==0)
{ copy_loop_lsp(a_LSDptr,r_LSDptr,a_len); mspref(r_MSDptr,0) = 0; }
var uintD* p_MSDptr;
var uintD* p_LSDptr;
UDS_UDS_mul_UDS(j+2,d_LSDptr, b_len,b_LSDptr, p_MSDptr=,,p_LSDptr=);
- // d ist um höchstens 2 zu groß, muß also evtl. zweimal um 1
+ // d ist um höchstens 2 zu groß, muß also evtl. zweimal um 1
// decrementieren, bis das Produkt <= a wird.
if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
{ dec_loop_lsp(d_LSDptr,j+2);
if (subfrom_loop_lsp(b_LSDptr,p_LSDptr,b_len))
dec_loop_lsp(p_LSDptr lspop b_len,j+2);
if ((mspref(p_MSDptr,0) > 0) || (compare_loop_msp(p_MSDptr mspop 1,r_MSDptr,a_len+1) > 0))
- cl_abort();
+ throw runtime_exception();
} }
// Rest bestimmen:
subfrom_loop_lsp(p_LSDptr,r_LSDptr,a_len+1);
- if (test_loop_msp(r_MSDptr,j)) cl_abort();
+ if (test_loop_msp(r_MSDptr,j)) throw runtime_exception();
r_MSDptr = r_LSDptr lspop b_len; // = r_MSDptr mspop (j+1);
- // d ist um höchstens 2 zu klein, muß also evtl. zweimal um 1
+ // d ist um höchstens 2 zu klein, muß also evtl. zweimal um 1
// incrementieren, bis der Rest < b wird.
if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
{ inc_loop_lsp(d_LSDptr,j+2);
if (subfrom_loop_lsp(b_LSDptr,r_LSDptr,b_len))
lspref(r_LSDptr,b_len) -= 1;
if ((lspref(r_MSDptr,0) > 0) || (compare_loop_msp(r_MSDptr,b_MSDptr,b_len) >= 0))
- cl_abort();
+ throw runtime_exception();
} }
// r ist fertig, q := d.
- if (mspref(d_MSDptr,0) > 0) cl_abort();
+ if (mspref(d_MSDptr,0) > 0) throw runtime_exception();
q_len = j+1; copy_loop_msp(d_MSDptr mspop 1,q_MSDptr,q_len);
}
else
var uintDD b_msdd = highlowDD(b_msd,b_2msd); // b[n-1]*beta+b[n-2]
#endif
// Divisions-Schleife: (wird m-n+1 mal durchlaufen)
- // j = Herabzähler, b_MSDptr/b_len/b_LSDptr = [b[n-1],...,b[0]], b_len=n,
+ // j = Herabzähler, b_MSDptr/b_len/b_LSDptr = [b[n-1],...,b[0]], b_len=n,
// r_MSDptr = Pointer auf r[n+j] = Pointer auf q[j],
// r_ptr = Pointer oberhalb von r[j].
do { var uintD q_stern;
var uintD c1;
if (mspref(r_MSDptr,0) < b_msd) // r[j+n] < b[n-1] ?
- { // Dividiere r[j+n]*beta+r[j+n-1] durch b[n-1], ohne Überlauf:
+ { // Dividiere r[j+n]*beta+r[j+n-1] durch b[n-1], ohne Überlauf:
#if HAVE_DD
divuD(highlowDD(mspref(r_MSDptr,0),mspref(r_MSDptr,1)),b_msd, q_stern=,c1=);
#else
#endif
}
else
- { // Überlauf, also r[j+n]*beta+r[j+n-1] >= beta*b[n-1]
+ { // Überlauf, also r[j+n]*beta+r[j+n-1] >= beta*b[n-1]
q_stern = bitm(intDsize)-1; // q* = beta-1
// Teste ob r[j+n]*beta+r[j+n-1] - (beta-1)*b[n-1] >= beta
// <==> r[j+n]*beta+r[j+n-1] + b[n-1] >= beta*b[n-1]+beta
#if HAVE_DD
{ var uintDD c2 = highlowDD(c1,mspref(r_MSDptr,2)); // c1*beta+r[j+n-2]
var uintDD c3 = muluD(b_2msd,q_stern); // b[n-2] * q*
- // Solange c2 < c3, c2 erhöhen, c3 erniedrigen:
+ // Solange c2 < c3, c2 erhöhen, c3 erniedrigen:
// Rechne dabei mit c3-c2:
// solange >0, um b[n-1]*beta+b[n-2] erniedrigen.
// Dies kann wegen b[n-1]*beta+b[n-2] >= beta^2/2
- // höchstens zwei mal auftreten.
+ // höchstens zwei mal auftreten.
if (c3 > c2)
{ q_stern = q_stern-1; // q* := q* - 1
if (c3-c2 > b_msdd)
{ // Subtraktionsschleife: r := r - b * q* * beta^j
var uintD carry = mulusub_loop_lsp(q_stern,b_LSDptr,r_ptr,b_len);
// Noch r_ptr[-b_len-1] -= carry, d.h. r_MSDptr[0] -= carry
- // durchführen und danach r_MSDptr[0] vergessen:
+ // durchführen und danach r_MSDptr[0] vergessen:
if (carry > mspref(r_MSDptr,0))
- // Subtraktion ergab Übertrag
+ // Subtraktion ergab Übertrag
{ q_stern = q_stern-1; // q* := q* - 1
addto_loop_lsp(b_LSDptr,r_ptr,b_len); // Additionsschleife
// r[n+j] samt Carry kann vergessen werden...
}
// Bit complexity (N = a_len): O(M(N)).
+} // namespace cln