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

📄 inline.h

📁 很好用的库
💻 H
📖 第 1 页 / 共 2 页
字号:
// inline.h // KMB 97 Dec 29/*Copyright (C) 1997 Keith Martin BriggsExcept where otherwise indicated,this program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*/// 97 Aug 04 KMB added ldexp// 97 Jul 11 Moved this stuff out of quad.h, created inline.h so it can//	be #included even if we're not inlining, by just "#define inline"// 97 Jul 12 Added all combos of doubledouble/double/int +-*/.  Only a couple actually//	written; most just call the others by swapping arguments.  Generates//	equivalent code with a good inlining compiler (tested with g++ 2.7.2).//	- e.g., all subtraction is now done by addition of unary minus.//	- removed if's from doubledouble*int. Zero-branch code is 2.5 faster (tested)//	- generally cleaned up and re-organized the order of the functions,//	  now they're grouped nicely by function.//	- tested Newton's division.  Works but is terribly slow, because//	  it needs to do several doubledouble + and * operations, and doubledouble ///	  without it is about the same speed at doubledouble * anyway, so no win.//	- moved recip here as an inline.//	- checked and tested doubledouble/double (BUG?), seems fine.// Absolute valueinline doubledouble fabs(const doubledouble& x) { if (x.h()>=0.0) return x; else return -x; }inline doubledouble abs(const doubledouble& x) { if (x.h()>=0.0) return x; else return -x; }// Addition/*      (C) W. Kahan 1989*       NOTICE:*       Copyrighted programs may not be translated, used, nor*       reproduced without the author's permission.  Normally that*       permission is granted freely for academic and scientific*       purposes subject to the following three requirements:*       1. This NOTICE and the copyright notices must remain attached*          to the programs and their translations.*       2. Users of such a program should regard themselves as voluntary*          participants in the author's researches and so are obliged*          to report their experience with the program back to the author.*       3. Neither the author nor the institution that employs him will*          be held responsible for the consequences of using a program*          for which neither has received payment.*       Would-be commercial users of these programs must correspond*       with the author to arrange terms of payment and warranty.*///////////////////////////////////////////////////////////////////////////////////  Addition and Subtraction ////////////////////////////////////////////////////////////////////////////////// Binary additioninline doubledouble operator +(const doubledouble& x, const doubledouble& y) {  x86_FIX  double H, h, T, t, S, s, e, f;  S = x.hi+y.hi; T = x.lo+y.lo; e = S-x.hi; f = T-x.lo; s = S-e; t = T-f;   s = (y.hi-e)+(x.hi-s); t = (y.lo-f)+(x.lo-t);   e = s+T; H = S+e; h = e+(S-H); e = t+h;  doubledouble z; z.hi = H+e; z.lo = e+double(H-z.hi);   END_x86_FIX  return z;}inline doubledouble operator +(const double& x, const doubledouble& y) {  x86_FIX  double H, h, S, s, e;  S = x+y.hi; e = S-x; s = S-e;  s = (y.hi-e)+(x-s); H = S+(s+y.lo); h = (s+y.lo)+(S-H);  doubledouble z; z.hi = H+h; z.lo = h+double(H-z.hi);   END_x86_FIX  return z;}inline doubledouble operator +(const doubledouble& x,const double& y ) { return y+x; }inline doubledouble operator +(const int x, const doubledouble& y) { return double(x)+y; }inline doubledouble operator +(const doubledouble& x, const int y) { return y+x; }// Subtractioninline doubledouble operator -(const doubledouble& x, const doubledouble& y)   { return x+(-y); }inline doubledouble operator -(const double& x, const doubledouble& y) { return x+(-y); }inline doubledouble operator -(const int x, const doubledouble& y)     { return x+(-y); }inline doubledouble operator -(const doubledouble& x, const double& y) { return x+(-y); }inline doubledouble operator -(const doubledouble& x, const int y)     { return x+(-y); }//////////////////////////  Self-Addition  ///////////////////////inline doubledouble& doubledouble::operator +=(const doubledouble& y) {  x86_FIX  double H, h, T, t, S, s, e, f;  S = hi+y.hi; T = lo+y.lo; e = S-hi; f = T-lo; s = S-e; t = T-f;   s = (y.hi-e)+(hi-s); t = (y.lo-f)+(lo-t); f = s+T; H = S+f; h = f+(S-H);  hi = H+(t+h); lo = (t+h)+double(H-hi);  END_x86_FIX  return *this;}inline doubledouble& doubledouble::operator +=(const double& y) {  x86_FIX  double H, h, S, s, e, f;  S = hi+y; e = S-hi; s = S-e;  s = (y-e)+(hi-s); f = s+lo; H = S+f; h = f+(S-H);  hi = H+h; lo = h+double(H-hi);   END_x86_FIX  return *this;}inline doubledouble& doubledouble::operator +=(const int y) { return *this += double(y); }// Self-Subtractioninline doubledouble& doubledouble::operator -=(const doubledouble& y)   { return *this += -y; }inline doubledouble& doubledouble::operator -=(const double& y) { return *this += -y; }inline doubledouble& doubledouble::operator -=(const int y)     { return *this += -y; }/////////////////////////////////////////////////////////////////////////////////  Multiplication  ////////////////////////////////////////////////////////////////////////////////////// Binary Multiplicationinline doubledouble operator *(const doubledouble& x, const doubledouble& y) {  x86_FIX  double hx, tx, hy, ty, C, c;  C = doubledouble::Split()*x.hi; hx = C-x.hi; c = doubledouble::Split()*y.hi;  hx = C-hx; tx = x.hi-hx; hy = c-y.hi;   C = 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);  doubledouble z; z.hi = C+c; hx=C-z.hi; z.lo = c+hx;   END_x86_FIX  return z;}// double*doubledoubleinline doubledouble operator *(const double& x, const doubledouble& y) {  x86_FIX  double hx, tx, hy, ty, C, c;  C = doubledouble::Split()*x; hx = C-x; c = doubledouble::Split()*y.hi; hx = C-hx ;   tx = x-hx; hy = c-y.hi; C = x*y.hi; hy = c-hy; ty = y.hi - hy;  c = ((((hx*hy-C)+hx*ty)+tx*hy)+tx*ty)+x*y.lo;  doubledouble z; z.hi = C+c; z.lo = c+double(C-z.hi);   END_x86_FIX  return z;}inline doubledouble operator *(const int x, const doubledouble& y ) 	{ return double(x)*y; }inline doubledouble operator *(const doubledouble& x, const double& y ) { return y*x; }inline doubledouble operator *(const doubledouble& x, const int y )     { return y*x; }// Self-multiplicationinline doubledouble& doubledouble::operator *=(const doubledouble& y ) {  x86_FIX  double hx, tx, hy, ty, C, c;  C = Split()*hi; hx = C-hi; c = Split()*y.hi;  hx = C-hx; tx = hi-hx; hy = c-y.hi;   C = hi*y.hi; hy = c-hy; ty = y.hi-hy;  c = ((((hx*hy-C)+hx*ty)+tx*hy)+tx*ty)+(hi*y.lo+lo*y.hi);  hx = C+c; hi = hx; lo = c+double(C-hx);  END_x86_FIX  return *this;}inline doubledouble& doubledouble::operator *=(const double& y ) {  x86_FIX  double hx, tx, hy, ty, C, c;  C = Split()*hi; hx = C-hi; c = Split()*y;  hx = C-hx; tx = hi-hx; hy = c-y;   C = hi*y; hy = c-hy; ty = y-hy;  c = ((((hx*hy-C)+hx*ty)+tx*hy)+tx*ty)+(lo*y);  hx = C+c; hi = hx; lo = c+double(C-hx);  END_x86_FIX  return *this;}inline doubledouble& doubledouble::operator *=(const int y ) { return *this *= double(y); }//////////////////////////////////////////////////////////////////////////////////////////  Division  //////////////////////////////////////////////////////////////////////////////////////////// Reciprocalinline doubledouble recip(const doubledouble& y) {  x86_FIX  double  hc, tc, hy, ty, C, c, U, u;  C = 1.0/y.h();   c = doubledouble::Split()*C;   hc =c-C;    u = doubledouble::Split()*y.h();  hc = c-hc; tc = C-hc; hy = u-y.h(); U = C*y.h(); hy = u-hy; ty = y.h()-hy;  u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty;  c = ((((1.0-U)-u))-C*y.l())/y.h();  doubledouble z; z.hi = C+c; z.lo = double(C-z.hi)+c;   END_x86_FIX  return z;}inline doubledouble operator /(const doubledouble& x,const doubledouble& y ) {  x86_FIX  double hc, tc, hy, ty, C, c, U, u;  C = x.hi/y.hi; c = doubledouble::Split()*C; hc =c-C;  u = doubledouble::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;  c = ((((x.hi-U)-u)+x.lo)-C*y.lo)/y.hi;  doubledouble z; z.hi = C+c; z.lo = double(C-z.hi)+c;   END_x86_FIX  return z;}// double/doubledouble:inline doubledouble operator /(const double& x,const doubledouble& y ) {  x86_FIX  double  hc, tc, hy, ty, C, c, U, u;  C = x/y.hi; c = doubledouble::Split()*C; hc =c-C;  u = doubledouble::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;  c = ((((x-U)-u))-C*y.lo)/y.hi;  doubledouble z; z.hi = C+c; z.lo = double(C-z.hi)+c;   END_x86_FIX  return z;}inline doubledouble operator /(const doubledouble& x,const double& y ) {  x86_FIX  double hc, tc, hy, ty, C, c, U, u;  C = x.hi/y; c = doubledouble::Split()*C; hc = c-C;  u = doubledouble::Split()*y; hc = c-hc;   tc = C-hc; hy = u-y; U = C*y; hy = u-hy; ty = y-hy;  u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty;  c = (((x.hi-U)-u)+x.lo)/y;  doubledouble z;  z.hi = C+c; z.lo = double(C-z.hi)+c;   END_x86_FIX  return z;}// doubledouble/intinline doubledouble operator /(const doubledouble& x, const int y) { return x/double(y); }inline doubledouble operator /(const int x, const doubledouble& y) { return double(x)/y; }// Self-division.inline doubledouble& doubledouble::operator /=(const doubledouble& y) {  x86_FIX  double hc, tc, hy, ty, C, c, U, u;  C = hi/y.hi; c = Split()*C; hc =c-C;  u = 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;  c = ((((hi-U)-u)+lo)-C*y.lo)/y.hi;  u = C+c; hi = u; lo = double(C-u)+c;   END_x86_FIX  return *this;}inline doubledouble& doubledouble::operator /=(const double& y) {  x86_FIX  double hc, tc, hy, ty, C, c, U, u;  C = hi/y; c = Split()*C; hc =c-C;  u = Split()*y; hc = c-hc;  tc = C-hc; hy = u-y; U = C * y; hy = u-hy; ty = y-hy;  u = (((hc*hy-U)+hc*ty)+tc*hy)+tc*ty;  c = (((hi-U)-u)+lo)/y;  u = C+c; hi = u; lo = double(C-u)+c;   END_x86_FIX  return *this;}inline doubledouble& doubledouble::operator /=(const int y) { return *this/=double(y); }inline void base_and_prec(void) { // Linnainmaa ACM TOMS 7, 272 Thm 3  int p;  x86_FIX  cerr<<"Base and precision determination by Linnainmaa's method:"<<endl;  {    double U,R,u,r,beta;    U=4.0/3.0;    U-=1; U*=3; U-=1; U=fabs(U);    R=U/2+1; R-=1;    if (R!=0.0) U=R;    u=2; u/=3; u-=0.5; u*=3; u-=0.5;     u=fabs(u); r=u/2+0.5; r-=0.5;    if (r!=0.0) u=r;    beta=U/u; p=int(-log(u)/log(beta)+0.5);    cout<<"Type double: base is "<<beta<<",  precision is "<<p<<endl;  } {    doubledouble U,R,u,r,beta;    U=4; U/=3;    U-=1; U*=3; U-=1; U=fabs(U);    R=U/2+1; R-=1;    if (R.h()!=0.0) U=R;    u=2; u/=3; u-=0.5; u*=3; u-=0.5;     u=fabs(u); r=u/2+0.5; r-=0.5;    if (r.h()!=0.0) u=r;    beta=U/u; p=int(-log(u)/log(beta)+0.5);    cout<<"Type doubledouble:   base is "<<beta<<",  precision is "<<p<<endl;  }  END_x86_FIX  return;}// number of decimal digits to which x and y agreeinline int digits(const doubledouble& x, const doubledouble& y){  doubledouble diff=fabs(x-y); if (diff.h()==0.0) return 32; int d=-intq(floor((0.4*log((diff/fabs(x))))).h()); return d<32?d:32;}inline doubledouble Qcopysign(const doubledouble& x, const double y){  if (y>=0.0) return fabs(x); else return -fabs(x); }inline doubledouble atodd(const char *s) {  doubledouble result = 0; int n, sign, ex = 0;  /* eat whitespace */ while (*s == ' ' || *s == '\t' || *s == '\n') s++;  switch (*s) { // get sign of mantissa    case '-': { sign = -1;  s++; break; }    case '+': s++;  // no break     default: sign = 1;  }  /* get digits before decimal point */  while (n=(*s++)-'0', n>=0 && n<10) result = 10.0*result+n;  s--;  if (*s == '.')   /* get digits after decimal point */ {    s++;    while (n=(*s++)-'0', n>=0 && n<10) { result = 10.0*result+n; --ex; }    s--;  }  if (*s == 'e' || *s == 'E') /* get exponent */ ex+=atoi(++s);  /* exponent adjustment */  // cerr<<"atodd: result="<<endl; result.dump(""); cerr<<"atodd: ex="<<ex<<endl;   while (ex-- > 0) result *= 10;  while (++ex < 0) result /= 10;  return (sign>=0) ? result : -result;}inline void doubledouble::dump(char* s="") const {  // debugging use only  cerr<<s<<setprecision(16)<<"doubledouble("<<hi<<","<<lo<<")";}// Constructor from stringinline doubledouble::doubledouble(const char* s){ *this=atodd(s); }// doubledouble = stringinline doubledouble& doubledouble::operator=(const char* s){ return *this=atodd(s); }inline istream& operator >> (istream& s, doubledouble& x){  doubledouble result=0.0; int n, sign=1, ex=0; char ch;  s>>ws; // eat whitespace  s>>ch;  if (ch=='-') { sign = -1;  s>>ch; } else if (ch=='+') { s>>ch; }  // get digits before decimal point  n=ch-'0';  while (n>=0 && n<10) {     result = 10*result+n;     s.get(ch);  // cannot use s>>ch; as that will eat whitespace    if (ch == ' ' || ch == '\t' || ch == '\n') goto fixup;    n=ch-'0';   }  if (ch=='.') {  // get digits after decimal point     s>>ch; n=ch-'0';     while (n>=0 && n<10) {        result = 10*result+n;        s.get(ch);       n=ch-'0'; --ex;        if (ch == ' ' || ch == '\t' || ch == '\n') goto fixup;     }  }  n=0;  if (ch == 'e' || ch == 'E') { s>>n; ex+=n; } // get exponent    else s.putback(ch);  fixup:  if (sign<0) result = -result;  // exponent adjustment  while (ex-- > 0) result *= 10;  while (++ex < 0) result /= 10;  x = result;  return s;}// outputinline ostream& operator << (ostream& s, const doubledouble& x){  if (x.h()==0.0)   { s << "0.0 "; return s; }  if (x.h()!=x.h()) { s << "NaN "; return s; }  int Digits=s.precision();  doubledouble ten=10.0,y=fabs(x); double q=log10(y.h());  int m,n=int(floor(q));   if (n<0) n++;  doubledouble l = powint(ten,n);  y = y/l;  if (sign(x)<0) s<<"-"; //else s<<" ";  int d = Digits>34 ? 34 : Digits;  d = d<3 ? 3 : d;  for (int i=1; i<=d; i++) {    if (2==i) s<<".";    m = int(floor(y));    if (m<0 || m>9) { cerr<<"Internal error in doubledouble.cc: digit="<<m<<                            " in ostream& operator <<\n"; 		      cerr<<"Argument to << was "; x.dump(""); cerr<<endl; 		      assert(0); }    s<<m;    y = (y-doubledouble(m))*ten;    if (y.h()<=0.0) break; // x must be an integer    //if (y.h()==0.0) break; // ???????????  }  if (n!=0) s<<"e"<<n; else s<<"";  s << "";  return s;}// rint (round to nearest int)inline doubledouble rint(const doubledouble& x){ return floor(x+doubledouble(0.5)); }// Another floor. V. Shoup 97 Sep 23...inline doubledouble floor_s(const doubledouble& x) {   double fhi=floor(x.h());  if (fhi!=x.h())     return doubledouble(fhi);  else      return doubledouble(fhi,floor(x.l()));}// Floor.  See Graham, Knuth and Patashnik `Concrete Mathematics' page 70.// Greatest integer <= x// maybe floor_s is better?inline doubledouble floor(const doubledouble& x) {   double fh=floor(x.h()), fl=floor(x.l());   double t1=x.h()-fh;  double t2=x.l()-fl;  double t3=t1+t2;  t3 = x.h()-fh+x.l()-fl;  int t=int(floor(t3));  doubledouble ret;  switch (t) {    case 0: ret = doubledouble(fh)+doubledouble(fl); break;

⌨️ 快捷键说明

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