⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 quad_float.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
📖 第 1 页 / 共 2 页
字号:
  // c = ((((x.hi-U)-u)+x.lo)-C*y.lo)/y.hi;  c = x.hi-U;  c = c-u;  c = c+x.lo;  t1 = 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 /=(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 = NTL_QUAD_FLOAT_SPLIT*C;  hc = c-C;  u = NTL_QUAD_FLOAT_SPLIT*y.hi;  hc = c-hc;  tc = C-hc;  hy = u-y.hi;  U = C * y.hi;  hy = u-hy;  ty = y.hi-hy;  // u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty;  u = hc*hy;  u = u-U;  t1 = hc*ty;  u = u+t1;  t1 = tc*hy;  u = u+t1;  t1 = 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 = C*y.lo;  c = c - t1;  c = c/y.hi;    hy = C+c;  ty = C-hy;  ty = ty+c;  x.hi = hy;  x.lo = ty;END_FIX  return x;}quad_float sqrt(const quad_float& y) {  if (y.hi < 0.0)     Error("Quad: attempto to take 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 = NTL_QUAD_FLOAT_SPLIT*c;   hx = (c-p);   hx = hx+p;   tx = c-hx;  p = hx*hx;  q = hx*tx;  q = q+q;  u = p+q;  uu = p-u;  uu = uu+q;  t1 = 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);}void power(quad_float& z, const quad_float& a, long e){   quad_float res, u;   unsigned long k;   if (e < 0)      k = -e;   else      k = e;   res = 1.0;   u = a;   while (k) {      if (k & 1)         res = res * u;      k = k >> 1;      if (k)         u = u * u;   }   if (e < 0)      z = 1.0/res;   else      z = res;}void power2(quad_float& z, long e){   int ee;   ee = e;   if (ee != e) Error("overflow in power2");   z.hi = ldexp(1.0, ee);   z.lo = 0;}long to_long(const quad_float& x){   DOUBLE fhi, flo;   long lhi, llo;   fhi = floor(x.hi);   if (fhi > 0)      lhi = -long(-fhi);   else      lhi = long(fhi);   if (fhi == x.hi) {      flo = floor(x.lo);      llo = long(flo);   }   else      llo = 0;   return lhi + llo;}// This version of ZZ to quad_float coversion relies on the// precise rounding rules implemented by the ZZ to double conversion.void conv(quad_float& z, const ZZ& a){   DOUBLE xhi, xlo;   conv(xhi, a);   if (!IsFinite(&xhi)) {      z.hi = xhi;      z.lo = 0;      return;   }   static ZZ t;   conv(t, xhi);   sub(t, a, t);   conv(xlo, t);   normalize(z, xhi, xlo);   if (fabs(z.hi) < NTL_FDOUBLE_PRECISION && z.lo != 0)      Error("internal error: ZZ to quad_float conversion");} void conv(ZZ& z, const quad_float& x){    static ZZ t1, t2, t3;   DOUBLE fhi, flo;   fhi = floor(x.hi);   if (fhi == x.hi) {      flo = floor(x.lo);      conv(t1, fhi);      conv(t2, flo);      add(z, t1, t2);   }   else      conv(z, fhi);}ostream& operator<<(ostream& s, const quad_float& a){   quad_float aa = a;   if (!IsFinite(&aa)) {      s << "NaN";      return s;   }   long old_p = RR::precision();   long old_op = RR::OutputPrecision();   RR::SetPrecision(long(3.33*quad_float::oprec) + 10);   RR::SetOutputPrecision(quad_float::oprec);   static RR t;   conv(t, a);   s << t;   RR::SetPrecision(old_p);   RR::SetOutputPrecision(old_op);   return s;}istream& operator>>(istream& s, quad_float& x){   long old_p = RR::precision();   RR::SetPrecision(4*NTL_DOUBLE_PRECISION);   static RR t;   s >> t;   conv(x, t);   RR::SetPrecision(old_p);   return s;}void random(quad_float& x){   long old_p = RR::precision();   RR::SetPrecision(4*NTL_DOUBLE_PRECISION);   static RR t;   random(t);   conv(x, t);   RR::SetPrecision(old_p);}quad_float random_quad_float(){   quad_float x;   random(x);   return x;}      long IsFinite(quad_float *x){   return IsFinite(&x->hi) && IsFinite(&x->lo);}long PrecisionOK(){START_FIX   long k;   DOUBLE l1 = (double)1;   DOUBLE lh = 1/(double)2;   DOUBLE epsilon;   DOUBLE fudge, oldfudge;   epsilon = l1;   fudge = l1+l1;   k = 0;   do {      k++;      epsilon = epsilon * lh;      oldfudge = fudge;      fudge = l1 + epsilon;   } while (fudge > l1 && fudge < oldfudge);END_FIX   return k == NTL_DOUBLE_PRECISION;}quad_float floor(const quad_float& x){   DOUBLE fhi, flo, u, v;   fhi = floor(x.hi);   if (fhi != x.hi)      return quad_float(fhi, 0.0);   else {      flo = floor(x.lo);START_FIX      u = fhi + flo;      v = fhi - u;      v = v + flo;END_FIX      return quad_float(u, v);   }}quad_float ceil(const quad_float& x) {   return -floor(-x);}quad_float trunc(const quad_float& x) {   if (x>=0.0) return floor(x); else return -floor(-x);}long compare(const quad_float& x, const quad_float& y){   if (x.hi > y.hi)       return 1;   else if (x.hi < y.hi)      return -1;   else if (x.lo > y.lo)      return 1;   else if (x.lo < y.lo)       return -1;   else      return 0;}quad_float fabs(const quad_float& x) { if (x.hi>=0.0) return x; else return -x; }quad_float to_quad_float(const char *s){   quad_float x;   long old_p = RR::precision();   RR::SetPrecision(4*NTL_DOUBLE_PRECISION);   static RR t;   conv(t, s);   conv(x, t);   RR::SetPrecision(old_p);   return x;}quad_float ldexp(const quad_float& x, long exp) { // x*2^exp  if (int(exp) != exp) Error("quad_float ldexp: overflow");  return quad_float(ldexp(x.hi,int(exp)),ldexp(x.lo,int(exp)));}quad_float exp(const quad_float& x) { // New version 97 Aug 05/*!  Calculate a quadruple-precision exponential!  Method:!   x    x.log2(e)    nint[x.log2(e)] + frac[x.log2(e)]!  e  = 2          = 2!!                     iy    fy!                  = 2   . 2!  Then!   fy    y.loge(2)!  2   = e!!  Now y.loge(2) will be less than 0.3466 in absolute value.!  This is halved and a Pade aproximation is used to approximate e^x over!  the region (-0.1733, +0.1733).   This approximation is then squared.!  WARNING: No overflow checks!*/  if (x.hi<DBL_MIN_10_EXP*2.302585092994045684017991)     return to_quad_float(0.0);  if (x.hi>DBL_MAX_10_EXP*2.302585092994045684017991) {    Error("exp(quad_float): overflow");  }  const quad_float Log2 =     to_quad_float("0.6931471805599453094172321214581765680755");  quad_float y,temp,ysq,sum1,sum2;  long iy;  y=x/Log2;  temp = floor(y+0.5);  iy = to_long(temp);  y=(y-temp)*Log2;  y=ldexp(y,-1L);  ysq=y*y;  sum1=y*((((ysq+3960.0)*ysq+2162160.0)*ysq+302702400.0)*ysq+8821612800.0);  sum2=(((90.0*ysq+110880.0)*ysq+30270240.0)*ysq+2075673600.0)*ysq+17643225600.0;/*!                     sum2 + sum1         2.sum1! Now approximation = ----------- = 1 + ----------- = 1 + 2.temp!                     sum2 - sum1       sum2 - sum1!! Then (1 + 2.temp)^2 = 4.temp.(1 + temp) + 1*/  temp=sum1/(sum2-sum1);  y=temp*(temp+1);  y=ldexp(y,2L);  return ldexp(y+1,iy);}quad_float log(const quad_float& t) { // Newton method. See Bailey, MPFUN  if (t.hi <= 0.0) {    Error("log(quad_float): argument must be positive");  }  double s1 = log(t.hi);  ForceToMem(&s1);  // Again, this is fairly paranoid.  quad_float s;  s = s1;  quad_float e;  e=exp(s);  return s+(t-e)/e;  // Newton step}long operator> (const quad_float& x, const quad_float& y) {   return (x.hi> y.hi) || (x.hi==y.hi && x.lo> y.lo); }long operator>=(const quad_float& x, const quad_float& y) {   return (x.hi>y.hi) || (x.hi==y.hi && x.lo>=y.lo); }long operator< (const quad_float& x, const quad_float& y) {   return (x.hi< y.hi) || (x.hi==y.hi && x.lo< y.lo); }long operator<=(const quad_float& x, const quad_float& y) {   return (x.hi<y.hi) || (x.hi==y.hi && x.lo<=y.lo); }long operator==(const quad_float& x, const quad_float& y)   { return x.hi==y.hi && x.lo==y.lo; }long operator!=(const quad_float& x, const quad_float& y)   { return x.hi!=y.hi || x.lo!=y.lo; }NTL_END_IMPL

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -