#REFACTORING by cg
class: QDouble
class definition
comment/format in:
#productFromFloat:
#quotientFromQDouble:
changed:
#productFromQDouble:
#sumFromFloat:
#sumFromQDouble:
"
COPYRIGHT (c) 2017 by eXept Software AG
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
"{ Package: 'stx:libbasic2' }"
"{ NameSpace: Smalltalk }"
LimitedPrecisionReal variableByteSubclass:#QDouble
instanceVariableNames:''
classVariableNames:'DefaultPrintFormat QDoubleZero QDoubleOne Pi E Ln2 Ln10 Epsilon'
poolDictionaries:''
category:'Magnitude-Numbers'
!
!QDouble primitiveDefinitions!
%{
#include <stdio.h>
#include <errno.h>
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
/*
* on some systems, errno is a macro ... check for it here
*/
#ifndef errno
extern errno;
#endif
#if !defined (__win32__)
# include <locale.h>
#endif
#if defined (__aix__)
# include <float.h>
#endif
#if defined(__irix__) || defined(__solaris__) || defined(__sunos__)
# include <nan.h>
#endif
#if defined(__linux__)
# ifndef NAN
# include <bits/nan.h>
# endif
#endif
#if defined(__x86__) || defined(__x86_64__)
# ifndef _FPU_EXTENDED
# define _FPU_EXTENDED 0x0300
# endif
# ifndef _FPU_DOUBLE
# define _FPU_DOUBLE 0x0200
# endif
# if defined( __win32__ ) && (defined( __BORLANDC__ ) || defined( __VISUALC__ ))
# define fpu_fix_start(old_cw_ptr)\
{\
*old_cw_ptr = _control87(0, 0); \
_control87(_FPU_DOUBLE, _FPU_EXTENDED);\
}
# define fpu_fix_end(old_cw_ptr)\
{\
_control87(*old_cw_ptr, _FPU_EXTENDED);\
}
# else // assume MINGW, GCC or CLANG
# ifndef _FPU_GETCW
# define _FPU_GETCW(x) asm volatile ("fnstcw %0":"=m" (x));
# endif
# ifndef _FPU_SETCW
# define _FPU_SETCW(x) asm volatile ("fldcw %0": :"m" (x));
# endif
# define fpu_fix_start(old_cw_ptr)\
{\
volatile unsigned short cw, new_cw;\
_FPU_GETCW(cw);\
new_cw = (cw & ~_FPU_EXTENDED) | _FPU_DOUBLE;\
_FPU_SETCW(new_cw);\
*old_cw_ptr = cw;\
}
# define fpu_fix_end(old_cw_ptr)\
{\
volatile unsigned short cw = *old_cw_ptr;\
_FPU_SETCW(cw);\
}
# endif
#endif
struct qd_real {
double x[4]; /* The Components. */
};
struct __quadDoubleStruct {
STX_OBJ_HEADER
#ifdef __NEED_DOUBLE_ALIGN
__FILLTYPE_DOUBLE f_filler;
#endif
double d_quadDoubleValue[4];
};
#define __QuadDoubleInstPtr(obj) ((struct __quadDoubleStruct *)(__objPtr(obj)))
#ifndef __isQuadDouble
# define __isQuadDouble(o) \
(__Class(o) == @global(QuadDouble))
#endif
#ifndef __qIsQuadDouble
# define __qIsQuadDouble(o) \
(__qClass(o) == @global(QuadDouble))
#endif
#define __qNew_qdReal(newQD, d0,d1,d2,d3) { \
__qNew(newQD, sizeof(struct __quadDoubleStruct)); \
__stx_setClass(newQD, QDouble); \
__QuadDoubleInstPtr(newQD)->d_quadDoubleValue[0] = d0; \
__QuadDoubleInstPtr(newQD)->d_quadDoubleValue[1] = d1; \
__QuadDoubleInstPtr(newQD)->d_quadDoubleValue[2] = d2; \
__QuadDoubleInstPtr(newQD)->d_quadDoubleValue[3] = d3; \
}
// qd_real(c0, c1, c2, c3);
#define _QD_SPLITTER 134217729.0 // = 2^27 + 1
#define _QD_SPLIT_THRESH 6.69692879491417e+299 // = 2^996
#define m_quick_two_sum(rslt, a, b, err) {\
double s = a + b;\
err = b - (s - a);\
rslt = s; \
}
#define m_quick_two_diff(rslt, a, b, err) {\
double s = a - b;\
err = (a - s) - b;\
rslt = s;\
}
#define m_two_sum(rslt, a, b, err) {\
double s = a + b;\
double bb = s - a;\
err = (a - (s - bb)) + (b - bb);\
rslt = s;\
}
/* Computes fl(a-b) and err(a-b). */
#define m_two_diff(rslt, a, b, err) {\
double s = a - b;\
double bb = s - a;\
err = (a - (s - bb)) - (b + bb);\
rslt = s;\
}
#define m_three_sum(a, b, c) { \
double t1, t2, t3; \
m_two_sum(t1, a, b, t2); \
m_two_sum(a, c, t1, t3); \
m_two_sum(b, t2, t3, c); \
}
#define m_three_sum2(a, b, c) {\
double t1, t2, t3;\
m_two_sum(t1, a, b, t2);\
m_two_sum(a, c, t1, t3);\
b = t2 + t3;\
}
#ifndef QD_FMS
/* Computes high word and lo word of a */
#define m_split(a, hi, lo) {\
double temp;\
if (a > _QD_SPLIT_THRESH || a < -_QD_SPLIT_THRESH) {\
a *= 3.7252902984619140625e-09;\
temp = _QD_SPLITTER * a;\
hi = temp - (temp - a);\
lo = a - hi;\
hi *= 268435456.0;\
lo *= 268435456.0;\
} else {\
temp = _QD_SPLITTER * a;\
hi = temp - (temp - a);\
lo = a - hi;\
}\
}
#endif
#ifdef QD_FMS
/* Computes fl(a*b) and err(a*b). */
#define m_two_prod(rslt, a, b, err) {\
double p = a * b;\
err = QD_FMS(a, b, p);\
rslt = p; \
}
#else
#define m_two_prod(rslt, a, b, err) {\
double a_hi, a_lo, b_hi, b_lo;\
double p = a * b;\
m_split(a, a_hi, a_lo);\
m_split(b, b_hi, b_lo);\
err = ((a_hi * b_hi - p) + a_hi * b_lo + a_lo * b_hi) + a_lo * b_lo;\
rslt = p; \
}
#endif
#ifdef QD_FMS
#define m_two_sqr(rslt, a, err) {\
double p = a * a;\
err = QD_FMS(a, a, p);\
rslt = p;\
}
#else
#define m_two_sqr(rslt, a, err) {\
double hi, lo;\
double q = a * a;\
m_split(a, hi, lo);\
err = ((hi * hi - q) + 2.0 * hi * lo) + lo * lo;\
rslt = q;\
}
#endif
#define m_renorm4(c0, c1, c2, c3) {\
double s0, s1, s2 = 0.0, s3 = 0.0;\
\
if (! isinf(c0)) { \
\
m_quick_two_sum(s0, c2, c3, c3);\
m_quick_two_sum(s0, c1, s0, c2);\
m_quick_two_sum(c0, c0, s0, c1);\
\
s0 = c0;\
s1 = c1;\
if (s1 != 0.0) {\
m_quick_two_sum(s1, s1, c2, s2);\
if (s2 != 0.0) {\
m_quick_two_sum(s2, s2, c3, s3);\
} else {\
m_quick_two_sum(s1, s1, c3, s2);\
}\
} else {\
m_quick_two_sum(s0, s0, c2, s1);\
if (s1 != 0.0) {\
m_quick_two_sum(s1, s1, c3, s2);\
} else {\
m_quick_two_sum(s0, s0, c3, s1);\
}\
}\
\
c0 = s0;\
c1 = s1;\
c2 = s2;\
c3 = s3;\
}\
}
#define m_renorm5(c0, c1, c2, c3, c4) { \
double s0, s1, s2 = 0.0, s3 = 0.0; \
\
if (! isinf(c0)) { \
m_two_sum(s0, c3, c4, c4); \
m_quick_two_sum(s0, c2, s0, c3); \
m_quick_two_sum(s0, c1, s0, c2); \
m_quick_two_sum(c0, c0, s0, c1); \
\
s0 = c0; \
s1 = c1; \
\
m_two_sum(s0, c0, c1, s1); \
if (s1 != 0.0) { \
m_quick_two_sum(s1, s1, c2, s2); \
if (s2 != 0.0) { \
m_quick_two_sum(s2 ,s2, c3, s3); \
if (s3 != 0.0) {\
s3 += c4; \
} else {\
s2 += c4;\
}\
} else { \
m_quick_two_sum(s1, s1, c3, s2); \
if (s2 != 0.0) {\
m_quick_two_sum(s2, s2, c4, s3); \
} else { \
m_quick_two_sum(s1, s1, c4, s2); \
} \
} \
} else { \
m_quick_two_sum(s0,s0, c2, s1); \
if (s1 != 0.0) { \
m_quick_two_sum(s1,s1, c3, s2); \
if (s2 != 0.0) {\
m_quick_two_sum(s2,s2, c4, s3); \
} else { \
m_quick_two_sum(s1 ,s1, c4, s2); \
} \
} else { \
m_quick_two_sum(s0,s0, c3, s1); \
if (s1 != 0.0) { \
m_quick_two_sum(s1,s1, c4, s2); \
} else { \
m_quick_two_sum(s0,s0, c4, s1); \
} \
} \
} \
\
c0 = s0; \
c1 = s1; \
c2 = s2; \
c3 = s3; \
} \
}
%}
! !
!QDouble primitiveFunctions!
%{
/*********** Basic Functions ************/
/* Computes fl(a+b) and err(a+b). Assumes |a| >= |b|. */
inline double
quick_two_sum(double a, double b, double *errPtr) {
double s = a + b;
*errPtr = b - (s - a);
return s;
}
/* Computes fl(a-b) and err(a-b). Assumes |a| >= |b| */
inline double
quick_two_diff(double a, double b, double *errPtr) {
double s = a - b;
*errPtr = (a - s) - b;
return s;
}
/* Computes fl(a+b) and err(a+b). */
inline double
two_sum(double a, double b, double *errPtr) {
double s = a + b;
double bb = s - a;
*errPtr = (a - (s - bb)) + (b - bb);
return s;
}
/* Computes fl(a-b) and err(a-b). */
inline double
two_diff(double a, double b, double *errPtr) {
double s = a - b;
double bb = s - a;
*errPtr = (a - (s - bb)) - (b + bb);
return s;
}
#ifndef QD_FMS
/* Computes high word and lo word of a */
inline void
split(double a, double *hiPtr, double *loPtr) {
double temp;
if (a > _QD_SPLIT_THRESH || a < -_QD_SPLIT_THRESH) {
a *= 3.7252902984619140625e-09; // 2^-28
temp = _QD_SPLITTER * a;
*hiPtr = temp - (temp - a);
*loPtr = a - *hiPtr;
*hiPtr *= 268435456.0; // 2^28
*loPtr *= 268435456.0; // 2^28
} else {
temp = _QD_SPLITTER * a;
*hiPtr = temp - (temp - a);
*loPtr = a - *hiPtr;
}
}
#endif
/* Computes fl(a*b) and err(a*b). */
inline double
two_prod(double a, double b, double *errPtr) {
#ifdef QD_FMS
double p = a * b;
*errPtr = QD_FMS(a, b, p);
return p;
#else
double a_hi, a_lo, b_hi, b_lo;
double p = a * b;
split(a, &a_hi, &a_lo);
split(b, &b_hi, &b_lo);
*errPtr = ((a_hi * b_hi - p) + a_hi * b_lo + a_lo * b_hi) + a_lo * b_lo;
return p;
#endif
}
/* Computes fl(a*a) and err(a*a). Faster than the above method. */
inline double
two_sqr(double a, double *errPtr) {
#ifdef QD_FMS
double p = a * a;
*errPtr = QD_FMS(a, a, p);
return p;
#else
double hi, lo;
double q = a * a;
split(a, &hi, &lo);
*errPtr = ((hi * hi - q) + 2.0 * hi * lo) + lo * lo;
return q;
#endif
}
/* Computes the nearest integer to d. */
inline double
nint(double d) {
if (d == floor(d))
return d;
return floor(d + 0.5);
}
/* Computes the truncated integer. */
inline double
aint(double d) {
return (d >= 0.0) ? floor(d) : ceil(d);
}
inline void
renorm4(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr) {
double s0, s1, s2 = 0.0, s3 = 0.0;
double c0 = *c0Ptr;
if (isinf(c0)) return;
s0 = quick_two_sum(*c2Ptr, *c3Ptr, c3Ptr);
s0 = quick_two_sum(*c1Ptr, s0, c2Ptr);
c0 = quick_two_sum(c0, s0, c1Ptr);
s0 = c0;
s1 = *c1Ptr;
if (s1 != 0.0) {
s1 = quick_two_sum(s1, *c2Ptr, &s2);
if (s2 != 0.0)
s2 = quick_two_sum(s2, *c3Ptr, &s3);
else
s1 = quick_two_sum(s1, *c3Ptr, &s2);
} else {
s0 = quick_two_sum(s0, *c2Ptr, &s1);
if (s1 != 0.0)
s1 = quick_two_sum(s1, *c3Ptr, &s2);
else
s0 = quick_two_sum(s0, *c3Ptr, &s1);
}
*c0Ptr = s0;
*c1Ptr = s1;
*c2Ptr = s2;
*c3Ptr = s3;
}
inline void
renorm5(double *c0Ptr, double *c1Ptr, double *c2Ptr, double *c3Ptr, double *c4Ptr) {
double s0, s1, s2 = 0.0, s3 = 0.0;
if (isinf(*c0Ptr)) return;
s0 = quick_two_sum(*c3Ptr, *c4Ptr, c4Ptr);
s0 = quick_two_sum(*c2Ptr, s0, c3Ptr);
s0 = quick_two_sum(*c1Ptr, s0, c2Ptr);
*c0Ptr = quick_two_sum(*c0Ptr, s0, c1Ptr);
s0 = *c0Ptr;
s1 = *c1Ptr;
s0 = quick_two_sum(*c0Ptr, *c1Ptr, &s1);
if (s1 != 0.0) {
s1 = quick_two_sum(s1, *c2Ptr, &s2);
if (s2 != 0.0) {
s2 =quick_two_sum(s2, *c3Ptr, &s3);
if (s3 != 0.0)
s3 += *c4Ptr;
else
s2 += *c4Ptr;
} else {
s1 = quick_two_sum(s1, *c3Ptr, &s2);
if (s2 != 0.0)
s2 = quick_two_sum(s2, *c4Ptr, &s3);
else
s1 = quick_two_sum(s1, *c4Ptr, &s2);
}
} else {
s0 = quick_two_sum(s0, *c2Ptr, &s1);
if (s1 != 0.0) {
s1 = quick_two_sum(s1, *c3Ptr, &s2);
if (s2 != 0.0)
s2 = quick_two_sum(s2, *c4Ptr, &s3);
else
s1 = quick_two_sum(s1, *c4Ptr, &s2);
} else {
s0 = quick_two_sum(s0, *c3Ptr, &s1);
if (s1 != 0.0)
s1 = quick_two_sum(s1, *c4Ptr, &s2);
else
s0 = quick_two_sum(s0, *c4Ptr, &s1);
}
}
*c0Ptr = s0;
*c1Ptr = s1;
*c2Ptr = s2;
*c3Ptr = s3;
}
inline void
three_sum(double *aPtr, double *bPtr, double *cPtr) {
double t1, t2, t3;
t1 = two_sum(*aPtr, *bPtr, &t2);
*aPtr = two_sum(*cPtr, t1, &t3);
*bPtr = two_sum(t2, t3, cPtr);
}
inline void three_sum2(double *aPtr, double *bPtr, double *cPtr) {
double t1, t2, t3;
t1 = two_sum(*aPtr, *bPtr, &t2);
*aPtr = two_sum(*cPtr, t1, &t3);
*bPtr = t2 + t3;
}
#if 0
/* These are provided to give consistent
interface for double with double-double and quad-double. */
inline void
sincosh(double t, double &sinh_t, double &cosh_t) {
sinh_t = sinh(t);
cosh_t = cosh(t);
}
inline double
sqr(double t) {
return t * t;
}
inline double
to_double(double a) {
return a;
}
inline int
to_int(double a) {
return static_cast<int>(a);
}
#endif
%}
! !
!QDouble class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 2017 by eXept Software AG
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
!
documentation
"
QDoubles represent rational numbers with extended, but still limited precision.
In contrast to Floats (which use the C-compilers native 64bit 'double' format),
QDoubles give you 212 bit or approx. 64 decimal digits of precision.
Representation:
QDoubles use 4 IEEE doubles, each keeping 53 bits of precision.
Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
[author:]
Claus Gittinger
[see also:]
Number
Float ShortFloat Fraction FixedPoint Integer Complex
FloatArray DoubleArray
"
! !
!QDouble class methodsFor:'instance creation'!
basicNew
"return a new quad-precision double - here we return 0.0
Notice that numbers are usually NOT created this way ...
It's implemented here to allow things like binary store & load
of floats. (but even this support will go away eventually, it's not
a good idea to store the bits of a float - the reader might have a
totally different representation - so floats should be
binary stored in a device independent format."
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
ERROR("trying to instantiate a quad double");
#else
OBJ newFloat;
printf("xxx\n");
__qNew(newFloat, sizeof(struct __quadDoubleStruct));
__stx_setClass(newFloat, QDouble);
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = 0.0;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;
RETURN (newFloat);
#endif /* not SCHTEAM */
%}
"
self basicNew
"
"Created: / 12-06-2017 / 16:00:38 / cg"
!
d0:d0 d1:d1 d2:d2 d3:d3
"return a new quad-precision double from individual double components"
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
ERROR("trying to instantiate a quad double");
#else
OBJ newQD;
if (__isFloatLike(d0)
&& __isFloatLike(d1)
&& __isFloatLike(d2)
&& __isFloatLike(d3)) {
__qNew_qdReal(newQD, __floatVal(d0), __floatVal(d1),
__floatVal(d2), __floatVal(d3));
RETURN (newQD);
}
#endif
%}.
self error:'invalid argument'
"
self d0: 3.141592653589793116e+00
d1: 1.224646799147353207e-16
d2: -2.994769809718339666e-33
d3: 1.112454220863365282e-49
"
"Created: / 12-06-2017 / 20:17:14 / cg"
!
fromDoubleArray:aDoubleArray
"return a new quad-precision double from coercing a double array"
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
ERROR("trying to instantiate a quad double");
#else
OBJ newQD;
if (__isDoubleArray(aDoubleArray)) {
__qNew_qdReal(newQD,
__DoubleArrayInstPtr(aDoubleArray)->d_element[0],
__DoubleArrayInstPtr(aDoubleArray)->d_element[1],
__DoubleArrayInstPtr(aDoubleArray)->d_element[2],
__DoubleArrayInstPtr(aDoubleArray)->d_element[3]);
RETURN (newQD);
}
#endif
%}.
self error:'invalid argument'
"
self fromDoubleArray(DoubleArray
with: 3.141592653589793116e+00
with: 1.224646799147353207e-16
with: -2.994769809718339666e-33
with: 1.112454220863365282e-49)
"
"Created: / 12-06-2017 / 18:25:32 / cg"
!
fromFloat:aFloat
"return a new quad-precision double from coercing aFloat"
%{ /* NOCONTEXT */
#ifdef __SCHTEAM__
ERROR("trying to instantiate a quad double");
#else
double dVal;
OBJ newFloat;
if (__isFloatLike(aFloat)) {
dVal = __floatVal(aFloat);
} else if (__isShortFloat(aFloat)) {
dVal = __shortFloatVal(aFloat);
} else {
goto badArg;
}
__qNew(newFloat, sizeof(struct __quadDoubleStruct));
__stx_setClass(newFloat, QDouble);
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = dVal;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;
RETURN (newFloat);
badArg: ;
#endif
%}.
self error:'invalid argument'
"
self fromFloat:1.0
"
"Created: / 12-06-2017 / 16:06:54 / cg"
!
fromInteger:anInteger
"return a new quad-precision double from coercing anInteger"
%{ /* NOCONTEXT */
#ifndef __SCHTEAM__
OBJ newFloat;
if (__isSmallInteger(anInteger)) {
__qNew(newFloat, sizeof(struct __quadDoubleStruct));
__stx_setClass(newFloat, QDouble);
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[0] = (double)(__smallIntegerVal(anInteger));
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[1] = 0.0;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[2] = 0.0;
__QuadDoubleInstPtr(newFloat)->d_quadDoubleValue[3] = 0.0;
RETURN (newFloat);
}
#endif
%}.
^ super fromInteger:anInteger
"
self fromInteger:2
"
"Created: / 12-06-2017 / 16:10:10 / cg"
! !
!QDouble class methodsFor:'constants'!
e
"return the constant e as quad precision double.
(returns approx. 212 bits of precision)"
E isNil ifTrue:[
E := self fromDoubleArray(DoubleArray
with: 2.718281828459045091e+00
with: 1.445646891729250158e-16
with: -2.127717108038176765e-33
with: 1.515630159841218954e-49)
].
^ E
"
self e
"
"Created: / 12-06-2017 / 18:29:36 / cg"
!
ln10
"return the constant e as quad precision double.
(returns approx. 212 bits of precision)"
Ln10 isNil ifTrue:[
Ln10 := self fromDoubleArray(DoubleArray
with: 2.302585092994045901e+00
with: -2.170756223382249351e-16
with: -9.984262454465776570e-33
with: -4.023357454450206379e-49)
].
^ Ln10
"
self ln10
"
"Created: / 12-06-2017 / 18:32:29 / cg"
!
ln2
"return the constant e as quad precision double.
(returns approx. 212 bits of precision)"
Ln2 isNil ifTrue:[
Ln2 := self fromDoubleArray(DoubleArray
with: 6.931471805599452862e-01
with: 2.319046813846299558e-17
with: 5.707708438416212066e-34
with: -3.582432210601811423e-50)
].
^ Ln2
"
self ln2
"
"Created: / 12-06-2017 / 18:31:34 / cg"
!
pi
"return the constant pi as quad precision double.
(returns approx. 212 bits of precision)"
Pi isNil ifTrue:[
Pi := self fromDoubleArray(DoubleArray
with: 3.141592653589793116e+00
with: 1.224646799147353207e-16
with: -2.994769809718339666e-33
with: 1.112454220863365282e-49)
].
^ Pi
"
self pi
"
"Created: / 12-06-2017 / 18:27:13 / cg"
! !
!QDouble class methodsFor:'queries'!
epsilon
"return the maximum relative spacing of instances of mySelf
(i.e. the value-delta of the least significant bit)"
^ Float epsilon
"
Float epsilon
ShortFloat epsilon
QDouble epsilon
"
"Created: / 12-06-2017 / 18:52:44 / cg"
!
numBitsInExponent
"answer the number of bits in the exponent"
^ Float numBitsInExponent
"
1.0 asQDouble class numBitsInExponent
"
"Created: / 12-06-2017 / 11:11:04 / cg"
!
numBitsInMantissa
"answer the number of bits in the mantissa"
^ Float precision * 4
"
1.0 class numBitsInMantissa
1.0 asShortFloat class numBitsInMantissa
1.0 asLongFloat class numBitsInMantissa
1.0 asDDouble class numBitsInMantissa
1.0 asQDouble class numBitsInMantissa
Float numBitsInMantissa
ShortFloat numBitsInMantissa
QDouble numBitsInMantissa
"
"Created: / 12-06-2017 / 11:13:44 / cg"
"Modified: / 12-06-2017 / 18:48:48 / cg"
!
precision
"answer the number of bits in the mantissa"
^ Float precision * 4
"
1.0 class numBitsInMantissa
1.0 asShortFloat class numBitsInMantissa
1.0 asLongFloat class numBitsInMantissa
1.0 asDDouble class numBitsInMantissa
1.0 asQDouble class numBitsInMantissa
Float numBitsInMantissa
ShortFloat numBitsInMantissa
QDouble numBitsInMantissa
QDouble precision
"
"Created: / 12-06-2017 / 18:49:11 / cg"
!
radix
"answer the radix of a Floats exponent
This is an IEEE float, which is represented as binary"
^ Float radix
"Created: / 12-06-2017 / 18:50:04 / cg"
! !
!QDouble methodsFor:'arithmetic'!
* aNumber
"return the product of the receiver and the argument, aNumber"
^ aNumber productFromQDouble:self
"
((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) asDoubleArray
"
"Created: / 13-06-2017 / 01:00:47 / cg"
!
+ aNumber
"return the sum of the receiver and the argument, aNumber"
^ aNumber sumFromQDouble:self
"
((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) asDoubleArray
"
"Created: / 12-06-2017 / 16:17:46 / cg"
"Modified: / 12-06-2017 / 23:06:22 / cg"
!
- aNumber
"return the sum of the receiver and the argument, aNumber"
^ (aNumber negated) sumFromQDouble:self
"
(QDouble fromFloat:1e20) asDoubleArray
((QDouble fromFloat:1e20) - (QDouble fromFloat:1.0)) asDoubleArray
(QDouble fromFloat:1e-20) asDoubleArray
((QDouble fromFloat:1e-20) - (QDouble fromFloat:1.0)) asDoubleArray
((QDouble fromFloat:2.0) - (QDouble fromFloat:1.0)) asDoubleArray
"
"Created: / 12-06-2017 / 23:41:39 / cg"
!
/ aNumber
"return the quotient of the receiver and the argument, aNumber"
^ aNumber quotientFromQDouble:self
"
((QDouble fromFloat:1e20) / (QDouble fromFloat:2.0)) asDoubleArray
"
"Created: / 13-06-2017 / 17:59:09 / cg"
! !
!QDouble methodsFor:'coercing & converting'!
asDoubleArray
^ DoubleArray
with:self d0
with:self d1
with:self d2
with:self d3.
"
(QDouble fromFloat:1.0) asDoubleArray
(QDouble fromFloat:2.0) asDoubleArray
"
"Created: / 12-06-2017 / 18:19:19 / cg"
"Modified (comment): / 13-06-2017 / 17:58:09 / cg"
!
asFloat
^ self d0
"
(QDouble fromFloat:1.0) asFloat
(QDouble fromFloat:2.0) asFloat
"
"Created: / 12-06-2017 / 18:15:27 / cg"
"Modified: / 13-06-2017 / 17:56:50 / cg"
!
coerce:aNumber
"convert the argument aNumber into an instance of the receiver's class and return it."
^ aNumber asQDouble
"Created: / 12-06-2017 / 17:13:47 / cg"
"Modified: / 12-06-2017 / 21:09:06 / cg"
!
generality
"return the generality value - see ArithmeticValue>>retry:coercing:"
^ 95
"Created: / 12-06-2017 / 17:13:14 / cg"
!
negative
^ self d0 negative
"
(QDouble fromFloat:0.0) negative
(QDouble fromFloat:1.0) negative
(QDouble fromFloat:-1.0) negative
"
"Created: / 13-06-2017 / 01:57:39 / cg"
"Modified: / 13-06-2017 / 17:58:26 / cg"
!
positive
^ self d0 positive
"
(QDouble fromFloat:1.0) positive
(QDouble fromFloat:-1.0) positive
"
"Created: / 13-06-2017 / 01:56:53 / cg"
"Modified: / 13-06-2017 / 17:58:41 / cg"
! !
!QDouble methodsFor:'comparing'!
< aNumber
"return true, if the argument, aNumber is greater than the receiver"
^ aNumber lessFromQDouble:self
"Created: / 13-06-2017 / 16:58:53 / cg"
!
= aNumber
"return true, if the argument, aNumber has the same value as than the receiver"
^ aNumber equalFromQDouble:self
"Created: / 13-06-2017 / 17:12:09 / cg"
! !
!QDouble methodsFor:'double dispatching'!
differenceFromFloat:aFloat
"aFloat - self"
^ aFloat + (self negated)
"
1.0 - (QDouble fromFloat:1.0)
1e20 - (QDouble fromFloat:1.0)
(1.0 - (QDouble fromFloat:1.0)) asFloat
(1e20 - (QDouble fromFloat:1.0)) asFloat
(1.0 - (QDouble fromFloat:1.0)) asDoubleArray
(1e20 - (QDouble fromFloat:1.0)) asDoubleArray
(1e20 - (QDouble fromFloat:1.0) + 1e-20) asDoubleArray
"
"Created: / 12-06-2017 / 23:38:05 / cg"
!
differenceFromQDouble:aQDouble
"aQDouble - self"
^ aQDouble + (self negated)
"
1.0 - (QDouble fromFloat:1.0)
1e20 - (QDouble fromFloat:1.0)
(1.0 - (QDouble fromFloat:1.0)) asFloat
(1e20 - (QDouble fromFloat:1.0)) asFloat
(1.0 - (QDouble fromFloat:1.0)) asDoubleArray
(1e20 - (QDouble fromFloat:1.0)) asDoubleArray
(1e20 - (QDouble fromFloat:1.0) + 1e-20) asDoubleArray
"
"Created: / 12-06-2017 / 23:38:19 / cg"
!
equalFromQDouble:aQDouble
%{
if (__Class(aQDouble) == QDouble) {
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
RETURN ((a[0] == b[0]
&& a[1] == b[1]
&& a[2] == b[2]
&& a[3] == b[3]) ? true : false);
}
%}.
^ (aQDouble d0 = self d0)
and:[ (aQDouble d1 = self d1)
and:[ (aQDouble d2 = self d2)
and:[ (aQDouble d3 = self d3) ]]]
"
(QDouble fromFloat:1.0) = (QDouble fromFloat:1.0)
(QDouble fromFloat:1.0) = 1.0
1.0 = (QDouble fromFloat:1.0)
"
"Created: / 13-06-2017 / 03:01:19 / cg"
"Modified: / 13-06-2017 / 18:01:52 / cg"
!
lessFromQDouble:aQDouble
"sent when aQDouble does not know how to compare to the receiver..
Return true if aQDouble < self"
%{
if (__Class(aQDouble) == QDouble) {
double *a = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
double *b = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
// now compare if a < b!
RETURN
((a[0] < b[0] ||
(a[0] == b[0] && (a[1] < b[1] ||
(a[1] == b[1] && (a[2] < b[2] ||
(a[2] == b[2] && a[3] < b[3])))))) ? true : false);
}
%}.
^ super lessFromQDouble:aQDouble
"
(1.0 + 1e-40) > 1.0
((QDouble fromFloat:1.0) + (QDouble fromFloat:1e-40)) > (QDouble fromFloat:1.0)
(QDouble fromFloat:1.0) > (QDouble fromFloat:1.0)
(QDouble fromFloat:1.1) > (QDouble fromFloat:1.0)
(QDouble fromFloat:1.0) > 1.0
(QDouble fromFloat:1.1) > 1.0
1.0 > (QDouble fromFloat:1.0)
"
"Created: / 13-06-2017 / 17:07:47 / cg"
!
productFromFloat:aFloat
%{
if (__isFloatLike(aFloat)) {
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
double b = __floatVal(aFloat);
double p0, p1, p2, p3;
double q0, q1, q2;
double s0, s1, s2, s3, s4;
OBJ newQD;
int savedCV;
fpu_fix_start(&savedCV);
m_two_prod(p0, a[0], b, q0);
m_two_prod(p1, a[1], b, q1);
m_two_prod(p2, a[2], b, q2);
p3 = a[3] * b;
s0 = p0;
m_two_sum(s1, q0, p1, s2);
m_three_sum(s2, q1, p2);
m_three_sum2(q1, q2, p3);
s3 = q1;
s4 = q2 + p2;
m_renorm5(s0, s1, s2, s3, s4);
fpu_fix_end(&savedCV);
__qNew_qdReal(newQD, s0, s1, s2, s3);
RETURN( newQD );
}
%}.
^ super productFromFloat:aFloat.
"
(QDouble fromFloat:1.0) productFromFloat:2.0
((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2.0
((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) productFromFloat:2e20
2.0 * (QDouble fromFloat:1.0)
2.0 * (QDouble fromFloat:3.0)
2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))
(2.0 * ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) - (QDouble fromFloat:1e20) - (QDouble fromFloat:1e20)
(2.0 * (QDouble fromFloat:1.0)) asFloat
(1e20 * (QDouble fromFloat:1.0)) asFloat
(1e20 * (QDouble fromFloat:1.0) * 1e-20) asDoubleArray
"
"Created: / 13-06-2017 / 00:58:56 / cg"
"Modified: / 14-06-2017 / 11:42:57 / cg"
!
productFromQDouble:aQDouble
%{
if (__Class(aQDouble) == QDouble) {
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
OBJ newQD;
// sloppy
double p0, p1, p2, p3, p4, p5;
double q0, q1, q2, q3, q4, q5;
double t0, t1;
double s0, s1, s2;
int savedCV;
fpu_fix_start(&savedCV);
m_two_prod(p0, a[0], b[0], q0);
fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[0], p0, q0);
m_two_prod(p1, a[0], b[1], q1);
m_two_prod(p2, a[1], b[0], q2);
fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[1], p1, q1);
fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[0], p2, q2);
m_two_prod(p3, a[0], b[2], q3);
m_two_prod(p4, a[1], b[1], q4);
m_two_prod(p5, a[2], b[0], q5);
fprintf(stderr, "%f * %f -> %f, %f\n", a[0], b[2], p3, q3);
fprintf(stderr, "%f * %f -> %f, %f\n", a[1], b[1], p4, q4);
fprintf(stderr, "%f * %f -> %f, %f\n", a[2], b[0], p5, q5);
/* Start Accumulation */
m_three_sum(p1, p2, q0);
/* Six-Three Sum of p2, q1, q2, p3, p4, p5. */
m_three_sum(p2, q1, q2);
m_three_sum(p3, p4, p5);
/* compute (s0, s1, s2) = (p2, q1, q2) + (p3, p4, p5). */
m_two_sum(s0, p2, p3, t0);
m_two_sum(s1, q1, p4, t1);
s2 = q2 + p5;
m_two_sum(s1, s1, t0, t0);
s2 += (t0 + t1);
/* O(eps^3) order terms */
s1 += a[0]*b[3] + a[1]*b[2] + a[2]*b[1] + a[3]*b[0] + q0 + q3 + q4 + q5;
m_renorm5(p0, p1, s0, s1, s2);
fpu_fix_end(&savedCV);
__qNew_qdReal(newQD, p0, p1, s0, s1);
RETURN( newQD );
}
%}.
^ super productFromQDouble:aQDouble.
"
(QDouble fromFloat:1.0) * 2.0
2.0 * (QDouble fromFloat:1.0)
(QDouble fromFloat:1.0) * (QDouble fromFloat:2.0)
1e20 * (QDouble fromFloat:1.0)
(2.0 * (QDouble fromFloat:1.0)) asFloat
(1e20 * (QDouble fromFloat:1.0)) asFloat
(1e20 * (QDouble fromFloat:1.0) * 1e-20) asDoubleArray
"
"Created: / 13-06-2017 / 01:06:22 / cg"
"Modified: / 14-06-2017 / 11:43:28 / cg"
!
quotientFromQDouble:aQDouble
"sloppy"
|q0 q1 q2 q3 r|
q0 := self d0 / aQDouble d0.
r := self - (aQDouble * q0).
q1 := r d0 / aQDouble d0.
r := r - (aQDouble * q1).
q2 := r d0 / aQDouble d0.
r := r - (aQDouble * q2).
q3 := r d0 / aQDouble d0.
r := self class d0:q0 d1:q1 d2:q2 d3:q3.
r renorm.
^ r
"
2.0 / (QDouble fromFloat:2.0)
2.0 / (QDouble fromFloat:1.0)
1e20 / (QDouble fromFloat:1.0)
(2.0 / (QDouble fromFloat:1.0)) asFloat
(1e20 / (QDouble fromFloat:1.0)) asFloat
(QDouble fromFloat:2.0) / 2.0
(QDouble fromFloat:1e20) / 2.0
((QDouble fromFloat:1.0) / 2.0) asFloat
((QDouble fromFloat:1e20 / 2.0)) asFloat
((1e20 + (QDouble fromFloat:1.0) + 1e-20) / 2.0) asDoubleArray
"
"Created: / 13-06-2017 / 17:50:35 / cg"
!
sumFromFloat:aFloat
%{
if (__isFloatLike(aFloat)) {
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
double b = __floatVal(aFloat);
double c0, c1, c2, c3;
double e;
OBJ newQD;
int savedCV;
fpu_fix_start(&savedCV);
m_two_sum(c0, a[0], b, e);
m_two_sum(c1 ,a[1], e, e);
m_two_sum(c2, a[2], e, e);
m_two_sum(c3, a[3], e, e);
m_renorm5(c0, c1, c2, c3, e);
fpu_fix_end(&savedCV);
__qNew_qdReal(newQD, c0, c1, c2, c3);
RETURN( newQD );
}
%}.
^ super sumFromFloat:aFloat.
"
1.0 + (QDouble fromFloat:1.0)
1e20 + (QDouble fromFloat:1.0)
(1.0 + (QDouble fromFloat:1.0)) asFloat
(1e20 + (QDouble fromFloat:1.0)) asFloat
(1.0 + (QDouble fromFloat:1.0)) asDoubleArray
(1e20 + (QDouble fromFloat:1.0)) asDoubleArray
(1e20 + (QDouble fromFloat:1.0) + 1e-20) asDoubleArray
"
"Created: / 12-06-2017 / 17:16:41 / cg"
"Modified: / 14-06-2017 / 11:43:47 / cg"
!
sumFromQDouble:aQDouble
%{
if (__Class(aQDouble) == QDouble) {
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
double *b = __QuadDoubleInstPtr(aQDouble)->d_quadDoubleValue;
OBJ newQD;
#ifndef QD_IEEE_ADD
// sloppy_add...
/*
double s0, s1, s2, s3;
double t0, t1, t2, t3;
int savedCV;
fpu_fix_start(&savedCV);
m_two_sum(s0, a[0], b[0], t0);
m_two_sum(s1, a[1], b[1], t1);
m_two_sum(s2, a[2], b[2], t2);
m_two_sum(s3, a[3], b[3], t3);
m_two_sum(s1, s1, t0, t0);
m_three_sum(s2, t0, t1);
m_three_sum2(s3, t0, t2);
t0 = t0 + t1 + t3;
fpu_fix_end(&savedCV);
m_renorm5(s0, s1, s2, s3, t0);
return qd_real(s0, s1, s2, s3, t0);
*/
/* Same as above, but addition re-organized to minimize
data dependency ... unfortunately some compilers are
not very smart to do this automatically */
double s0, s1, s2, s3;
double t0, t1, t2, t3;
double v0, v1, v2, v3;
double u0, u1, u2, u3;
double w0, w1, w2, w3;
int savedCV;
fpu_fix_start(&savedCV);
s0 = a[0] + b[0];
s1 = a[1] + b[1];
s2 = a[2] + b[2];
s3 = a[3] + b[3];
v0 = s0 - a[0];
v1 = s1 - a[1];
v2 = s2 - a[2];
v3 = s3 - a[3];
u0 = s0 - v0;
u1 = s1 - v1;
u2 = s2 - v2;
u3 = s3 - v3;
w0 = a[0] - u0;
w1 = a[1] - u1;
w2 = a[2] - u2;
w3 = a[3] - u3;
u0 = b[0] - v0;
u1 = b[1] - v1;
u2 = b[2] - v2;
u3 = b[3] - v3;
t0 = w0 + u0;
t1 = w1 + u1;
t2 = w2 + u2;
t3 = w3 + u3;
m_two_sum(s1, s1, t0, t0);
m_three_sum(s2, t0, t1);
m_three_sum2(s3, t0, t2);
t0 = t0 + t1 + t3;
/* renormalize */
m_renorm5(s0, s1, s2, s3, t0);
fpu_fix_end(&savedCV);
__qNew_qdReal(newQD, s0, s1, s2, s3);
RETURN(newQD);
#else
// ieee_add...
int i, j, k;
double s, t;
double u, v; /* double-length accumulator */
double x[4] = {0.0, 0.0, 0.0, 0.0};
int savedCV;
fpu_fix_start(&savedCV);
i = j = k = 0;
if (abs(a[i]) > abs(b[j]))
u = a[i++];
else
u = b[j++];
if (abs(a[i]) > abs(b[j]))
v = a[i++];
else
v = b[j++];
u = quick_two_sum(u, v, v);
while (k < 4) {
if (i >= 4 && j >= 4) {
x[k] = u;
if (k < 3)
x[++k] = v;
break;
}
if (i >= 4)
t = b[j++];
else if (j >= 4)
t = a[i++];
else if (abs(a[i]) > abs(b[j])) {
t = a[i++];
} else
t = b[j++];
s = quick_three_accum(u, v, t);
if (s != 0.0) {
x[k++] = s;
}
}
/* add the rest. */
for (k = i; k < 4; k++)
x[3] += a[k];
for (k = j; k < 4; k++)
x[3] += b[k];
m_renorm4(x[0], x[1], x[2], x[3]);
fpu_fix_end(&savedCV);
__qNew_qdReal(newQD, x[0], x[1], x[2], x[3]);
RETURN(newQD);
#endif
}
%}.
^ super sumFromQDouble:aQDouble
"
(QDouble fromFloat:1.0) + (QDouble fromFloat:1.0)
(QDouble fromFloat:1.0) + 1.0
1.0 + (QDouble fromFloat:1.0)
((QDouble fromFloat:1.0) + (QDouble fromFloat:1.0)) asDoubleArray
((QDouble fromFloat:1.0) + 1.0) asDoubleArray
(1.0 + (QDouble fromFloat:1.0)) asDoubleArray
(1e-20 + (QDouble fromFloat:1.0)) asDoubleArray
(1e20 + (QDouble fromFloat:1.0)) asDoubleArray
"
"Created: / 12-06-2017 / 21:15:43 / cg"
"Modified: / 14-06-2017 / 11:44:53 / cg"
! !
!QDouble methodsFor:'inspecting'!
inspectorExtraAttributes
"extra (pseudo instvar) entries to be shown in an inspector."
^ super inspectorExtraAttributes
add:'-{doubles}' ->
[
self asDoubleArray printString
];
yourself
"Created: / 12-06-2017 / 23:43:05 / cg"
! !
!QDouble methodsFor:'mathematical functions'!
floor
"return the receiver truncated towards negative infinity"
%{
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
OBJ newQD;
double x0, x1, x2, x3;
x1 = x2 = x3 = 0.0;
x0 =floor(a[0]);
if (x0 == a[0]) {
x1 = floor(a[1]);
if (x1 == a[1]) {
x2 = floor(a[2]);
if (x2 == a[2]) {
x3 = floor(a[3]);
}
}
m_renorm4(x0, x1, x2, x3);
__qNew_qdReal(newQD, x0, x1, x2, x3);
RETURN( newQD );
}
__qNew_qdReal(newQD, x0, x1, x2, x3);
RETURN( newQD );
%}.
"
(QDouble fromFloat:4.0) floor
(QDouble fromFloat:4.1) floor
(QDouble fromFloat:0.1) floor
(0.1 + (QDouble fromFloat:1.0)) floor
(1e20 + (QDouble fromFloat:1.0)) floor
(QDouble fromFloat:1.5) floor
(QDouble fromFloat:0.5) floor
(QDouble fromFloat:-0.5) floor
(QDouble fromFloat:-1.5) floor
"
"Created: / 13-06-2017 / 01:52:44 / cg"
"Modified (comment): / 13-06-2017 / 17:33:19 / cg"
!
negated
^ self class
d0:(self d0) negated
d1:(self d1) negated
d2:(self d2) negated
d3:(self d3) negated
"
(QDouble fromFloat:1.0) negated
((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0)) negated asDoubleArray
(((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))
+ ((QDouble fromFloat:1e20) + (QDouble fromFloat:1.0))) asDoubleArray
"
"Created: / 12-06-2017 / 20:14:55 / cg"
"Modified (comment): / 12-06-2017 / 23:46:57 / cg"
!
squared
%{
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
double p0, p1, p2, p3, p4, p5;
double q0, q1, q2, q3;
double s0, s1;
double t0, t1;
double t;
OBJ newQD;
m_two_sqr(p0, a[0], q0);
t = 2.0 * a[0];
m_two_prod(p1, t, a[1], q1);
m_two_prod(p2, t, a[2], q2);
m_two_sqr(p3, a[1], q3);
m_two_sum(p1, q0, p1, q0);
m_two_sum(q0, q0, q1, q1);
m_two_sum(p2, p2, p3, p3);
m_two_sum(s0, q0, p2, t0);
m_two_sum(s1, q1, p3, t1);
m_two_sum(s1, s1, t0, t0);
t0 += t1;
m_quick_two_sum(s1, s1, t0, t0);
m_quick_two_sum(p2, s0, s1, t1);
m_quick_two_sum(p3, t1, t0, q0);
p4 = 2.0 * a[0] * a[3];
p5 = 2.0 * a[1] * a[2];
m_two_sum(p4, p4, p5, p5);
m_two_sum(q2, q2, q3, q3);
m_two_sum(t0, p4, q2, t1);
t1 = t1 + p5 + q3;
m_two_sum(p3, p3, t0, p4);
p4 = p4 + q0 + t1;
m_renorm5(p0, p1, p2, p3, p4);
__qNew_qdReal(newQD, p0, p1, s0, s1);
RETURN( newQD );
%}.
"
(QDouble fromFloat:4.0) squared
(1e20 + (QDouble fromFloat:1.0)) squared
"
"Created: / 13-06-2017 / 01:27:58 / cg"
! !
!QDouble methodsFor:'printing & storing'!
printDigitsOn:outStream precision:precision exponentInto:expn
|numDigits r e i d|
numDigits := precision+1. "/ number of digits
r := self abs.
self d0 = 0.0 ifTrue:[
expn value:0.
precision timesRepeat:[ outStream nextPut:$0 ].
^ self.
].
"/ determine approx. exponent
e := self d0 abs log10 floor.
self halt.
e < -300 ifTrue:[
r := r * (10.0 raisedToInteger:300).
r := r / (10.0 raisedToInteger:(e+300)).
] ifFalse:[
e > 300 ifTrue:[
] ifFalse:[
]
].
"
1.2345 asQDouble printDigitsOn:Transcript precision:5 exponentInto:[:e |]
"
"Created: / 13-06-2017 / 17:28:08 / cg"
!
printString
"return a printed representation of the receiver"
self d1 = 0.0 ifTrue:[
^ self d0 printString
].
^ self d0 printString , '...'
"Created: / 12-06-2017 / 23:41:04 / cg"
! !
!QDouble methodsFor:'private accessing'!
d0
"the most significant (and highest valued) 53 bits of precision"
%{
RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[0]) );
%}
"Created: / 12-06-2017 / 20:15:12 / cg"
"Modified (comment): / 13-06-2017 / 17:59:47 / cg"
!
d1
"the next most significant (and next highest valued) 53 bits of precision"
%{
RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[1]) );
%}
"Created: / 12-06-2017 / 20:15:12 / cg"
"Modified (comment): / 13-06-2017 / 18:00:00 / cg"
!
d2
%{
RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[2]) );
%}
"Created: / 12-06-2017 / 20:15:29 / cg"
!
d3
"the least significant (and smallest valued) 53 bits of precision"
%{
RETURN ( __MKFLOAT(__QuadDoubleInstPtr(self)->d_quadDoubleValue[3]) );
%}
"Created: / 12-06-2017 / 20:15:32 / cg"
"Modified (comment): / 13-06-2017 / 18:00:18 / cg"
!
renorm
%{
double *a = __QuadDoubleInstPtr(self)->d_quadDoubleValue;
double c0, c1, c2, c3;
OBJ newQD;
c0 = a[0];
c1 = a[1];
c2 = a[2];
c3 = a[3];
m_renorm4(c0, c1, c2, c3);
a[0] = c0;
a[1] = c1;
a[2] = c2;
a[3] = c3;
RETURN( self );
%}.
^ self error.
"
(QDouble fromFloat:1.0) renorm
"
"Created: / 13-06-2017 / 18:05:33 / cg"
! !
!QDouble class methodsFor:'documentation'!
version
^ '$Header$'
!
version_CVS
^ '$Header$'
! !