--- a/LongFloat.st Wed Jan 23 10:08:55 2013 +0000
+++ b/LongFloat.st Mon Jan 28 21:53:19 2013 +0000
@@ -38,6 +38,10 @@
extern errno;
#endif
+#if !defined (WIN32)
+# include <locale.h>
+#endif
+
#if defined (_AIX)
# include <float.h>
#endif
@@ -234,46 +238,46 @@
(thus, longFloat code is not guaranteed to be portable).
NO GARANTY:
- on systems which do not support 'long doubles', LongFloats are (silently)
- represented as 'doubles'.
+ on systems which do not support 'long doubles', LongFloats are (silently)
+ represented as 'doubles'.
Representation:
- gcc-i386:
- 80bit extended IEE floats stored in in 96bits (12bytes);
- 64 bit mantissa,
- 16 bit exponent,
- 19 decimal digits (approx)
-
- borland-i386 (WIN32):
- 80bit extended IEE floats stored in in 80bits (10bytes);
- 64 bit mantissa,
- 16 bit exponent,
- 19 decimal digits (approx)
-
- gcc-sparc:
- 128bit quad IEE floats (16bytes);
- 112 bit mantissa,
- 16 bit exponent,
- 34 decimal digits (approx)
+ gcc-i386:
+ 80bit extended IEE floats stored in in 96bits (12bytes);
+ 64 bit mantissa,
+ 16 bit exponent,
+ 19 decimal digits (approx)
+
+ borland-i386 (WIN32):
+ 80bit extended IEE floats stored in in 80bits (10bytes);
+ 64 bit mantissa,
+ 16 bit exponent,
+ 19 decimal digits (approx)
+
+ gcc-sparc:
+ 128bit quad IEE floats (16bytes);
+ 112 bit mantissa,
+ 16 bit exponent,
+ 34 decimal digits (approx)
Mixed mode arithmetic:
- longFloat op longFloat -> longFloat
- longFloat op fix -> longFloat
- longFloat op fraction -> longFloat
- longFloat op integer -> longFloat
- longFloat op shortFloat -> longFloat
- longFloat op float -> longFloat
- longFloat op complex -> complex
+ longFloat op longFloat -> longFloat
+ longFloat op fix -> longFloat
+ longFloat op fraction -> longFloat
+ longFloat op integer -> longFloat
+ longFloat op shortFloat -> longFloat
+ longFloat op float -> longFloat
+ longFloat op complex -> complex
Range and Precision of Storage Formats: see LimitedPrecisionReal >> documentation
[author:]
- Claus Gittinger
+ Claus Gittinger
[see also:]
- Number
- Float ShortFloat Fraction FixedPoint Integer Complex
- FloatArray DoubleArray
+ Number
+ Float ShortFloat Fraction FixedPoint Integer Complex
+ FloatArray DoubleArray
"
! !
@@ -403,11 +407,11 @@
"do not write a literal constant here - we cannot depend on the underlying C-compiler here..."
Pi isNil ifTrue:[
- DefaultPrintFormat := '.19'. "/ 19 valid digits
-
- "/ enough digits for 128bit IEEE quads
- Pi := self readFrom:'3.1415926535897932384626433832795029'. "/ 3.14159265358979323846264338327950288419716939937510582097494459q
- E := self readFrom:'2.7182818284590452353602874713526625'.
+ DefaultPrintFormat := '.19'. "/ 19 valid digits
+
+ "/ enough digits for 128bit IEEE quads
+ Pi := self readFrom:'3.1415926535897932384626433832795029'. "/ 3.14159265358979323846264338327950288419716939937510582097494459q
+ E := self readFrom:'2.7182818284590452353602874713526625'.
].
"
@@ -595,25 +599,25 @@
LONGFLOAT result, val;
if (__isSmallInteger(aNumber)) {
- val = (LONGFLOAT)(__intVal(aNumber));
+ val = (LONGFLOAT)(__intVal(aNumber));
doMul:
- result = __longFloatVal(self) * val;
- __qMKLFLOAT(newFloat, result);
- RETURN ( newFloat );
+ result = __longFloatVal(self) * val;
+ __qMKLFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (aNumber != nil) {
- if (__qIsLongFloat(aNumber)) {
- val = __longFloatVal(aNumber);
- goto doMul;
- }
- if (__qIsFloatLike(aNumber)) {
- val = (LONGFLOAT)(__floatVal(aNumber));
- goto doMul;
- }
- if (__qIsShortFloat(aNumber)) {
- val = (LONGFLOAT)(__shortFloatVal(aNumber));
- goto doMul;
- }
+ if (__qIsLongFloat(aNumber)) {
+ val = __longFloatVal(aNumber);
+ goto doMul;
+ }
+ if (__qIsFloatLike(aNumber)) {
+ val = (LONGFLOAT)(__floatVal(aNumber));
+ goto doMul;
+ }
+ if (__qIsShortFloat(aNumber)) {
+ val = (LONGFLOAT)(__shortFloatVal(aNumber));
+ goto doMul;
+ }
}
%}.
^ aNumber productFromLongFloat:self
@@ -628,25 +632,25 @@
LONGFLOAT result, val;
if (__isSmallInteger(aNumber)) {
- val = (LONGFLOAT)(__intVal(aNumber));
+ val = (LONGFLOAT)(__intVal(aNumber));
doAdd:
- result = __longFloatVal(self) + val;
- __qMKLFLOAT(newFloat, result);
- RETURN ( newFloat );
+ result = __longFloatVal(self) + val;
+ __qMKLFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (aNumber != nil) {
- if (__qIsLongFloat(aNumber)) {
- val = __longFloatVal(aNumber);
- goto doAdd;
- }
- if (__qIsFloatLike(aNumber)) {
- val = (LONGFLOAT)(__floatVal(aNumber));
- goto doAdd;
- }
- if (__qIsShortFloat(aNumber)) {
- val = (LONGFLOAT)(__shortFloatVal(aNumber));
- goto doAdd;
- }
+ if (__qIsLongFloat(aNumber)) {
+ val = __longFloatVal(aNumber);
+ goto doAdd;
+ }
+ if (__qIsFloatLike(aNumber)) {
+ val = (LONGFLOAT)(__floatVal(aNumber));
+ goto doAdd;
+ }
+ if (__qIsShortFloat(aNumber)) {
+ val = (LONGFLOAT)(__shortFloatVal(aNumber));
+ goto doAdd;
+ }
}
%}.
^ aNumber sumFromLongFloat:self
@@ -661,25 +665,25 @@
LONGFLOAT result, val;
if (__isSmallInteger(aNumber)) {
- val = (LONGFLOAT)(__intVal(aNumber));
+ val = (LONGFLOAT)(__intVal(aNumber));
doSub:
- result = __longFloatVal(self) - val;
- __qMKLFLOAT(newFloat, result);
- RETURN ( newFloat );
+ result = __longFloatVal(self) - val;
+ __qMKLFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (aNumber != nil) {
- if (__qIsLongFloat(aNumber)) {
- val = __longFloatVal(aNumber);
- goto doSub;
- }
- if (__qIsFloatLike(aNumber)) {
- val = (LONGFLOAT)(__floatVal(aNumber));
- goto doSub;
- }
- if (__qIsShortFloat(aNumber)) {
- val = (LONGFLOAT)(__shortFloatVal(aNumber));
- goto doSub;
- }
+ if (__qIsLongFloat(aNumber)) {
+ val = __longFloatVal(aNumber);
+ goto doSub;
+ }
+ if (__qIsFloatLike(aNumber)) {
+ val = (LONGFLOAT)(__floatVal(aNumber));
+ goto doSub;
+ }
+ if (__qIsShortFloat(aNumber)) {
+ val = (LONGFLOAT)(__shortFloatVal(aNumber));
+ goto doSub;
+ }
}
%}.
^ aNumber differenceFromLongFloat:self
@@ -694,39 +698,86 @@
LONGFLOAT result, val;
if (__isSmallInteger(aNumber)) {
- val = (LONGFLOAT)(__intVal(aNumber));
+ val = (LONGFLOAT)(__intVal(aNumber));
doDiv:
- if (val == 0.0) goto badArg;
-
- result = __longFloatVal(self) / val;
- __qMKLFLOAT(newFloat, result);
- RETURN ( newFloat );
+ if (val == 0.0) goto badArg;
+
+ result = __longFloatVal(self) / val;
+ __qMKLFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (aNumber != nil) {
- if (__qIsLongFloat(aNumber)) {
- val = __longFloatVal(aNumber);
- goto doDiv;
- }
- if (__qIsFloatLike(aNumber)) {
- val = (LONGFLOAT)(__floatVal(aNumber));
- goto doDiv;
- }
- if (__qIsShortFloat(aNumber)) {
- val = (LONGFLOAT)(__shortFloatVal(aNumber));
- goto doDiv;
- }
+ if (__qIsLongFloat(aNumber)) {
+ val = __longFloatVal(aNumber);
+ goto doDiv;
+ }
+ if (__qIsFloatLike(aNumber)) {
+ val = (LONGFLOAT)(__floatVal(aNumber));
+ goto doDiv;
+ }
+ if (__qIsShortFloat(aNumber)) {
+ val = (LONGFLOAT)(__shortFloatVal(aNumber));
+ goto doDiv;
+ }
}
badArg: ;
%}.
((aNumber == 0) or:[aNumber = 0.0]) ifTrue:[
- "
- No, you shalt not divide by zero
- "
- ^ ZeroDivide raiseRequestWith:thisContext.
+ "
+ No, you shalt not divide by zero
+ "
+ ^ ZeroDivide raiseRequestWith:thisContext.
].
^ aNumber quotientFromLongFloat:self
!
+rem: aNumber
+ "return the floating point remainder of the receiver and the argument, aNumber"
+
+%{ /* NOCONTEXT */
+
+ /*
+ * notice:
+ * the following inline code handles some common cases,
+ * and exists as an optimization, to speed up those cases.
+ *
+ * Conceptionally, (and for most other argument types),
+ * mixed arithmetic is implemented by double dispatching
+ * (see the message send at the bottom)
+ */
+ OBJ newFloat;
+ LONGFLOAT result, val;
+
+ if (__isSmallInteger(aNumber)) {
+ if (aNumber != __mkSmallInteger(0)) {
+ val = (LONGFLOAT)__intVal(aNumber);
+ if (val == 0.0) goto badArg;
+computeResult:
+ result = fmodl(__longFloatVal(self), val) ;
+ __qMKLFLOAT(newFloat, result);
+ RETURN ( newFloat );
+ }
+ } else if (__isFloatLike(aNumber)) {
+ val = (LONGFLOAT)__floatVal(aNumber);
+ goto computeResult;
+ } else if (__isShortFloat(aNumber)) {
+ val = (LONGFLOAT)__shortFloatVal(aNumber);
+ goto computeResult;
+ } else if (__isLongFloat(aNumber)) {
+ val = __longFloatVal(aNumber);
+ goto computeResult;
+ }
+badArg: ;
+%}.
+ ((aNumber == 0) or:[aNumber = 0.0]) ifTrue:[
+ "
+ No, you shalt not divide by zero
+ "
+ ^ ZeroDivide raiseRequestWith:thisContext.
+ ].
+ ^ aNumber remainderFromLongFloat:self
+!
+
abs
"return the absolute value of the receiver
reimplemented here for speed"
@@ -774,25 +825,25 @@
LONGFLOAT result, val;
if (__isSmallInteger(aNumber)) {
- val = (LONGFLOAT)(__intVal(aNumber));
+ val = (LONGFLOAT)(__intVal(aNumber));
doDiv:
- result = __longFloatVal(self) / val;
- __qMKLFLOAT(newFloat, result);
- RETURN ( newFloat );
+ result = __longFloatVal(self) / val;
+ __qMKLFLOAT(newFloat, result);
+ RETURN ( newFloat );
}
if (aNumber != nil) {
- if (__qIsLongFloat(aNumber)) {
- val = __longFloatVal(aNumber);
- goto doDiv;
- }
- if (__qIsShortFloat(aNumber)) {
- val = (LONGFLOAT)(__shortFloatVal(aNumber));
- goto doDiv;
- }
- if (__qIsFloatLike(aNumber)) {
- val = (LONGFLOAT)(__floatVal(aNumber));
- goto doDiv;
- }
+ if (__qIsLongFloat(aNumber)) {
+ val = __longFloatVal(aNumber);
+ goto doDiv;
+ }
+ if (__qIsShortFloat(aNumber)) {
+ val = (LONGFLOAT)(__shortFloatVal(aNumber));
+ goto doDiv;
+ }
+ if (__qIsFloatLike(aNumber)) {
+ val = (LONGFLOAT)(__floatVal(aNumber));
+ goto doDiv;
+ }
}
%}.
^ aNumber quotientFromLongFloat:self
@@ -1341,9 +1392,9 @@
int len ;
if (__isStringLike(@global(DefaultPrintFormat))) {
- fmt = (char *) __stringVal(@global(DefaultPrintFormat));
+ fmt = (char *) __stringVal(@global(DefaultPrintFormat));
} else {
- fmt = ".19";
+ fmt = ".19";
}
/*
* build a printf format string
@@ -1352,12 +1403,12 @@
strncpy(fmtBuffer+1, fmt, 10);
if (sizeof(LONGFLOAT) == sizeof(double)) {
#ifdef SYSV
- strcat(fmtBuffer, "lg");
+ strcat(fmtBuffer, "lg");
#else
- strcat(fmtBuffer, "G");
+ strcat(fmtBuffer, "G");
#endif
} else {
- strcat(fmtBuffer, "LG");
+ strcat(fmtBuffer, "LG");
}
/*
@@ -1370,33 +1421,33 @@
__END_PROTECT_REGISTERS__
if (len >= 0 && len < sizeof(buffer)-3) {
- /*
- * kludge to make integral float f prints as "f.0" (not as "f" as printf does)
- * (i.e. look if string contains '.' or 'e' and append '.0' if not)
- */
- for (cp = buffer; *cp; cp++) {
- if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break;
- }
- if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) {
- if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
- *cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
- } else {
- *cp++ = '.';
- }
- *cp++ = '0';
- *cp = '\0';
- } else {
- if (cp && (*cp == '.')) {
- if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
- *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
- }
- }
- }
-
- s = __MKSTRING(buffer);
- if (s != nil) {
- RETURN (s);
- }
+ /*
+ * kludge to make integral float f prints as "f.0" (not as "f" as printf does)
+ * (i.e. look if string contains '.' or 'e' and append '.0' if not)
+ */
+ for (cp = buffer; *cp; cp++) {
+ if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break;
+ }
+ if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) {
+ if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
+ *cp++ = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
+ } else {
+ *cp++ = '.';
+ }
+ *cp++ = '0';
+ *cp = '\0';
+ } else {
+ if (cp && (*cp == '.')) {
+ if (__isCharacter(@global(DecimalPointCharacterForPrinting))) {
+ *cp = __intVal(__characterVal(@global(DecimalPointCharacterForPrinting)));
+ }
+ }
+ }
+
+ s = __MKSTRING(buffer);
+ if (s != nil) {
+ RETURN (s);
+ }
}
%}.
"
@@ -1409,24 +1460,24 @@
^ ObjectMemory allocationFailureSignal raise.
"
- 1.234 asLongFloat printString.
- 1.0 asLongFloat printString.
- 1e10 asLongFloat printString.
- 1.2e3 asLongFloat printString.
- 1.2e30 asLongFloat printString.
- (1.0 uncheckedDivide:0) asLongFloat printString.
- (0.0 uncheckedDivide:0) asLongFloat printString.
- self pi printString.
-
- DecimalPointCharacterForPrinting := $,.
- 1.234 asLongFloat printString.
- 1.0 asLongFloat printString.
- 1e10 asLongFloat printString.
- 1.2e3 asLongFloat printString.
- 1.2e30 asLongFloat printString.
- (1.0 uncheckedDivide:0) asLongFloat printString.
- (0.0 uncheckedDivide:0) asLongFloat printString.
- DecimalPointCharacterForPrinting := $.
+ 1.234 asLongFloat printString.
+ 1.0 asLongFloat printString.
+ 1e10 asLongFloat printString.
+ 1.2e3 asLongFloat printString.
+ 1.2e30 asLongFloat printString.
+ (1.0 uncheckedDivide:0) asLongFloat printString.
+ (0.0 uncheckedDivide:0) asLongFloat printString.
+ self pi printString.
+
+ DecimalPointCharacterForPrinting := $,.
+ 1.234 asLongFloat printString.
+ 1.0 asLongFloat printString.
+ 1e10 asLongFloat printString.
+ 1.2e3 asLongFloat printString.
+ 1.2e30 asLongFloat printString.
+ (1.0 uncheckedDivide:0) asLongFloat printString.
+ (0.0 uncheckedDivide:0) asLongFloat printString.
+ DecimalPointCharacterForPrinting := $.
"
!
@@ -1447,23 +1498,23 @@
int len;
if (__isStringLike(formatString)) {
- /*
- * actually only needed on sparc: since thisContext is
- * in a global register, which gets destroyed by printf,
- * manually save it here - very stupid ...
- */
- __BEGIN_PROTECT_REGISTERS__
-
- len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __longFloatVal(self));
-
- __END_PROTECT_REGISTERS__
-
- if (len < 0) goto fail;
-
- s = __MKSTRING_L(buffer, len);
- if (s != nil) {
- RETURN (s);
- }
+ /*
+ * actually only needed on sparc: since thisContext is
+ * in a global register, which gets destroyed by printf,
+ * manually save it here - very stupid ...
+ */
+ __BEGIN_PROTECT_REGISTERS__
+
+ len = snprintf(buffer, sizeof(buffer), __stringVal(formatString), __longFloatVal(self));
+
+ __END_PROTECT_REGISTERS__
+
+ if (len < 0) goto fail;
+
+ s = __MKSTRING_L(buffer, len);
+ if (s != nil) {
+ RETURN (s);
+ }
}
fail: ;
%}.
@@ -1491,41 +1542,41 @@
int len;
char *fmtBuffer;
- if (sizeof(LONGFLOAT) == sizeof(double)) {
-#ifdef SYSV
- fmtBuffer = "%.19lg";
-#else
- fmtBuffer = "%.19G";
-#endif
- } else {
- fmtBuffer = "%.19LG";
- }
/*
* build a printf format string
*/
+ if (sizeof(LONGFLOAT) == sizeof(double)) {
+#ifdef SYSV
+ fmtBuffer = "%.19lg";
+#else
+ fmtBuffer = "%.19G";
+#endif
+ } else {
+ fmtBuffer = "%.19LG";
+ }
__BEGIN_PROTECT_REGISTERS__
len = snprintf(buffer, sizeof(buffer), fmtBuffer, __longFloatVal(self));
__END_PROTECT_REGISTERS__
if (len >= 0 && len < sizeof(buffer)-3) {
- /*
- * kludge to make integral float f prints as "f.0" (not as "f" as printf does)
- * (i.e. look if string contains '.' or 'e' and append '.0' if not)
- */
- for (cp = buffer; *cp; cp++) {
- if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break;
- }
- if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) {
- *cp++ = '.';
- *cp++ = '0';
- *cp = '\0';
- }
-
- s = __MKSTRING(buffer);
- if (s != nil) {
- RETURN (s);
- }
+ /*
+ * kludge to make integral float f prints as "f.0" (not as "f" as printf does)
+ * (i.e. look if string contains '.' or 'e' and append '.0' if not)
+ */
+ for (cp = buffer; *cp; cp++) {
+ if ((*cp == '.') || (*cp == ',') || (*cp == 'E') || (*cp == 'e')) break;
+ }
+ if (!*cp && (cp[-1] >= '0') && (cp[-1] <= '9')) {
+ *cp++ = '.';
+ *cp++ = '0';
+ *cp = '\0';
+ }
+
+ s = __MKSTRING(buffer);
+ if (s != nil) {
+ RETURN (s);
+ }
}
%}.
"
@@ -1538,26 +1589,26 @@
^ ObjectMemory allocationFailureSignal raise.
"
- 1.0 asLongFloat storeString
- 1.234 asLongFloat storeString
- 1e10 asLongFloat storeString
- 1.2e3 asLongFloat storeString
- 1.2e30 asLongFloat storeString
- LongFloat pi asLongFloat storeString
- (1.0 uncheckedDivide:0) asLongFloat storeString
- (0.0 uncheckedDivide:0) asLongFloat storeString
+ 1.0 asLongFloat storeString
+ 1.234 asLongFloat storeString
+ 1e10 asLongFloat storeString
+ 1.2e3 asLongFloat storeString
+ 1.2e30 asLongFloat storeString
+ LongFloat pi asLongFloat storeString
+ (1.0 uncheckedDivide:0) asLongFloat storeString
+ (0.0 uncheckedDivide:0) asLongFloat storeString
notice that the storeString is NOT affected by DecimalPointCharacterForPrinting:
- DecimalPointCharacterForPrinting := $,.
- 1.234 asLongFloat storeString.
- 1.0 asLongFloat storeString.
- 1e10 asLongFloat storeString.
- 1.2e3 asLongFloat storeString.
- 1.2e30 asLongFloat storeString.
- (1.0 uncheckedDivide:0) asLongFloat storeString.
- (0.0 uncheckedDivide:0) asLongFloat storeString.
- DecimalPointCharacterForPrinting := $.
+ DecimalPointCharacterForPrinting := $,.
+ 1.234 asLongFloat storeString.
+ 1.0 asLongFloat storeString.
+ 1e10 asLongFloat storeString.
+ 1.2e3 asLongFloat storeString.
+ 1.2e30 asLongFloat storeString.
+ (1.0 uncheckedDivide:0) asLongFloat storeString.
+ (0.0 uncheckedDivide:0) asLongFloat storeString.
+ DecimalPointCharacterForPrinting := $.
"
! !
@@ -2540,11 +2591,11 @@
!LongFloat class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.71 2012-12-17 18:28:24 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.73 2013-01-23 18:02:20 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.71 2012-12-17 18:28:24 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/LongFloat.st,v 1.73 2013-01-23 18:02:20 cg Exp $'
! !