#QUALITY by cg
authorClaus Gittinger <cg@exept.de>
Tue, 28 May 2019 08:32:36 +0200
changeset 2248 55f846f2839b
parent 2247 78f2b8da16ec
child 2249 098f9577859b
#QUALITY by cg class: RegressionTests::LargeFloatTest class definition added:82 methods class: RegressionTests::LargeFloatTest class added: #documentation #version #version_CVS
RegressionTests__LargeFloatTest.st
--- a/RegressionTests__LargeFloatTest.st	Mon May 27 16:56:05 2019 +0200
+++ b/RegressionTests__LargeFloatTest.st	Tue May 28 08:32:36 2019 +0200
@@ -1,585 +1,808 @@
 "{ Encoding: utf8 }"
 
-"{ Package: 'stx:goodies/regression' }"
-
 "{ NameSpace: RegressionTests }"
 
 TestCase subclass:#LargeFloatTest
-	instanceVariableNames:''
+	instanceVariableNames:'zero one two half minusOne minusTwo huge'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'tests-Regression-Numbers'
 !
 
-
-!LargeFloatTest methodsFor:'helpers'!
-
-actualPrecisionOf:aFloatClass
-    "get the actual number of valid bits in the mantissa.
-     This does a real test (i.e. does not believe the compiled-in ifdefs)"
-
-    |one half x count|
-
-    one := aFloatClass unity.  "/ 1.0 in this class
-    
-    "/ largefloats have infinite precition (potentially)
-    one precision isFinite ifFalse:[^ Infinity positive].
-    
-    half := one coerce:0.5.
-    x := one.
-    count := 0.
-
-    [ one + x ~= one] whileTrue:[
-        x := x * half.
-        count := count + 1.
-    ].
-    ^ count
-
-    "
-     self basicNew actualPrecisionOf:ShortFloat
-     self basicNew actualPrecisionOf:Float
-     self basicNew actualPrecisionOf:LongFloat
-    "
-
-    "Modified: / 10-10-2017 / 12:50:21 / cg"
-! !
-
-!LargeFloatTest methodsFor:'tests'!
-
-test01_Nan
-    "NaN in all avaliable formats."
-
-    |shouldBeNaN|
-
-    shouldBeNaN := 0.0 asLargeFloat uncheckedDivide: 0.0.
-    self assert:( shouldBeNaN isMemberOf:LargeFloat ).
-    self assert:( shouldBeNaN isNaN ).
-    self assert:( shouldBeNaN isFinite not ).
-
-
-    shouldBeNaN := 0.0 asLargeFloat uncheckedDivide: 0.0.
-    self assert:( shouldBeNaN asShortFloat isNaN ).
-    self assert:( shouldBeNaN asLongFloat isNaN ).
-    self should:[ shouldBeNaN asInteger ] raise:DomainError.
-
-
-    self assert:( shouldBeNaN + 1 ) isNaN.
-    self assert:( shouldBeNaN + 1.0 ) isNaN.
-    self assert:( shouldBeNaN + 1.0 asShortFloat ) isNaN.
-    self assert:( shouldBeNaN + 1.0 asLongFloat ) isNaN.
-    self assert:( shouldBeNaN + 1.0 asLargeFloat ) isNaN.
-
-    self assert:( 1 + shouldBeNaN ) isNaN.
-    self assert:( 1.0 + shouldBeNaN ) isNaN.
-    self assert:( 1.0 asShortFloat + shouldBeNaN ) isNaN.
-    self assert:( 1.0 asLongFloat + shouldBeNaN ) isNaN.
-    self assert:( 1.0 asLargeFloat + shouldBeNaN ) isNaN.
-
-    self assert:( shouldBeNaN - 1 ) isNaN.
-    self assert:( shouldBeNaN - 1.0 ) isNaN.
-    self assert:( shouldBeNaN - 1.0 asShortFloat ) isNaN.
-    self assert:( shouldBeNaN - 1.0 asLongFloat ) isNaN.
-    self assert:( shouldBeNaN - 1.0 asLargeFloat ) isNaN.
-
-    self assert:( 1 - shouldBeNaN ) isNaN.
-    self assert:( 1.0 - shouldBeNaN ) isNaN.
-    self assert:( 1.0 asShortFloat - shouldBeNaN ) isNaN.
-    self assert:( 1.0 asLongFloat - shouldBeNaN ) isNaN.
-    self assert:( 1.0 asLargeFloat - shouldBeNaN ) isNaN.
-
-    "
-     self basicNew test01_Nan
-    "
-!
-
-test02_Inf
-    "Infinity in all avaliable formats."
-
-    |check posInf negInf|
-
-    check :=
-	[:v1 :v2 |
-
-	    posInf := v1 uncheckedDivide: v2.
-
-	    self assert:( posInf isMemberOf:v1 class ).
-	    self assert:( posInf isNaN not ).
-	    self assert:( posInf isFinite not ).
-	    self assert:( posInf isInfinite ).
-	    self assert:( posInf positive ).
-	    self assert:( posInf negative not ).
-	    self assert:( posInf isNegativeInfinity not).
-	    self assert:( posInf isPositiveInfinity ).
-
-	    negInf := v1 negated uncheckedDivide: v2.
-
-	    self assert:( negInf isMemberOf:v1 class ).
-	    self assert:( negInf isNaN not ).
-	    self assert:( negInf isFinite not ).
-	    self assert:( negInf isInfinite ).
-	    self assert:( negInf positive not).
-	    self assert:( negInf negative ).
-	    self assert:( negInf isNegativeInfinity ).
-	    self assert:( negInf isPositiveInfinity not ).
-
-	    self assert:( negInf + negInf = negInf).
-	    self assert:( posInf + posInf = posInf).
-	    self assert:( negInf + posInf) isNaN.
-	    self assert:( posInf + negInf) isNaN.
-
-	    self assert:( negInf - posInf = negInf).
-	    self assert:( negInf - negInf) isNaN.
-	    self assert:( posInf - negInf = posInf).
-	    self assert:( posInf - posInf) isNaN.
-
-	    self assert:( posInf + v1) = posInf.
-	    self assert:( posInf - v1) = posInf.
-	    self assert:( negInf + v1) = negInf.
-	    self assert:( negInf - v1) = negInf.
-	].
-
-    check value: 1.0 asLargeFloat value: 0.0 asLargeFloat.
-
-    "
-     self basicNew test02_Inf
-    "
-!
-
-test03_Conversion
-    self assert:( 1.0 asLargeFloat asTrueFraction == 1 ).
-    self assert:( 2.0 asLargeFloat asTrueFraction == 2 ).
-    self assert:( 4.0 asLargeFloat asTrueFraction == 4 ).
-    self assert:( 8.0 asLargeFloat asTrueFraction == 8 ).
-    self assert:( 16.0 asLargeFloat asTrueFraction == 16 ).
-    self assert:( 1048576.0 asLargeFloat asTrueFraction == 1048576 ).
-    self assert:( 0.5 asLargeFloat asTrueFraction = (1/2) ).
-    self assert:( 0.25 asLargeFloat asTrueFraction = (1/4) ).
-    self assert:( 0.125 asLargeFloat asTrueFraction = (1/8) ).
-
-    "
-     self basicNew test03_Conversion
-    "
-
-    "Modified: / 10-10-2017 / 15:27:24 / cg"
-!
-
-test04_Arithmetic
-    self assert:( 1.0 asLargeFloat + 1.0 ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat + 1.0 asShortFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat + 1.0 asFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat + 1 ) class == LargeFloat.
-
-    self assert:( 1.0 asLargeFloat - 1.0 ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat - 1.0 asShortFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat - 1.0 asFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat - 1 ) class == LargeFloat.
-
-    self assert:( 1.0 asLargeFloat * 1.0 ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat * 1.0 asShortFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat * 1.0 asFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat * 1 ) class == LargeFloat.
-
-    self assert:( 1.0 asLargeFloat / 1.0 ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat / 1.0 asShortFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat / 1.0 asFloat ) class == LargeFloat.
-    self assert:( 1.0 asLargeFloat / 1 ) class == LargeFloat.
-
-    self assert:( 1.0 asLargeFloat + 1.0 asLargeFloat) = 2.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat + 0.0 asLargeFloat) = 1.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat + 2.0 asLargeFloat) = 3.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat + 3.0 asLargeFloat) = 4.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat + 1.0 asLargeFloat negated) = 0.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat + 2.0 asLargeFloat negated) = -1.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat + -1.0 asLargeFloat negated) = 2.0 asLargeFloat.
-
-    self assert:( 1.0 asLargeFloat - 1.0 asLargeFloat) = 0.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat - 0.0 asLargeFloat) = 1.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat - 2.0 asLargeFloat) = -1.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat - 3.0 asLargeFloat) = -2.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat - 1.0 asLargeFloat negated) = 2.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat - 2.0 asLargeFloat negated) = 3.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat - -1.0 asLargeFloat negated) = 0.0 asLargeFloat.
-
-    self assert:( 1.0 asLargeFloat * 1.0 asLargeFloat) = 1.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat * 0.0 asLargeFloat) = 0.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat * 2.0 asLargeFloat) = 2.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat * 3.0 asLargeFloat) = 3.0 asLargeFloat.
-    self assert:( 2.0 asLargeFloat * 3.0 asLargeFloat) = 6.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat * 1.0 asLargeFloat negated) = -1.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat * 2.0 asLargeFloat negated) = -2.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat * -1.0 asLargeFloat negated) = 1.0 asLargeFloat.
-
-    self assert:( 1.0 asLargeFloat / 1.0 asLargeFloat) = 1.0 asLargeFloat.
-    self assert:( 1.0 asLargeFloat / 2.0 asLargeFloat) = 0.5 asLargeFloat.
-    self assert:( 3.0 asLargeFloat / 2.0 asLargeFloat) = (3/2) asLargeFloat.
-
-    "
-     self basicNew test04_Arithmetic
-    "
-!
-
-test04b_Division
-    |epsilon|
-    
-"/    self assert:( 1.0 asLargeFloat / 1.0 ) class == LargeFloat.
-"/    self assert:( 1.0 asLargeFloat / 1.0 asShortFloat ) class == LargeFloat.
-"/    self assert:( 1.0 asLargeFloat / 1.0 asFloat ) class == LargeFloat.
-"/    self assert:( 1.0 asLargeFloat / 1 ) class == LargeFloat.
-"/
-"/    self assert:( 1.0 asLargeFloat / 1.0 asLargeFloat) = 1.0 asLargeFloat.
-"/    self assert:( 1.0 asLargeFloat / 2.0 asLargeFloat) = 0.5 asLargeFloat.
-"/    self assert:( 3.0 asLargeFloat / 2.0 asLargeFloat) = (3/2) asLargeFloat.
-
-    self assert:( 0.25 asLargeFloat / 2.0 asLargeFloat) = 0.125 asLargeFloat.
-
-    self assert:( 1.0 asLargeFloat / 2.0 asLargeFloat) = 0.5 asLargeFloat.
-    self assert:( 1.0 asLargeFloat / 4.0 asLargeFloat) = 0.25 asLargeFloat.
-    self assert:( 1.0 asLargeFloat / 8.0 asLargeFloat) = 0.125 asLargeFloat.
-
-    "/ the precision of a largeInteger is the precision of its origin
-    epsilon := 1.0 asLargeFloat epsilon.
-    
-    self assert:(( 1.0 asLargeFloat / 5.0 asLargeFloat) isAlmostEqualTo:0.2 withError:epsilon).
-    self assert:(( 1.0 asLargeFloat / 10.0 asLargeFloat) isAlmostEqualTo:0.1 withError:epsilon).
-
-    "/ the precision of a largeInteger is the precision of its origin
-    epsilon := 1.0 / (2 raisedTo:(LargeFloat defaultPrecision - 1)).
-    epsilon := 0.00000000000000001. "/ -- fails
-    epsilon := 0.0000000000000001.
-
-    self assert:(( 1 asLargeFloat / 5 asLargeFloat) isAlmostEqualTo:0.2 withError:epsilon).
-    self assert:(( 1 asLargeFloat / 10 asLargeFloat) isAlmostEqualTo:0.1 withError:epsilon).
-
-    "
-     self basicNew test04b_Division
-    "
-
-    "Created: / 10-10-2017 / 15:13:28 / cg"
-!
-
-test04c_Multiplication
-    self assert:((1 asLargeFloat to:50 asLargeFloat) product) = (50 factorial)
-
-    "
-     self basicNew test04c_Multiplication
-    "
-
-    "Created: / 10-10-2017 / 16:22:56 / cg"
+LargeFloatTest comment:'Test to check FloatingPoint numbers with arbitrary precision'
 !
 
-test05_Comparing
-    |compiledMethod|
-
-    self assert:( 2.0 asLargeFloat = 2 ).
-    self assert:( 2.0 asLargeFloat = 2.0 asShortFloat ).
-    self assert:( 2.0 asLargeFloat = 2.0 ).
-    self assert:( 2.0 asLargeFloat = 2.0 asLongFloat ).
-    self assert:( 2.0 asLargeFloat = 2.0 asLargeFloat ).
-
-    self assert:( 2.0 asLargeFloat = 3 ) not.
-    self assert:( 2.0 asLargeFloat = 3.0 asShortFloat ) not.
-    self assert:( 2.0 asLargeFloat = 3.0 ) not.
-    self assert:( 2.0 asLargeFloat = 3.0 asLongFloat ) not.
-    self assert:( 2.0 asLargeFloat = 3.0 asLargeFloat ) not.
-
-    self assert:( 2.0 asLargeFloat < 3 ).
-    self assert:( 2.0 asLargeFloat < 3.0 asShortFloat ).
-    self assert:( 2.0 asLargeFloat < 3.0 asLargeFloat ).
-
-    "/ test fails when stc code, jit code works
-    compiledMethod := self class compiledMethodAt:#'test05_Comparing'.
-    (compiledMethod notNil 
-    and:[compiledMethod byteCode isNil]) ifTrue:[ 
-        "/ stc-compiled code handles not slightly differently
-        "/ listed compares will fail
-        'LargeFloatTest >> test05_Comparing test with 200000000000000000000 or similiar are skipped due would fail when stc code' infoPrintCR.
-    ] ifFalse:[    
-        self assert:( 200000000000000000000.0 asLargeFloat < 200000000000100000000 ).
-        self assert:( 200000000000000000000 < 200001000000000000000.0 asLargeFloat ).
-
-        self assert:( 200000000000000000000.0 asLargeFloat <= 200000000000000000001 ).
-        self assert:( 200000000000000000000.0 asLargeFloat <= 200000000000000000000 ).
-
-        self assert:( 200000000000000000000 <= 200001000000000000000.0 asLargeFloat ).
-        self assert:( 200000000000000000000 <= 200000000000000000000.0 asLargeFloat ).  
-    ].
-
-
-    self assert:( 2.0 asLargeFloat <= 3 ).
-    self assert:( 2.0 asLargeFloat <= 2 ).
-    self assert:( 2.0 asLargeFloat <= 3.0 asShortFloat ).
-    self assert:( 2.0 asLargeFloat <= 2.0 asShortFloat ).
-    self assert:( 2.0 asLargeFloat <= 3.0 asLongFloat ).
-    self assert:( 2.0 asLargeFloat <= 2.0 asLongFloat ).
-    self assert:( 2.0 asLargeFloat <= 3.0 asLargeFloat ).
-    self assert:( 2.0 asLargeFloat <= 2.0 asLargeFloat ).
-
-    1 to:1000 do:[:a |
-        0 to:a-1 do:[:b |
-            |fA fB|
-            
-            self assert:(b < a).
-            self assert:(b <= a).
-            self assert:(a > b).
-            self assert:(a >= b).
-            self assert:(a ~= b).
-            self assert:(a = b) not.
-
-            fA := a asLargeFloat.
-            fB := b asLargeFloat.
-            self assert:(fB < fA).
-            self assert:(fB <= fA).
-            self assert:(fA > fB).
-            self assert:(fA >= fB).
-            self assert:(fA ~= fB).
-            self assert:(fA = fB) not.
-        ].
-    ].
-
-    1 asLargeFloat to:1000 asLargeFloat do:[:fA |
-        0 asLargeFloat to:fA-1 do:[:fB |
-            self assert:(fB < fA).
-            self assert:(fB <= fA).
-            self assert:(fA > fB).
-            self assert:(fA >= fB).
-            self assert:(fA ~= fB).
-            self assert:(fA = fB) not.
-        ].
-    ].
-
-    "
-     self basicNew test05_Comparing
-    "
-
-    "Modified (format): / 10-10-2017 / 15:20:37 / cg"
-!
-
-test06_MiscMath
-    #(
-        sqrt       100000.0
-        sqrt       1000.0
-        sqrt       100.0
-        sqrt       100
-        sqrt       2.0
-        sqrt       1.0
-        sqrt       0.5
-        sqrt       0.0
-        
-"/        exp        0.5
-"/        ln         100.0
-"/        ln         10.0
-"/        ln         0.5
-        
-"/        log10      100.0
-"/        log10      10.0
-"/        log10      0.5
-
-"/        sin        0.5
-"/        cos        0.5
-"/        tan        0.5
-"/        arcSin     0.5
-"/        arcCos     0.5
-"/        arcTan     0.5
-
-        sinh       0.5
-        cosh       0.5
-        tanh       0.5
-"/        arcSinh    0.5
-"/        arcCosh    1.5
-"/        arcTanh    0.5
-    ) pairWiseDo:[:op :arg |
-"/        self assert:( arg asLargeFloat perform:op ) class == LargeFloat.
-        ( arg asLargeFloat perform:op ) class == LargeFloat ifFalse:[
-            Transcript showCR:'warning: missing LargeFloat function: ' , op.
-        ].
-
-        self assert:( (arg perform:op) - (arg asLargeFloat perform:op) ) < 0.000001.
-        self assert:( (arg perform:op) - (arg perform:op) asLargeFloat ) < 0.000001.
-    ].
-
-    "
-     self basicNew test06_MiscMath
-    "
-
-    "Modified: / 10-10-2017 / 12:54:52 / cg"
-!
-
-test07_Truncation
-    |check|
-
-    check := [:num |
-	self assert:( num fractionPart + num truncated ) = num.
-	self assert:( num fractionPart + num truncated ) class == num class.
-    ].
-
-    check value:1.6 asLargeFloat.
-    check value:-1.6 asLargeFloat.
-
-
-    self assert:( 1.6 asLargeFloat ceiling ) = 2.
-
-    self assert:( 1.6 asLargeFloat ceilingAsFloat ) = 2.0 asLargeFloat.
-    self assert:( 1.6 asLargeFloat ceilingAsFloat ) class == LargeFloat.
-
-
-    self assert:( 1.6 asLargeFloat floor ) = 1.
-
-    self assert:( 1.6 asLargeFloat floorAsFloat ) = 1.0 asLargeFloat.
-    self assert:( 1.6 asLargeFloat floorAsFloat ) class == LargeFloat.
-
-
-    self assert:( 0.4 asLargeFloat rounded ) class == SmallInteger.
-    self assert:( 0.4 asLargeFloat rounded = 0 ).
-    self assert:( 0.5 asLargeFloat rounded = 1 ).
-    self assert:( 0.6 asLargeFloat rounded = 1 ).
-    self assert:( -0.4 asLargeFloat rounded = 0 ).
-    self assert:( -0.5 asLargeFloat rounded = -1 ).
-    self assert:( -0.6 asLargeFloat rounded = -1 ).
-
-    self assert:( 0.4 asLargeFloat roundedAsFloat ) class == LargeFloat.
-    self assert:( 0.4 asLargeFloat roundedAsFloat  = 0.0 ).
-    self assert:( 0.5 asLargeFloat roundedAsFloat  = 1.0 ).
-    self assert:( 0.6 asLargeFloat roundedAsFloat  = 1.0 ).
-    self assert:( -0.4 asLargeFloat roundedAsFloat = 0 ).
-    self assert:( -0.5 asLargeFloat roundedAsFloat = -1.0 ).
-    self assert:( -0.6 asLargeFloat roundedAsFloat = -1.0 ).
-
-    self assert:( 0.4 truncated ) class == SmallInteger.
-    self assert:( 0.4 truncated = 0 ).
-    self assert:( 0.5 truncated = 0 ).
-    self assert:( 0.6 truncated = 0 ).
-    self assert:( -0.4 truncated = 0 ).
-    self assert:( -0.5 truncated = 0 ).
-    self assert:( -0.6 truncated = 0 ).
-
-    self assert:( 0.4 truncatedAsFloat ) class == Float.
-    self assert:( 0.4 truncatedAsFloat  = 0.0 ).
-    self assert:( 0.5 truncatedAsFloat  = 0.0 ).
-    self assert:( 0.6 truncatedAsFloat  = 0.0 ).
-    self assert:( -0.4 truncatedAsFloat = 0 ).
-    self assert:( -0.5 truncatedAsFloat = 0.0 ).
-    self assert:( -0.6 truncatedAsFloat = 0.0 ).
-
-    self assert:( 0.4 asShortFloat truncated ) class == SmallInteger.
-    self assert:( 0.4 asShortFloat truncated = 0 ).
-    self assert:( 0.5 asShortFloat truncated = 0 ).
-    self assert:( 0.6 asShortFloat truncated = 0 ).
-    self assert:( -0.4 asShortFloat truncated = 0 ).
-    self assert:( -0.5 asShortFloat truncated = 0 ).
-    self assert:( -0.6 asShortFloat truncated = 0 ).
-
-    self assert:( 0.4 asShortFloat truncatedAsFloat ) class == ShortFloat.
-    self assert:( 0.4 asShortFloat truncatedAsFloat  = 0.0 ).
-    self assert:( 0.5 asShortFloat truncatedAsFloat  = 0.0 ).
-    self assert:( 0.6 asShortFloat truncatedAsFloat  = 0.0 ).
-    self assert:( -0.4 asShortFloat truncatedAsFloat = 0 ).
-    self assert:( -0.5 asShortFloat truncatedAsFloat = 0.0 ).
-    self assert:( -0.6 asShortFloat truncatedAsFloat = 0.0 ).
-
-    self assert:( 0.4 asLargeFloat truncated ) class == SmallInteger.
-    self assert:( 0.4 asLargeFloat truncated = 0 ).
-    self assert:( 0.5 asLargeFloat truncated = 0 ).
-    self assert:( 0.6 asLargeFloat truncated = 0 ).
-    self assert:( -0.4 asLargeFloat truncated = 0 ).
-    self assert:( -0.5 asLargeFloat truncated = 0 ).
-    self assert:( -0.6 asLargeFloat truncated = 0 ).
-
-    self assert:( 0.4 asLargeFloat truncatedAsFloat ) class == LargeFloat.
-    self assert:( 0.4 asLargeFloat truncatedAsFloat  = 0.0 ).
-    self assert:( 0.5 asLargeFloat truncatedAsFloat  = 0.0 ).
-    self assert:( 0.6 asLargeFloat truncatedAsFloat  = 0.0 ).
-    self assert:( -0.4 asLargeFloat truncatedAsFloat = 0 ).
-    self assert:( -0.5 asLargeFloat truncatedAsFloat = 0.0 ).
-    self assert:( -0.6 asLargeFloat truncatedAsFloat = 0.0 ).
-
-    "
-     self basicNew test07_Truncation
-    "
-!
-
-test08_Representation
-    self assert:( LargeFloat new
-                    mantissa:1 exponent:1) printString = '2.0'.
-
-    self assert:( 0.0 asLargeFloat mantissa == 0).
-    self assert:( 0.0 asLargeFloat exponent == 0).
-
-    self assert:( 1.0 asLargeFloat mantissa == 1).
-    self assert:( 1.0 asLargeFloat exponent == 0).
-
-    self assert:( 2.0 asLargeFloat mantissa == 1).
-    self assert:( 2.0 asLargeFloat exponent == 1).
-
-    self assert:( 4.0 asLargeFloat mantissa == 1).
-    self assert:( 4.0 asLargeFloat exponent == 2).
-
-    self assert:( 5.0 asLargeFloat mantissa == 5).
-    self assert:( 5.0 asLargeFloat exponent == 0).
-
-    self assert:( 7.0 asLargeFloat mantissa == 7).
-    self assert:( 7.0 asLargeFloat exponent == 0).
-
-    self assert:( 14.0 asLargeFloat mantissa == 7).
-    self assert:( 14.0 asLargeFloat exponent == 1).
-
-    self assert:( 0.5 asLargeFloat mantissa == 1).
-    self assert:( 0.5 asLargeFloat exponent == -1).
-
-    self assert:( 0.25 asLargeFloat mantissa == 1).
-    self assert:( 0.25 asLargeFloat exponent == -2).
-
-    "
-     self basicNew test08_Representation
-    "
-
-    "Modified (format): / 10-10-2017 / 15:28:08 / cg"
-!
-
-test09_Testing
-    self assert:( 0.0 asLargeFloat isZero ).
-    self assert:( 1.0 asLargeFloat isZero not ).
-
-    self assert:( 0.0 asLargeFloat negative not ).
-    self assert:( 1.0 asLargeFloat negative not ).
-    self assert:( -1.0 asLargeFloat negative ).
-
-    self assert:( 0.0 asLargeFloat positive ).
-    self assert:( 1.0 asLargeFloat positive ).
-    self assert:( -1.0 asLargeFloat positive not ).
-
-    self assert:( 0.0 asLargeFloat strictlyPositive not ).
-    self assert:( 1.0 asLargeFloat strictlyPositive ).
-    self assert:( -1.0 asLargeFloat strictlyPositive not ).
-
-    self assert:( 0.0 asLargeFloat sign == 0 ).
-    self assert:( 1.0 asLargeFloat sign == 1 ).
-    self assert:( -1.0 asLargeFloat sign == -1 ).
-
-    "
-     self basicNew test09_Testing
-    "
-!
-
-test10_Printing
-    |fac50|
-
-    fac50 := (1 asLargeFloat to:50 asLargeFloat) product.
-    self assert:(fac50 printString = (50 factorial printString , '.0'))
-    
-    "
-     self basicNew test10_Printing
-    "
-
-    "Created: / 10-10-2017 / 16:22:15 / cg"
-! !
-
 !LargeFloatTest class methodsFor:'documentation'!
 
-version
-    ^ '$Header$'
+documentation
+"
+    documentation to be added.
+
+    [author:]
+        Claus Gittinger
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+
+"
+! !
+
+
+!LargeFloatTest methodsFor:'private'!
+
+checkDoublePrecision: y forFunction: func precision: n
+	"Check that doubling the precision, then rounding would lead to the same result"
+	
+	| anLargeFloat singlePrecisionResult |
+	anLargeFloat _ y asLargeFloatPrecision: n.
+	singlePrecisionResult _ anLargeFloat perform: func.
+	self checkThatEvaluatingFunction: func toDoublePrecisionOf: anLargeFloat equals: singlePrecisionResult.
+	^singlePrecisionResult
+!
+
+checkDoublePrecisionSerie: serie forFunction: func 
+	^self checkDoublePrecisionSerie: serie forFunction: func precision: Float precision
+!
+
+checkDoublePrecisionSerie: serie forFunction: func precision: n
+	serie do: [:y | self checkDoublePrecision: y forFunction: func precision: n]
+!
+
+checkDoublePrecisionSerieVsFloat: serie forFunction: func 
+	^serie reject: [:y |
+		| farb |
+		farb _ self checkDoublePrecision: y forFunction: func precision: Float precision.
+		[(y asFloat perform: func) = farb] on: ZeroDivide do: [false]]
+!
+
+checkThatEvaluatingFunction: func toDoublePrecisionOf: anLargeFloat equals: singlePrecisionResult
+	"Check that doubling the precision, then rounding would lead to the same result"
+	
+	| n doublePrecision doublePrecisionResult lowBits |
+	n _ anLargeFloat precision.
+	doublePrecision _ anLargeFloat asLargeFloatPrecision: n * 2.
+	doublePrecisionResult _ doublePrecision perform: func.
+	
+	"Note: the test must be guarded against double rounding error condition.
+	For example, suppose the single precision is 4 bits, double precision 8 bits.
+	If exact result is 1.001 | 0111 | 1001...
+	Then the nearest double is rounded to upper 1.001 | 1000
+	Then the nearest single to the double is rounded to upper 1.010
+	But the nearest single to the exact result should have been 1.001
+	To avoid this, we have to check if the second rounding is an exact tie"
+	doublePrecisionResult normalize.
+	lowBits _ doublePrecisionResult mantissa bitAnd: 1<<n-1.
+	lowBits = (1<<(n-1))
+		ifTrue:
+			["double precision is ambiguous - retry with quadruple..."
+			^self checkThatEvaluatingFunction: func toQuadruplePrecisionOf: anLargeFloat equals: singlePrecisionResult].
+	self assert: ((doublePrecisionResult asLargeFloatPrecision: n)- singlePrecisionResult) isZero
+	
+!
+
+checkThatEvaluatingFunction: func toQuadruplePrecisionOf: anLargeFloat equals: singlePrecisionResult
+	"Check that quadrupling the precision, then rounding would lead to the same result"
+	
+	| n quadruplePrecision quadruplePrecisionResult lowBits |
+	n _ anLargeFloat precision.
+	quadruplePrecision _ anLargeFloat asLargeFloatPrecision: n * 4.
+	quadruplePrecisionResult _ quadruplePrecision perform: func.
+	
+	"Guard against double rounding error condition (exact tie)"
+	quadruplePrecisionResult normalize.
+	lowBits _ quadruplePrecisionResult mantissa bitAnd: 1<<(3*n)-1.
+	lowBits = (1<<(3*n-1))
+		ifTrue:
+			["quadruple precision is ambiguous - give up..."
+			^self].
+	self assert: ((quadruplePrecisionResult asLargeFloatPrecision: n)- singlePrecisionResult) isZero.
+! !
+
+!LargeFloatTest methodsFor:'setup'!
+
+setUp
+        zero := 0 asLargeFloatPrecision: 53.
+        one := 1 asLargeFloatPrecision: 53.
+        two := 2 asLargeFloatPrecision: 53.
+        half := (1/2) asLargeFloatPrecision: 53.
+        minusOne := -1 asLargeFloatPrecision: 53.
+        minusTwo := -2 asLargeFloatPrecision: 53.
+        huge := (10 raisedTo: 100) asLargeFloatPrecision: 53.
+
+    "Modified (format): / 27-05-2019 / 08:25:42 / Claus Gittinger"
+! !
+
+!LargeFloatTest methodsFor:'testing-arithmetic'!
+
+testDivide
+        | serie |
+        serie := {1. 2. 3. 5. 6. 7. 9. 10. 11. 12. 19. 243. 
+                 10 raisedTo: Float precision + 1. 
+                 Float precision factorial. 
+                 Float pi.
+                }.
+        serie do: [:num |
+                | nf na |
+                nf := num asFloat.
+                na := num asLargeFloatPrecision: Float precision.
+                serie do:[:den |
+                        | df da ff fa |
+                        df := den asFloat.
+                        da := den asLargeFloatPrecision: Float precision.
+                        ff := nf / df.
+                        fa := na / da.
+                        self assert: ff = fa]].
+
+    "Modified (format): / 27-05-2019 / 10:13:11 / Claus Gittinger"
+!
+
+testIEEEArithmeticVersusFloat
+	| floats ops ref new |
+	floats _ #(1.0 2.0 3.0 5.0 10.0 2r1.0e52 2r1.0e53 2r1.0e54 0.5 0.25 2r1.0e-52 2r1.0e-53 2r1.0e-54 1.0e60 0.1 1.1e-30 1.0e-60) copyWith: Float pi.
+	ops _ #(#+ #- #* #/ #= #< #> ).
+	ops
+		do: [:op | floats
+				do: [:f1 | floats
+						do: [:f2 | 
+							ref _ f1 perform: op with: f2.
+							new _ (f1 asLargeFloatPrecision: 53)
+										perform: op
+										with: (f2 asLargeFloatPrecision: 53).
+							self assert: new = ref]]]
+!
+
+testIEEEArithmeticVersusIntegerAndFraction
+	"check that results are the same as IEEE 754 accelerated hardware
+	WARNING: this cannot be the case for denormalized numbers (gradual underflow)
+	because our exponent is unlimited"
+
+	| floats ops ref new intAndFractions |
+	floats _ #(1.0e0 2.0e0 3.0e0 5.0e0 10.0e0) 
+				, (#(52 53 54 -52 -53 -54) collect: [:e | 1.0e0 timesTwoPower: e]) 
+					, #(0.5e0 0.25e0 1.0e60 0.1e0 1.1e-30 1.0e-60) copyWith: Float pi.
+	intAndFractions _ #(1 3 5 10 12345678901234567890 -1 -22 -3) copyWith: 7/9.
+	intAndFractions _ intAndFractions , (intAndFractions collect: [:e | e reciprocal]).
+	
+	ops _ 1/10 = 0.1
+		ifTrue: [#(#+ #- #* #/)]
+		ifFalse: [#(#+ #- #* #/ #= #< #>)]. "BEWARE: LargeFloat compare exactly, Float don't, unless http://bugs.squeak.org/view.php?id=3374"
+	ops do: 
+			[:op | 
+			floats do: 
+					[:f1 | 
+					intAndFractions do: 
+							[:f2 | 
+							ref _ f1 perform: op with: f2 asFloat.
+							new _ (f1 asLargeFloatPrecision: 53) perform: op
+										with: (f2 asLargeFloatPrecision: 53).
+							self assert: new = ref.
+							new _ f1 perform: op
+										with: (f2 asLargeFloatPrecision: 53).
+							self assert: new = ref.
+							
+							ref _ f1 perform: op with: f2.
+							new _ (f1 asLargeFloatPrecision: 53) perform: op
+										with: f2.
+							self assert: new = ref.
+							
+							ref _ f2 asFloat perform: op with: f1.
+							new _ (f2 asLargeFloatPrecision: 53) perform: op
+										with: (f1 asLargeFloatPrecision: 53).
+							self assert: new = ref.
+							new _ (f2 asLargeFloatPrecision: 53) perform: op with: f1.
+							self assert: new = ref.
+							
+							ref _ f2 perform: op with: f1.
+							new _ f2 perform: op
+										with: (f1 asLargeFloatPrecision: 53).
+							self assert: new = ref]]]
+!
+
+testMultiply
+	self assert: zero * zero = zero.
+	self assert: zero * minusOne = zero.
+	self assert: huge * zero = zero.
+	self assert: one * zero = zero.
+	
+	self assert: one * two = two.
+	self assert: minusOne * one = minusOne.
+	self assert: minusOne * minusTwo = two.
+	
+	self assert: half * two = one.
+	
+	"check rounding"
+	self assert: huge * one = huge.
+!
+
+testNegated
+	self assert: zero negated = zero.
+	self assert: one negated = minusOne.
+	self assert: minusTwo negated = two.
+	self assert: huge negated negated = huge.
+!
+
+testPi
+	"check computation of pi"
+
+	self assert: (1 asLargeFloatPrecision: 53) pi = Float pi.
+!
+
+testRaisedToNegativeInteger
+	| n |
+	n _ 11.
+	1 to: 1<<n-1 do: [:i |
+		self assert: ((i asLargeFloatPrecision: n) raisedToInteger: -49)
+			equals: ((i raisedToInteger: -49) asLargeFloatPrecision: n) ].
+!
+
+testRaisedToPositiveInteger
+	| n |
+	n _ 11.
+	1 to: 1<<n-1 do: [:i |
+		self assert: ((i asLargeFloatPrecision: n) raisedToInteger: 49)
+			equals: ((i raisedToInteger: 49) asLargeFloatPrecision: n) ].
+!
+
+testReciprocal
+	| b |
+	b _ 1 << (Float precision - 1).
+	1 to: 10000 do: [:i |
+		| a |
+		a _ i asLargeFloatPrecision: Float precision.
+		self assert: a reciprocal = i asFloat reciprocal.
+		self assert: (a+b) reciprocal = (i+b) asFloat reciprocal.
+		self assert: a negated reciprocal = i asFloat negated reciprocal.]
+!
+
+testRoundToNearestEven
+	"Check that IEEE default rounding mode is honoured,
+	that is rounding to nearest even"
+		
+	self assert: ((one timesTwoPower: 52)+(0+(1/4))) asTrueFraction = ((1 bitShift: 52)+0).
+	self assert: ((one timesTwoPower: 52)+(0+(1/2))) asTrueFraction = ((1 bitShift: 52)+0).
+	self assert: ((one timesTwoPower: 52)+(0+(3/4))) asTrueFraction = ((1 bitShift: 52)+1).
+	self assert: ((one timesTwoPower: 52)+(1+(1/4))) asTrueFraction = ((1 bitShift: 52)+1).
+	self assert: ((one timesTwoPower: 52)+(1+(1/2))) asTrueFraction = ((1 bitShift: 52)+2).
+	self assert: ((one timesTwoPower: 52)+(1+(3/4))) asTrueFraction = ((1 bitShift: 52)+2).
+!
+
+testRoundToNearestEvenAgainstIEEEDouble
+	"Check that IEEE default rounding mode is honoured"
+
+	#(1 2 3 5 6 7) do: 
+			[:i | 
+			self assert: ((one timesTwoPower: 52) + (i / 4)) asTrueFraction 
+						= ((1 asFloat timesTwoPower: 52) + (i / 4)) asTrueFraction.
+			self assert: ((one timesTwoPower: 52) - (i / 4)) asTrueFraction 
+						= ((1 asFloat timesTwoPower: 52) - (i / 4)) asTrueFraction]
+!
+
+testSubtract
+	self assert: zero - zero = zero.
+	self assert: zero - minusOne = one.
+	self assert: huge - zero = huge.
+	self assert: one - zero = one.
+	
+	self assert: one - minusOne = two.
+	self assert: minusOne - minusTwo = one.
+	self assert: minusOne - one = minusTwo.
+	
+	"check rounding"
+	self assert: huge - one = huge.
+!
+
+testSum
+	self assert: zero + zero = zero.
+	self assert: zero + minusOne = minusOne.
+	self assert: huge + zero = huge.
+	self assert: one + zero = one.
+	
+	self assert: one + minusOne = zero.
+	self assert: minusOne + two = one.
+	self assert: one + minusTwo = minusOne.
+	
+	"check rounding"
+	self assert: huge + one = huge.
+!
+
+testZeroOne
+
+	self assert: (312 asLargeFloatPrecision: 53) one = 1.
+	self assert: (312 asLargeFloatPrecision: 24) zero isZero.
+
+	self assert: (312 asLargeFloatPrecision: 53) one asInteger = 1.
+	self assert: (312 asLargeFloatPrecision: 24) zero asInteger isZero.
+! !
+
+!LargeFloatTest methodsFor:'testing-coercing'!
+
+testCoercingDivide
+	(Array with: 1/2 with: 0.5e0) do: [:heteroHalf |
+		self assert: one / heteroHalf = two.
+		self assert: (one / heteroHalf) class = one class.
+		self assert: (one / heteroHalf) precision = one precision.
+		self assert: heteroHalf / one = half.
+		self assert: (heteroHalf / one) class = one class.
+		self assert: (heteroHalf / one) precision = one precision].
+
+	self assert: one / 2 = half.
+	self assert: (one / 2) class = one class.
+	self assert: (one / 2) precision = one precision.
+	self assert: -2 / two = minusOne.
+	self assert: (-2 / two) class = two class.
+	self assert: (-2 / two) precision = two precision.
+!
+
+testCoercingEqual
+	self assert: half = (1/2).
+	self assert: (1/2) = half.
+	self deny: half = (1/3).
+	self deny: (1/3) = half.
+
+	self assert: two = 2.
+	self assert: -2 = minusTwo.
+	self deny: -3 = two.
+	self deny: two = 3.
+
+	self assert: half = (0.5e0).
+	self assert: (0.5e0) = half.
+	self deny: half = (0.33e0).
+	self deny: (0.33e0) = half.
+!
+
+testCoercingLessThan
+	self deny: half < (1/2).
+	self assert: (1/3) < half.
+	self assert: minusOne < (1/2).
+	self deny: (1/3) < minusTwo.
+
+	self assert: two < 3.
+	self deny: two < 2.
+	self deny: two < 1.
+	self deny: two < -1.
+	self assert:  minusTwo < -1.
+	self assert:  minusTwo < 1.
+	self deny: minusTwo < -2.
+	self deny: minusTwo < -3.
+
+	self deny: half < (0.5e0).
+	self deny: half < (0.33e0).
+	self assert: half < (0.66e0).
+	self deny: (0.5e0) < half.
+	self assert: (0.33e0) < half.
+	self deny: (0.66e0) < half.
+!
+
+testCoercingMultiply
+	(Array with: 1/2 with: 0.5e0) do: [:heteroHalf |
+		self assert: two * heteroHalf = one.
+		self assert: (two * heteroHalf) class = half class.
+		self assert: (two * heteroHalf) precision = half precision.
+		self assert: heteroHalf * two = one.
+		self assert: (heteroHalf * two) class = half class.
+		self assert: (heteroHalf * two) precision = half precision].
+
+	self assert: minusOne * 2 = minusTwo.
+	self assert: (minusOne * 2) class = minusOne class.
+	self assert: (minusOne * 2) precision = minusOne precision.
+	self assert: 2 * one = two.
+	self assert: (2 * one) class = one class.
+	self assert: (2 * one) precision = one precision.
+!
+
+testCoercingSubtract
+	(Array with: 1/2 with: 0.5e0) do: [:heteroHalf |
+		self assert: half - heteroHalf = zero.
+		self assert: (half - heteroHalf) class = half class.
+		self assert: (half - heteroHalf) precision = half precision.
+		self assert: heteroHalf - half = zero.
+		self assert: (heteroHalf - half) class = half class.
+		self assert: (heteroHalf - half) precision = half precision].
+
+	self assert: one - 1 = zero.
+	self assert: (one - 1) class = minusOne class.
+	self assert: (one - 1) precision = minusOne precision.
+	self assert: -2 - minusTwo = zero.
+	self assert: (-2 - minusTwo) class = minusTwo class.
+	self assert: (-2 - minusTwo) precision = minusTwo precision.
 !
 
-version_CVS
-    ^ '$Header$'
+testCoercingSum
+	(Array with: 1/2 with: 0.5e0) do: [:heteroHalf |
+		self assert: half + heteroHalf = one.
+		self assert: (half + heteroHalf) class = half class.
+		self assert: (half + heteroHalf) precision = half precision.
+		self assert: heteroHalf + half = one.
+		self assert: (heteroHalf + half) class = half class.
+		self assert: (heteroHalf + half) precision = half precision].
+
+	self assert: minusOne + 1 = zero.
+	self assert: (minusOne + 1) class = minusOne class.
+	self assert: (minusOne + 1) precision = minusOne precision.
+	self assert: 2 + minusTwo = zero.
+	self assert: (2 + minusTwo) class = minusTwo class.
+	self assert: (2 + minusTwo) precision = minusTwo precision.
+!
+
+testInfinityAndNaN
+	| inf nan |
+	inf _ Float infinity.
+	nan _ Float nan.
+	self assert: inf + two equals: inf.
+	self assert: half + inf negated equals: inf negated.	
+	self assert: (nan + minusOne)  isNaN .
+	self assert: inf - huge equals: inf.
+	self assert: half - inf equals: inf negated.
+	self assert: minusTwo - inf negated equals: inf.
+	self assert: (one - nan) isNaN.
+	self assert: inf * two equals: inf.
+	self assert: minusOne * inf equals: inf negated.
+	self assert: inf negated * minusOne equals: inf.
+	self assert: (huge * nan) isNaN.
+	self assert: inf negated / minusTwo equals: inf.
+	self assert: zero / inf negated equals: 0.	
+	self assert: one / inf equals: 0.
+	self should: [inf / zero] raise: ZeroDivide.	
+	self assert: (nan  / two) isNaN.	
+	self assert: (inf raisedTo: huge) equals: inf.
+	self assert: (huge raisedTo: inf) equals: inf.
+	self assert: (nan raisedTo: two) isNaN.
+	self assert: (two raisedTo: nan) isNaN.
+	self deny: nan <= one.
+	self deny: zero >= nan.
+	self assert: one < inf.
+	self assert: zero ~= nan.
+	self deny: nan = one.
+! !
+
+!LargeFloatTest methodsFor:'testing-compare'!
+
+testEqual
+	self assert: zero = zero.
+	self assert: one = one.
+	self assert: one = one copy.
+	self assert: one = (one asLargeFloatPrecision: one precision * 2).
+
+	self deny: zero = one.
+	self deny: minusOne = one.
+
+	self assert: zero = 0.
+	self assert: 0 = zero.
+	self assert: zero = 0.0.
+	self assert: 0.0 = zero.
+
+	self deny: two = (1/2).
+	self deny: (1/2) = two.
+	self deny: zero = 1.0.
+	self deny: 0.0 = one.
+
+	self deny: one = nil.
+	self deny: nil = one.
+!
+
+testGreaterThan
+	
+	self assert: zero < one.
+	self deny: one > two.
+	self deny: two > huge.
+	self deny: minusOne > one.
+	self deny: minusTwo > minusOne.
+	self deny: minusTwo > huge.
+	
+	self assert: huge > one.
+	self assert: huge > zero.
+	self assert: huge > minusOne.
+	self assert: one > minusOne.
+	self assert: minusOne > minusTwo.
+!
+
+testIsZero
+	self assert: zero isZero.
+	self deny: one isZero.
+	self deny: minusTwo isZero.
+!
+
+testLessThan
+	
+	self assert: zero < one.
+	self assert: one < two.
+	self assert: two < huge.
+	self assert: minusOne < one.
+	self assert: minusTwo < minusOne.
+	self assert: minusTwo < huge.
+	
+	self deny: huge < one.
+	self deny: huge < zero.
+	self deny: huge < minusOne.
+	self deny: one < minusOne.
+	self deny: minusOne < minusTwo.
+!
+
+testNegative
+	
+	self deny: zero negative.
+	self deny: two negative.
+	self assert: minusTwo negative.
+!
+
+testPositive
+	
+	self assert: zero positive.
+	self assert: one positive.
+	self deny: minusOne positive.
+! !
+
+!LargeFloatTest methodsFor:'testing-converting'!
+
+testAsFloat
+	self assert: (half asLargeFloatPrecision: Float precision) asFloat = 0.5e0.
+	self assert: (half asLargeFloatPrecision: Float precision * 2) asFloat = 0.5e0.
+!
+
+testAsFloatWithUnderflow
+	| fmin fminA |
+	fmin _ Float fmin.
+	fminA _ fmin asLargeFloatPrecision: one precision.
+	Float emin - Float precision + 1 to: Float emin + 1 do: [:n |
+		self assert: ((one timesTwoPower: n) + fminA) asFloat = ((1.0e0 timesTwoPower: n) + fmin)].
+!
+
+testAsMinimalDecimalFraction
+	| emax emin leadingOne significands |
+	significands _ 0 to: 1<<10-1.
+	leadingOne _ 1<<10.
+	emin _ -14.
+	emax _ 15.
+	
+	"Test all normal finite half precision float"
+	emin to: emax do: [:e | 
+		significands do: [:s |
+			| f |
+			f _ (leadingOne + s asLargeFloatPrecision: 11) timesTwoPower: e - 10.
+			self assert: (f asMinimalDecimalFraction asLargeFloatPrecision: 11) = f]].
+	
+	"Test all subnormal finite half precision float"
+	significands do: [:s |
+		| f |
+		f _ (s asLargeFloatPrecision: s highBit) timesTwoPower: emin - 10.
+		self assert: (f asMinimalDecimalFraction asLargeFloatPrecision: s highBit) = f].
+!
+
+testPrintAndEvaluate
+	<timeout: 50 "seconds">
+	| emax emin leadingOne significands |
+	significands _ 0 to: 1<<10-1.
+	leadingOne _ 1<<10.
+	emin _ -14.
+	emax _ 15.
+	
+	"Test all normal finite half precision float"
+	emin to: emax do: [:e | 
+		significands do: [:s |
+			| f |
+			f _ (leadingOne + s asLargeFloatPrecision: 11) timesTwoPower: e - 10.
+			self assert: (Compiler evaluate: f storeString) = f.
+			self assert: (Compiler evaluate: f printString) = f.]].
+	
+	"Test all subnormal finite half precision float"
+	significands do: [:s |
+		| f |
+		f _ (s asLargeFloatPrecision: s highBit) timesTwoPower: emin - 10.
+		self assert: (Compiler evaluate: f storeString) = f.
+		self assert: (Compiler evaluate: f printString) = f].
 ! !
 
+!LargeFloatTest methodsFor:'testing-functions'!
+
+testExp
+	<timeout: 10 "seconds">
+	| badExp serie |
+	serie _ ((-20 to: 20) collect: [:e |e asFloat]).
+	badExp _ self checkDoublePrecisionSerieVsFloat: serie forFunction: #exp.
+	badExp isEmpty ifFalse: [Transcript cr; show: 'bad exp for ' , badExp printString]
+!
+
+testExpLn
+	|n|
+	self assert: (1 asLargeFloatPrecision: 53) exp asFloat = 1 asFloat exp.
+	n _ 5 exp.
+	self assert: ((5 asLargeFloatPrecision: 53) exp - n)abs <= n ulp.
+	"self assert: (5 asLargeFloatPrecision: 53) exp asFloat = 5 asFloat exp."
+	self assert: ((5 asLargeFloatPrecision: 53) exp ln asFloat - n ln)abs <= 5.0 ulp.
+	"this test was skipped. changed that & loosened 2. test,
+	 since '5 exp' seems to round up instead of down here,
+	 which results in an error of almost one ulp in '5 exp'"
+!
+
+testLn
+	<timeout: 10 "seconds">
+	| badLn serie |
+	serie _ ((1 to: 100) collect: [:e |e asFloat]).
+	badLn _ self checkDoublePrecisionSerieVsFloat: serie forFunction: #ln.
+	badLn isEmpty ifFalse: [Transcript cr; show: 'bad ln for ' , badLn printString]
+!
+
+testLnDomainError
+	self should: [(-2 asLargeFloatPrecision: 24) ln] raise: DomainError.
+!
+
+testSqrt
+	<timeout: 10 "seconds">
+	| badSqrt serie |
+	"knowing that (10**3) < (2**10), 100 bits are enough for representing 10**30 exactly"
+	self assert: ((10 raisedTo: 30) asLargeFloatPrecision: 100) sqrt = (10 raisedTo: 15).
+
+	serie _ ((0 to: 20) collect: [:e | e asFloat]) , ((2 to: 20) collect: [:e | e reciprocal asFloat]).
+	badSqrt _ self checkDoublePrecisionSerieVsFloat: serie forFunction: #sqrt.
+	badSqrt isEmpty ifFalse: [Transcript cr; show: 'bad sqrt for ' , badSqrt printString]
+!
+
+testSqrtDomainError
+	self should: [(-2 asLargeFloatPrecision: 24) sqrt] raise: DomainError.
+! !
+
+!LargeFloatTest methodsFor:'testing-hyperbolic'!
+
+hyperbolicSerie
+	^#(-3.0e0  -0.1e0  0.0e0  1.0e-20  1.0e-10  0.99e0 1.0e0  2.5e0  3.0e0  10.25e0) , (Array with: (3/10) asFloat with: (22/7) asFloat)
+!
+
+testArCosh
+	<timeout: 5 "seconds">
+	| serie |
+	serie _ ((1 to: 10) , #(1.0001 100 1000 1.0e20)) collect: [:e | e asFloat].
+	self checkDoublePrecisionSerie: serie forFunction: #arCosh
+!
+
+testArCoshDomainError
+	self should: [(1/2 asLargeFloatPrecision: 24) arCosh] raise: DomainError.
+!
+
+testArSinh
+	<timeout: 10 "seconds">
+	| serie |
+	serie _ ((-5 to: 10) , #(1.0e-20 1.0e-10  0.9999 1.0001 100 1000 1.0e20)) collect: [:e | e asFloat].
+	self checkDoublePrecisionSerie: serie forFunction: #arSinh
+!
+
+testArTanh
+	<timeout: 20 "seconds">
+	| serie |
+	serie _ ((-19 to: 19) collect: [:e | (e / 20) asFloat]) , ((-6 to: 6) collect: [:e | (e / 7) asFloat]) , #(1.0e-20 1.0e-10 0.99 0.9999 0.999999).
+	self checkDoublePrecisionSerie: serie forFunction: #arTanh
+!
+
+testArTanhDomainError
+	self should: [(2 asLargeFloatPrecision: 24) arTanh] raise: DomainError.
+	self should: [(-3 asLargeFloatPrecision: 24) arTanh] raise: DomainError.
+!
+
+testCosh
+	<timeout: 10 "seconds">
+	self checkDoublePrecisionSerie: self hyperbolicSerie forFunction: #cosh
+!
+
+testSinh
+	<timeout: 10 "seconds">
+	self checkDoublePrecisionSerie: self hyperbolicSerie forFunction: #sinh
+!
+
+testTanh
+	<timeout: 10 "seconds">
+	self checkDoublePrecisionSerie: self hyperbolicSerie forFunction: #tanh
+! !
+
+!LargeFloatTest methodsFor:'testing-trigonometry'!
+
+inverseTrigonometricSerie
+	^((-20 to: 20) collect: [:e | (e / 20) asFloat]) , ((-6 to: 6) collect: [:e | (e / 7) asFloat])
+!
+
+largeTrigonometricSerie
+	^#(1.0e15 1.1e21 1.2e28 1.0e32 1.1e34 -1.23e51 1.345e67 1.777e151 1.211e308)
+!
+
+testArcCos
+	<timeout: 10 "seconds">
+	| badArcCos |
+	badArcCos _ self checkDoublePrecisionSerieVsFloat: self inverseTrigonometricSerie forFunction: #arcCos.
+	badArcCos isEmpty ifFalse: [Transcript cr; show: 'bad arcCos for ' , badArcCos printString]
+!
+
+testArcCosDomainError
+	self should: [(2 asLargeFloatPrecision: 24) arcCos] raise: DomainError.
+	self should: [(-3 asLargeFloatPrecision: 24) arcCos] raise: DomainError.
+!
+
+testArcSin
+	<timeout: 10 "seconds">
+	| badArcSin |
+	badArcSin _ self checkDoublePrecisionSerieVsFloat: self inverseTrigonometricSerie forFunction: #arcSin.
+	badArcSin isEmpty ifFalse: [Transcript cr; show: 'bad arcSin for ' , badArcSin printString]
+!
+
+testArcSinDomainError
+	self should: [(2 asLargeFloatPrecision: 24) arcSin] raise: DomainError.
+	self should: [(-3 asLargeFloatPrecision: 24) arcSin] raise: DomainError.
+!
+
+testArcTan
+	<timeout: 10 "seconds">
+	| badArcTan serie |
+	serie _ ((-50 to: 50) collect: [:e | (e / 10) asFloat]).
+	badArcTan _ self checkDoublePrecisionSerieVsFloat: serie forFunction: #arcTan.
+	badArcTan isEmpty ifFalse: [Transcript cr; show: 'bad arcTan for ' , badArcTan printString]
+!
+
+testArcTan2
+	<timeout: 30 "seconds">
+	-5 to: 5 by: 4/10 do: [:y |
+		| yf yd |
+		yf _ y asLargeFloatPrecision: Float precision.
+		yd _ yf asLargeFloatPrecision: Float precision * 2.
+		-5 to: 5 by: 4/10 do: [:x |
+			| xf xd  |
+			xf _ x asLargeFloatPrecision: Float precision.
+			xd _ xf asLargeFloatPrecision: Float precision * 2.
+			self assert: ((yd arcTan: xd) asFloat - (yf arcTan: xf) asFloat) isZero]].
+!
+
+testCos
+	<timeout: 30 "seconds">
+	| badCos |
+	badCos _ self checkDoublePrecisionSerieVsFloat: self trigonometricSerie forFunction: #cos.
+	badCos isEmpty ifFalse: [Transcript cr; show: 'bad cos for angles (degrees) ' , (badCos collect: [:i | i radiansToDegrees rounded]) printString]
+!
+
+testSin
+	<timeout: 30 "seconds">
+	| badSin |
+	badSin _ self checkDoublePrecisionSerieVsFloat: self trigonometricSerie forFunction: #sin.
+	badSin isEmpty ifFalse: [Transcript cr; show: 'bad sin for angles (degrees) ' , (badSin collect: [:i | i radiansToDegrees rounded]) printString]
+!
+
+testSincos
+	<timeout: 30 "seconds">
+	self trigonometricSerie do: [:aFloat |
+		| x sc s c |
+		x _ aFloat asLargeFloatPrecision: 53.
+		sc _ x sincos.
+		s _ x sin.
+		c _ x cos.
+		self assert: sc size = 2.
+
+		self assert: sc first = s.
+		self assert: sc last = c]
+!
+
+testTan
+	<timeout: 30 "seconds">
+	| badTan |
+	badTan _ self checkDoublePrecisionSerieVsFloat: self trigonometricSerie forFunction: #tan.
+	badTan isEmpty ifFalse: [Transcript cr; show: 'bad tan for angles (degrees) ' , (badTan collect: [:i | i radiansToDegrees rounded]) printString]
+!
+
+testVeryLargeCos
+	<timeout: 10 "seconds">
+	self checkDoublePrecisionSerie: self largeTrigonometricSerie forFunction: #cos.
+!
+
+testVeryLargeSin
+	<timeout: 10 "seconds">
+	self checkDoublePrecisionSerie: self largeTrigonometricSerie forFunction: #sin.
+!
+
+testVeryLargeTan
+	<timeout: 10 "seconds">
+	self checkDoublePrecisionSerie: self largeTrigonometricSerie forFunction: #tan.
+!
+
+trigonometricSerie
+	^(-720 to: 720) collect: [:i | i asFloat degreesToRadians]
+! !
+
+
+