30 effective digital floating-point structure Solve the Double data type Multiple accumulated significant error standard C or C Double data type only 15 valid numbers (it seems to have such a thing, see IEEE 754), thus generated Digitally have multiple obvious errors, in financial calculations, this error is unacceptable. See http://blog.9cbs.net/l1t/archive/2004/109/129110.aspx from LCC-Win32 SRC / Doubledouble / DoubleDouble.c (Author Home: http: //members.lycos.co. There is also a C encapsulated class on UK / Keithmbriggs / DoubleDouble.html, interested people can go to see. Use 2 Double variables to construct a Doubledouble structure and solve this problem. Test method: replace the contents of the main () function to the following. INT main (void) {doubledouble (5.0, 0.0); doubledouble b = new_doubledouble (4.0, 0.0); doubledouble c = a * b; double x1, x2; char buffer [256]; int i; a = a -a 99999999.99; C = C-C 0.0; for (i = 0; i <81920; i ) {c = c a;} DoubledouBletoa (C, Buffer); Printf ("SUM () =% s / n ", buffer; c = a * 81920.0; DoubledouBletoa (C, buffer); Printf (" MULT () =% S / N ", Buffer; x1 = c.hi c.lo; printf (" Mult) ) =% 18.2lf / n ", x1); return 0;} run results: sum () = 8.191999999180799560546875000000000e12mult () = 8.191999999180799560546875000000000e12mult () = 8191999999180.80 in Lcc-win32 may compile without modification. If compiled under GCC, you need to define macro #define GCC in GCC and VS.NET 2003, function Doubledouble Ddexp (const Doubledouble & x) {... Sum1 = Y * ((((YSQ 3960.) * YSQ 2162160 * YSQ 302702400.) * YSQ 8821612800.); SUM2 = (((90. * YSQ 110880.) * YSQ 30270240.) * YSQ 2075673600.) * YSQ 17643225600 .;
...} The above 2 lines cannot be compiled, and if this function is not required, you can delete it.
/ * Doubledouble.c * / # include
Except 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 inline, 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) .2) .// - EG, All Subtraction is now done by addition of unary minus.// - Removed if's from doubledouble * int. Zero-branch code is 2.5 Faster (tester) // - 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.TypedEf Struct Doubledo uble {double hi; double lo;} doubledouble; #ifdef __LCC __ # define x86_FIX / unsigned short __old_cw, __new_cw; / _asm ( "/ tfnstcw / t% __ old_cw"); / __new_cw = (__old_cw & ~ 0x300) | 0x200; / _asm ( "/ tfldcw / t% __ new_cw") # define END_x86_FIX _asm ( "/ tfldcw / t% __ old_cw") # else # define x86_FIX unsigned short __old_cw, __ new_cw; _asm {fnstcw __old_cw} / __new_cw = (__old_cw & ~ 0x300) | 0x200; / _ASM {FLDCW __NEW_CW}; # define end_x86_fix _asm {fldcw __new_cw} # endif # ifdef GCC # undef x86_fix # undef end_x86_fix # define x86_fix # define end_x86_fix # ENDIF
Static double split = 134217729.0; doubledouble new_doubledouble (double x, double y);
Doubledouble Operator- (const doubledouble) {doubledouble z; z.hi = -x.hi; z.lo = -x.lo; return z;}
// absolute valueDoubledouble ddfabs (const Doubledouble & x) {if (x.hi> = 0.0) Return X; else {Doubledouble Result
Result.hi = -x.hi; result.lo = -x.lo; returnrate;}}}
// 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 additionDoubledouble Operator (const doubledouble & y) {double h, h, t, t, s, s, e, f; doubledouble z; x86_fix; s = x.hi y.Hi; t = X.LO Y.LO; E = SX.HI; f = tx.lo; // s = se; t = tf; s = (y.Hi-e) (x.Hi- (se)); T = (Y.LO-F) (x.LO- (tf)); E = S T; H = S E; H = E (SH); E = T H; z.Hi = h E; Z.LO = E (double) (HZ.HI); END_X86_FIX; RETURN Z;} Doubledouble Operator (Const Double & X, Const Doubledouble & Y) {Double H, H, S, S, E; Doubledouble Z; X86_fix; s = x y.HI; E = SX; s = SE; S = (Y.Hi-e) (XS); h = s (s Y.LO); h = (s y. LO) (sh); z.Hi = h h; z.LO = H (double) (hz.hi); end_x86_fix; return z;} Doubledouble Operator (Const DoubleDouble & X, Const Double & Y) {Return Y x;} DoubleDouble Operator (int X, const doubledouble & y) {return (x) y;} doubledouble operator (doubledouble "{RETURN Y X;}
// Subtractiondoubledouble operator - (const doubledouble & x, const doubledouble & y) {return x (- y);} doubledouble operator - (const double & x, const doubledouble & y) {return x (- y);} doubledouble operator - (const int x, const doubledouble & y) {RETURN X (- Y);} Doubledouble Operator - (Const Double & Y) {Return X (- Y);} Doubledouble Operator - (Const Doubledouble & X, Const I) {Return X (- y);
// Self-addition /// Doubledouble & Operator = (Doubledouble & Y) {Double H, H, T, T, S, S, E, F; X86_FIX; s = this.hi y.HI; T = this.lo Y.LO; E = s-this.hi; f = t-this.lo; s = se; t = Tf; s = (y.Hi-e) (this.hi-s ); T = (Y.LO-f) (this.lo-t); f = s t; h = s f; h = f (sh); this.hi = h (t h); THISLO = (T H) (H-this.hi); end_x86_fix; return this;} Doubledouble & operator = (DoubleDouble & this, const double & y) {Double H, H, S, S, E , f; x86_fix;
S = this.hi y; e = s-this.hi; s = se; s = (ye) (this.hi-s); f = s this.lo; h = s f; h = F (sh); this.hi = h h; this.lo = h (double.hi) (H-this.hi); end_x86_fix; return this;} Doubledouble & operator = (doubledouble & this, const int y) {Return THIS = (Double) (Y);
// Self-Subtractiondoubledouble & operator - = (doubledouble & This, const doubledouble & y) {return This = -y;} doubledouble & operator - = (doubledouble & This, const double & y) {return This = -y;} doubledouble & operator - = (Doubledouble & this, const y) {return this = -y;}
/ MULTIPLICATION / ////
// binary multiplicationDoubledouble operator * (const doubledouble & y) {Double HX, TX, Hy, Ty, C, C; Doubledouble Z; X86_FIX;
C = Split * x.Hi; hx = cx.hi; c = split * y.Hi; hx = c-hx; tx = x.Hi-hx; hy = cy.hi; c = x.hi * y. Hi; hy = c-hy; type; c = ((((((hx * Hy-c) hx * type tx * hy) tx * type) (x.hi * y .lo x.lo * y.hi); z.HI = C C; hx = CZ.HI; z.LO = C HX; END_X86_FIX; RETURN Z;} // Double * DoubledoubleDoubleDoubleDouble Operator * (Const Double & x, const doubledouble & y) {Double HX, TX, Hy, Ty, C, C; Doubledouble Z; X86_FIX; C = Split * x; HX = CX; C = Split * Y.Hi; HX = C-HX; TX = x-hx; hy = cy.hi; c = x * y.Hi; hy = c-hy; type = y.Hi - hy; c = ((((hx * Hy-c) hx * type) TX * HY) TX * TY) x * Y.LO; z.Hi = C C; Z.LO = C (double) (CZ.HI); END_X86_FIX; Return Z;}
DoubleDouble Operator * (int x, const doubledouble & y) {return (x)) * y;} Doubledouble Operator * (Const Double & Y) {Return Y * x;} Doubledouble Operator * (Const) Doubledouble & X, Const Int Y) {Return Y * x;}
// self-multiplicationDoubledouble & operator * = (doubledouble & mix) {Double HX, TX, Hy, Ty, C, C; X86_FIX; C = Split * this.hi; hx = c-this.hi; c = Split * y.Hi; hx = c-hx; tx = this.hi-hx; hy = cy.hi; c = this.hi * y.HI; hy = c-hy; type; = y.Hi-hy; c = ((((((((hx * Hy-C) HX * TY) TX * HY) TX * TY) (this.hi * Y.LO THISLO * Y.HI); HX = C C; this.hi = hx; this.lo = C (double) (C-HX); END_X86_FIX; Return THIS;
Doubledouble & operator * = (DoubleDouble & this, const double "{Double HX, TX, HY, TY, C, C; X86_FIX; C = Split * this.hi; hx = c-this.hi; c = split * y; HX = c-hx; tx = this.hi-hx; hy = cy; c = this.hi * y; hy = c-hy; type = y-hy; c = ((((hx * Hy-c) HX * TY) TX * HY) TX * TY) (this.lo * y); hx = C C; this.hi = HX; this.lo = C (double) (C-HX); END_X86_FIX; RETURN THIS;} Doubledouble & Operator * = (DoubleDouble & this, const y) {return this * = (const Double) (Y);}
// Division //
// ReciprocalDoubledouble Recip (const doubledouble & y) {Double HC, TC, Hy, Ty, C, C, U, U; Doubledouble Z; X86_FIX;
C = 1.0 / y.HI; C = Split * C; hc = cc; u = split * y.HI; HC = C-HC; Tc = c-hc; hy = uY.HI; u = c * y. Hi; hy = u-hy; type; u = ((HC * HY-U) HC * TY) TC * HY) TC * TY; c = (((((((1.0- U) -U)) - C * Y.LO) /y.HI; z.Hi = C C; z.LO = (double) (CZ.HI) C; END_X86_FIX; RETURN Z;}
DoubleDouble Operator / (Const Doubledouble & Y) {Double HC, TC, Hy, Ty, C, C, U, U; Doubledouble Z; X86_FIX; C = x.hi / y.HI; C = Split * C ; Hc = cc; u = split * y.HI; HC = c-hc; Tc = c-hc; hy = uY.Hi; u = c * y.Hi; hy = u-hy; type = 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; z.Hi = C C; z.LO = (double) (CZ.HI) C; END_X86_FIX; RETURN Z;}
// Double / Doubledouble: doubleDouble Operator / (Const Double & X, Const Doubledouble & Y) {Double HC, TC, Hy, Ty, C, C, U, U; Doubledouble Z; X86_FIX; C = X / Y.HI; C = Split * c; hc = cc; u = split * y.HI; hc = c-hc; Tc = c-hc; hy = uY.Hi; u = c * y.Hi; hy = u-hy; TY = y.Hi-hy; u = (((HC * HY-U) HC * TY) TC * HY) TC * TY; C = (((xu) -u)) - c * y. LO) /Y.HI; z.Hi = C C; z.LO = (double) (CZ.HI) C; END_X86_FIX; RETURN Z; DoubleDouble Operator / (Const Doubledouble) / (Const Double & Y) {Double HC, TC, Hy, Ty, C, C, U, U; Doubledouble Z;
X86_fix; c = x.hi / y; c = split * c; hc = cc; u = split * y; hc = c-hc; tc = c-hc; hy = uY; u = c * y; hy = U-hy; type = ((HC * HY-U) HC * TY) TC * HY) TC * TY; C = ((x.Hi-U) -U) x.lo) / y; z.Hi = C C; z.LO = (double) (CZ.HI) C; END_X86_FIX; RETURN Z;}
// Doubledouble / INTDOUBLEDOUBLE Operator / (Const Doubledouble & X, Const I) {Return X / (Y);} Doubledouble Operator / (Const Int X, Const Doubledouble & Y) {Return (const Double) (x) / y;
// self-division.doubledouble & operator / = (doubledouble & mix) {Double HC, TC, Hy, Ty, C, C, U, U; X86_FIX; C = this.hi / y.Hi; c = Split * c; hc = cc; u = split * y.HI; hc = c-hc; tc = c-hc; hy = uY.Hi; u = c * y.Hi; hy = u-hy; type = y.Hi-hy; u = (((HC * HY-U) HC * TY) TC * HY) TC * TY; C = ((((THIS.HI-U) -U) THIS. LO) -C * Y.LO) /y.hi; u = C C; this.hi = u; this.lo = (double) (CU) C; END_X86_FIX; return this;}
Doubledouble & operator / = (DoubleDouble & this, const Double & y) {Double HC, TC, Hy, Ty, C, C, U, U; X86_FIX; C = this.hi / y; c = Split * C; hc = cc; u = split * y; hc = c-hc; Tc = c-hc; hy = uY; u = c * y; hy = u-hy; type = y-hy; u = (((hc * HY-U ) hc * TY) TC * HY) TC * TY; C = ((THIS.HI-U) -U) this.lo) / y; u = C C; THIS.HI = U; THIS.LO = (Double) (CU) C; END_X86_FIX; RETURN THIS;}
Doubledouble & operator / = (double) {return (this) / = (const Double) (Y);} Doubledouble qcopysign (const Doubledouble & x, const double {if (y> = 0.0) Return DDFABS x); else return -ddfabs (x);
Doubledouble atodd (const char * s) {Doubledouble Result = {0.0, 0.0}; int N, sign, ex = 0; / * Eat white * / 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) {results = 10.0 * Result n; --ex;} s -;} if (* s == 'e' || * s == 'e') / * get exponent * / ex = atoi ( s); / * Exponent Adjustment * / while (ex -> 0) Result * = 10.0; while ( ex <0) Result / = 10.0; return (Sign> = 0)? Result: -Result;} // Square (Faster Than X * x) Doubledouble SQR (Const Doubledouble & X) {Double HX, TX, C, C; Doubledouble R; X86_FIX; C = Split * x.Hi; HX = Cx.Hi; HX = C-hx; tx = x.hi -HX; C = x.Hi * x.Hi; c = ((((((((((hx * hx-c) 2.0 * hx * tx)) TX * TX) 2.0 * x.hi * x.lo; HX = C C; R.Hi = HX; R.LO = C (C-HX); END_X86_FIX; RTURN R; Extern Double Pow (Double, Double); // Doubledouble ^ INTDOUBLE POWINT (Const Doubledouble & U, INT C ) {Doubledouble Result; if (c <0) RETURN RECIP (Powint (U, -C)); Switch (c) {case 0: result.hi = result.lo = 0.0; if (u.hi == 0.0) Result.lo = POW (0.0, 0.0); ELSE Result.lo = 1.0; returnrate; // ip Math.h Handle 0 ^ 0. Case 1: Return U; Case 2: Return SQR (U); Case 3: Return SQR (U) * U; Default: {/ / binary methodint n = c, m; doubledouble y = {1.0, 0.0}, z = u; if (n <0) n = -n; while (1) {m = n; n / = 2; if (n n! = m) {// if m odd
Y * = z; if (0 == n) return y;} z = sqr (z);}}} / * not reached * / return u;}
Doubledouble new_doubledouble (double x, double y) {doubledouble result; x86_fix; result.hi = x y; result.lo = y (x-result.hi); end_x86_fix; return result;}
// Floor. See Graham, Knuth And Patashnik `Concrete Mathematics' Page 70.// GreateSt Integer <= x // Maybe Floor_s Is Better? Doubledouble Ddfloor (Const Double Double Double Floor (x.hi), FL = floor (x.lo); double t1 = x.hi-fh; double t2 = x.lo-fl; double t3 = t1 t2; int T; t3 = x.Hi-fH x.lo-fl; T = (INT) (Floor (t3)); switch (t) {cas 0: return new_doubledouble (fH, 0.0) new_doubledouble (fl, 0.0); case 1: return new_doubledouble (fH, 0.0) new_doubledouble (fl 1, 0.0); // Case 2 Can Only Arise When FP ({Hi}) <= 1, FP ({LO}) <= 1, but
FP ({hi} {lo}) = 2 case 2: return new_doubledouble (fH, 0.0) new_doubledouble (fl 1.0, 0.0);} // never get here return new_doubledouble (0.0, 0.0);} // signumint SIGN (DoubleDouble & X) {IF (x.Hi> 0.0) Return 1; Else IF (x.Hi <0.0) Return -1; else return 0;}
Char * DoubledouBletoa (Doubledouble & X, Char * S) {Int Digits; Doubledouble Ten = New_DOUBLEDOUBLE (10.0, 0.0), L, Y, Z; Double Q; INT M, N, D, I; IF (x.Hi == 0.0) {structure (s, "0.0"); return s;} if (x.Hi! = X.hi) {struct (s, "nan"); returnz;} digits = 34; y = ddfabs (x ); Q = log10 (y.Hi); n = (int)); if (n <0) n ; if (n == 0) l = new_doubledouble (1.0, 0.0); Else L = Powint (Ten, N); Y = Y / L; IF (SIGN (X) <0) * S = '-'; // Else S << "
D = DIGITS> 34? 34: DIGITS; D = D <3? 3: D; for (i = 1; i <= d; i ) {IF (2 == i) * S = '.'; m = (int) (DDFLOOR (Y) .hi); if (m <0 || m> 9) {// fprintf (stderr, // "internal error in doubledouble.cc: Digit =% D", M);} Sprintf (s, "% d", m); s = strlen (s); // z.LO = 0.0; // z.HI = (double) m; z = new_doubledouble ((double) m, 0.0) Y = (yz) * Ten; if (y.Hi <= 0.0) Break; // x must be an integer // if (y.HI == 0.0) Break; // ???????? ???}} if (n! = 0) {* S = 'e'; Sprintf (s, "% d", n); s = strlen (s);} else * s = 0; returnz INT Operator> (const doubledouble & y) {return (x.hi> y.hi) || (x.hi == y.hi && x.lo> Y.LO);} int operator> = Const Doubledouble & X, Const Doubledouble & Y) {Return (x.hi> y.hi) || (x.hi == y.hi && x.lo> = y.lo);} int operator <(Const Doubledouble & X, Const doubledouble & y) {return (x.hi Struct DDCONSTANTS {DoubleDouble Log2; Doubledouble Log10; Doubledouble Pi; Doubledouble TWOPI; Doubledouble Pion2; Doubledouble Pion4; Doubledouble_pi;} DDCONST void InitConstants (void) {ddconst.Log2 = atodd ( "0.6931471805599453094172321214581765680755"); ddconst.Log10 = atodd ( "2.302585092994045684017991454684364207601"); ddconst.Pi = atodd ( "3.1415926535897932384626433832795028841972"); ddconst.TwoPi = atodd ( "6.2831853071795864769252867665590057683943"); ddconst.Pion2 = atodd ( "1.5707963267948966192313216916397514420985"); ddconst.Pion4 = atodd ( "0.7853981633974483096156608458198757210493"); ddconst._Pi = atodd ( "0.3183098861837906715377675267450287240689");} doubledouble ddldexp (const doubledouble x, const int exp) {// x * 2 ^ EXP Return new_doubledouble (ldexp (x.hi, exp), ldexp (x.lo, exp));} // another floor. v. shouP 97 Sep 23 ... doubledouble ddfloor_s (const doubledouble) {double fhi = floor x.hi); if (fhi! = x.hi) Return new_doubledouble (fhi, 0.0); else return new_doubledouble (fhi, floor (x.lo));} // Round to Nearest Int Doubledouble DDRINT (Const Doubledouble & X) {const Doubledouble & rx = x new_doubledouble (0.5, 0.0); return ddfloor (rx);} DoubleDouble DDEXP (Const Doubledouble & X) {/ * Uses Some Ideas By Alan Miller Method: 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 'approximant is used to approximate e ^ x over the region (-0.1733, 0.1733). This approximation is then squared. * / INT IY; Doubledouble Y, Temp, YSQ, Sum1, Sum2; IF (x.Hi <-744.4400719213812) Return new_doubledouble (0.0, 0.0); // Exp (x) <1e-300 Y = x / ddconst.log2; IY = (int) (DDRINT (Y)). hi; temp = new_doubledouble (double) iY, 0.0); y = (Y-TEMP) * DDCONST.LOG2; Y = DDLDEXP ( Y, -1); YSQ = SQR (Y); SUM1 = Y * ((((YSQ 3960.) * YSQ 2162160.) * YSQ 302702400.) * YSQ 8821612800.); Sum2 = 90. * YSQ 110880.) * YSQ 30270240.) * YSQ 2075673600.) * YSQ 17643225600 .; / * Sum2 Sum1 2. Sum1 Now Approximation = --------- = 1 ----------- = 1 2.Temp Sum2 - Sum1 Sum2 - Sum1Then (1 2.Temp) ^ 2 = 4.Temp. (1 TEMP) 1 * / Temp = Sum1 / (SUM2-SUM1); Y = Temp * (Temp 1); Y = DDLDEXP (Y, 2); Return DDLDEXP (Y 1, IY); // Natural LogarithmDoubleDouble DDLog (const Doubledouble & X) {// newton method Doubledouble S, E; IF (X.Hi <0.0) {fprintf (stderr, "/ ndoubledouble: attempt to take log of negative Argument! / n "); return new_doubledouble (0.0, 0.0);} if (x.Hi == 0.0) {fprintf (stderr," / ndoubledouble: attempt to take Log (0)! / n "); return new_doubledouble 0.0, 0.0);} s = new_doubledouble (log (x.hi), 0.0), E = DDEXP (s); // s = double approximation to Result Return S (X-E) / E; // NEWTON CORRECTION, Good Enough // Doubledouble D = (X-E) / E; RETURN S D-0.5 * SQR (D); // or 2nd Order Correction} Void Base_and_Prec (Void) {// LinnainMa A ACM Toms 7, 272 THM 3 INT P; X86_FIX; Printf ("Base and Precision Determination by Linnainmaa's Method: / N"); {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); Printf ("Type Double: Base IS% G, Precision% D / N", Beta, P);} {Doubledouble DDU, DDR, U, R, Beta; DDU = new_doubledouble (4.0, 0.0); DDU / = new_doubledouble (3.0, 0.0); DDU- = 1; DDU * = 3; DDU- = 1; DDU = DDFABS (DDU); DDR = DDU / 2 1 DDR- = 1; if (ddr.hi! = 0.0) DDU = DDR; u = new_doubledouble (2.0, 0.0); u / = 3.0; u- = 0.5; u * = 3; u- = 0.5; u = DDFABS (U); R = U / 2 0.5; R- = 0.5; if (R.Hi! = 0.0) u = r; beta = DDU / U; P = (int) (- DDLog (u) / ddlog (beta) 0.5) .hi; PrintF ("Type Doubledouble: Base IS% G, Precision% D / N", Beta.hi, P);} END_X86_FIX;} // Assumption: if IT Works, Don't Even Bother Doing Outputint Verify (Char Msg [], Doubledouble Correct, Doubledouble Computed {// default Fractional Error Allowed. Doubledouble delta = new_doubledouble (1.1e-31, 0.0); if (correct == computed) Return 1; Else if (Correct.Hi == 0.0) // can't do a relative test {error: Printf ("% s ", MSG); Printf (" Corret.hi% G Correct.LO% G ", Correct.hi, Correct.LO); Printf (" / Ngot Hi% G, LO% g / n ", computed.hi, computed .lo); Return 0;} else IF (DDFABS (CORRECT-COMPUTED) / CORRECT <= DELTA) RETURN 1; Else Goto Error;} INT main (void) {DoubleDouble A = new_doubledouble (5.0, 0.0); doubledouble b = new_doubledouble (4.0, 0.0); doubledouble c = a * b; double x1, x2; char buffer [256]; int i; initconstants () Base_and_prec (); DoubledouBletoa (DDCONST.LOG2, BUFFER); Printf ("% s / n", buffer; x1 = (POW (2, 53) -2) / POW (2, 53); x2 = (3.0 ) / POW (2,55); Verify ("Test -2: Should BE 0:", New_DOUBLEDOUBLE (0.0, 0.0), DDFLOOR (new_doubledouble (x1, 0.0) new_doubledouble (x2, 0.0))); Verify (" TEST-1: SHOULD BE 0: ", new_doubledouble (0.0, 0.0), DDFLOOR (ATODD (" 0.99999999999999997791953952737 ") ATODD ("0.000000000000000000877405377723750"))); for (i = 0; i <5; i ) {c = c * c; doubledoubletoa (c, buffer); Printf ("% s / n", buffer; a = C - 1.0; b = new_doubledouble (-1.0, 0.0); A = C B; DoubledouBletoa (A, Buffer); Printf ("% s / n", buffer;} return 0;}