QDouble.st
changeset 4388 742f099741bf
parent 4387 879309cae427
child 4389 54ec85aa8943
equal deleted inserted replaced
4387:879309cae427 4388:742f099741bf
     1 "
     1 "
     2  COPYRIGHT (c) 2017 by eXept Software AG
     2  COPYRIGHT (c) 2017 by eXept Software AG
     3               All Rights Reserved
     3 	      All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
    63 
    63 
    64 # ifndef _FPU_DOUBLE
    64 # ifndef _FPU_DOUBLE
    65 #  define _FPU_DOUBLE 0x0200
    65 #  define _FPU_DOUBLE 0x0200
    66 # endif
    66 # endif
    67 
    67 
    68 # if defined( __win32__ ) && (defined( __BORLANDC__ ) || defined( __VISUALC__ )) 
    68 # if defined( __win32__ ) && (defined( __BORLANDC__ ) || defined( __VISUALC__ ))
    69 
    69 
    70 #  define fpu_fix_start(old_cw_ptr)\
    70 #  define fpu_fix_start(old_cw_ptr)\
    71     {\
    71     {\
    72         *old_cw_ptr = _control87(0, 0); \        
    72 	*old_cw_ptr = _control87(0, 0); \
    73         _control87(_FPU_DOUBLE, _FPU_EXTENDED);\
    73 	_control87(_FPU_DOUBLE, _FPU_EXTENDED);\
    74     }
    74     }
    75 
    75 
    76 #  define fpu_fix_end(old_cw_ptr)\
    76 #  define fpu_fix_end(old_cw_ptr)\
    77     {\
    77     {\
    78         _control87(*old_cw_ptr, _FPU_EXTENDED);\
    78 	_control87(*old_cw_ptr, _FPU_EXTENDED);\
    79     }
    79     }
    80 
    80 
    81 # else // assume MINGW, GCC or CLANG
    81 # else // assume MINGW, GCC or CLANG
    82 
    82 
    83 #  ifndef _FPU_GETCW
    83 #  ifndef _FPU_GETCW
    87 #   define _FPU_SETCW(x) asm volatile ("fldcw %0": :"m" (x));
    87 #   define _FPU_SETCW(x) asm volatile ("fldcw %0": :"m" (x));
    88 #  endif
    88 #  endif
    89 
    89 
    90 #  define fpu_fix_start(old_cw_ptr)\
    90 #  define fpu_fix_start(old_cw_ptr)\
    91     {\
    91     {\
    92         volatile unsigned short cw, new_cw;\
    92 	volatile unsigned short cw, new_cw;\
    93         _FPU_GETCW(cw);\
    93 	_FPU_GETCW(cw);\
    94         new_cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;\
    94 	new_cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;\
    95         _FPU_SETCW(new_cw);\
    95 	_FPU_SETCW(new_cw);\
    96         *old_cw_ptr = cw;\
    96 	*old_cw_ptr = cw;\
    97     }
    97     }
    98 
    98 
    99 #  define fpu_fix_end(old_cw_ptr)\
    99 #  define fpu_fix_end(old_cw_ptr)\
   100     {\
   100     {\
   101         volatile unsigned short cw = *old_cw_ptr;\
   101 	volatile unsigned short cw = *old_cw_ptr;\
   102         _FPU_SETCW(cw);\
   102 	_FPU_SETCW(cw);\
   103     }
   103     }
   104 
   104 
   105 # endif
   105 # endif
   106 
   106 
   107 #endif
   107 #endif
   110 struct qd_real {
   110 struct qd_real {
   111     double x[4];    /* The Components. */
   111     double x[4];    /* The Components. */
   112 };
   112 };
   113 
   113 
   114 struct __quadDoubleStruct {
   114 struct __quadDoubleStruct {
   115         STX_OBJ_HEADER
   115 	STX_OBJ_HEADER
   116 #ifdef __NEED_DOUBLE_ALIGN
   116 #ifdef __NEED_DOUBLE_ALIGN
   117         __FILLTYPE_DOUBLE f_filler;
   117 	__FILLTYPE_DOUBLE f_filler;
   118 #endif
   118 #endif
   119         double d_quadDoubleValue[4];
   119 	double d_quadDoubleValue[4];
   120 };
   120 };
   121 
   121 
   122 #define __QuadDoubleInstPtr(obj)      ((struct __quadDoubleStruct *)(__objPtr(obj)))
   122 #define __QuadDoubleInstPtr(obj)      ((struct __quadDoubleStruct *)(__objPtr(obj)))
   123 
   123 
   124 #ifndef __isQuadDouble
   124 #ifndef __isQuadDouble
   125 # define __isQuadDouble(o) \
   125 # define __isQuadDouble(o) \
   126         (__Class(o) == @global(QuadDouble))
   126 	(__Class(o) == @global(QuadDouble))
   127 #endif
   127 #endif
   128 
   128 
   129 #ifndef __qIsQuadDouble
   129 #ifndef __qIsQuadDouble
   130 # define __qIsQuadDouble(o) \
   130 # define __qIsQuadDouble(o) \
   131         (__qClass(o) == @global(QuadDouble))
   131 	(__qClass(o) == @global(QuadDouble))
   132 #endif
   132 #endif
   133 
   133 
   134 #define __qNew_qdReal(newQD, d0,d1,d2,d3) { \
   134 #define __qNew_qdReal(newQD, d0,d1,d2,d3) { \
   135     __qNew(newQD, sizeof(struct __quadDoubleStruct)); \
   135     __qNew(newQD, sizeof(struct __quadDoubleStruct)); \
   136     __stx_setClass(newQD, QDouble);                \
   136     __stx_setClass(newQD, QDouble);                \
   254 #define m_renorm4(c0, c1, c2, c3) {\
   254 #define m_renorm4(c0, c1, c2, c3) {\
   255   double s0, s1, s2 = 0.0, s3 = 0.0;\
   255   double s0, s1, s2 = 0.0, s3 = 0.0;\
   256 \
   256 \
   257     if (! isinf(c0)) { \
   257     if (! isinf(c0)) { \
   258 \
   258 \
   259         m_quick_two_sum(s0, c2, c3, c3);\
   259 	m_quick_two_sum(s0, c2, c3, c3);\
   260         m_quick_two_sum(s0, c1, s0, c2);\
   260 	m_quick_two_sum(s0, c1, s0, c2);\
   261         m_quick_two_sum(c0, c0, s0, c1);\
   261 	m_quick_two_sum(c0, c0, s0, c1);\
   262 \
   262 \
   263         s0 = c0;\
   263 	s0 = c0;\
   264         s1 = c1;\
   264 	s1 = c1;\
   265         if (s1 != 0.0) {\
   265 	if (s1 != 0.0) {\
   266              m_quick_two_sum(s1, s1, c2, s2);\
   266 	     m_quick_two_sum(s1, s1, c2, s2);\
   267             if (s2 != 0.0) {\
   267 	    if (s2 != 0.0) {\
   268                  m_quick_two_sum(s2, s2, c3, s3);\
   268 		 m_quick_two_sum(s2, s2, c3, s3);\
   269             } else {\
   269 	    } else {\
   270                  m_quick_two_sum(s1, s1, c3, s2);\
   270 		 m_quick_two_sum(s1, s1, c3, s2);\
   271             }\
   271 	    }\
   272         } else {\
   272 	} else {\
   273             m_quick_two_sum(s0, s0, c2, s1);\
   273 	    m_quick_two_sum(s0, s0, c2, s1);\
   274             if (s1 != 0.0) {\
   274 	    if (s1 != 0.0) {\
   275                  m_quick_two_sum(s1, s1, c3, s2);\
   275 		 m_quick_two_sum(s1, s1, c3, s2);\
   276             } else {\
   276 	    } else {\
   277                  m_quick_two_sum(s0, s0, c3, s1);\
   277 		 m_quick_two_sum(s0, s0, c3, s1);\
   278             }\
   278 	    }\
   279         }\
   279 	}\
   280 \
   280 \
   281         c0 = s0;\
   281 	c0 = s0;\
   282         c1 = s1;\
   282 	c1 = s1;\
   283         c2 = s2;\
   283 	c2 = s2;\
   284         c3 = s3;\
   284 	c3 = s3;\
   285     }\
   285     }\
   286 }
   286 }
   287 
   287 
   288 #define m_renorm5(c0, c1, c2, c3, c4) { \
   288 #define m_renorm5(c0, c1, c2, c3, c4) { \
   289     double s0, s1, s2 = 0.0, s3 = 0.0; \
   289     double s0, s1, s2 = 0.0, s3 = 0.0; \
   290 \
   290 \
   291     if (! isinf(c0)) { \
   291     if (! isinf(c0)) { \
   292         m_two_sum(s0, c3, c4, c4); \
   292 	m_two_sum(s0, c3, c4, c4); \
   293         m_quick_two_sum(s0, c2, s0, c3); \
   293 	m_quick_two_sum(s0, c2, s0, c3); \
   294         m_quick_two_sum(s0, c1, s0, c2); \
   294 	m_quick_two_sum(s0, c1, s0, c2); \
   295         m_quick_two_sum(c0, c0, s0, c1); \
   295 	m_quick_two_sum(c0, c0, s0, c1); \
   296 \
   296 \
   297         s0 = c0; \
   297 	s0 = c0; \
   298         s1 = c1; \
   298 	s1 = c1; \
   299 \
   299 \
   300         m_two_sum(s0, c0, c1, s1); \
   300 	m_two_sum(s0, c0, c1, s1); \
   301         if (s1 != 0.0) { \
   301 	if (s1 != 0.0) { \
   302             m_quick_two_sum(s1, s1, c2, s2); \
   302 	    m_quick_two_sum(s1, s1, c2, s2); \
   303             if (s2 != 0.0) { \
   303 	    if (s2 != 0.0) { \
   304                 m_quick_two_sum(s2 ,s2, c3, s3); \
   304 		m_quick_two_sum(s2 ,s2, c3, s3); \
   305                 if (s3 != 0.0) {\
   305 		if (s3 != 0.0) {\
   306                     s3 += c4; \
   306 		    s3 += c4; \
   307                 } else {\
   307 		} else {\
   308                     s2 += c4;\
   308 		    s2 += c4;\
   309                 }\
   309 		}\
   310             } else { \
   310 	    } else { \
   311                 m_quick_two_sum(s1, s1, c3, s2); \
   311 		m_quick_two_sum(s1, s1, c3, s2); \
   312                 if (s2 != 0.0) {\
   312 		if (s2 != 0.0) {\
   313                     m_quick_two_sum(s2, s2, c4, s3); \
   313 		    m_quick_two_sum(s2, s2, c4, s3); \
   314                 } else { \
   314 		} else { \
   315                     m_quick_two_sum(s1, s1, c4, s2); \
   315 		    m_quick_two_sum(s1, s1, c4, s2); \
   316                 } \
   316 		} \
   317             } \
   317 	    } \
   318         } else { \
   318 	} else { \
   319             m_quick_two_sum(s0,s0, c2, s1); \
   319 	    m_quick_two_sum(s0,s0, c2, s1); \
   320             if (s1 != 0.0) { \
   320 	    if (s1 != 0.0) { \
   321                 m_quick_two_sum(s1,s1, c3, s2); \
   321 		m_quick_two_sum(s1,s1, c3, s2); \
   322                 if (s2 != 0.0) {\
   322 		if (s2 != 0.0) {\
   323                     m_quick_two_sum(s2,s2, c4, s3); \
   323 		    m_quick_two_sum(s2,s2, c4, s3); \
   324                 } else { \
   324 		} else { \
   325                     m_quick_two_sum(s1 ,s1, c4, s2); \
   325 		    m_quick_two_sum(s1 ,s1, c4, s2); \
   326                 } \
   326 		} \
   327             } else { \
   327 	    } else { \
   328                 m_quick_two_sum(s0,s0, c3, s1); \
   328 		m_quick_two_sum(s0,s0, c3, s1); \
   329                 if (s1 != 0.0) { \
   329 		if (s1 != 0.0) { \
   330                     m_quick_two_sum(s1,s1, c4, s2); \
   330 		    m_quick_two_sum(s1,s1, c4, s2); \
   331                 } else { \
   331 		} else { \
   332                     m_quick_two_sum(s0,s0, c4, s1); \
   332 		    m_quick_two_sum(s0,s0, c4, s1); \
   333                 } \
   333 		} \
   334             } \
   334 	    } \
   335         } \
   335 	} \
   336  \
   336  \
   337         c0 = s0; \
   337 	c0 = s0; \
   338         c1 = s1; \
   338 	c1 = s1; \
   339         c2 = s2; \
   339 	c2 = s2; \
   340         c3 = s3; \
   340 	c3 = s3; \
   341     } \
   341     } \
   342 }
   342 }
   343 
   343 
   344 %}
   344 %}
   345 ! !
   345 ! !
   347 !QDouble primitiveFunctions!
   347 !QDouble primitiveFunctions!
   348 %{
   348 %{
   349 
   349 
   350 /*********** Basic Functions ************/
   350 /*********** Basic Functions ************/
   351 /* Computes fl(a+b) and err(a+b).  Assumes |a| >= |b|. */
   351 /* Computes fl(a+b) and err(a+b).  Assumes |a| >= |b|. */
   352 inline double 
   352 inline double
   353 quick_two_sum(double a, double b, double *errPtr) {
   353 quick_two_sum(double a, double b, double *errPtr) {
   354   double s = a + b;
   354   double s = a + b;
   355   *errPtr = b - (s - a);
   355   *errPtr = b - (s - a);
   356   return s;
   356   return s;
   357 }
   357 }
   358 
   358 
   359 /* Computes fl(a-b) and err(a-b).  Assumes |a| >= |b| */
   359 /* Computes fl(a-b) and err(a-b).  Assumes |a| >= |b| */
   360 inline double 
   360 inline double
   361 quick_two_diff(double a, double b, double *errPtr) {
   361 quick_two_diff(double a, double b, double *errPtr) {
   362   double s = a - b;
   362   double s = a - b;
   363   *errPtr = (a - s) - b;
   363   *errPtr = (a - s) - b;
   364   return s;
   364   return s;
   365 }
   365 }
   366 
   366 
   367 /* Computes fl(a+b) and err(a+b).  */
   367 /* Computes fl(a+b) and err(a+b).  */
   368 inline double 
   368 inline double
   369 two_sum(double a, double b, double *errPtr) {
   369 two_sum(double a, double b, double *errPtr) {
   370   double s = a + b;
   370   double s = a + b;
   371   double bb = s - a;
   371   double bb = s - a;
   372   *errPtr = (a - (s - bb)) + (b - bb);
   372   *errPtr = (a - (s - bb)) + (b - bb);
   373   return s;
   373   return s;
   374 }
   374 }
   375 
   375 
   376 /* Computes fl(a-b) and err(a-b).  */
   376 /* Computes fl(a-b) and err(a-b).  */
   377 inline double 
   377 inline double
   378 two_diff(double a, double b, double *errPtr) {
   378 two_diff(double a, double b, double *errPtr) {
   379   double s = a - b;
   379   double s = a - b;
   380   double bb = s - a;
   380   double bb = s - a;
   381   *errPtr = (a - (s - bb)) - (b + bb);
   381   *errPtr = (a - (s - bb)) - (b + bb);
   382   return s;
   382   return s;
   383 }
   383 }
   384 
   384 
   385 #ifndef QD_FMS
   385 #ifndef QD_FMS
   386 /* Computes high word and lo word of a */
   386 /* Computes high word and lo word of a */
   387 inline void 
   387 inline void
   388 split(double a, double *hiPtr, double *loPtr) {
   388 split(double a, double *hiPtr, double *loPtr) {
   389   double temp;
   389   double temp;
   390   if (a > _QD_SPLIT_THRESH || a < -_QD_SPLIT_THRESH) {
   390   if (a > _QD_SPLIT_THRESH || a < -_QD_SPLIT_THRESH) {
   391     a *= 3.7252902984619140625e-09;  // 2^-28
   391     a *= 3.7252902984619140625e-09;  // 2^-28
   392     temp = _QD_SPLITTER * a;
   392     temp = _QD_SPLITTER * a;
   401   }
   401   }
   402 }
   402 }
   403 #endif
   403 #endif
   404 
   404 
   405 /* Computes fl(a*b) and err(a*b). */
   405 /* Computes fl(a*b) and err(a*b). */
   406 inline double 
   406 inline double
   407 two_prod(double a, double b, double *errPtr) {
   407 two_prod(double a, double b, double *errPtr) {
   408 #ifdef QD_FMS
   408 #ifdef QD_FMS
   409   double p = a * b;
   409   double p = a * b;
   410   *errPtr = QD_FMS(a, b, p);
   410   *errPtr = QD_FMS(a, b, p);
   411   return p;
   411   return p;
   418   return p;
   418   return p;
   419 #endif
   419 #endif
   420 }
   420 }
   421 
   421 
   422 /* Computes fl(a*a) and err(a*a).  Faster than the above method. */
   422 /* Computes fl(a*a) and err(a*a).  Faster than the above method. */
   423 inline double 
   423 inline double
   424 two_sqr(double a, double *errPtr) {
   424 two_sqr(double a, double *errPtr) {
   425 #ifdef QD_FMS
   425 #ifdef QD_FMS
   426   double p = a * a;
   426   double p = a * a;
   427   *errPtr = QD_FMS(a, a, p);
   427   *errPtr = QD_FMS(a, a, p);
   428   return p;
   428   return p;
   434   return q;
   434   return q;
   435 #endif
   435 #endif
   436 }
   436 }
   437 
   437 
   438 /* Computes the nearest integer to d. */
   438 /* Computes the nearest integer to d. */
   439 inline double 
   439 inline double
   440 nint(double d) {
   440 nint(double d) {
   441   if (d == floor(d))
   441   if (d == floor(d))
   442     return d;
   442     return d;
   443   return floor(d + 0.5);
   443   return floor(d + 0.5);
   444 }
   444 }
   445 
   445 
   446 /* Computes the truncated integer. */
   446 /* Computes the truncated integer. */
   447 inline double 
   447 inline double
   448 aint(double d) {
   448 aint(double d) {
   449   return (d >= 0.0) ? floor(d) : ceil(d);
   449   return (d >= 0.0) ? floor(d) : ceil(d);
   450 }
   450 }
   451 
   451 
   452 inline void 
   452 inline void
   453 renorm4(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr) {
   453 renorm4(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr) {
   454   double s0, s1, s2 = 0.0, s3 = 0.0;
   454   double s0, s1, s2 = 0.0, s3 = 0.0;
   455   double c0 = *c0Ptr;
   455   double c0 = *c0Ptr;
   456   
   456 
   457   if (isinf(c0)) return;
   457   if (isinf(c0)) return;
   458 
   458 
   459   s0 = quick_two_sum(*c2Ptr, *c3Ptr, c3Ptr);
   459   s0 = quick_two_sum(*c2Ptr, *c3Ptr, c3Ptr);
   460   s0 = quick_two_sum(*c1Ptr, s0, c2Ptr);
   460   s0 = quick_two_sum(*c1Ptr, s0, c2Ptr);
   461   c0 = quick_two_sum(c0, s0, c1Ptr);
   461   c0 = quick_two_sum(c0, s0, c1Ptr);
   480   *c1Ptr = s1;
   480   *c1Ptr = s1;
   481   *c2Ptr = s2;
   481   *c2Ptr = s2;
   482   *c3Ptr = s3;
   482   *c3Ptr = s3;
   483 }
   483 }
   484 
   484 
   485 inline void 
   485 inline void
   486 renorm5(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr, double *c4Ptr) {
   486 renorm5(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr, double *c4Ptr) {
   487   double s0, s1, s2 = 0.0, s3 = 0.0;
   487   double s0, s1, s2 = 0.0, s3 = 0.0;
   488   
   488 
   489   if (isinf(*c0Ptr)) return;
   489   if (isinf(*c0Ptr)) return;
   490 
   490 
   491   s0 = quick_two_sum(*c3Ptr, *c4Ptr, c4Ptr);
   491   s0 = quick_two_sum(*c3Ptr, *c4Ptr, c4Ptr);
   492   s0 = quick_two_sum(*c2Ptr, s0, c3Ptr);
   492   s0 = quick_two_sum(*c2Ptr, s0, c3Ptr);
   493   s0 = quick_two_sum(*c1Ptr, s0, c2Ptr);
   493   s0 = quick_two_sum(*c1Ptr, s0, c2Ptr);
   500   if (s1 != 0.0) {
   500   if (s1 != 0.0) {
   501     s1 = quick_two_sum(s1, *c2Ptr, &s2);
   501     s1 = quick_two_sum(s1, *c2Ptr, &s2);
   502     if (s2 != 0.0) {
   502     if (s2 != 0.0) {
   503       s2 =quick_two_sum(s2, *c3Ptr, &s3);
   503       s2 =quick_two_sum(s2, *c3Ptr, &s3);
   504       if (s3 != 0.0)
   504       if (s3 != 0.0)
   505         s3 += *c4Ptr;
   505 	s3 += *c4Ptr;
   506       else
   506       else
   507         s2 += *c4Ptr;
   507 	s2 += *c4Ptr;
   508     } else {
   508     } else {
   509       s1 = quick_two_sum(s1, *c3Ptr, &s2);
   509       s1 = quick_two_sum(s1, *c3Ptr, &s2);
   510       if (s2 != 0.0)
   510       if (s2 != 0.0)
   511         s2 = quick_two_sum(s2, *c4Ptr, &s3);
   511 	s2 = quick_two_sum(s2, *c4Ptr, &s3);
   512       else
   512       else
   513         s1 = quick_two_sum(s1, *c4Ptr, &s2);
   513 	s1 = quick_two_sum(s1, *c4Ptr, &s2);
   514     }
   514     }
   515   } else {
   515   } else {
   516     s0 = quick_two_sum(s0, *c2Ptr, &s1);
   516     s0 = quick_two_sum(s0, *c2Ptr, &s1);
   517     if (s1 != 0.0) {
   517     if (s1 != 0.0) {
   518       s1 = quick_two_sum(s1, *c3Ptr, &s2);
   518       s1 = quick_two_sum(s1, *c3Ptr, &s2);
   519       if (s2 != 0.0)
   519       if (s2 != 0.0)
   520         s2 = quick_two_sum(s2, *c4Ptr, &s3);
   520 	s2 = quick_two_sum(s2, *c4Ptr, &s3);
   521       else
   521       else
   522         s1 = quick_two_sum(s1, *c4Ptr, &s2);
   522 	s1 = quick_two_sum(s1, *c4Ptr, &s2);
   523     } else {
   523     } else {
   524       s0 = quick_two_sum(s0, *c3Ptr, &s1);
   524       s0 = quick_two_sum(s0, *c3Ptr, &s1);
   525       if (s1 != 0.0)
   525       if (s1 != 0.0)
   526         s1 = quick_two_sum(s1, *c4Ptr, &s2);
   526 	s1 = quick_two_sum(s1, *c4Ptr, &s2);
   527       else
   527       else
   528         s0 = quick_two_sum(s0, *c4Ptr, &s1);
   528 	s0 = quick_two_sum(s0, *c4Ptr, &s1);
   529     }
   529     }
   530   }
   530   }
   531 
   531 
   532   *c0Ptr = s0;
   532   *c0Ptr = s0;
   533   *c1Ptr = s1;
   533   *c1Ptr = s1;
   534   *c2Ptr = s2;
   534   *c2Ptr = s2;
   535   *c3Ptr = s3;
   535   *c3Ptr = s3;
   536 }
   536 }
   537 
   537 
   538 inline void 
   538 inline void
   539 three_sum(double *aPtr, double *bPtr, double *cPtr) {
   539 three_sum(double *aPtr, double *bPtr, double *cPtr) {
   540   double t1, t2, t3;
   540   double t1, t2, t3;
   541   t1 = two_sum(*aPtr, *bPtr, &t2);
   541   t1 = two_sum(*aPtr, *bPtr, &t2);
   542   *aPtr  = two_sum(*cPtr, t1, &t3);
   542   *aPtr  = two_sum(*cPtr, t1, &t3);
   543   *bPtr  = two_sum(t2, t3, cPtr);
   543   *bPtr  = two_sum(t2, t3, cPtr);
   550   *bPtr = t2 + t3;
   550   *bPtr = t2 + t3;
   551 }
   551 }
   552 
   552 
   553 
   553 
   554 #if 0
   554 #if 0
   555 /* These are provided to give consistent 
   555 /* These are provided to give consistent
   556    interface for double with double-double and quad-double. */
   556    interface for double with double-double and quad-double. */
   557 inline void 
   557 inline void
   558 sincosh(double t, double &sinh_t, double &cosh_t) {
   558 sincosh(double t, double &sinh_t, double &cosh_t) {
   559   sinh_t = sinh(t);
   559   sinh_t = sinh(t);
   560   cosh_t = cosh(t);
   560   cosh_t = cosh(t);
   561 }
   561 }
   562 
   562 
   563 inline double 
   563 inline double
   564 sqr(double t) {
   564 sqr(double t) {
   565   return t * t;
   565   return t * t;
   566 }
   566 }
   567 
   567 
   568 inline double 
   568 inline double
   569 to_double(double a) { 
   569 to_double(double a) {
   570     return a; 
   570     return a;
   571 }
   571 }
   572 
   572 
   573 inline int    
   573 inline int
   574 to_int(double a)    { 
   574 to_int(double a)    {
   575     return static_cast<int>(a); 
   575     return static_cast<int>(a);
   576 }
   576 }
   577 #endif
   577 #endif
   578 
   578 
   579 %}
   579 %}
   580 ! !
   580 ! !
   582 !QDouble class methodsFor:'documentation'!
   582 !QDouble class methodsFor:'documentation'!
   583 
   583 
   584 copyright
   584 copyright
   585 "
   585 "
   586  COPYRIGHT (c) 2017 by eXept Software AG
   586  COPYRIGHT (c) 2017 by eXept Software AG
   587               All Rights Reserved
   587 	      All Rights Reserved
   588 
   588 
   589  This software is furnished under a license and may be used
   589  This software is furnished under a license and may be used
   590  only in accordance with the terms of that license and with the
   590  only in accordance with the terms of that license and with the
   591  inclusion of the above copyright notice.   This software may not
   591  inclusion of the above copyright notice.   This software may not
   592  be provided or otherwise made available to, or used by, any
   592  be provided or otherwise made available to, or used by, any
   601 
   601 
   602     In contrast to Floats (which use the C-compilers native 64bit 'double' format),
   602     In contrast to Floats (which use the C-compilers native 64bit 'double' format),
   603     QDoubles give you 212 bit or approx. 64 decimal digits of precision.
   603     QDoubles give you 212 bit or approx. 64 decimal digits of precision.
   604 
   604 
   605     Representation:
   605     Representation:
   606         QDoubles use 4 IEEE doubles, each keeping 53 bits of precision.
   606 	QDoubles use 4 IEEE doubles, each keeping 53 bits of precision.
   607 
   607 
   608     Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
   608     Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
   609 
   609 
   610     [author:]
   610     [author:]
   611         Claus Gittinger
   611 	Claus Gittinger
   612 
   612 
   613     [see also:]
   613     [see also:]
   614         Number
   614 	Number
   615         Float ShortFloat Fraction FixedPoint Integer Complex
   615 	Float ShortFloat Fraction FixedPoint Integer Complex
   616         FloatArray DoubleArray
   616 	FloatArray DoubleArray
   617 "
   617 "
   618 ! !
   618 ! !
   619 
   619 
   620 !QDouble class methodsFor:'instance creation'!
   620 !QDouble class methodsFor:'instance creation'!
   621 
   621 
   632 #ifdef __SCHTEAM__
   632 #ifdef __SCHTEAM__
   633     ERROR("trying to instantiate a quad double");
   633     ERROR("trying to instantiate a quad double");
   634 #else
   634 #else
   635     OBJ newFloat;
   635     OBJ newFloat;
   636 printf("xxx\n");
   636 printf("xxx\n");
   637     __qNew(newFloat, sizeof(struct __quadDoubleStruct));              
   637     __qNew(newFloat, sizeof(struct __quadDoubleStruct));
   638     __stx_setClass(newFloat, QDouble);                         
   638     __stx_setClass(newFloat, QDouble);
   639     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = 0.0;        
   639     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = 0.0;
   640     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;        
   640     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;
   641     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;        
   641     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;
   642     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;        
   642     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;
   643     RETURN (newFloat);
   643     RETURN (newFloat);
   644 #endif /* not SCHTEAM */
   644 #endif /* not SCHTEAM */
   645 %}
   645 %}
   646 
   646 
   647     "
   647     "
   658 #ifdef __SCHTEAM__
   658 #ifdef __SCHTEAM__
   659     ERROR("trying to instantiate a quad double");
   659     ERROR("trying to instantiate a quad double");
   660 #else
   660 #else
   661     OBJ newQD;
   661     OBJ newQD;
   662 
   662 
   663     if (__isFloatLike(d0) 
   663     if (__isFloatLike(d0)
   664      && __isFloatLike(d1)
   664      && __isFloatLike(d1)
   665      && __isFloatLike(d2)
   665      && __isFloatLike(d2)
   666      && __isFloatLike(d3)) {    
   666      && __isFloatLike(d3)) {
   667         __qNew_qdReal(newQD, __floatVal(d0), __floatVal(d1),        
   667 	__qNew_qdReal(newQD, __floatVal(d0), __floatVal(d1),
   668                              __floatVal(d2), __floatVal(d3));        
   668 			     __floatVal(d2), __floatVal(d3));
   669         RETURN (newQD);
   669 	RETURN (newQD);
   670     }
   670     }
   671 #endif
   671 #endif
   672 %}.
   672 %}.
   673     self error:'invalid argument'
   673     self error:'invalid argument'
   674 
   674 
   675     "
   675     "
   676      self d0: 3.141592653589793116e+00
   676      self d0: 3.141592653589793116e+00
   677           d1: 1.224646799147353207e-16
   677 	  d1: 1.224646799147353207e-16
   678           d2: -2.994769809718339666e-33
   678 	  d2: -2.994769809718339666e-33
   679           d3: 1.112454220863365282e-49
   679 	  d3: 1.112454220863365282e-49
   680     "
   680     "
   681 
   681 
   682     "Created: / 12-06-2017 / 20:17:14 / cg"
   682     "Created: / 12-06-2017 / 20:17:14 / cg"
   683 !
   683 !
   684 
   684 
   689 #ifdef __SCHTEAM__
   689 #ifdef __SCHTEAM__
   690     ERROR("trying to instantiate a quad double");
   690     ERROR("trying to instantiate a quad double");
   691 #else
   691 #else
   692     OBJ newQD;
   692     OBJ newQD;
   693 
   693 
   694     if (__isDoubleArray(aDoubleArray)) {    
   694     if (__isDoubleArray(aDoubleArray)) {
   695         __qNew_qdReal(newQD, 
   695 	__qNew_qdReal(newQD,
   696                     __DoubleArrayInstPtr(aDoubleArray)->d_element[0],        
   696 		    __DoubleArrayInstPtr(aDoubleArray)->d_element[0],
   697                     __DoubleArrayInstPtr(aDoubleArray)->d_element[1],        
   697 		    __DoubleArrayInstPtr(aDoubleArray)->d_element[1],
   698                     __DoubleArrayInstPtr(aDoubleArray)->d_element[2],        
   698 		    __DoubleArrayInstPtr(aDoubleArray)->d_element[2],
   699                     __DoubleArrayInstPtr(aDoubleArray)->d_element[3]);        
   699 		    __DoubleArrayInstPtr(aDoubleArray)->d_element[3]);
   700         RETURN (newQD);
   700 	RETURN (newQD);
   701     }
   701     }
   702 #endif
   702 #endif
   703 %}.
   703 %}.
   704     self error:'invalid argument'
   704     self error:'invalid argument'
   705 
   705 
   706     "
   706     "
   707      self fromDoubleArray(DoubleArray 
   707      self fromDoubleArray(DoubleArray
   708                                 with: 3.141592653589793116e+00
   708 				with: 3.141592653589793116e+00
   709                                 with: 1.224646799147353207e-16
   709 				with: 1.224646799147353207e-16
   710                                 with: -2.994769809718339666e-33
   710 				with: -2.994769809718339666e-33
   711                                 with: 1.112454220863365282e-49)
   711 				with: 1.112454220863365282e-49)
   712     "
   712     "
   713 
   713 
   714     "Created: / 12-06-2017 / 18:25:32 / cg"
   714     "Created: / 12-06-2017 / 18:25:32 / cg"
   715 !
   715 !
   716 
   716 
   723 #else
   723 #else
   724     double dVal;
   724     double dVal;
   725     OBJ newFloat;
   725     OBJ newFloat;
   726 
   726 
   727     if (__isFloatLike(aFloat)) {
   727     if (__isFloatLike(aFloat)) {
   728         dVal = __floatVal(aFloat);
   728 	dVal = __floatVal(aFloat);
   729     } else if (__isShortFloat(aFloat)) {       
   729     } else if (__isShortFloat(aFloat)) {
   730         dVal = __shortFloatVal(aFloat);
   730 	dVal = __shortFloatVal(aFloat);
   731     } else {
   731     } else {
   732         goto badArg;
   732 	goto badArg;
   733     }    
   733     }
   734         
   734 
   735     __qNew(newFloat, sizeof(struct __quadDoubleStruct));              
   735     __qNew(newFloat, sizeof(struct __quadDoubleStruct));
   736     __stx_setClass(newFloat, QDouble);                         
   736     __stx_setClass(newFloat, QDouble);
   737     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = dVal;        
   737     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = dVal;
   738     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;        
   738     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;
   739     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;        
   739     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;
   740     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;        
   740     __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;
   741     RETURN (newFloat);
   741     RETURN (newFloat);
   742 
   742 
   743 badArg: ;
   743 badArg: ;
   744 
   744 
   745 #endif
   745 #endif
   759 %{  /* NOCONTEXT */
   759 %{  /* NOCONTEXT */
   760 #ifndef __SCHTEAM__
   760 #ifndef __SCHTEAM__
   761     OBJ newFloat;
   761     OBJ newFloat;
   762 
   762 
   763     if (__isSmallInteger(anInteger)) {
   763     if (__isSmallInteger(anInteger)) {
   764         __qNew(newFloat, sizeof(struct __quadDoubleStruct));              
   764 	__qNew(newFloat, sizeof(struct __quadDoubleStruct));
   765         __stx_setClass(newFloat, QDouble);                         
   765 	__stx_setClass(newFloat, QDouble);
   766         __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = (double)(__smallIntegerVal(anInteger));        
   766 	__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = (double)(__smallIntegerVal(anInteger));
   767         __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;        
   767 	__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;
   768         __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;        
   768 	__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;
   769         __QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;        
   769 	__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;
   770         RETURN (newFloat);
   770 	RETURN (newFloat);
   771     }
   771     }
   772 #endif
   772 #endif
   773 %}.
   773 %}.
   774     ^ super fromInteger:anInteger
   774     ^ super fromInteger:anInteger
   775 
   775 
   785 e
   785 e
   786     "return the constant e as quad precision double.
   786     "return the constant e as quad precision double.
   787      (returns approx. 212 bits of precision)"
   787      (returns approx. 212 bits of precision)"
   788 
   788 
   789     E isNil ifTrue:[
   789     E isNil ifTrue:[
   790         E := self fromDoubleArray(DoubleArray 
   790 	E := self fromDoubleArray:(DoubleArray
   791                                     with: 2.718281828459045091e+00
   791 				    with: 2.718281828459045091e+00
   792                                     with: 1.445646891729250158e-16
   792 				    with: 1.445646891729250158e-16
   793                                     with: -2.127717108038176765e-33
   793 				    with: -2.127717108038176765e-33
   794                                     with: 1.515630159841218954e-49)
   794 				    with: 1.515630159841218954e-49)
   795     ].    
   795     ].
   796     ^ E
   796     ^ E
   797 
   797 
   798     "
   798     "
   799      self e
   799      self e
   800     "
   800     "
   805 ln10
   805 ln10
   806     "return the constant e as quad precision double.
   806     "return the constant e as quad precision double.
   807      (returns approx. 212 bits of precision)"
   807      (returns approx. 212 bits of precision)"
   808 
   808 
   809     Ln10 isNil ifTrue:[
   809     Ln10 isNil ifTrue:[
   810         Ln10 := self fromDoubleArray(DoubleArray 
   810 	Ln10 := self fromDoubleArray:(DoubleArray
   811                                     with: 2.302585092994045901e+00
   811 				    with: 2.302585092994045901e+00
   812                                     with: -2.170756223382249351e-16
   812 				    with: -2.170756223382249351e-16
   813                                     with: -9.984262454465776570e-33
   813 				    with: -9.984262454465776570e-33
   814                                     with: -4.023357454450206379e-49)
   814 				    with: -4.023357454450206379e-49)
   815     ].    
   815     ].
   816     ^ Ln10
   816     ^ Ln10
   817 
   817 
   818     "
   818     "
   819      self ln10
   819      self ln10
   820     "
   820     "
   825 ln2
   825 ln2
   826     "return the constant e as quad precision double.
   826     "return the constant e as quad precision double.
   827      (returns approx. 212 bits of precision)"
   827      (returns approx. 212 bits of precision)"
   828 
   828 
   829     Ln2 isNil ifTrue:[
   829     Ln2 isNil ifTrue:[
   830         Ln2 := self fromDoubleArray(DoubleArray 
   830 	Ln2 := self fromDoubleArray:(DoubleArray
   831                                     with: 6.931471805599452862e-01
   831 				    with: 6.931471805599452862e-01
   832                                     with: 2.319046813846299558e-17
   832 				    with: 2.319046813846299558e-17
   833                                     with: 5.707708438416212066e-34
   833 				    with: 5.707708438416212066e-34
   834                                     with: -3.582432210601811423e-50)
   834 				    with: -3.582432210601811423e-50)
   835     ].    
   835     ].
   836     ^ Ln2
   836     ^ Ln2
   837 
   837 
   838     "
   838     "
   839      self ln2
   839      self ln2
   840     "
   840     "
   845 pi
   845 pi
   846     "return the constant pi as quad precision double.
   846     "return the constant pi as quad precision double.
   847      (returns approx. 212 bits of precision)"
   847      (returns approx. 212 bits of precision)"
   848 
   848 
   849     Pi isNil ifTrue:[
   849     Pi isNil ifTrue:[
   850         Pi := self fromDoubleArray(DoubleArray 
   850 	Pi := self fromDoubleArray:(DoubleArray
   851                                     with: 3.141592653589793116e+00
   851 				    with: 3.141592653589793116e+00
   852                                     with: 1.224646799147353207e-16
   852 				    with: 1.224646799147353207e-16
   853                                     with: -2.994769809718339666e-33
   853 				    with: -2.994769809718339666e-33
   854                                     with: 1.112454220863365282e-49)
   854 				    with: 1.112454220863365282e-49)
   855     ].    
   855     ].
   856     ^ Pi
   856     ^ Pi
   857 
   857 
   858     "
   858     "
   859      self pi
   859      self pi
   860     "
   860     "
   893 
   893 
   894 numBitsInMantissa
   894 numBitsInMantissa
   895     "answer the number of bits in the mantissa"
   895     "answer the number of bits in the mantissa"
   896 
   896 
   897     ^ Float precision * 4
   897     ^ Float precision * 4
   898     
   898 
   899     "
   899     "
   900      1.0 class numBitsInMantissa
   900      1.0 class numBitsInMantissa
   901      1.0 asShortFloat class numBitsInMantissa
   901      1.0 asShortFloat class numBitsInMantissa
   902      1.0 asLongFloat class numBitsInMantissa
   902      1.0 asLongFloat class numBitsInMantissa
   903      1.0 asDDouble class numBitsInMantissa
   903      1.0 asDDouble class numBitsInMantissa
   914 
   914 
   915 precision
   915 precision
   916     "answer the number of bits in the mantissa"
   916     "answer the number of bits in the mantissa"
   917 
   917 
   918     ^ Float precision * 4
   918     ^ Float precision * 4
   919     
   919 
   920     "
   920     "
   921      1.0 class numBitsInMantissa
   921      1.0 class numBitsInMantissa
   922      1.0 asShortFloat class numBitsInMantissa
   922      1.0 asShortFloat class numBitsInMantissa
   923      1.0 asLongFloat class numBitsInMantissa
   923      1.0 asLongFloat class numBitsInMantissa
   924      1.0 asDDouble class numBitsInMantissa
   924      1.0 asDDouble class numBitsInMantissa
   998 ! !
   998 ! !
   999 
   999 
  1000 !QDouble methodsFor:'coercing & converting'!
  1000 !QDouble methodsFor:'coercing & converting'!
  1001 
  1001 
  1002 asDoubleArray
  1002 asDoubleArray
  1003     ^ DoubleArray 
  1003     ^ DoubleArray
  1004             with:self d0 
  1004 	    with:self d0
  1005             with:self d1 
  1005 	    with:self d1
  1006             with:self d2 
  1006 	    with:self d2
  1007             with:self d3.
  1007 	    with:self d3.
  1008 
  1008 
  1009     "
  1009     "
  1010      (QDouble fromFloat:1.0) asDoubleArray
  1010      (QDouble fromFloat:1.0) asDoubleArray
  1011      (QDouble fromFloat:2.0) asDoubleArray
  1011      (QDouble fromFloat:2.0) asDoubleArray
  1012     "
  1012     "
  1089 
  1089 
  1090 !QDouble methodsFor:'double dispatching'!
  1090 !QDouble methodsFor:'double dispatching'!
  1091 
  1091 
  1092 differenceFromFloat:aFloat
  1092 differenceFromFloat:aFloat
  1093     "aFloat - self"
  1093     "aFloat - self"
  1094     
  1094 
  1095     ^ aFloat + (self negated)
  1095     ^ aFloat + (self negated)
  1096 
  1096 
  1097     "
  1097     "
  1098      1.0 - (QDouble fromFloat:1.0)
  1098      1.0 - (QDouble fromFloat:1.0)
  1099      1e20 - (QDouble fromFloat:1.0)
  1099      1e20 - (QDouble fromFloat:1.0)
  1108     "Created: / 12-06-2017 / 23:38:05 / cg"
  1108     "Created: / 12-06-2017 / 23:38:05 / cg"
  1109 !
  1109 !
  1110 
  1110 
  1111 differenceFromQDouble:aQDouble
  1111 differenceFromQDouble:aQDouble
  1112     "aQDouble - self"
  1112     "aQDouble - self"
  1113     
  1113 
  1114     ^ aQDouble + (self negated)
  1114     ^ aQDouble + (self negated)
  1115 
  1115 
  1116     "
  1116     "
  1117      1.0 - (QDouble fromFloat:1.0)
  1117      1.0 - (QDouble fromFloat:1.0)
  1118      1e20 - (QDouble fromFloat:1.0)
  1118      1e20 - (QDouble fromFloat:1.0)
  1128 !
  1128 !
  1129 
  1129 
  1130 equalFromQDouble:aQDouble
  1130 equalFromQDouble:aQDouble
  1131 %{
  1131 %{
  1132     if (__Class(aQDouble) == QDouble) {
  1132     if (__Class(aQDouble) == QDouble) {
  1133         double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1133 	double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1134         double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1134 	double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1135 
  1135 
  1136         RETURN ((a[0] == b[0] 
  1136 	RETURN ((a[0] == b[0]
  1137                 && a[1] == b[1] 
  1137 		&& a[1] == b[1]
  1138                 && a[2] == b[2] 
  1138 		&& a[2] == b[2]
  1139                 && a[3] == b[3]) ? true : false);
  1139 		&& a[3] == b[3]) ? true : false);
  1140     }
  1140     }
  1141 %}.
  1141 %}.
  1142     ^ (aQDouble d0 = self d0)
  1142     ^ (aQDouble d0 = self d0)
  1143     and:[ (aQDouble d1 = self d1)
  1143     and:[ (aQDouble d1 = self d1)
  1144     and:[ (aQDouble d2 = self d2)
  1144     and:[ (aQDouble d2 = self d2)
  1145     and:[ (aQDouble d3 = self d3) ]]]
  1145     and:[ (aQDouble d3 = self d3) ]]]
  1146     
  1146 
  1147     "
  1147     "
  1148      (QDouble fromFloat:1.0) = (QDouble fromFloat:1.0)
  1148      (QDouble fromFloat:1.0) = (QDouble fromFloat:1.0)
  1149      (QDouble fromFloat:1.0) = 1.0
  1149      (QDouble fromFloat:1.0) = 1.0
  1150      1.0 = (QDouble fromFloat:1.0)
  1150      1.0 = (QDouble fromFloat:1.0)
  1151    "
  1151    "
  1158     "sent when aQDouble does not know how to compare to the receiver..
  1158     "sent when aQDouble does not know how to compare to the receiver..
  1159      Return true if aQDouble < self"
  1159      Return true if aQDouble < self"
  1160 
  1160 
  1161 %{
  1161 %{
  1162     if (__Class(aQDouble) == QDouble) {
  1162     if (__Class(aQDouble) == QDouble) {
  1163         double *a = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1163 	double *a = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1164         double *b = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1164 	double *b = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1165 
  1165 
  1166         // now compare if a < b!
  1166 	// now compare if a < b!
  1167         RETURN 
  1167 	RETURN
  1168             ((a[0] < b[0] || 
  1168 	    ((a[0] < b[0] ||
  1169               (a[0] == b[0] && (a[1] < b[1] ||
  1169 	      (a[0] == b[0] && (a[1] < b[1] ||
  1170                 (a[1] == b[1] && (a[2] < b[2] ||
  1170 		(a[1] == b[1] && (a[2] < b[2] ||
  1171                   (a[2] == b[2] && a[3] < b[3])))))) ? true : false);
  1171 		  (a[2] == b[2] && a[3] < b[3])))))) ? true : false);
  1172     }
  1172     }
  1173 %}.
  1173 %}.
  1174     ^ super lessFromQDouble:aQDouble
  1174     ^ super lessFromQDouble:aQDouble
  1175 
  1175 
  1176     "
  1176     "
  1188 !
  1188 !
  1189 
  1189 
  1190 productFromFloat:aFloat
  1190 productFromFloat:aFloat
  1191 %{
  1191 %{
  1192     if (__isFloatLike(aFloat)) {
  1192     if (__isFloatLike(aFloat)) {
  1193         double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; 
  1193 	double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1194         double b = __floatVal(aFloat);
  1194 	double b = __floatVal(aFloat);
  1195         double p0, p1, p2, p3;
  1195 	double p0, p1, p2, p3;
  1196         double q0, q1, q2;
  1196 	double q0, q1, q2;
  1197         double s0, s1, s2, s3, s4;
  1197 	double s0, s1, s2, s3, s4;
  1198         OBJ newQD;
  1198 	OBJ newQD;
  1199         int savedCV;
  1199 	int savedCV;
  1200         
  1200 
  1201         fpu_fix_start(&savedCV);
  1201 	fpu_fix_start(&savedCV);
  1202         
  1202 
  1203         m_two_prod(p0, a[0], b, q0);
  1203 	m_two_prod(p0, a[0], b, q0);
  1204         m_two_prod(p1, a[1], b, q1);
  1204 	m_two_prod(p1, a[1], b, q1);
  1205         m_two_prod(p2, a[2], b, q2);
  1205 	m_two_prod(p2, a[2], b, q2);
  1206         p3 = a[3] * b;
  1206 	p3 = a[3] * b;
  1207 
  1207 
  1208         s0 = p0;
  1208 	s0 = p0;
  1209 
  1209 
  1210         m_two_sum(s1, q0, p1, s2);
  1210 	m_two_sum(s1, q0, p1, s2);
  1211 
  1211 
  1212         m_three_sum(s2, q1, p2);
  1212 	m_three_sum(s2, q1, p2);
  1213         
  1213 
  1214         m_three_sum2(q1, q2, p3);
  1214 	m_three_sum2(q1, q2, p3);
  1215         s3 = q1;
  1215 	s3 = q1;
  1216 
  1216 
  1217         s4 = q2 + p2;
  1217 	s4 = q2 + p2;
  1218 
  1218 
  1219         m_renorm5(s0, s1, s2, s3, s4);
  1219 	m_renorm5(s0, s1, s2, s3, s4);
  1220         fpu_fix_end(&savedCV);
  1220 	fpu_fix_end(&savedCV);
  1221 
  1221 
  1222         __qNew_qdReal(newQD, s0, s1, s2, s3);
  1222 	__qNew_qdReal(newQD, s0, s1, s2, s3);
  1223         RETURN( newQD );
  1223 	RETURN( newQD );
  1224     }
  1224     }
  1225 %}.
  1225 %}.
  1226     ^ super productFromFloat:aFloat.
  1226     ^ super productFromFloat:aFloat.
  1227 
  1227 
  1228     "
  1228     "
  1230      ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2.0
  1230      ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2.0
  1231      ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2e20
  1231      ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2e20
  1232 
  1232 
  1233      2.0 * (QDouble fromFloat:1.0)
  1233      2.0 * (QDouble fromFloat:1.0)
  1234      2.0 * (QDouble fromFloat:3.0)
  1234      2.0 * (QDouble fromFloat:3.0)
  1235      
  1235 
  1236      2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) 
  1236      2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))
  1237      (2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) - (QDouble fromFloat:1e20) - (QDouble fromFloat:1e20)
  1237      (2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) - (QDouble fromFloat:1e20) - (QDouble fromFloat:1e20)
  1238 
  1238 
  1239      (2.0 * (QDouble fromFloat:1.0)) asFloat
  1239      (2.0 * (QDouble fromFloat:1.0)) asFloat
  1240      (1e20 * (QDouble fromFloat:1.0)) asFloat
  1240      (1e20 * (QDouble fromFloat:1.0)) asFloat
  1241 
  1241 
  1247 !
  1247 !
  1248 
  1248 
  1249 productFromQDouble:aQDouble
  1249 productFromQDouble:aQDouble
  1250 %{
  1250 %{
  1251     if (__Class(aQDouble) == QDouble) {
  1251     if (__Class(aQDouble) == QDouble) {
  1252         double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1252 	double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1253         double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1253 	double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1254         OBJ newQD;
  1254 	OBJ newQD;
  1255 
  1255 
  1256         // sloppy        
  1256 	// sloppy
  1257         double p0, p1, p2, p3, p4, p5;
  1257 	double p0, p1, p2, p3, p4, p5;
  1258         double q0, q1, q2, q3, q4, q5;
  1258 	double q0, q1, q2, q3, q4, q5;
  1259         double t0, t1;
  1259 	double t0, t1;
  1260         double s0, s1, s2;
  1260 	double s0, s1, s2;
  1261         int savedCV;
  1261 	int savedCV;
  1262         
  1262 
  1263         fpu_fix_start(&savedCV);
  1263 	fpu_fix_start(&savedCV);
  1264 
  1264 
  1265         m_two_prod(p0, a[0], b[0], q0);
  1265 	m_two_prod(p0, a[0], b[0], q0);
  1266 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[0], p0, q0);
  1266 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[0], p0, q0);
  1267 
  1267 
  1268         m_two_prod(p1, a[0], b[1], q1);
  1268 	m_two_prod(p1, a[0], b[1], q1);
  1269         m_two_prod(p2, a[1], b[0], q2);
  1269 	m_two_prod(p2, a[1], b[0], q2);
  1270 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[1], p1, q1);
  1270 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[1], p1, q1);
  1271 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[0], p2, q2);
  1271 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[0], p2, q2);
  1272 
  1272 
  1273         m_two_prod(p3, a[0], b[2], q3);
  1273 	m_two_prod(p3, a[0], b[2], q3);
  1274         m_two_prod(p4, a[1], b[1], q4);
  1274 	m_two_prod(p4, a[1], b[1], q4);
  1275         m_two_prod(p5, a[2], b[0], q5);
  1275 	m_two_prod(p5, a[2], b[0], q5);
  1276 
  1276 
  1277 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[2], p3, q3);
  1277 fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[2], p3, q3);
  1278 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[1], p4, q4);
  1278 fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[1], p4, q4);
  1279 fprintf(stderr, "%f * %f -> %f, %f\n", a[2], b[0], p5, q5);
  1279 fprintf(stderr, "%f * %f -> %f, %f\n", a[2], b[0], p5, q5);
  1280 
  1280 
  1281         /* Start Accumulation */
  1281 	/* Start Accumulation */
  1282         m_three_sum(p1, p2, q0);
  1282 	m_three_sum(p1, p2, q0);
  1283 
  1283 
  1284         /* Six-Three Sum  of p2, q1, q2, p3, p4, p5. */
  1284 	/* Six-Three Sum  of p2, q1, q2, p3, p4, p5. */
  1285         m_three_sum(p2, q1, q2);
  1285 	m_three_sum(p2, q1, q2);
  1286         m_three_sum(p3, p4, p5);
  1286 	m_three_sum(p3, p4, p5);
  1287         /* compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5). */
  1287 	/* compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5). */
  1288         m_two_sum(s0, p2, p3, t0);
  1288 	m_two_sum(s0, p2, p3, t0);
  1289         m_two_sum(s1, q1, p4, t1);
  1289 	m_two_sum(s1, q1, p4, t1);
  1290         s2 = q2 + p5;
  1290 	s2 = q2 + p5;
  1291         m_two_sum(s1, s1, t0, t0);
  1291 	m_two_sum(s1, s1, t0, t0);
  1292         s2 += (t0 + t1);
  1292 	s2 += (t0 + t1);
  1293 
  1293 
  1294         /* O(eps^3) order terms */
  1294 	/* O(eps^3) order terms */
  1295         s1 += a[0]*b[3] + a[1]*b[2] + a[2]*b[1] + a[3]*b[0] + q0 + q3 + q4 + q5;
  1295 	s1 += a[0]*b[3] + a[1]*b[2] + a[2]*b[1] + a[3]*b[0] + q0 + q3 + q4 + q5;
  1296         m_renorm5(p0, p1, s0, s1, s2);
  1296 	m_renorm5(p0, p1, s0, s1, s2);
  1297 
  1297 
  1298         fpu_fix_end(&savedCV);
  1298 	fpu_fix_end(&savedCV);
  1299 
  1299 
  1300         __qNew_qdReal(newQD, p0, p1, s0, s1);
  1300 	__qNew_qdReal(newQD, p0, p1, s0, s1);
  1301         RETURN( newQD );
  1301 	RETURN( newQD );
  1302     }
  1302     }
  1303 %}.
  1303 %}.
  1304     ^ super productFromQDouble:aQDouble.
  1304     ^ super productFromQDouble:aQDouble.
  1305 
  1305 
  1306     "
  1306     "
  1319     "Modified: / 14-06-2017 / 11:43:28 / cg"
  1319     "Modified: / 14-06-2017 / 11:43:28 / cg"
  1320 !
  1320 !
  1321 
  1321 
  1322 quotientFromQDouble:aQDouble
  1322 quotientFromQDouble:aQDouble
  1323     "sloppy"
  1323     "sloppy"
  1324     
  1324 
  1325     |q0 q1 q2 q3 r|
  1325     |q0 q1 q2 q3 r|
  1326 
  1326 
  1327     q0 := self d0 / aQDouble d0.
  1327     q0 := self d0 / aQDouble d0.
  1328     r := self - (aQDouble * q0).
  1328     r := self - (aQDouble * q0).
  1329 
  1329 
  1330     q1 := r d0 / aQDouble d0.
  1330     q1 := r d0 / aQDouble d0.
  1331     r := r - (aQDouble * q1).
  1331     r := r - (aQDouble * q1).
  1332     
  1332 
  1333     q2 := r d0 / aQDouble d0.
  1333     q2 := r d0 / aQDouble d0.
  1334     r := r - (aQDouble * q2).
  1334     r := r - (aQDouble * q2).
  1335 
  1335 
  1336     q3 := r d0 / aQDouble d0.
  1336     q3 := r d0 / aQDouble d0.
  1337 
  1337 
  1348 
  1348 
  1349      (QDouble fromFloat:2.0) / 2.0
  1349      (QDouble fromFloat:2.0) / 2.0
  1350      (QDouble fromFloat:1e20) / 2.0
  1350      (QDouble fromFloat:1e20) / 2.0
  1351      ((QDouble fromFloat:1.0) / 2.0) asFloat
  1351      ((QDouble fromFloat:1.0) / 2.0) asFloat
  1352      ((QDouble fromFloat:1e20 / 2.0)) asFloat
  1352      ((QDouble fromFloat:1e20 / 2.0)) asFloat
  1353      
  1353 
  1354      ((1e20 + (QDouble fromFloat:1.0) + 1e-20) / 2.0) asDoubleArray
  1354      ((1e20 + (QDouble fromFloat:1.0) + 1e-20) / 2.0) asDoubleArray
  1355     "
  1355     "
  1356 
  1356 
  1357     "Created: / 13-06-2017 / 17:50:35 / cg"
  1357     "Created: / 13-06-2017 / 17:50:35 / cg"
  1358 !
  1358 !
  1359 
  1359 
  1360 sumFromFloat:aFloat
  1360 sumFromFloat:aFloat
  1361 %{
  1361 %{
  1362     if (__isFloatLike(aFloat)) {
  1362     if (__isFloatLike(aFloat)) {
  1363         double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; 
  1363 	double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1364         double b = __floatVal(aFloat);
  1364 	double b = __floatVal(aFloat);
  1365         double c0, c1, c2, c3;
  1365 	double c0, c1, c2, c3;
  1366         double e;
  1366 	double e;
  1367         OBJ newQD;
  1367 	OBJ newQD;
  1368         int savedCV;
  1368 	int savedCV;
  1369         
  1369 
  1370         fpu_fix_start(&savedCV);
  1370 	fpu_fix_start(&savedCV);
  1371 
  1371 
  1372         m_two_sum(c0, a[0], b, e);
  1372 	m_two_sum(c0, a[0], b, e);
  1373         m_two_sum(c1 ,a[1], e, e);
  1373 	m_two_sum(c1 ,a[1], e, e);
  1374         m_two_sum(c2, a[2], e, e);
  1374 	m_two_sum(c2, a[2], e, e);
  1375         m_two_sum(c3, a[3], e, e);
  1375 	m_two_sum(c3, a[3], e, e);
  1376 
  1376 
  1377         m_renorm5(c0, c1, c2, c3, e);
  1377 	m_renorm5(c0, c1, c2, c3, e);
  1378         fpu_fix_end(&savedCV);
  1378 	fpu_fix_end(&savedCV);
  1379         __qNew_qdReal(newQD, c0, c1, c2, c3);
  1379 	__qNew_qdReal(newQD, c0, c1, c2, c3);
  1380         RETURN( newQD );
  1380 	RETURN( newQD );
  1381     }
  1381     }
  1382 %}.
  1382 %}.
  1383     ^ super sumFromFloat:aFloat.
  1383     ^ super sumFromFloat:aFloat.
  1384 
  1384 
  1385     "
  1385     "
  1398 !
  1398 !
  1399 
  1399 
  1400 sumFromQDouble:aQDouble
  1400 sumFromQDouble:aQDouble
  1401 %{
  1401 %{
  1402     if (__Class(aQDouble) == QDouble) {
  1402     if (__Class(aQDouble) == QDouble) {
  1403         double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1403 	double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1404         double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1404 	double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
  1405         OBJ newQD;
  1405 	OBJ newQD;
  1406         
  1406 
  1407 #ifndef QD_IEEE_ADD
  1407 #ifndef QD_IEEE_ADD
  1408         // sloppy_add...
  1408 	// sloppy_add...
  1409 
  1409 
  1410         /*
  1410 	/*
  1411         double s0, s1, s2, s3;
  1411 	double s0, s1, s2, s3;
  1412         double t0, t1, t2, t3;
  1412 	double t0, t1, t2, t3;
  1413         int savedCV;
  1413 	int savedCV;
  1414 
  1414 
  1415         fpu_fix_start(&savedCV);
  1415 	fpu_fix_start(&savedCV);
  1416         m_two_sum(s0, a[0], b[0], t0);
  1416 	m_two_sum(s0, a[0], b[0], t0);
  1417         m_two_sum(s1, a[1], b[1], t1);
  1417 	m_two_sum(s1, a[1], b[1], t1);
  1418         m_two_sum(s2, a[2], b[2], t2);
  1418 	m_two_sum(s2, a[2], b[2], t2);
  1419         m_two_sum(s3, a[3], b[3], t3);
  1419 	m_two_sum(s3, a[3], b[3], t3);
  1420 
  1420 
  1421         m_two_sum(s1, s1, t0, t0);
  1421 	m_two_sum(s1, s1, t0, t0);
  1422         m_three_sum(s2, t0, t1);
  1422 	m_three_sum(s2, t0, t1);
  1423         m_three_sum2(s3, t0, t2);
  1423 	m_three_sum2(s3, t0, t2);
  1424         t0 = t0 + t1 + t3;
  1424 	t0 = t0 + t1 + t3;
  1425 
  1425 
  1426         fpu_fix_end(&savedCV);
  1426 	fpu_fix_end(&savedCV);
  1427         m_renorm5(s0, s1, s2, s3, t0);
  1427 	m_renorm5(s0, s1, s2, s3, t0);
  1428         return qd_real(s0, s1, s2, s3, t0);
  1428 	return qd_real(s0, s1, s2, s3, t0);
  1429         */
  1429 	*/
  1430 
  1430 
  1431         /* Same as above, but addition re-organized to minimize
  1431 	/* Same as above, but addition re-organized to minimize
  1432            data dependency ... unfortunately some compilers are
  1432 	   data dependency ... unfortunately some compilers are
  1433            not very smart to do this automatically */
  1433 	   not very smart to do this automatically */
  1434         double s0, s1, s2, s3;
  1434 	double s0, s1, s2, s3;
  1435         double t0, t1, t2, t3;
  1435 	double t0, t1, t2, t3;
  1436         double v0, v1, v2, v3;
  1436 	double v0, v1, v2, v3;
  1437         double u0, u1, u2, u3;
  1437 	double u0, u1, u2, u3;
  1438         double w0, w1, w2, w3;
  1438 	double w0, w1, w2, w3;
  1439         int savedCV;
  1439 	int savedCV;
  1440         
  1440 
  1441         fpu_fix_start(&savedCV);
  1441 	fpu_fix_start(&savedCV);
  1442         s0 = a[0] + b[0];
  1442 	s0 = a[0] + b[0];
  1443         s1 = a[1] + b[1];
  1443 	s1 = a[1] + b[1];
  1444         s2 = a[2] + b[2];
  1444 	s2 = a[2] + b[2];
  1445         s3 = a[3] + b[3];
  1445 	s3 = a[3] + b[3];
  1446 
  1446 
  1447         v0 = s0 - a[0];
  1447 	v0 = s0 - a[0];
  1448         v1 = s1 - a[1];
  1448 	v1 = s1 - a[1];
  1449         v2 = s2 - a[2];
  1449 	v2 = s2 - a[2];
  1450         v3 = s3 - a[3];
  1450 	v3 = s3 - a[3];
  1451 
  1451 
  1452         u0 = s0 - v0;
  1452 	u0 = s0 - v0;
  1453         u1 = s1 - v1;
  1453 	u1 = s1 - v1;
  1454         u2 = s2 - v2;
  1454 	u2 = s2 - v2;
  1455         u3 = s3 - v3;
  1455 	u3 = s3 - v3;
  1456 
  1456 
  1457         w0 = a[0] - u0;
  1457 	w0 = a[0] - u0;
  1458         w1 = a[1] - u1;
  1458 	w1 = a[1] - u1;
  1459         w2 = a[2] - u2;
  1459 	w2 = a[2] - u2;
  1460         w3 = a[3] - u3;
  1460 	w3 = a[3] - u3;
  1461 
  1461 
  1462         u0 = b[0] - v0;
  1462 	u0 = b[0] - v0;
  1463         u1 = b[1] - v1;
  1463 	u1 = b[1] - v1;
  1464         u2 = b[2] - v2;
  1464 	u2 = b[2] - v2;
  1465         u3 = b[3] - v3;
  1465 	u3 = b[3] - v3;
  1466 
  1466 
  1467         t0 = w0 + u0;
  1467 	t0 = w0 + u0;
  1468         t1 = w1 + u1;
  1468 	t1 = w1 + u1;
  1469         t2 = w2 + u2;
  1469 	t2 = w2 + u2;
  1470         t3 = w3 + u3;
  1470 	t3 = w3 + u3;
  1471 
  1471 
  1472         m_two_sum(s1, s1, t0, t0);
  1472 	m_two_sum(s1, s1, t0, t0);
  1473         m_three_sum(s2, t0, t1);
  1473 	m_three_sum(s2, t0, t1);
  1474         m_three_sum2(s3, t0, t2);
  1474 	m_three_sum2(s3, t0, t2);
  1475         t0 = t0 + t1 + t3;
  1475 	t0 = t0 + t1 + t3;
  1476 
  1476 
  1477         /* renormalize */
  1477 	/* renormalize */
  1478         m_renorm5(s0, s1, s2, s3, t0);
  1478 	m_renorm5(s0, s1, s2, s3, t0);
  1479         fpu_fix_end(&savedCV);
  1479 	fpu_fix_end(&savedCV);
  1480         __qNew_qdReal(newQD, s0, s1, s2, s3);
  1480 	__qNew_qdReal(newQD, s0, s1, s2, s3);
  1481         RETURN(newQD);                 
  1481 	RETURN(newQD);
  1482 #else
  1482 #else
  1483         // ieee_add...
  1483 	// ieee_add...
  1484         int i, j, k;
  1484 	int i, j, k;
  1485         double s, t;
  1485 	double s, t;
  1486         double u, v;   /* double-length accumulator */
  1486 	double u, v;   /* double-length accumulator */
  1487         double x[4] = {0.0, 0.0, 0.0, 0.0};
  1487 	double x[4] = {0.0, 0.0, 0.0, 0.0};
  1488         int savedCV;
  1488 	int savedCV;
  1489         
  1489 
  1490         fpu_fix_start(&savedCV);
  1490 	fpu_fix_start(&savedCV);
  1491         i = j = k = 0;
  1491 	i = j = k = 0;
  1492         if (abs(a[i]) > abs(b[j]))
  1492 	if (abs(a[i]) > abs(b[j]))
  1493           u = a[i++];
  1493 	  u = a[i++];
  1494         else
  1494 	else
  1495           u = b[j++];
  1495 	  u = b[j++];
  1496         if (abs(a[i]) > abs(b[j]))
  1496 	if (abs(a[i]) > abs(b[j]))
  1497           v = a[i++];
  1497 	  v = a[i++];
  1498         else
  1498 	else
  1499           v = b[j++];
  1499 	  v = b[j++];
  1500 
  1500 
  1501         u = quick_two_sum(u, v, v);
  1501 	u = quick_two_sum(u, v, v);
  1502 
  1502 
  1503         while (k < 4) {
  1503 	while (k < 4) {
  1504           if (i >= 4 && j >= 4) {
  1504 	  if (i >= 4 && j >= 4) {
  1505             x[k] = u;
  1505 	    x[k] = u;
  1506             if (k < 3)
  1506 	    if (k < 3)
  1507               x[++k] = v;
  1507 	      x[++k] = v;
  1508             break;
  1508 	    break;
  1509           }
  1509 	  }
  1510 
  1510 
  1511           if (i >= 4)
  1511 	  if (i >= 4)
  1512             t = b[j++];
  1512 	    t = b[j++];
  1513           else if (j >= 4)
  1513 	  else if (j >= 4)
  1514             t = a[i++];
  1514 	    t = a[i++];
  1515           else if (abs(a[i]) > abs(b[j])) {
  1515 	  else if (abs(a[i]) > abs(b[j])) {
  1516             t = a[i++];
  1516 	    t = a[i++];
  1517           } else
  1517 	  } else
  1518             t = b[j++];
  1518 	    t = b[j++];
  1519 
  1519 
  1520           s = quick_three_accum(u, v, t);
  1520 	  s = quick_three_accum(u, v, t);
  1521 
  1521 
  1522           if (s != 0.0) {
  1522 	  if (s != 0.0) {
  1523             x[k++] = s;
  1523 	    x[k++] = s;
  1524           }
  1524 	  }
  1525         }
  1525 	}
  1526 
  1526 
  1527         /* add the rest. */
  1527 	/* add the rest. */
  1528         for (k = i; k < 4; k++)
  1528 	for (k = i; k < 4; k++)
  1529           x[3] += a[k];
  1529 	  x[3] += a[k];
  1530         for (k = j; k < 4; k++)
  1530 	for (k = j; k < 4; k++)
  1531           x[3] += b[k];
  1531 	  x[3] += b[k];
  1532 
  1532 
  1533         m_renorm4(x[0], x[1], x[2], x[3]);
  1533 	m_renorm4(x[0], x[1], x[2], x[3]);
  1534         fpu_fix_end(&savedCV);
  1534 	fpu_fix_end(&savedCV);
  1535         __qNew_qdReal(newQD, x[0], x[1], x[2], x[3]);
  1535 	__qNew_qdReal(newQD, x[0], x[1], x[2], x[3]);
  1536         RETURN(newQD);                 
  1536 	RETURN(newQD);
  1537 #endif
  1537 #endif
  1538     }
  1538     }
  1539 %}.
  1539 %}.
  1540     ^ super sumFromQDouble:aQDouble
  1540     ^ super sumFromQDouble:aQDouble
  1541     
  1541 
  1542     "
  1542     "
  1543      (QDouble fromFloat:1.0) + (QDouble fromFloat:1.0)
  1543      (QDouble fromFloat:1.0) + (QDouble fromFloat:1.0)
  1544      (QDouble fromFloat:1.0) + 1.0
  1544      (QDouble fromFloat:1.0) + 1.0
  1545      1.0 + (QDouble fromFloat:1.0)
  1545      1.0 + (QDouble fromFloat:1.0)
  1546 
  1546 
  1559 
  1559 
  1560 inspectorExtraAttributes
  1560 inspectorExtraAttributes
  1561     "extra (pseudo instvar) entries to be shown in an inspector."
  1561     "extra (pseudo instvar) entries to be shown in an inspector."
  1562 
  1562 
  1563     ^ super inspectorExtraAttributes
  1563     ^ super inspectorExtraAttributes
  1564         add:'-{doubles}' ->
  1564 	add:'-{doubles}' ->
  1565             [
  1565 	    [
  1566                 self asDoubleArray printString
  1566 		self asDoubleArray printString
  1567             ];
  1567 	    ];
  1568         yourself
  1568 	yourself
  1569 
  1569 
  1570     "Created: / 12-06-2017 / 23:43:05 / cg"
  1570     "Created: / 12-06-2017 / 23:43:05 / cg"
  1571 ! !
  1571 ! !
  1572 
  1572 
  1573 !QDouble methodsFor:'mathematical functions'!
  1573 !QDouble methodsFor:'mathematical functions'!
  1582     double x0, x1, x2, x3;
  1582     double x0, x1, x2, x3;
  1583     x1 = x2 = x3 = 0.0;
  1583     x1 = x2 = x3 = 0.0;
  1584     x0 =floor(a[0]);
  1584     x0 =floor(a[0]);
  1585 
  1585 
  1586     if (x0 == a[0]) {
  1586     if (x0 == a[0]) {
  1587         x1 = floor(a[1]);
  1587 	x1 = floor(a[1]);
  1588 
  1588 
  1589         if (x1 == a[1]) {
  1589 	if (x1 == a[1]) {
  1590             x2 = floor(a[2]);
  1590 	    x2 = floor(a[2]);
  1591 
  1591 
  1592             if (x2 == a[2]) {
  1592 	    if (x2 == a[2]) {
  1593                 x3 = floor(a[3]);
  1593 		x3 = floor(a[3]);
  1594             }
  1594 	    }
  1595         }
  1595 	}
  1596 
  1596 
  1597         m_renorm4(x0, x1, x2, x3);
  1597 	m_renorm4(x0, x1, x2, x3);
  1598         __qNew_qdReal(newQD, x0, x1, x2, x3);
  1598 	__qNew_qdReal(newQD, x0, x1, x2, x3);
  1599         RETURN( newQD );
  1599 	RETURN( newQD );
  1600     }
  1600     }
  1601 
  1601 
  1602     __qNew_qdReal(newQD, x0, x1, x2, x3);
  1602     __qNew_qdReal(newQD, x0, x1, x2, x3);
  1603     RETURN( newQD );
  1603     RETURN( newQD );
  1604 %}.
  1604 %}.
  1606     "
  1606     "
  1607      (QDouble fromFloat:4.0) floor
  1607      (QDouble fromFloat:4.0) floor
  1608      (QDouble fromFloat:4.1) floor
  1608      (QDouble fromFloat:4.1) floor
  1609      (QDouble fromFloat:0.1) floor
  1609      (QDouble fromFloat:0.1) floor
  1610      (0.1 + (QDouble fromFloat:1.0)) floor
  1610      (0.1 + (QDouble fromFloat:1.0)) floor
  1611      (1e20 + (QDouble fromFloat:1.0)) floor 
  1611      (1e20 + (QDouble fromFloat:1.0)) floor
  1612 
  1612 
  1613      (QDouble fromFloat:1.5) floor
  1613      (QDouble fromFloat:1.5) floor
  1614      (QDouble fromFloat:0.5) floor
  1614      (QDouble fromFloat:0.5) floor
  1615      (QDouble fromFloat:-0.5) floor
  1615      (QDouble fromFloat:-0.5) floor
  1616      (QDouble fromFloat:-1.5) floor
  1616      (QDouble fromFloat:-1.5) floor
  1619     "Created: / 13-06-2017 / 01:52:44 / cg"
  1619     "Created: / 13-06-2017 / 01:52:44 / cg"
  1620     "Modified (comment): / 13-06-2017 / 17:33:19 / cg"
  1620     "Modified (comment): / 13-06-2017 / 17:33:19 / cg"
  1621 !
  1621 !
  1622 
  1622 
  1623 negated
  1623 negated
  1624     ^ self class 
  1624     ^ self class
  1625         d0:(self d0) negated 
  1625 	d0:(self d0) negated
  1626         d1:(self d1) negated 
  1626 	d1:(self d1) negated
  1627         d2:(self d2) negated 
  1627 	d2:(self d2) negated
  1628         d3:(self d3) negated
  1628 	d3:(self d3) negated
  1629 
  1629 
  1630     "    
  1630     "
  1631      (QDouble fromFloat:1.0) negated
  1631      (QDouble fromFloat:1.0) negated
  1632      ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) negated asDoubleArray
  1632      ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) negated asDoubleArray
  1633 
  1633 
  1634      (((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))
  1634      (((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))
  1635      + ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) asDoubleArray
  1635      + ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) asDoubleArray
  1646     double q0, q1, q2, q3;
  1646     double q0, q1, q2, q3;
  1647     double s0, s1;
  1647     double s0, s1;
  1648     double t0, t1;
  1648     double t0, t1;
  1649     double t;
  1649     double t;
  1650     OBJ newQD;
  1650     OBJ newQD;
  1651     
  1651 
  1652     m_two_sqr(p0, a[0], q0);
  1652     m_two_sqr(p0, a[0], q0);
  1653     t = 2.0 * a[0];
  1653     t = 2.0 * a[0];
  1654 
  1654 
  1655     m_two_prod(p1, t, a[1], q1);
  1655     m_two_prod(p1, t, a[1], q1);
  1656     m_two_prod(p2, t, a[2], q2);
  1656     m_two_prod(p2, t, a[2], q2);
  1689     RETURN( newQD );
  1689     RETURN( newQD );
  1690 %}.
  1690 %}.
  1691 
  1691 
  1692     "
  1692     "
  1693      (QDouble fromFloat:4.0) squared
  1693      (QDouble fromFloat:4.0) squared
  1694      (1e20 + (QDouble fromFloat:1.0)) squared 
  1694      (1e20 + (QDouble fromFloat:1.0)) squared
  1695     "
  1695     "
  1696 
  1696 
  1697     "Created: / 13-06-2017 / 01:27:58 / cg"
  1697     "Created: / 13-06-2017 / 01:27:58 / cg"
  1698 ! !
  1698 ! !
  1699 
  1699 
  1703     |numDigits r e i d|
  1703     |numDigits r e i d|
  1704 
  1704 
  1705     numDigits := precision+1. "/ number of digits
  1705     numDigits := precision+1. "/ number of digits
  1706     r := self abs.
  1706     r := self abs.
  1707     self d0 = 0.0 ifTrue:[
  1707     self d0 = 0.0 ifTrue:[
  1708         expn value:0.
  1708 	expn value:0.
  1709         precision timesRepeat:[ outStream nextPut:$0 ].
  1709 	precision timesRepeat:[ outStream nextPut:$0 ].
  1710         ^ self.
  1710 	^ self.
  1711     ].
  1711     ].
  1712 
  1712 
  1713     "/ determine approx. exponent
  1713     "/ determine approx. exponent
  1714     e := self d0 abs log10 floor.
  1714     e := self d0 abs log10 floor.
  1715     self halt.
  1715     self halt.
  1716     e < -300 ifTrue:[
  1716     e < -300 ifTrue:[
  1717         r := r * (10.0 raisedToInteger:300).
  1717 	r := r * (10.0 raisedToInteger:300).
  1718         r := r / (10.0 raisedToInteger:(e+300)).
  1718 	r := r / (10.0 raisedToInteger:(e+300)).
  1719     ] ifFalse:[
  1719     ] ifFalse:[
  1720         e > 300 ifTrue:[
  1720 	e > 300 ifTrue:[
  1721         ] ifFalse:[
  1721 	] ifFalse:[
  1722         ]
  1722 	]
  1723     ].
  1723     ].
  1724     
  1724 
  1725     
  1725 
  1726     "
  1726     "
  1727      1.2345 asQDouble printDigitsOn:Transcript precision:5 exponentInto:[:e |]
  1727      1.2345 asQDouble printDigitsOn:Transcript precision:5 exponentInto:[:e |]
  1728     "
  1728     "
  1729 
  1729 
  1730     "Created: / 13-06-2017 / 17:28:08 / cg"
  1730     "Created: / 13-06-2017 / 17:28:08 / cg"
  1732 
  1732 
  1733 printString
  1733 printString
  1734     "return a printed representation of the receiver"
  1734     "return a printed representation of the receiver"
  1735 
  1735 
  1736     self d1 = 0.0 ifTrue:[
  1736     self d1 = 0.0 ifTrue:[
  1737         ^ self d0 printString
  1737 	^ self d0 printString
  1738     ].
  1738     ].
  1739     ^ self d0 printString , '...'
  1739     ^ self d0 printString , '...'
  1740 
  1740 
  1741     "Created: / 12-06-2017 / 23:41:04 / cg"
  1741     "Created: / 12-06-2017 / 23:41:04 / cg"
  1742 ! !
  1742 ! !
  1744 !QDouble methodsFor:'private accessing'!
  1744 !QDouble methodsFor:'private accessing'!
  1745 
  1745 
  1746 d0
  1746 d0
  1747     "the most significant (and highest valued) 53 bits of precision"
  1747     "the most significant (and highest valued) 53 bits of precision"
  1748 %{
  1748 %{
  1749     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[0]) ); 
  1749     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[0]) );
  1750 %}
  1750 %}
  1751 
  1751 
  1752     "Created: / 12-06-2017 / 20:15:12 / cg"
  1752     "Created: / 12-06-2017 / 20:15:12 / cg"
  1753     "Modified (comment): / 13-06-2017 / 17:59:47 / cg"
  1753     "Modified (comment): / 13-06-2017 / 17:59:47 / cg"
  1754 !
  1754 !
  1755 
  1755 
  1756 d1
  1756 d1
  1757     "the next most significant (and next highest valued) 53 bits of precision"
  1757     "the next most significant (and next highest valued) 53 bits of precision"
  1758 %{
  1758 %{
  1759     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[1]) ); 
  1759     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[1]) );
  1760 %}
  1760 %}
  1761 
  1761 
  1762     "Created: / 12-06-2017 / 20:15:12 / cg"
  1762     "Created: / 12-06-2017 / 20:15:12 / cg"
  1763     "Modified (comment): / 13-06-2017 / 18:00:00 / cg"
  1763     "Modified (comment): / 13-06-2017 / 18:00:00 / cg"
  1764 !
  1764 !
  1765 
  1765 
  1766 d2
  1766 d2
  1767 %{
  1767 %{
  1768     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[2]) ); 
  1768     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[2]) );
  1769 %}
  1769 %}
  1770 
  1770 
  1771     "Created: / 12-06-2017 / 20:15:29 / cg"
  1771     "Created: / 12-06-2017 / 20:15:29 / cg"
  1772 !
  1772 !
  1773 
  1773 
  1774 d3
  1774 d3
  1775     "the least significant (and smallest valued) 53 bits of precision"
  1775     "the least significant (and smallest valued) 53 bits of precision"
  1776 %{
  1776 %{
  1777     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[3]) ); 
  1777     RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[3]) );
  1778 %}
  1778 %}
  1779 
  1779 
  1780     "Created: / 12-06-2017 / 20:15:32 / cg"
  1780     "Created: / 12-06-2017 / 20:15:32 / cg"
  1781     "Modified (comment): / 13-06-2017 / 18:00:18 / cg"
  1781     "Modified (comment): / 13-06-2017 / 18:00:18 / cg"
  1782 !
  1782 !
  1783 
  1783 
  1784 renorm
  1784 renorm
  1785 %{
  1785 %{
  1786     double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue; 
  1786     double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
  1787     double c0, c1, c2, c3;
  1787     double c0, c1, c2, c3;
  1788     OBJ newQD;
  1788     OBJ newQD;
  1789 
  1789 
  1790     c0 = a[0];
  1790     c0 = a[0];
  1791     c1 = a[1];
  1791     c1 = a[1];
  1814 !
  1814 !
  1815 
  1815 
  1816 version_CVS
  1816 version_CVS
  1817     ^ '$Header$'
  1817     ^ '$Header$'
  1818 ! !
  1818 ! !
  1819