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

📄 xdouble.c

📁 密码大家Shoup写的数论算法c语言实现
💻 C
字号:
#include <NTL/xdouble.h>#include <NTL/RR.h>#include <NTL/new.h>NTL_START_IMPLlong xdouble::oprec = 10;void xdouble::SetOutputPrecision(long p){   if (p < 1) p = 1;   if (p >= (1L << (NTL_BITS_PER_LONG-4)))       Error("xdouble: output precision too big");   oprec = p;}void xdouble::normalize() {   if (x == 0)       e = 0;   else if (x > 0) {      while (x < NTL_XD_HBOUND_INV) { x *= NTL_XD_BOUND; e--; }      while (x > NTL_XD_HBOUND) { x *= NTL_XD_BOUND_INV; e++; }   }   else {      while (x > -NTL_XD_HBOUND_INV) { x *= NTL_XD_BOUND; e--; }      while (x < -NTL_XD_HBOUND) { x *= NTL_XD_BOUND_INV; e++; }   }   if (e >= (1L << (NTL_BITS_PER_LONG-4)))      Error("xdouble: overflow");   if (e <= -(1L << (NTL_BITS_PER_LONG-4)))      Error("xdouble: underflow");}   xdouble to_xdouble(double a){   if (a == 0 || a == 1 || (a > 0 && a >= NTL_XD_HBOUND_INV && a <= NTL_XD_HBOUND)       || (a < 0 && a <= -NTL_XD_HBOUND_INV && a >= -NTL_XD_HBOUND)) {            return xdouble(a, 0);    }   if (!IsFinite(&a))      Error("double to xdouble conversion: non finite value");   xdouble z = xdouble(a, 0);   z.normalize();   return z;}void conv(double& xx, const xdouble& a){   double x;   long e;   x = a.x;   e = a.e;   while (e > 0) { x *= NTL_XD_BOUND; e--; }   while (e < 0) { x *= NTL_XD_BOUND_INV; e++; }   xx = x;}xdouble operator+(const xdouble& a, const xdouble& b){   xdouble z;   if (a.x == 0)       return b;   if (b.x == 0)     return a;         if (a.e == b.e) {      z.x = a.x + b.x;      z.e = a.e;      z.normalize();      return z;   }   else if (a.e > b.e) {      if (a.e > b.e+1)         return a;      z.x = a.x + b.x*NTL_XD_BOUND_INV;      z.e = a.e;      z.normalize();      return z;   }   else {      if (b.e > a.e+1)         return b;      z.x = a.x*NTL_XD_BOUND_INV + b.x;      z.e = b.e;      z.normalize();      return z;   }}xdouble operator-(const xdouble& a, const xdouble& b){   xdouble z;   if (a.x == 0)      return -b;   if (b.x == 0)      return a;   if (a.e == b.e) {      z.x = a.x - b.x;      z.e = a.e;      z.normalize();      return z;   }   else if (a.e > b.e) {      if (a.e > b.e+1)         return a;      z.x = a.x - b.x*NTL_XD_BOUND_INV;      z.e = a.e;      z.normalize();      return z;   }   else {      if (b.e > a.e+1)         return -b;      z.x = a.x*NTL_XD_BOUND_INV - b.x;      z.e = b.e;      z.normalize();      return z;   }}xdouble operator-(const xdouble& a){   xdouble z;   z.x = -a.x;   z.e = a.e;   return z;}xdouble operator*(const xdouble& a, const xdouble& b){   xdouble z;   z.e = a.e + b.e;   z.x = a.x * b.x;   z.normalize();   return z;}xdouble operator/(const xdouble& a, const xdouble& b){   xdouble z;   if (b.x == 0) Error("xdouble division by 0");   z.e = a.e - b.e;   z.x = a.x / b.x;   z.normalize();   return z;}long compare(const xdouble& a, const xdouble& b){   xdouble z = a - b;   if (z.x < 0)      return -1;   else if (z.x == 0)      return 0;   else      return 1;}long sign(const xdouble& z){   if (z.x < 0)      return -1;   else if (z.x == 0)      return 0;   else      return 1;}   xdouble trunc(const xdouble& a){   if (a.x >= 0)      return floor(a);   else      return ceil(a);}xdouble floor(const xdouble& aa){   xdouble z;   xdouble a = aa;   ForceToMem(&a.x);   if (a.e == 0) {      z.x = floor(a.x);      z.e = 0;      z.normalize();      return z;   }   else if (a.e > 0) {      return a;   }   else {      if (a.x < 0)         return to_xdouble(-1);      else         return to_xdouble(0);   }}xdouble ceil(const xdouble& aa){   xdouble z;   xdouble a = aa;   ForceToMem(&a.x);   if (a.e == 0) {      z.x = ceil(a.x);      z.e = 0;      z.normalize();      return z;   }   else if (a.e > 0) {      return a;   }   else {      if (a.x < 0)         return to_xdouble(0);      else         return to_xdouble(1);   }}xdouble to_xdouble(const ZZ& a){   long old_p = RR::precision();   RR::SetPrecision(NTL_DOUBLE_PRECISION);      static RR t;   conv(t, a);   double x;   conv(x, t.mantissa());   xdouble y, z, res;   conv(y, x);   power2(z, t.exponent());   res = y*z;   RR::SetPrecision(old_p);   return res;}void conv(ZZ& x, const xdouble& a){   xdouble b = floor(a);   long old_p = RR::precision();   RR::SetPrecision(NTL_DOUBLE_PRECISION);   static RR t;   conv(t, b);   conv(x, t);   RR::SetPrecision(old_p);}xdouble fabs(const xdouble& a){   xdouble z;   z.e = a.e;   z.x = fabs(a.x);   return z;}xdouble sqrt(const xdouble& a){   if (a == 0)      return to_xdouble(0);   if (a < 0)      Error("xdouble: sqrt of negative number");   xdouble t;   if (a.e & 1) {      t.e = (a.e - 1)/2;      t.x = sqrt(a.x * NTL_XD_BOUND);   }   else {      t.e = a.e/2;      t.x = sqrt(a.x);   }   t.normalize();   return t;}      void power(xdouble& z, const xdouble& a, const ZZ& e){   xdouble b, res;   b = a;   res = 1;   long n = NumBits(e);   long i;   for (i = n-1; i >= 0; i--) {      res = res * res;      if (bit(e, i))         res = res * b;   }   if (sign(e) < 0)       z = 1/res;   else      z = res;}void power(xdouble& z, const xdouble& a, long e){   static ZZ E;   E = e;   power(z, a, E);}      void power2(xdouble& z, long e){   long hb = NTL_XD_HBOUND_LOG;   long b = 2*hb;   long q, r;   q = e/b;   r = e%b;   while (r >= hb) {      r -= b;      q++;   }   while (r < -hb) {      r += b;      q--;   }   if (q >= (1L << (NTL_BITS_PER_LONG-4)))      Error("xdouble: overflow");   if (q <= -(1L << (NTL_BITS_PER_LONG-4)))      Error("xdouble: underflow");   int rr = r;   double x = ldexp(1.0, rr);   z.x = x;   z.e = q;}void MulAdd(xdouble& z, const xdouble& a, const xdouble& b, const xdouble& c)// z = a + b*c{   double x;   long e;   e = b.e + c.e;   x = b.x * c.x;   if (x == 0) {       z = a;      return;   }   if (a.x == 0) {      z.e = e;      z.x = x;      z.normalize();      return;   }         if (a.e == e) {      z.x = a.x + x;      z.e = e;      z.normalize();      return;   }   else if (a.e > e) {      if (a.e > e+1) {         z = a;         return;      }      z.x = a.x + x*NTL_XD_BOUND_INV;      z.e = a.e;      z.normalize();      return;   }   else {      if (e > a.e+1) {         z.x = x;         z.e = e;         z.normalize();         return;      }      z.x = a.x*NTL_XD_BOUND_INV + x;      z.e = e;      z.normalize();      return;   }}void MulSub(xdouble& z, const xdouble& a, const xdouble& b, const xdouble& c)// z = a - b*c{   double x;   long e;   e = b.e + c.e;   x = b.x * c.x;   if (x == 0) {       z = a;      return;   }   if (a.x == 0) {      z.e = e;      z.x = -x;      z.normalize();      return;   }         if (a.e == e) {      z.x = a.x - x;      z.e = e;      z.normalize();      return;   }   else if (a.e > e) {      if (a.e > e+1) {         z = a;         return;      }      z.x = a.x - x*NTL_XD_BOUND_INV;      z.e = a.e;      z.normalize();      return;   }   else {      if (e > a.e+1) {         z.x = -x;         z.e = e;         z.normalize();         return;      }      z.x = a.x*NTL_XD_BOUND_INV - x;      z.e = e;      z.normalize();      return;   }}double log(const xdouble& a){   static double LogBound = log(NTL_XD_BOUND);   if (a.x <= 0) {      Error("log(xdouble): argument must be positive");   }   return log(a.x) + a.e*LogBound;}xdouble xexp(double x){   const double LogBound = log(NTL_XD_BOUND);   double y = x/LogBound;   double iy = floor(y+0.5);   if (iy >= (1L << (NTL_BITS_PER_LONG-4)))      Error("xdouble: overflow");   if (iy <= -(1L << (NTL_BITS_PER_LONG-4)))      Error("xdouble: underflow");   double fy = y - iy;   xdouble res;   res.e = long(iy);   res.x = exp(fy*LogBound);   res.normalize();   return res;}/**************  input / output routines **************/void ComputeLn2(RR&);void ComputeLn10(RR&);long ComputeMax10Power(){   long old_p = RR::precision();   RR::SetPrecision(NTL_BITS_PER_LONG);   RR ln2, ln10;   ComputeLn2(ln2);   ComputeLn10(ln10);   long k = to_long( to_RR(1L << (NTL_BITS_PER_LONG-5)) * ln2 / ln10 );   RR::SetPrecision(old_p);   return k;}xdouble PowerOf10(const ZZ& e){   static long init = 0;   static xdouble v10k;   static long k;   if (!init) {      long old_p = RR::precision();      k = ComputeMax10Power();      RR::SetPrecision(NTL_DOUBLE_PRECISION);      v10k = to_xdouble(power(to_RR(10), k));       RR::SetPrecision(old_p);      init = 1;   }   ZZ e1;   long neg;   if (e < 0) {      e1 = -e;      neg = 1;   }   else {      e1 = e;      neg = 0;   }   long r;   ZZ q;   r = DivRem(q, e1, k);   long old_p = RR::precision();   RR::SetPrecision(NTL_DOUBLE_PRECISION);   xdouble x1 = to_xdouble(power(to_RR(10), r));   RR::SetPrecision(old_p);   xdouble x2 = power(v10k, q);   xdouble x3 = x1*x2;   if (neg) x3 = 1/x3;   return x3;}ostream& operator<<(ostream& s, const xdouble& a){   if (a == 0) {      s << "0";      return s;   }   long old_p = RR::precision();   long temp_p = long(log(fabs(log(fabs(a))) + 1.0)/log(2.0)) + 10;    RR::SetPrecision(temp_p);   RR ln2, ln10, log_2_10;   ComputeLn2(ln2);   ComputeLn10(ln10);   log_2_10 = ln10/ln2;   ZZ log_10_a = to_ZZ(  (to_RR(a.e)*to_RR(2*NTL_XD_HBOUND_LOG) + log(fabs(a.x))/log(2.0))/log_2_10);   RR::SetPrecision(old_p);   xdouble b;   long neg;   if (a < 0) {      b = -a;      neg = 1;   }   else {      b = a;      neg = 0;   }   ZZ k = xdouble::OutputPrecision() - log_10_a;   xdouble c, d;   c = PowerOf10(to_ZZ(xdouble::OutputPrecision()));   d = PowerOf10(log_10_a);   b = b / d;   b = b * c;   while (b < c) {      b = b * 10.0;      k++;   }   while (b >= c) {      b = b / 10.0;      k--;   }   b = b + 0.5;   k = -k;   ZZ B;   conv(B, b);   long bp_len = xdouble::OutputPrecision()+10;   char *bp = NTL_NEW_OP char[bp_len];   if (!bp) Error("xdouble output: out of memory");   long len, i;   len = 0;   do {      if (len >= bp_len) Error("xdouble output: buffer overflow");      bp[len] = DivRem(B, B, 10) + '0';      len++;   } while (B > 0);   for (i = 0; i < len/2; i++) {      char tmp;      tmp = bp[i];      bp[i] = bp[len-1-i];      bp[len-1-i] = tmp;   }   i = len-1;   while (bp[i] == '0') i--;   k += (len-1-i);   len = i+1;   bp[len] = '\0';   if (k > 3 || k < -len - 3) {      // use scientific notation      if (neg) s << "-";      s << "0." << bp << "e" << (k + len);   }   else {      long kk = to_long(k);      if (kk >= 0) {         if (neg) s << "-";         s << bp;         for (i = 0; i < kk; i++)             s << "0";      }      else if (kk <= -len) {         if (neg) s << "-";         s << "0.";         for (i = 0; i < -len-kk; i++)            s << "0";         s << bp;      }      else {         if (neg) s << "-";         for (i = 0; i < len+kk; i++)            s << bp[i];            s << ".";            for (i = len+kk; i < len; i++)            s << bp[i];      }   }   delete [] bp;   return s;}istream& operator>>(istream& s, xdouble& x){   long c;   long sign;   ZZ a, b;   if (!s) Error("bad xdouble input");   c = s.peek();   while (c == ' ' || c == '\n' || c == '\t') {      s.get();      c = s.peek();   }   if (c == '-') {      sign = -1;      s.get();      c = s.peek();   }   else      sign = 1;   long got1 = 0;   long got_dot = 0;   long got2 = 0;   a = 0;   b = 1;   if (c >= '0' && c <= '9') {      got1 = 1;      while (c >= '0' && c <= '9') {         mul(a, a, 10);         add(a, a, c-'0');         s.get();         c = s.peek();      }   }   if (c == '.') {      got_dot = 1;      s.get();      c = s.peek();      if (c >= '0' && c <= '9') {         got2 = 1;            while (c >= '0' && c <= '9') {            mul(a, a, 10);            add(a, a, c-'0');            mul(b, b, 10);            s.get();            c = s.peek();         }      }   }   if (got_dot && !got1 && !got2)  Error("bad xdouble input");   ZZ e;   long got_e = 0;   long e_sign;   if (c == 'e' || c == 'E') {      got_e = 1;      s.get();      c = s.peek();      if (c == '-') {         e_sign = -1;         s.get();         c = s.peek();      }      else if (c == '+') {         e_sign = 1;         s.get();         c = s.peek();      }      else         e_sign = 1;      if (c < '0' || c > '9') Error("bad xdouble input");      e = 0;      while (c >= '0' && c <= '9') {         mul(e, e, 10);         add(e, e, c-'0');         s.get();         c = s.peek();      }   }   if (!got1 && !got2 && !got_e) Error("bad xdouble input");   xdouble t1, t2, v;   if (got1 || got2) {      conv(t1, a);      conv(t2, b);      v = t1/t2;   }   else      v = 1;   if (sign < 0)      v = -v;   if (got_e) {      if (e_sign < 0) negate(e, e);      t1 = PowerOf10(e);      v = v * t1;   }   x = v;   return s;}xdouble to_xdouble(const char *s){   long c;   long sign;   ZZ a, b;   long i=0;   if (!s) Error("bad xdouble input");   c = s[i];   while (c == ' ' || c == '\n' || c == '\t') {      i++;      c = s[i];   }   if (c == '-') {      sign = -1;      i++;      c = s[i];   }   else      sign = 1;   long got1 = 0;   long got_dot = 0;   long got2 = 0;   a = 0;   b = 1;   if (c >= '0' && c <= '9') {      got1 = 1;      while (c >= '0' && c <= '9') {         mul(a, a, 10);         add(a, a, c-'0');         i++;         c = s[i];      }   }   if (c == '.') {      got_dot = 1;      i++;      c = s[i];      if (c >= '0' && c <= '9') {         got2 = 1;            while (c >= '0' && c <= '9') {            mul(a, a, 10);            add(a, a, c-'0');            mul(b, b, 10);            i++;            c = s[i];         }      }   }   if (got_dot && !got1 && !got2)  Error("bad xdouble input");   ZZ e;   long got_e = 0;   long e_sign;   if (c == 'e' || c == 'E') {      got_e = 1;      i++;      c = s[i];      if (c == '-') {         e_sign = -1;         i++;         c = s[i];      }      else if (c == '+') {         e_sign = 1;         i++;         c = s[i];      }      else         e_sign = 1;      if (c < '0' || c > '9') Error("bad xdouble input");      e = 0;      while (c >= '0' && c <= '9') {         mul(e, e, 10);         add(e, e, c-'0');         i++;         c = s[i];      }   }   if (!got1 && !got2 && !got_e) Error("bad xdouble input");   xdouble t1, t2, v;   if (got1 || got2) {      conv(t1, a);      conv(t2, b);      v = t1/t2;   }   else      v = 1;   if (sign < 0)      v = -v;   if (got_e) {      if (e_sign < 0) negate(e, e);      t1 = PowerOf10(e);      v = v * t1;   }   return v;}NTL_END_IMPL

⌨️ 快捷键说明

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