#FEATURE by exept
authorClaus Gittinger <cg@exept.de>
Sun, 01 Dec 2019 16:10:10 +0100
changeset 25024 57c1f14cf202
parent 25023 668578d60026
child 25025 330fd8b05eaf
#FEATURE by exept class: LimitedPrecisionReal added: #decimalEmax comment/format in: #decimalPrecision #digitBytes #mantissa #numBitsInMantissa changed: #emax #emin class: LimitedPrecisionReal class added: #decimalEmax comment/format in: #decimalPrecision #defaultPrintPrecision #exactDecimalPrecision #hasSharedInstances #isIEEEFormat #numBitsInIntegerPart #numBitsInMantissa #radix
LimitedPrecisionReal.st
--- a/LimitedPrecisionReal.st	Sun Dec 01 05:54:02 2019 +0100
+++ b/LimitedPrecisionReal.st	Sun Dec 01 16:10:10 2019 +0100
@@ -650,16 +650,35 @@
 
 !LimitedPrecisionReal class methodsFor:'queries'!
 
+decimalEmax
+    "Answer how many digits of accuracy this class supports"
+
+    ^ (self emax / (10.0 log:self radix))
+
+    "
+     ShortFloat emax   
+     ShortFloat decimalEmax  
+
+     Float emax  
+     Float emin
+     Float decimalEmax  
+
+     LongFloat emax        
+     LongFloat emin        
+     LongFloat decimalEmax  
+    "
+!
+
 decimalPrecision
     "return the number of valid decimal digits"
 
-    ^ ((self precision + 1) / (10.0 log:self radix)) 
-        "/ ceiling   "use ceiling, since the last decimal digit contains some precision"
+    ^ (self precision / (10.0 log:self radix)) 
         floor   "use floor, since the last decimal digit is usually wrong"
 
     "
+     HalfFloat decimalPrecision  -> 3
      ShortFloat decimalPrecision -> 7
-     Float decimalPrecision      -> 16
+     Float decimalPrecision      -> 16 
      LongFloat decimalPrecision  -> 19
      QuadFloat decimalPrecision  -> 34
      OctaFloat decimalPrecision  -> 71
@@ -675,9 +694,11 @@
     ^ 6
 
     "
-     ShortFloat defaultPrintPrecision 
-     Float defaultPrintPrecision      
-     LongFloat defaultPrintPrecision  
+     ShortFloat defaultPrintPrecision -> 5 
+     Float defaultPrintPrecision      -> 6 
+     LongFloat defaultPrintPrecision  -> 8 
+     QDouble defaultPrintPrecision    -> 10
+     LargeFloat defaultPrintPrecision -> 12
     "
 
     "Created: / 17-06-2017 / 02:56:43 / cg"
@@ -696,7 +717,7 @@
     ^ ((self precision) / (10.0 log:self radix))
 
     "
-     HalfFloat exactDecimalPrecision  -> 7.224719895935548004
+     HalfFloat exactDecimalPrecision  -> 3.612359947967774002
      ShortFloat exactDecimalPrecision -> 7.224719895935548004
      Float exactDecimalPrecision      -> 15.95458977019100184      
      LongFloat exactDecimalPrecision  -> 19.26591972249479468
@@ -709,14 +730,12 @@
 !
 
 hasSharedInstances
-    "return true if this class has shared instances, that is, instances
-     with the same value are identical.
+    "return true if this class can share instances when stored binary, 
+     that is, instances with the same value can be stored by reference.
      Although not really shared, floats should be treated
      so, to be independent of the implementation of the arithmetic methods."
 
     ^ true
-
-
 !
 
 isAbstract
@@ -736,8 +755,8 @@
      to convert their floats into this (which is only relevant,
      if such a machine wants to send floats as binary to some other
      machine).
-     Machines with non-IEEE format are VAXed and IBM370-type systems
-     (among others). Today, most systems use IEEE format floats."
+     Machines with non-IEEE format are VAXen and IBM370-type systems
+     (among others). Today, every system uses IEEE format floats."
 
 %{
 #ifdef __s390__
@@ -756,6 +775,7 @@
 
 numBitsInIntegerPart
     "answer the number of bits in the integer part of the mantissa.
+     I.e. 0 is returned if there is a hidden bit, 1 if not.
      Most floating point formats are normalized to get rid of the extra bit."
 
     ^ 0
@@ -764,8 +784,8 @@
 !
 
 numBitsInMantissa
-    "return the number of bits in the mantissa
-     (typically 1 less than the precision due to the hidden bit)"
+    "return the number of bits in the mantissa (the significant)
+     Typically the precision is 1 more than the significant due to the hidden bit"
 
     ^ self subclassResponsibility
 !
@@ -788,7 +808,7 @@
 !
 
 radix
-    "return the radix (base)"
+    "answer the radix of my instance's exponent"
 
     self subclassResponsibility
 
@@ -935,7 +955,7 @@
 !LimitedPrecisionReal methodsFor:'bytes access'!
 
 digitBytes
-    "answer the float's digit bytes im IEEE format.
+    "answer the float's digit bytes imnIEEE format.
      Use the native machine byte ordering."
 
     |sz "{ Class:SmallInteger }"
@@ -1364,15 +1384,36 @@
 
 !LimitedPrecisionReal methodsFor:'queries'!
 
+decimalEmax
+    "Answer how many digits of exponent-accuracy this class supports"
+
+    ^ self class decimalEmax
+
+    "
+     1.0 asShortFloat emax   
+     1.0 asShortFloat decimalEmax  
+
+     1.0 asFloat emax  
+     1.0 asFloat emin
+     1.0 asFloat decimalEmax  
+
+     1.0 asLongFloat emax        
+     1.0 asLongFloat emin        
+     1.0 asLongFloat decimalEmax  
+    "
+
+    "Created: / 10-10-2017 / 15:46:43 / cg"
+!
+
 decimalPrecision
-    "Answer how many digits of accuracy this class supports"
+    "Answer how many significant digits (accuracy) this class supports"
 
     ^ self class decimalPrecision 
 
     "
-     1.0 asFloat decimalPrecision
-     1.0 asLongFloat decimalPrecision
      1.0 asShortFloat decimalPrecision
+     1.0 asFloat decimalPrecision   
+     1.0 asLongFloat decimalPrecision     
      1.0 asQDouble decimalPrecision
      1.0 asLargeFloat decimalPrecision
     "
@@ -1406,7 +1447,7 @@
     "return the largest exponent.
      The computation below assumes standard IEEE format"
 
-    ^ (1 << (self numBitsInExponent-1))
+    ^ (1 << (self numBitsInExponent-1)) - 1
 
     "
      Float emax       -> 1023
@@ -1416,11 +1457,11 @@
      OctaFloat emax   -> 262143
      QDouble emax     -> 1023
     "
-
 !
 
 emin
-    ^ 3 - (1 << (self numBitsInExponent-1))
+    ^ 1 - self emax
+
 !
 
 exponent
@@ -1584,11 +1625,15 @@
 
 mantissa
     "extract a normalized float's mantissa.
+     That is a float of the same type as the receiver,
+     such that:
+        (2 ^ f exponent) * f mantissa = f
      This is a fallback for systems which do not provide frexp in their math lib,
      and also for error reporting (NaN or Inf)."
      
-    |shifty expPart numBytes numBitsInMantissa maskMantissa numBitsInExponent maskExponent
-     biasExponent numIntegerBits fractionPart|
+    |m numBitsInMantissa numBitsInExponent maskExponent numIntegerBits
+     bits "maskMantissa shifty expPart numBytes 
+     biasExponent  fractionPart"|
 
     (self isNaN or:[self isInfinite]) ifTrue:[
         ^ self class
@@ -1597,28 +1642,52 @@
             selector:#mantissa
             arguments:#()
             errorString:'bad receiver (Inf or NaN) in mantissa'
-    ].    
+    ].
+    numBitsInExponent := self numBitsInExponent. 
+    numBitsInMantissa := self numBitsInMantissa.
+    numIntegerBits := self numBitsInIntegerPart.
+
+    maskExponent := (1 bitShift:numBitsInExponent) - 1.
 
-    "Extract the bits of an IEEE anySize float "
-    numBytes := self basicSize.
-    numBitsInMantissa := self numBitsInMantissa. maskMantissa := (1 bitShift:numBitsInMantissa) - 1.
-    numBitsInExponent := self numBitsInExponent. maskExponent := (1 bitShift:numBitsInExponent) - 1.
-    numIntegerBits := self numBitsInIntegerPart.
-    biasExponent := maskExponent bitShift:-1.
+    "/ Extract the bits of the IEEE float, mask out everything except the characteristic
+    "/ and the sign; set the exponent to eBias
+    m := self copy.
+    bits := LargeInteger digitBytes:self digitBytes.
+    "/ mask out the exponent
+    bits := bits bitClear:(maskExponent bitShift:numBitsInMantissa + numIntegerBits).
+    "/ set to zero
+    bits := bits bitOr:(self eBias - 1 bitShift:numBitsInMantissa + numIntegerBits).
+    1 to:self basicSize do:[:i | m basicAt:i put:(bits digitAt:i)].
+    ^ m.
 
-    shifty := LargeInteger basicNew numberOfDigits:numBytes.
-    UninterpretedBytes isBigEndian ifTrue:[
-        1 to:numBytes do:[:i | shifty digitAt:(numBytes+1-i) put:(self basicAt:i)].
-    ] ifFalse:[
-        1 to:numBytes do:[:i | shifty digitAt:i put:(self basicAt:i)].
-    ].
-
-    " Extract the sign and the biased exponent "
-    expPart := (shifty rightShift:numBitsInMantissa) bitAnd: maskExponent.
-
-    " Extract fractional part; answer 0 if this is a true 0.0 value "
-    fractionPart := shifty bitAnd:maskMantissa.
-    ^ fractionPart.
+"/    "Extract the bits of an IEEE anySize float "
+"/    numBytes := self basicSize.
+"/    numBitsInMantissa := maskMantissa := (1 bitShift:numBitsInMantissa) - 1.
+"/    biasExponent := maskExponent bitShift:-1.
+"/
+"/    shifty := LargeInteger basicNew numberOfDigits:numBytes.
+"/    UninterpretedBytes isBigEndian ifTrue:[
+"/        1 to:numBytes do:[:i | shifty digitAt:(numBytes+1-i) put:(self basicAt:i)].
+"/    ] ifFalse:[
+"/        1 to:numBytes do:[:i | shifty digitAt:i put:(self basicAt:i)].
+"/    ].
+"/
+"/    expPart := (shifty rightShift:numBitsInMantissa) bitAnd: maskExponent.
+"/
+"/    "/ Extract fractional part; answer 0 if this is a true 0.0 value
+"/    fractionPart := shifty bitAnd:maskMantissa.
+"/    fractionPart == 0 ifTrue:[
+"/        expPart == 0 ifTrue:[
+"/            ^ 0
+"/        ]
+"/    ].
+"/
+"/    "/ or in any hidden bit
+"/    numIntegerBits == 0 ifTrue:[
+"/        fractionPart := fractionPart bitOr:(1 bitShift:numBitsInMantissa).
+"/    ].
+"/    "/ should I make it a limited precision real?
+"/    ^ fractionPart / (1 bitShift:numBitsInMantissa).
     
     "
      0.3 asFloat mantissa  
@@ -1716,15 +1785,20 @@
 !
 
 numBitsInMantissa
-    "answer the number of bits in the mantissa (any hidden bits are not counted).
+    "answer the number of bits in the mantissa (the significant)
+     any hidden bits are not counted.
+     11 for half precision:
+        seeeemmm mmmmmmmm
+     23 for single precision:
+        seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
      52 for double precision:
         seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
-     23 for single precision:
-        seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
      64 for longfloat precision (x86):
         00000000 00000000 seeeeeee eeeeeeee immmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
      112 for longfloat precision (sparc):
         seeeeeee eeeeeeee mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm...
+     112 for quadfloat precision:
+        seeeeeee eeeeeeee mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm...
     "
 
     ^ self class numBitsInMantissa