quad_float operator +(const quad_float& x, const quad_float& y ) { START_FIX DOUBLE H, h, T, t, S, s, e, f; DOUBLE t1; S = x.hi + y.hi; T = x.lo + y.lo; e = S - x.hi; f = T - x.lo; t1 = S-e; t1 = x.hi-t1; s = y.hi-e; s = s + t1; t1 = T-f; t1 = x.lo-t1; t = y.lo-f; t = t + t1; s = s + T; H = S + s; h = S - H; h = h + s; h = h + t; e = H + h; f = H - e; f = f + h; END_FIX return quad_float(e, f); }
quad_float to_quad_float(unsigned long n) { START_FIX DOUBLE xhi, xlo, t; DOUBLE u, v; const double bnd = double(1L << (NTL_BITS_PER_LONG-2))*4.0; xhi = double(n); if (xhi >= bnd) t = xhi - bnd; else t = xhi; // we use the "to_long" function here to be as portable as possible. long llo = to_long(n - (unsigned long)(t)); xlo = double(llo); // renormalize...just to be safe u = xhi + xlo; v = xhi - u; v = v + xlo; END_FIX return quad_float(u, v); }
quad_float sqrt(const quad_float& y) { if (y.hi < 0.0) ArithmeticError("quad_float: square root of negative number"); if (y.hi == 0.0) return quad_float(0.0,0.0); double c; c = sqrt(y.hi); ForceToMem(&c); // This is fairly paranoid, but it doesn't cost too much. START_FIX DOUBLE p,q,hx,tx,u,uu,cc; DOUBLE t1; p = Protect(NTL_QUAD_FLOAT_SPLIT*c); hx = (c-p); hx = hx+p; tx = c-hx; p = Protect(hx*hx); q = Protect(hx*tx); q = q+q; u = p+q; uu = p-u; uu = uu+q; t1 = Protect(tx*tx); uu = uu+t1; cc = y.hi-u; cc = cc-uu; cc = cc+y.lo; t1 = c+c; cc = cc/t1; hx = c+cc; tx = c-hx; tx = tx+cc; END_FIX return quad_float(hx, tx); }
quad_float floor(const quad_float& x) { double fhi = floor(x.hi); if (fhi != x.hi) return quad_float(fhi, 0.0); else { double flo = floor(x.lo); quad_float z; normalize(z, fhi, flo); return z; } }
quad_float operator /(const quad_float& x, const quad_float& y ) { START_FIX DOUBLE hc, tc, hy, ty, C, c, U, u; DOUBLE t1; C = x.hi/y.hi; c = Protect(NTL_QUAD_FLOAT_SPLIT*C); hc = c-C; u = Protect(NTL_QUAD_FLOAT_SPLIT*y.hi); hc = c-hc; tc = C-hc; hy = u-y.hi; U = Protect(C * y.hi); hy = u-hy; ty = y.hi-hy; // u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty; u = Protect(hc*hy); u = u-U; t1 = Protect(hc*ty); u = u+t1; t1 = Protect(tc*hy); u = u+t1; t1 = Protect(tc*ty); u = u+t1; // c = ((((x.hi-U)-u)+x.lo)-C*y.lo)/y.hi; c = x.hi-U; c = c-u; c = c+x.lo; t1 = Protect(C*y.lo); c = c - t1; c = c/y.hi; hy = C+c; ty = C-hy; ty = ty+c; END_FIX return quad_float(hy, ty); }
quad_float operator -(const quad_float& x) { START_FIX DOUBLE xhi, xlo, u, v; xhi = -x.hi; xlo = -x.lo; // it is a good idea to renormalize here, just in case // the rounding rule depends on sign, and thus we will // maintain the "normal form" for quad_float's. u = xhi + xlo; v = xhi - u; v = v + xlo; END_FIX return quad_float(u, v); }
quad_float operator *(const quad_float& x,const quad_float& y ) { START_FIX DOUBLE hx, tx, hy, ty, C, c; DOUBLE t1, t2; C = Protect(NTL_QUAD_FLOAT_SPLIT*x.hi); hx = C-x.hi; c = Protect(NTL_QUAD_FLOAT_SPLIT*y.hi); hx = C-hx; tx = x.hi-hx; hy = c-y.hi; C = Protect(x.hi*y.hi); hy = c-hy; ty = y.hi-hy; // c = ((((hx*hy-C)+hx*ty)+tx*hy)+tx*ty)+(x.hi*y.lo+x.lo*y.hi); t1 = Protect(hx*hy); t1 = t1-C; t2 = Protect(hx*ty); t1 = t1+t2; t2 = Protect(tx*hy); t1 = t1+t2; t2 = Protect(tx*ty); c = t1+t2; t1 = Protect(x.hi*y.lo); t2 = Protect(x.lo*y.hi); t1 = t1+t2; c = c + t1; hx = C+c; tx = C-hx; tx = tx+c; END_FIX return quad_float(hx, tx); }
quad_float to_quad_float(long n) { START_FIX DOUBLE xhi, xlo; DOUBLE u, v; xhi = double(n); // Because we are assuming 2's compliment integer // arithmetic, the following prevents long(xhi) from overflowing. if (n > 0) xlo = double(n+long(-xhi)); else xlo = double(n-long(xhi)); // renormalize...just to be safe u = xhi + xlo; v = xhi - u; v = v + xlo; END_FIX return quad_float(u, v); }