X-Git-Url: https://ginac.de/CLN/cln.git//cln.git?a=blobdiff_plain;ds=sidebyside;f=src%2Finteger%2Fbitwise%2Fcl_I_ash_I.cc;h=6c11f475197bb37d19b4b0a43f3d01672cd5560f;hb=740c032627dfc7ac87d90d6e75b5e87e78c9e716;hp=2ea5cd2419b0a98d7c1b699428ccbb351b4011b9;hpb=850abfde7f0d985ba01526c346bcd0d733562943;p=cln.git diff --git a/src/integer/bitwise/cl_I_ash_I.cc b/src/integer/bitwise/cl_I_ash_I.cc index 2ea5cd2..6c11f47 100644 --- a/src/integer/bitwise/cl_I_ash_I.cc +++ b/src/integer/bitwise/cl_I_ash_I.cc @@ -1,7 +1,7 @@ // ash(). // General includes. -#include "cl_sysdep.h" +#include "base/cl_sysdep.h" // Specification. #include "cln/integer.h" @@ -9,9 +9,8 @@ // Implementation. -#include "cl_I.h" -#include "cl_DS.h" -#include "cl_I_ash.h" +#include "integer/cl_I.h" +#include "base/digitseq/cl_DS.h" namespace cln { @@ -21,11 +20,11 @@ const cl_I ash (const cl_I& x, const cl_I& y) // x = 0 -> 0 als Ergebnis // y = 0 -> x als Ergebnis // y > 0 -> y = intDsize*k + i, j=k+(1 falls i>0, 0 falls i=0). - // j Wörter mehr reservieren, k Nullwörter, dann übertragen, + // j Wörter mehr reservieren, k Nullwörter, dann übertragen, // bei i>0: um i Bits links schieben (i=1 geht einfacher). - // y < 0 -> y <= - intDsize * (Länge(A0) in Digits) -> Ergebnis = 0 oder -1. - // Sonst: -y = intDsize*k + i mit k y <= - intDsize * (Länge(A0) in Digits) -> Ergebnis = 0 oder -1. + // Sonst: -y = intDsize*k + i mit k0: schiebe sie um i Bits nach rechts (i=1 geht einfacher). if (zerop(x)) return 0; // x=0 -> 0 als Ergebnis @@ -35,23 +34,24 @@ const cl_I ash (const cl_I& x, const cl_I& y) if (!minusp(y)) { // y>=0 var uintL i; // i = y mod intDsize, >=0, =0, <2^intCsize + var uintC k; // k = y div intDsize, >=0, <2^intCsize if (bignump(y)) { #if (log2_intDsize+intCsize <= cl_value_len-1) // y >= 2^(cl_value_len-1) >= intDsize*2^intCsize - cl_ash_error(y); + throw ash_exception(y); #else // y >= 2^(cl_value_len-1) // usable only if y < intDsize*2^intCsize var cl_heap_bignum* bn = TheBignum(y); var uintC len = bn->length; if (len > ceiling(log2_intDsize+intCsize+1,intDsize)) - cl_ash_error(y); + throw ash_exception(y); // bn_minlength <= len <= ceiling(log2_intDsize+intCsize+1,intDsize). if (bn_minlength == ceiling(log2_intDsize+intCsize+1,intDsize) || len == ceiling(log2_intDsize+intCsize+1,intDsize)) if (mspref(arrayMSDptr(bn->data,len),0) >= (uintD)bit((log2_intDsize+intCsize)%intDsize)) - cl_ash_error(y); + throw ash_exception(y); + #if (log2_intDsize+intCsize > intDsize) #define IF_LENGTH(i) \ if (bn_minlength <= i && i <= ceiling(log2_intDsize+intCsize+1,intDsize) && (i == ceiling(log2_intDsize+intCsize+1,intDsize) || len == i)) IF_LENGTH(1) @@ -65,23 +65,28 @@ const cl_I ash (const cl_I& x, const cl_I& y) else IF_LENGTH(5) k = get_uint4D_Dptr(arrayLSDptr(bn->data,5) lspop 1); else - cl_abort(); + throw runtime_exception(); #undef IF_LENGTH k = k << (intDsize-log2_intDsize); + #else + // log2_intDsize+intCsize <= intDsize, + // implies len==1 or len==2 && lspref(arrayLSDptr(bn->data,len),1) == 0. + k = 0; + #endif k |= lspref(arrayLSDptr(bn->data,len),0) >> log2_intDsize; i = lspref(arrayLSDptr(bn->data,len),0) % intDsize; #endif } else { - var uintL y_ = FN_to_L(y); // Wert von y, >=0, =0, = (uintC)(~(uintC)len)) // kann len+k+1 Überlauf geben? - { cl_ash_error(y); } // ja -> Fehler + I_to_NDS_nocopy(x, ,len=,x_LSDptr=,false,); // DS zu x bilden. + if (k >= (uintC)(~len)) // kann len+k+1 Überlauf geben? + { throw ash_exception(y); } // ja -> Fehler num_stack_alloc_1(len+k,,LSDptr=); LSDptr = clear_loop_lsp(LSDptr,k); // k Nulldigits var uintD* MSDptr = copy_loop_lsp(x_LSDptr,LSDptr,len); @@ -105,7 +110,7 @@ const cl_I ash (const cl_I& x, const cl_I& y) } else { // y<0 var uintL i; // i = (-y) mod intDsize, >=0, =0, <2^intCsize + var uintC k; // k = (-y) div intDsize, >=0, <2^intCsize if (bignump(y)) { #if (log2_intDsize+intCsize <= cl_value_len-1) // -y-1 >= 2^(cl_value_len-1) >= intDsize*2^intCsize @@ -123,6 +128,7 @@ const cl_I ash (const cl_I& x, const cl_I& y) || len == ceiling(log2_intDsize+intCsize+1,intDsize)) if (mspref(arrayMSDptr(bn->data,len),0) < (uintD)(-bit((log2_intDsize+intCsize)%intDsize))) goto sign; + #if (log2_intDsize+intCsize > intDsize) #define IF_LENGTH(i) \ if (bn_minlength <= i && i <= ceiling(log2_intDsize+intCsize+1,intDsize) && (i == ceiling(log2_intDsize+intCsize+1,intDsize) || len == i)) IF_LENGTH(1) @@ -136,9 +142,14 @@ const cl_I ash (const cl_I& x, const cl_I& y) else IF_LENGTH(5) k = ~get_sint4D_Dptr(arrayLSDptr(bn->data,5) lspop 1); else - cl_abort(); + throw runtime_exception(); #undef IF_LENGTH k = k << (intDsize-log2_intDsize); + #else + // log2_intDsize+intCsize <= intDsize, + // implies len==1 or len==2 && lspref(arrayLSDptr(bn->data,len),1) == ~0. + k = 0; + #endif k |= (uintD)(~lspref(arrayLSDptr(bn->data,len),0)) >> log2_intDsize; i = (uintD)(-lspref(arrayLSDptr(bn->data,len),0)) % intDsize; if (i == 0) @@ -146,7 +157,7 @@ const cl_I ash (const cl_I& x, const cl_I& y) goto sign; #endif } else { - var uintL y_ = -FN_to_L(y); // Wert von -y, >0, 0, =len) goto sign; // -y >= intDsize*len -> Vorzeichen von x zurück + if (k>=len) goto sign; // -y >= intDsize*len -> Vorzeichen von x zurück len -= k; // rechte k Digits einfach streichen // Noch ist len>0. Um i Bits nach rechts schieben: if (!(i==0)) // Bei i>0: