• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PolyMathOrg / PolyMath / 4385132063

pending completion
4385132063

push

github

GitHub
Merge pull request #316 from jecisc/divers-cleanings

2977 of 2977 new or added lines in 214 files covered. (100.0%)

19725 of 24212 relevant lines covered (81.47%)

2.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.66
/src/Math-Tests-ArbitraryPrecisionFloat/PMArbitraryPrecisionFloatTest.class.st
1
"
2
Test to check FloatingPoint numbers with arbitrary precision
3
"
4
Class {
5
        #name : #PMArbitraryPrecisionFloatTest,
6
        #superclass : #TestCase,
7
        #instVars : [
8
                'zero',
9
                'one',
10
                'two',
11
                'half',
12
                'minusOne',
13
                'minusTwo',
14
                'huge'
15
        ],
16
        #category : #'Math-Tests-ArbitraryPrecisionFloat'
17
}
18

19
{ #category : #accessing }
20
PMArbitraryPrecisionFloatTest class >> defaultTimeLimit [
3✔
21
^ 120 seconds
3✔
22
]
3✔
23

24
{ #category : #private }
25
PMArbitraryPrecisionFloatTest >> checkDoublePrecision: y forFunction: func nBits: n [
3✔
26
        "Check that doubling the precision, then rounding would lead to the same result"
3✔
27

3✔
28
        | anArbitraryPrecisionFloat singlePrecisionResult |
3✔
29
        anArbitraryPrecisionFloat := y asArbitraryPrecisionFloatNumBits: n.
3✔
30
        singlePrecisionResult := anArbitraryPrecisionFloat perform: func.
3✔
31
        self checkThatEvaluatingFunction: func toDoublePrecisionOf: anArbitraryPrecisionFloat equals: singlePrecisionResult.
3✔
32
        ^singlePrecisionResult
3✔
33
]
3✔
34

35
{ #category : #private }
36
PMArbitraryPrecisionFloatTest >> checkDoublePrecisionSerie: serie forFunction: func [
3✔
37
        ^self checkDoublePrecisionSerie: serie forFunction: func nBits: Float precision
3✔
38
]
3✔
39

40
{ #category : #private }
41
PMArbitraryPrecisionFloatTest >> checkDoublePrecisionSerie: serie forFunction: func nBits: n [
3✔
42
        serie do: [:y | self checkDoublePrecision: y forFunction: func nBits: n]
3✔
43
]
3✔
44

45
{ #category : #private }
46
PMArbitraryPrecisionFloatTest >> checkDoublePrecisionSerieVsFloat: serie forFunction: func [
3✔
47
        ^serie reject: [:y |
3✔
48
                | farb |
3✔
49
                farb := self checkDoublePrecision: y forFunction: func nBits: Float precision.
3✔
50
                [(y asFloat perform: func) = farb] on: ZeroDivide do: [false]]
3✔
51
]
3✔
52

53
{ #category : #private }
54
PMArbitraryPrecisionFloatTest >> checkThatEvaluatingFunction: func toDoublePrecisionOf: anArbitraryPrecisionFloat equals: singlePrecisionResult [
3✔
55
        "Check that doubling the precision, then rounding would lead to the same result"
3✔
56

3✔
57
        | n doublePrecision doublePrecisionResult lowBits |
3✔
58
        n := anArbitraryPrecisionFloat numBits.
3✔
59
        doublePrecision := anArbitraryPrecisionFloat asArbitraryPrecisionFloatNumBits: n * 2.
3✔
60
        doublePrecisionResult := doublePrecision perform: func.
3✔
61

3✔
62
        "Note: the test must be guarded against double rounding error condition.
3✔
63
        For example, suppose the single precision is 4 bits, double precision 8 bits.
3✔
64
        If exact result is 1.001 | 0111 | 1001...
3✔
65
        Then the nearest double is rounded to upper 1.001 | 1000
3✔
66
        Then the nearest single to the double is rounded to upper 1.010
3✔
67
        But the nearest single to the exact result should have been 1.001
3✔
68
        To avoid this, we have to check if the second rounding is an exact tie"
3✔
69
        doublePrecisionResult normalize.
3✔
70
        lowBits := doublePrecisionResult mantissa bitAnd: 1<<n-1.
3✔
71
        lowBits = (1<<(n-1))
3✔
72
                ifTrue:
3✔
73
                        ["double precision is ambiguous - retry with quadruple..."
3✔
74
                        ^self checkThatEvaluatingFunction: func toQuadruplePrecisionOf: anArbitraryPrecisionFloat equals: singlePrecisionResult].
3✔
75
        self assert: ((doublePrecisionResult asArbitraryPrecisionFloatNumBits: n)- singlePrecisionResult) isZero
3✔
76
]
3✔
77

78
{ #category : #private }
79
PMArbitraryPrecisionFloatTest >> checkThatEvaluatingFunction: func toQuadruplePrecisionOf: anArbitraryPrecisionFloat equals: singlePrecisionResult [
×
80
        "Check that quadrupling the precision, then rounding would lead to the same result"
×
81

×
82
        | n quadruplePrecision quadruplePrecisionResult lowBits |
×
83
        n := anArbitraryPrecisionFloat numBits.
×
84
        quadruplePrecision := anArbitraryPrecisionFloat asArbitraryPrecisionFloatNumBits: n * 4.
×
85
        quadruplePrecisionResult := quadruplePrecision perform: func.
×
86

×
87
        "Guard against double rounding error condition (exact tie)"
×
88
        quadruplePrecisionResult normalize.
×
89
        lowBits := quadruplePrecisionResult mantissa bitAnd: 1<<(3*n)-1.
×
90
        lowBits = (1<<(3*n-1))
×
91
                ifTrue:
×
92
                        ["quadruple precision is ambiguous - give up..."
×
93
                        ^self].
×
94
        self assert: ((quadruplePrecisionResult asArbitraryPrecisionFloatNumBits: n)- singlePrecisionResult) isZero
×
95
]
×
96

97
{ #category : #'testing-hyperbolic' }
98
PMArbitraryPrecisionFloatTest >> hyperbolicSerie [
3✔
99
        ^#(-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)
3✔
100
]
3✔
101

102
{ #category : #'testing-trigonometry' }
103
PMArbitraryPrecisionFloatTest >> inverseTrigonometricSerie [
3✔
104
        ^((-20 to: 20) collect: [:e | (e / 20) asFloat]) , ((-6 to: 6) collect: [:e | (e / 7) asFloat])
3✔
105
]
3✔
106

107
{ #category : #'testing-trigonometry' }
108
PMArbitraryPrecisionFloatTest >> largeTrigonometricSerie [
3✔
109
        ^#(1.0e15 1.1e21 1.2e28 1.0e32 1.1e34 -1.23e51 1.345e67 1.777e151 1.211e308)
3✔
110
]
3✔
111

112
{ #category : #running }
113
PMArbitraryPrecisionFloatTest >> setUp [
3✔
114

3✔
115
        super setUp.
3✔
116
        zero := 0 asArbitraryPrecisionFloatNumBits: 53.
3✔
117
        one := 1 asArbitraryPrecisionFloatNumBits: 53.
3✔
118
        two := 2 asArbitraryPrecisionFloatNumBits: 53.
3✔
119
        half := 1 / 2 asArbitraryPrecisionFloatNumBits: 53.
3✔
120
        minusOne := -1 asArbitraryPrecisionFloatNumBits: 53.
3✔
121
        minusTwo := -2 asArbitraryPrecisionFloatNumBits: 53.
3✔
122
        huge := (10 raisedTo: 100) asArbitraryPrecisionFloatNumBits: 53
3✔
123
]
3✔
124

125
{ #category : #'testing-hyperbolic' }
126
PMArbitraryPrecisionFloatTest >> testArCosh [
3✔
127
        <timeout: 5 "seconds">
3✔
128
        | serie |
3✔
129
        serie := ((1 to: 10) , #(1.0001 100 1000 1.0e20)) collect: [:e | e asFloat].
3✔
130
        self checkDoublePrecisionSerie: serie forFunction: #arCosh
3✔
131
]
3✔
132

133
{ #category : #'testing-hyperbolic' }
134
PMArbitraryPrecisionFloatTest >> testArCoshDomainError [
3✔
135
        self should: [(1/2 asArbitraryPrecisionFloatNumBits: 24) arCosh] raise: DomainError
3✔
136
]
3✔
137

138
{ #category : #'testing-hyperbolic' }
139
PMArbitraryPrecisionFloatTest >> testArSinh [
3✔
140
        <timeout: 10 "seconds">
3✔
141
        | serie |
3✔
142
        serie := ((-5 to: 10) , #(1.0e-20 1.0e-10  0.9999 1.0001 100 1000 1.0e20)) collect: [:e | e asFloat].
3✔
143
        self checkDoublePrecisionSerie: serie forFunction: #arSinh
3✔
144
]
3✔
145

146
{ #category : #'testing-hyperbolic' }
147
PMArbitraryPrecisionFloatTest >> testArTanh [
3✔
148
        <timeout: 20 "seconds">
3✔
149
        | serie |
3✔
150
        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).
3✔
151
        self checkDoublePrecisionSerie: serie forFunction: #arTanh
3✔
152
]
3✔
153

154
{ #category : #'testing-hyperbolic' }
155
PMArbitraryPrecisionFloatTest >> testArTanhDomainError [
3✔
156
        self should: [(2 asArbitraryPrecisionFloatNumBits: 24) arTanh] raise: DomainError.
3✔
157
        self should: [(-3 asArbitraryPrecisionFloatNumBits: 24) arTanh] raise: DomainError
3✔
158
]
3✔
159

160
{ #category : #'testing-trigonometry' }
161
PMArbitraryPrecisionFloatTest >> testArcCos [
3✔
162
        "seconds"
3✔
163

3✔
164
        <timeout: 10>
3✔
165
        self checkDoublePrecisionSerieVsFloat: self inverseTrigonometricSerie forFunction: #arcCos
3✔
166
]
3✔
167

168
{ #category : #'testing-trigonometry' }
169
PMArbitraryPrecisionFloatTest >> testArcCosDomainError [
3✔
170
        self should: [(2 asArbitraryPrecisionFloatNumBits: 24) arcCos] raise: DomainError.
3✔
171
        self should: [(-3 asArbitraryPrecisionFloatNumBits: 24) arcCos] raise: DomainError
3✔
172
]
3✔
173

174
{ #category : #'testing-trigonometry' }
175
PMArbitraryPrecisionFloatTest >> testArcSin [
3✔
176
        "seconds"
3✔
177

3✔
178
        <timeout: 10>
3✔
179
        self checkDoublePrecisionSerieVsFloat: self inverseTrigonometricSerie forFunction: #arcSin
3✔
180
]
3✔
181

182
{ #category : #'testing-trigonometry' }
183
PMArbitraryPrecisionFloatTest >> testArcSinDomainError [
3✔
184
        self should: [(2 asArbitraryPrecisionFloatNumBits: 24) arcSin] raise: DomainError.
3✔
185
        self should: [(-3 asArbitraryPrecisionFloatNumBits: 24) arcSin] raise: DomainError
3✔
186
]
3✔
187

188
{ #category : #'testing-trigonometry' }
189
PMArbitraryPrecisionFloatTest >> testArcTan [
3✔
190
        "seconds"
3✔
191

3✔
192
        <timeout: 10>
3✔
193
        | serie |
3✔
194
        serie := (-50 to: 50) collect: [ :e | (e / 10) asFloat ].
3✔
195
        self checkDoublePrecisionSerieVsFloat: serie forFunction: #arcTan
3✔
196
]
3✔
197

198
{ #category : #'testing-trigonometry' }
199
PMArbitraryPrecisionFloatTest >> testArcTan2 [
3✔
200
        <timeout: 30 "seconds">
3✔
201
        -5 to: 5 by: 4/10 do: [:y |
3✔
202
                | yf yd |
3✔
203
                yf := y asArbitraryPrecisionFloatNumBits: Float precision.
3✔
204
                yd := yf asArbitraryPrecisionFloatNumBits: Float precision * 2.
3✔
205
                -5 to: 5 by: 4/10 do: [:x |
3✔
206
                        | xf xd  |
3✔
207
                        xf := x asArbitraryPrecisionFloatNumBits: Float precision.
3✔
208
                        xd := xf asArbitraryPrecisionFloatNumBits: Float precision * 2.
3✔
209
                        self assert: ((yd arcTan: xd) asFloat - (yf arcTan: xf) asFloat) isZero]]
3✔
210
]
3✔
211

212
{ #category : #'testing-converting' }
213
PMArbitraryPrecisionFloatTest >> testAsFloat [
3✔
214

3✔
215
        self assert: (half asArbitraryPrecisionFloatNumBits: Float precision) asFloat equals: 0.5e0.
3✔
216
        self assert: (half asArbitraryPrecisionFloatNumBits: Float precision * 2) asFloat equals: 0.5e0
3✔
217
]
3✔
218

219
{ #category : #'testing-converting' }
220
PMArbitraryPrecisionFloatTest >> testAsFloatWithUnderflow [
3✔
221

3✔
222
        | fmin fminA |
3✔
223
        fmin := Float fmin.
3✔
224
        fminA := fmin asArbitraryPrecisionFloatNumBits: one numBits.
3✔
225
        Float emin - Float precision + 1 to: Float emin + 1 do: [ :n | self assert: ((one timesTwoPower: n) + fminA) asFloat equals: (1.0e0 timesTwoPower: n) + fmin ]
3✔
226
]
3✔
227

228
{ #category : #'testing-converting' }
229
PMArbitraryPrecisionFloatTest >> testAsMinimalDecimalFraction [
3✔
230

3✔
231
        | emax emin leadingOne significands |
3✔
232
        significands := 0 to: 1 << 10 - 1.
3✔
233
        leadingOne := 1 << 10.
3✔
234
        emin := -14.
3✔
235
        emax := 15.
3✔
236

3✔
237
        "Test all normal finite half precision float"
3✔
238
        emin to: emax do: [ :e |
3✔
239
                significands do: [ :s |
3✔
240
                        | f |
3✔
241
                        f := (leadingOne + s asArbitraryPrecisionFloatNumBits: 11) timesTwoPower: e - 10.
3✔
242
                        self assert: (f asMinimalDecimalFraction asArbitraryPrecisionFloatNumBits: 11) equals: f ] ].
3✔
243

3✔
244
        "Test all subnormal finite half precision float"
3✔
245
        significands do: [ :s |
3✔
246
                | f |
3✔
247
                f := (s asArbitraryPrecisionFloatNumBits: s highBit) timesTwoPower: emin - 10.
3✔
248
                self assert: (f asMinimalDecimalFraction asArbitraryPrecisionFloatNumBits: s highBit) equals: f ]
3✔
249
]
3✔
250

251
{ #category : #'testing-coercing' }
252
PMArbitraryPrecisionFloatTest >> testCoercingDivide [
3✔
253

3✔
254
        (Array with: 1 / 2 with: 0.5e0 with: 0.5s1) do: [ :heteroHalf |
3✔
255
                self assert: one / heteroHalf equals: two.
3✔
256
                self assert: (one / heteroHalf) class equals: one class.
3✔
257
                self assert: (one / heteroHalf) numBits equals: one numBits.
3✔
258
                self assert: heteroHalf / one equals: half.
3✔
259
                self assert: (heteroHalf / one) class equals: one class.
3✔
260
                self assert: (heteroHalf / one) numBits equals: one numBits ].
3✔
261

3✔
262
        self assert: one / 2 equals: half.
3✔
263
        self assert: (one / 2) class equals: one class.
3✔
264
        self assert: (one / 2) numBits equals: one numBits.
3✔
265
        self assert: -2 / two equals: minusOne.
3✔
266
        self assert: (-2 / two) class equals: two class.
3✔
267
        self assert: (-2 / two) numBits equals: two numBits
3✔
268
]
3✔
269

270
{ #category : #'testing-coercing' }
271
PMArbitraryPrecisionFloatTest >> testCoercingEqual [
3✔
272

3✔
273
        self assert: half equals: 1 / 2.
3✔
274
        self assert: 1 / 2 equals: half.
3✔
275
        self deny: half equals: 1 / 3.
3✔
276
        self deny: 1 / 3 equals: half.
3✔
277

3✔
278
        self assert: two equals: 2.
3✔
279
        self assert: -2 equals: minusTwo.
3✔
280
        self deny: -3 equals: two.
3✔
281
        self deny: two equals: 3.
3✔
282

3✔
283
        self assert: half equals: 0.5e0.
3✔
284
        self assert: 0.5e0 equals: half.
3✔
285
        self deny: half equals: 0.33e0.
3✔
286
        self deny: 0.33e0 equals: half.
3✔
287

3✔
288
        self assert: half equals: 0.5s1.
3✔
289
        self assert: 0.5s1 equals: half.
3✔
290
        self deny: half equals: 0.33s2.
3✔
291
        self deny: 0.33s2 equals: half
3✔
292
]
3✔
293

294
{ #category : #'testing-coercing' }
295
PMArbitraryPrecisionFloatTest >> testCoercingLessThan [
3✔
296
        self deny: half < (1/2).
3✔
297
        self assert: (1/3) < half.
3✔
298
        self assert: minusOne < (1/2).
3✔
299
        self deny: (1/3) < minusTwo.
3✔
300

3✔
301
        self assert: two < 3.
3✔
302
        self deny: two < 2.
3✔
303
        self deny: two < 1.
3✔
304
        self deny: two < -1.
3✔
305
        self assert:  minusTwo < -1.
3✔
306
        self assert:  minusTwo < 1.
3✔
307
        self deny: minusTwo < -2.
3✔
308
        self deny: minusTwo < -3.
3✔
309

3✔
310
        self deny: half < (0.5e0).
3✔
311
        self deny: half < (0.33e0).
3✔
312
        self assert: half < (0.66e0).
3✔
313
        self deny: (0.5e0) < half.
3✔
314
        self assert: (0.33e0) < half.
3✔
315
        self deny: (0.66e0) < half.
3✔
316

3✔
317
        self deny: half < (0.5s1).
3✔
318
        self deny: half < (0.33s2).
3✔
319
        self assert: half < (0.66s2).
3✔
320
        self deny: (0.5s1) < half.
3✔
321
        self assert: (0.33s2) < half.
3✔
322
        self deny: (0.66s2) < half
3✔
323
]
3✔
324

325
{ #category : #'testing-coercing' }
326
PMArbitraryPrecisionFloatTest >> testCoercingMultiply [
3✔
327

3✔
328
        (Array with: 1 / 2 with: 0.5e0 with: 0.5s1) do: [ :heteroHalf |
3✔
329
                self assert: two * heteroHalf equals: one.
3✔
330
                self assert: (two * heteroHalf) class equals: half class.
3✔
331
                self assert: (two * heteroHalf) numBits equals: half numBits.
3✔
332
                self assert: heteroHalf * two equals: one.
3✔
333
                self assert: (heteroHalf * two) class equals: half class.
3✔
334
                self assert: (heteroHalf * two) numBits equals: half numBits ].
3✔
335

3✔
336
        self assert: minusOne * 2 equals: minusTwo.
3✔
337
        self assert: (minusOne * 2) class equals: minusOne class.
3✔
338
        self assert: (minusOne * 2) numBits equals: minusOne numBits.
3✔
339
        self assert: 2 * one equals: two.
3✔
340
        self assert: (2 * one) class equals: one class.
3✔
341
        self assert: (2 * one) numBits equals: one numBits
3✔
342
]
3✔
343

344
{ #category : #'testing-coercing' }
345
PMArbitraryPrecisionFloatTest >> testCoercingSubtract [
3✔
346

3✔
347
        (Array with: 1 / 2 with: 0.5e0 with: 0.5s1) do: [ :heteroHalf |
3✔
348
                self assert: half - heteroHalf equals: zero.
3✔
349
                self assert: (half - heteroHalf) class equals: half class.
3✔
350
                self assert: (half - heteroHalf) numBits equals: half numBits.
3✔
351
                self assert: heteroHalf - half equals: zero.
3✔
352
                self assert: (heteroHalf - half) class equals: half class.
3✔
353
                self assert: (heteroHalf - half) numBits equals: half numBits ].
3✔
354

3✔
355
        self assert: one - 1 equals: zero.
3✔
356
        self assert: (one - 1) class equals: minusOne class.
3✔
357
        self assert: (one - 1) numBits equals: minusOne numBits.
3✔
358
        self assert: -2 - minusTwo equals: zero.
3✔
359
        self assert: (-2 - minusTwo) class equals: minusTwo class.
3✔
360
        self assert: (-2 - minusTwo) numBits equals: minusTwo numBits
3✔
361
]
3✔
362

363
{ #category : #'testing-coercing' }
364
PMArbitraryPrecisionFloatTest >> testCoercingSum [
3✔
365

3✔
366
        (Array with: 1 / 2 with: 0.5e0 with: 0.5s1) do: [ :heteroHalf |
3✔
367
                self assert: half + heteroHalf equals: one.
3✔
368
                self assert: (half + heteroHalf) class equals: half class.
3✔
369
                self assert: (half + heteroHalf) numBits equals: half numBits.
3✔
370
                self assert: heteroHalf + half equals: one.
3✔
371
                self assert: (heteroHalf + half) class equals: half class.
3✔
372
                self assert: (heteroHalf + half) numBits equals: half numBits ].
3✔
373

3✔
374
        self assert: minusOne + 1 equals: zero.
3✔
375
        self assert: (minusOne + 1) class equals: minusOne class.
3✔
376
        self assert: (minusOne + 1) numBits equals: minusOne numBits.
3✔
377
        self assert: 2 + minusTwo equals: zero.
3✔
378
        self assert: (2 + minusTwo) class equals: minusTwo class.
3✔
379
        self assert: (2 + minusTwo) numBits equals: minusTwo numBits
3✔
380
]
3✔
381

382
{ #category : #'testing-trigonometry' }
383
PMArbitraryPrecisionFloatTest >> testCos [
3✔
384
        "seconds"
3✔
385

3✔
386
        <timeout: 30>
3✔
387
        self checkDoublePrecisionSerieVsFloat: self trigonometricSerie forFunction: #cos
3✔
388
]
3✔
389

390
{ #category : #'testing-hyperbolic' }
391
PMArbitraryPrecisionFloatTest >> testCosh [
3✔
392
        <timeout: 10 "seconds">
3✔
393
        self checkDoublePrecisionSerie: self hyperbolicSerie forFunction: #cosh
3✔
394
]
3✔
395

396
{ #category : #'testing-arithmetic' }
397
PMArbitraryPrecisionFloatTest >> testDivide [
3✔
398

3✔
399
        | serie |
3✔
400
        serie := #( 1 2 3 5 6 7 9 10 11 12 19 243 ) asOrderedCollection
3✔
401
                         add: (10 raisedTo: Float precision + 1);
3✔
402
                         add: Float precision factorial;
3✔
403
                         add: Float pi;
3✔
404
                         asArray.
3✔
405
        serie do: [ :num |
3✔
406
                | nf na |
3✔
407
                nf := num asFloat.
3✔
408
                na := num asArbitraryPrecisionFloatNumBits: Float precision.
3✔
409
                serie do: [ :den |
3✔
410
                        | df da ff fa |
3✔
411
                        df := den asFloat.
3✔
412
                        da := den asArbitraryPrecisionFloatNumBits: Float precision.
3✔
413
                        ff := nf / df.
3✔
414
                        fa := na / da.
3✔
415
                        self assert: ff equals: fa ] ]
3✔
416
]
3✔
417

418
{ #category : #'testing-compare' }
419
PMArbitraryPrecisionFloatTest >> testEqual [
3✔
420

3✔
421
        self assert: zero equals: zero.
3✔
422
        self assert: one equals: one.
3✔
423
        self assert: one equals: one copy.
3✔
424
        self assert: one equals: (one asArbitraryPrecisionFloatNumBits: one numBits * 2).
3✔
425

3✔
426
        self deny: zero equals: one.
3✔
427
        self deny: minusOne equals: one.
3✔
428

3✔
429
        self assert: zero equals: 0.
3✔
430
        self assert: 0 equals: zero.
3✔
431
        self assert: zero equals: 0.0.
3✔
432
        self assert: 0.0 equals: zero.
3✔
433

3✔
434
        self deny: two equals: 1 / 2.
3✔
435
        self deny: 1 / 2 equals: two.
3✔
436
        self deny: zero equals: 1.0.
3✔
437
        self deny: 0.0 equals: one.
3✔
438

3✔
439
        self deny: one isNil.
3✔
440
        self deny: nil equals: one
3✔
441
]
3✔
442

443
{ #category : #'testing-functions' }
444
PMArbitraryPrecisionFloatTest >> testExp [
3✔
445
        "seconds"
3✔
446

3✔
447
        <timeout: 10>
3✔
448
        | badExp serie |
3✔
449
        serie := (-20 to: 20) collect: [ :e | e asFloat ].
3✔
450
        badExp := self checkDoublePrecisionSerieVsFloat: serie forFunction: #exp.
3✔
451
        badExp ifNotEmpty: [
3✔
452
                Transcript
3✔
453
                        cr;
3✔
454
                        show: 'bad exp for ' , badExp printString ]
3✔
455
]
3✔
456

457
{ #category : #'testing-functions' }
458
PMArbitraryPrecisionFloatTest >> testExpLn [
3✔
459

3✔
460
        | n |
3✔
461
        self assert: (1 asArbitraryPrecisionFloatNumBits: 53) exp asFloat equals: 1 asFloat exp.
3✔
462
        n := 5 exp.
3✔
463
        self assert: ((5 asArbitraryPrecisionFloatNumBits: 53) exp - n) abs <= n ulp.
3✔
464
        "self assert: (5 asArbitraryPrecisionFloatNumBits: 53) exp asFloat = 5 asFloat exp."
3✔
465
        self assert: ((5 asArbitraryPrecisionFloatNumBits: 53) exp ln asFloat - n ln) abs <= 5.0 ulp
3✔
466
        "this test was skipped. changed that & loosened 2. test,
3✔
467
         since '5 exp' seems to round up instead of down here,
3✔
468
         which results in an error of almost one ulp in '5 exp'"
3✔
469
]
3✔
470

471
{ #category : #'testing-compare' }
472
PMArbitraryPrecisionFloatTest >> testGreaterThan [
3✔
473

3✔
474
        self assert: zero < one.
3✔
475
        self deny: one > two.
3✔
476
        self deny: two > huge.
3✔
477
        self deny: minusOne > one.
3✔
478
        self deny: minusTwo > minusOne.
3✔
479
        self deny: minusTwo > huge.
3✔
480

3✔
481
        self assert: huge > one.
3✔
482
        self assert: huge > zero.
3✔
483
        self assert: huge > minusOne.
3✔
484
        self assert: one > minusOne.
3✔
485
        self assert: minusOne > minusTwo
3✔
486
]
3✔
487

488
{ #category : #'testing-arithmetic' }
489
PMArbitraryPrecisionFloatTest >> testIEEEArithmeticVersusFloat [
3✔
490

3✔
491
        | floats ops ref new |
3✔
492
        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.
3✔
493
        ops := #( #+ #- #* #/ #= #< #> ).
3✔
494
        ops do: [ :op |
3✔
495
                floats do: [ :f1 |
3✔
496
                        floats do: [ :f2 |
3✔
497
                                ref := f1 perform: op with: f2.
3✔
498
                                new := (f1 asArbitraryPrecisionFloatNumBits: 53) perform: op with: (f2 asArbitraryPrecisionFloatNumBits: 53).
3✔
499
                                self assert: new equals: ref ] ] ]
3✔
500
]
3✔
501

502
{ #category : #'testing-arithmetic' }
503
PMArbitraryPrecisionFloatTest >> testIEEEArithmeticVersusIntegerAndFraction [
3✔
504
        "check that results are the same as IEEE 754 accelerated hardware
3✔
505
        WARNING: this cannot be the case for denormalized numbers (gradual underflow)
3✔
506
        because our exponent is unlimited"
3✔
507

3✔
508
        | floats ops ref new intAndFractions |
3✔
509
        floats := #( 1.0e0 2.0e0 3.0e0 5.0e0 10.0e0 ) , (#( 52 53 54 -52 -53 -54 ) collect: [ :e | 1.0e0 timesTwoPower: e ])
3✔
510
                  , #( 0.5e0 0.25e0 1.0e60 0.1e0 1.1e-30 1.0e-60 ) copyWith: Float pi.
3✔
511
        intAndFractions := #( 1 3 5 10 12345678901234567890 -1 -22 -3 1.2s1 ) copyWith: 7 / 9.
3✔
512
        intAndFractions := intAndFractions , (intAndFractions collect: [ :e | e reciprocal ]).
3✔
513

3✔
514
        ops := 1 / 10 = 0.1
3✔
515
                       ifTrue: [ #( #+ #- #* #/ ) ]
3✔
516
                       ifFalse: [ #( #+ #- #* #/ #= #< #> ) ]. "BEWARE: ArbitraryPrecisionFloat compare exactly, Float don't, unless http://bugs.squeak.org/view.php?id=3374"
3✔
517
        ops do: [ :op |
3✔
518
                floats do: [ :f1 |
3✔
519
                        intAndFractions do: [ :f2 |
3✔
520
                                ref := f1 perform: op with: f2 asFloat.
3✔
521
                                new := (f1 asArbitraryPrecisionFloatNumBits: 53) perform: op with: (f2 asArbitraryPrecisionFloatNumBits: 53).
3✔
522
                                self assert: new equals: ref.
3✔
523
                                new := f1 perform: op with: (f2 asArbitraryPrecisionFloatNumBits: 53).
3✔
524
                                self assert: new equals: ref.
3✔
525

3✔
526
                                ref := f1 perform: op with: f2.
3✔
527
                                new := (f1 asArbitraryPrecisionFloatNumBits: 53) perform: op with: f2.
3✔
528
                                self assert: new equals: ref.
3✔
529

3✔
530
                                ref := f2 asFloat perform: op with: f1.
3✔
531
                                new := (f2 asArbitraryPrecisionFloatNumBits: 53) perform: op with: (f1 asArbitraryPrecisionFloatNumBits: 53).
3✔
532
                                self assert: new equals: ref.
3✔
533
                                new := (f2 asArbitraryPrecisionFloatNumBits: 53) perform: op with: f1.
3✔
534
                                self assert: new equals: ref.
3✔
535

3✔
536
                                ref := f2 perform: op with: f1.
3✔
537
                                new := f2 perform: op with: (f1 asArbitraryPrecisionFloatNumBits: 53).
3✔
538
                                self assert: new equals: ref ] ] ]
3✔
539
]
3✔
540

541
{ #category : #'testing-coercing' }
542
PMArbitraryPrecisionFloatTest >> testInfinityAndNaN [
3✔
543

3✔
544
        | inf nan |
3✔
545
        inf := Float infinity.
3✔
546
        nan := Float nan.
3✔
547
        self assert: inf + two equals: inf.
3✔
548
        self assert: half + inf negated equals: inf negated.
3✔
549
        self assert: (nan + minusOne) isNaN.
3✔
550
        self assert: inf - huge equals: inf.
3✔
551
        self assert: half - inf equals: inf negated.
3✔
552
        self assert: minusTwo - inf negated equals: inf.
3✔
553
        self assert: (one - nan) isNaN.
3✔
554
        self assert: inf * two equals: inf.
3✔
555
        self assert: minusOne * inf equals: inf negated.
3✔
556
        self assert: inf negated * minusOne equals: inf.
3✔
557
        self assert: (huge * nan) isNaN.
3✔
558
        self assert: inf negated / minusTwo equals: inf.
3✔
559
        self assert: zero / inf negated equals: 0.
3✔
560
        self assert: one / inf equals: 0.
3✔
561
        self should: [ inf / zero ] raise: ZeroDivide.
3✔
562
        self assert: (nan / two) isNaN.
3✔
563
        self assert: (inf raisedTo: huge) equals: inf.
3✔
564
        self assert: (huge raisedTo: inf) equals: inf.
3✔
565
        self assert: (nan raisedTo: two) isNaN.
3✔
566
        self assert: (two raisedTo: nan) isNaN.
3✔
567
        self deny: nan <= one.
3✔
568
        self deny: zero >= nan.
3✔
569
        self assert: one < inf.
3✔
570
        self assert: zero ~= nan.
3✔
571
        self deny: nan equals: one
3✔
572
]
3✔
573

574
{ #category : #'testing-compare' }
575
PMArbitraryPrecisionFloatTest >> testIsZero [
3✔
576
        self assert: zero isZero.
3✔
577
        self deny: one isZero.
3✔
578
        self deny: minusTwo isZero
3✔
579
]
3✔
580

581
{ #category : #'testing-compare' }
582
PMArbitraryPrecisionFloatTest >> testLessThan [
3✔
583

3✔
584
        self assert: zero < one.
3✔
585
        self assert: one < two.
3✔
586
        self assert: two < huge.
3✔
587
        self assert: minusOne < one.
3✔
588
        self assert: minusTwo < minusOne.
3✔
589
        self assert: minusTwo < huge.
3✔
590

3✔
591
        self deny: huge < one.
3✔
592
        self deny: huge < zero.
3✔
593
        self deny: huge < minusOne.
3✔
594
        self deny: one < minusOne.
3✔
595
        self deny: minusOne < minusTwo
3✔
596
]
3✔
597

598
{ #category : #'testing-functions' }
599
PMArbitraryPrecisionFloatTest >> testLn [
3✔
600
        "seconds"
3✔
601

3✔
602
        <timeout: 10>
3✔
603
        | badLn serie |
3✔
604
        serie := (1 to: 100) collect: [ :e | e asFloat ].
3✔
605
        badLn := self checkDoublePrecisionSerieVsFloat: serie forFunction: #ln.
3✔
606
        badLn ifNotEmpty: [
3✔
607
                Transcript
3✔
608
                        cr;
3✔
609
                        show: 'bad ln for ' , badLn printString ]
3✔
610
]
3✔
611

612
{ #category : #'testing-functions' }
613
PMArbitraryPrecisionFloatTest >> testLnDomainError [
3✔
614
        self should: [(-2 asArbitraryPrecisionFloatNumBits: 24) ln] raise: DomainError
3✔
615
]
3✔
616

617
{ #category : #'testing-arithmetic' }
618
PMArbitraryPrecisionFloatTest >> testMultiply [
3✔
619

3✔
620
        self assert: zero * zero equals: zero.
3✔
621
        self assert: zero * minusOne equals: zero.
3✔
622
        self assert: huge * zero equals: zero.
3✔
623
        self assert: one * zero equals: zero.
3✔
624

3✔
625
        self assert: one * two equals: two.
3✔
626
        self assert: minusOne * one equals: minusOne.
3✔
627
        self assert: minusOne * minusTwo equals: two.
3✔
628

3✔
629
        self assert: half * two equals: one.
3✔
630

3✔
631
        "check rounding"
3✔
632
        self assert: huge * one equals: huge
3✔
633
]
3✔
634

635
{ #category : #'testing-arithmetic' }
636
PMArbitraryPrecisionFloatTest >> testNegated [
3✔
637

3✔
638
        self assert: zero negated equals: zero.
3✔
639
        self assert: one negated equals: minusOne.
3✔
640
        self assert: minusTwo negated equals: two.
3✔
641
        self assert: huge negated negated equals: huge
3✔
642
]
3✔
643

644
{ #category : #'testing-compare' }
645
PMArbitraryPrecisionFloatTest >> testNegative [
3✔
646

3✔
647
        self deny: zero negative.
3✔
648
        self deny: two negative.
3✔
649
        self assert: minusTwo negative
3✔
650
]
3✔
651

652
{ #category : #'testing-arithmetic' }
653
PMArbitraryPrecisionFloatTest >> testPi [
3✔
654
        "check computation of pi"
3✔
655

3✔
656
        self assert: (1 asArbitraryPrecisionFloatNumBits: 53) pi equals: Float pi
3✔
657
]
3✔
658

659
{ #category : #'testing-compare' }
660
PMArbitraryPrecisionFloatTest >> testPositive [
3✔
661

3✔
662
        self assert: zero positive.
3✔
663
        self assert: one positive.
3✔
664
        self deny: minusOne positive
3✔
665
]
3✔
666

667
{ #category : #'testing-converting' }
668
PMArbitraryPrecisionFloatTest >> testPrintAndEvaluate [
3✔
669
        "seconds"
3✔
670

3✔
671
        <timeout: 50>
3✔
672
        | emax emin leadingOne significands |
3✔
673
        significands := 0 to: (1 << 10) - 1.
3✔
674
        leadingOne := 1 << 10.
3✔
675
        emin := -14.
3✔
676
        emax := 15.
3✔
677

3✔
678
        "Test all normal finite half precision float"
3✔
679
        emin to: emax do: [ :e |
3✔
680
                significands
3✔
681
                        do: [ :s |
3✔
682
                                | f |
3✔
683
                                f := (leadingOne + s asArbitraryPrecisionFloatNumBits: 11)
3✔
684
                                        timesTwoPower: e - 10.
3✔
685
                                self
3✔
686
                                        assert: (Smalltalk compiler evaluate: f storeString)
3✔
687
                                        equals: f.
3✔
688
                                self
3✔
689
                                        assert: (Smalltalk compiler evaluate: f printString)
3✔
690
                                        equals: f ] ].
3✔
691

3✔
692
        "Test all subnormal finite half precision float"
3✔
693
        significands
3✔
694
                do: [ :s |
3✔
695
                        | f |
3✔
696
                        f := (s asArbitraryPrecisionFloatNumBits: s highBit)
3✔
697
                                timesTwoPower: emin - 10.
3✔
698
                        self assert: (Smalltalk compiler evaluate: f storeString) equals: f.
3✔
699
                        self assert: (Smalltalk compiler evaluate: f printString) equals: f ]
3✔
700
]
3✔
701

702
{ #category : #'testing-arithmetic' }
703
PMArbitraryPrecisionFloatTest >> testRaisedToNegativeInteger [
3✔
704
        | n |
3✔
705
        n := 11.
3✔
706
        1 to: 1<<n-1 do: [:i |
3✔
707
                self assert: ((i asArbitraryPrecisionFloatNumBits: n) raisedToInteger: -49)
3✔
708
                        equals: ((i raisedToInteger: -49) asArbitraryPrecisionFloatNumBits: n) ]
3✔
709
]
3✔
710

711
{ #category : #'testing-arithmetic' }
712
PMArbitraryPrecisionFloatTest >> testRaisedToPositiveInteger [
3✔
713
        | n |
3✔
714
        n := 11.
3✔
715
        1 to: 1<<n-1 do: [:i |
3✔
716
                self assert: ((i asArbitraryPrecisionFloatNumBits: n) raisedToInteger: 49)
3✔
717
                        equals: ((i raisedToInteger: 49) asArbitraryPrecisionFloatNumBits: n) ]
3✔
718
]
3✔
719

720
{ #category : #'testing-arithmetic' }
721
PMArbitraryPrecisionFloatTest >> testReciprocal [
3✔
722

3✔
723
        | b |
3✔
724
        b := 1 << (Float precision - 1).
3✔
725
        1 to: 10000 do: [ :i |
3✔
726
                | a |
3✔
727
                a := i asArbitraryPrecisionFloatNumBits: Float precision.
3✔
728
                self assert: a reciprocal equals: i asFloat reciprocal.
3✔
729
                self assert: (a + b) reciprocal equals: (i + b) asFloat reciprocal.
3✔
730
                self assert: a negated reciprocal equals: i asFloat negated reciprocal ]
3✔
731
]
3✔
732

733
{ #category : #'testing-arithmetic' }
734
PMArbitraryPrecisionFloatTest >> testRoundToNearestEven [
3✔
735
        "Check that IEEE default rounding mode is honoured,
3✔
736
        that is rounding to nearest even"
3✔
737

3✔
738
        self assert: ((one timesTwoPower: 52) + (0 + (1 / 4))) asTrueFraction equals: (1 bitShift: 52) + 0.
3✔
739
        self assert: ((one timesTwoPower: 52) + (0 + (1 / 2))) asTrueFraction equals: (1 bitShift: 52) + 0.
3✔
740
        self assert: ((one timesTwoPower: 52) + (0 + (3 / 4))) asTrueFraction equals: (1 bitShift: 52) + 1.
3✔
741
        self assert: ((one timesTwoPower: 52) + (1 + (1 / 4))) asTrueFraction equals: (1 bitShift: 52) + 1.
3✔
742
        self assert: ((one timesTwoPower: 52) + (1 + (1 / 2))) asTrueFraction equals: (1 bitShift: 52) + 2.
3✔
743
        self assert: ((one timesTwoPower: 52) + (1 + (3 / 4))) asTrueFraction equals: (1 bitShift: 52) + 2
3✔
744
]
3✔
745

746
{ #category : #'testing-arithmetic' }
747
PMArbitraryPrecisionFloatTest >> testRoundToNearestEvenAgainstIEEEDouble [
3✔
748
        "Check that IEEE default rounding mode is honoured"
3✔
749

3✔
750
        #( 1 2 3 5 6 7 ) do: [ :i |
3✔
751
                self assert: ((one timesTwoPower: 52) + (i / 4)) asTrueFraction equals: ((1 asFloat timesTwoPower: 52) + (i / 4)) asTrueFraction.
3✔
752
                self assert: ((one timesTwoPower: 52) - (i / 4)) asTrueFraction equals: ((1 asFloat timesTwoPower: 52) - (i / 4)) asTrueFraction ]
3✔
753
]
3✔
754

755
{ #category : #'testing-trigonometry' }
756
PMArbitraryPrecisionFloatTest >> testSin [
3✔
757
        "seconds"
3✔
758

3✔
759
        <timeout: 30>
3✔
760
        self checkDoublePrecisionSerieVsFloat: self trigonometricSerie forFunction: #sin
3✔
761
]
3✔
762

763
{ #category : #'testing-trigonometry' }
764
PMArbitraryPrecisionFloatTest >> testSincos [
3✔
765
        "seconds"
3✔
766

3✔
767
        <timeout: 30>
3✔
768
        self trigonometricSerie do: [ :aFloat |
3✔
769
                | x sc s c |
3✔
770
                x := aFloat asArbitraryPrecisionFloatNumBits: 53.
3✔
771
                sc := x sincos.
3✔
772
                s := x sin.
3✔
773
                c := x cos.
3✔
774
                self assert: sc size equals: 2.
3✔
775

3✔
776
                self assert: sc first equals: s.
3✔
777
                self assert: sc last equals: c ]
3✔
778
]
3✔
779

780
{ #category : #'testing-hyperbolic' }
781
PMArbitraryPrecisionFloatTest >> testSinh [
3✔
782
        <timeout: 10 "seconds">
3✔
783
        self checkDoublePrecisionSerie: self hyperbolicSerie forFunction: #sinh
3✔
784
]
3✔
785

786
{ #category : #'testing-functions' }
787
PMArbitraryPrecisionFloatTest >> testSqrt [
3✔
788
        "seconds"
3✔
789

3✔
790
        <timeout: 10>
3✔
791
        | badSqrt serie |
3✔
792
        "knowing that (10**3) < (2**10), 100 bits are enough for representing 10**30 exactly"
3✔
793
        self assert: ((10 raisedTo: 30) asArbitraryPrecisionFloatNumBits: 100) sqrt equals: (10 raisedTo: 15).
3✔
794

3✔
795
        serie := ((0 to: 20) collect: [ :e | e asFloat ]) , ((2 to: 20) collect: [ :e | e reciprocal asFloat ]).
3✔
796
        badSqrt := self checkDoublePrecisionSerieVsFloat: serie forFunction: #sqrt.
3✔
797
        badSqrt ifNotEmpty: [
3✔
798
                Transcript
3✔
799
                        cr;
3✔
800
                        show: 'bad sqrt for ' , badSqrt printString ]
3✔
801
]
3✔
802

803
{ #category : #'testing-functions' }
804
PMArbitraryPrecisionFloatTest >> testSqrtDomainError [
3✔
805
        self should: [(-2 asArbitraryPrecisionFloatNumBits: 24) sqrt] raise: DomainError
3✔
806
]
3✔
807

808
{ #category : #'testing-arithmetic' }
809
PMArbitraryPrecisionFloatTest >> testSubtract [
3✔
810

3✔
811
        self assert: zero - zero equals: zero.
3✔
812
        self assert: zero - minusOne equals: one.
3✔
813
        self assert: huge - zero equals: huge.
3✔
814
        self assert: one - zero equals: one.
3✔
815

3✔
816
        self assert: one - minusOne equals: two.
3✔
817
        self assert: minusOne - minusTwo equals: one.
3✔
818
        self assert: minusOne - one equals: minusTwo.
3✔
819

3✔
820
        "check rounding"
3✔
821
        self assert: huge - one equals: huge
3✔
822
]
3✔
823

824
{ #category : #'testing-arithmetic' }
825
PMArbitraryPrecisionFloatTest >> testSum [
3✔
826

3✔
827
        self assert: zero + zero equals: zero.
3✔
828
        self assert: zero + minusOne equals: minusOne.
3✔
829
        self assert: huge + zero equals: huge.
3✔
830
        self assert: one + zero equals: one.
3✔
831

3✔
832
        self assert: one + minusOne equals: zero.
3✔
833
        self assert: minusOne + two equals: one.
3✔
834
        self assert: one + minusTwo equals: minusOne.
3✔
835

3✔
836
        "check rounding"
3✔
837
        self assert: huge + one equals: huge
3✔
838
]
3✔
839

840
{ #category : #'testing-trigonometry' }
841
PMArbitraryPrecisionFloatTest >> testTan [
3✔
842
        "seconds"
3✔
843

3✔
844
        <timeout: 30>
3✔
845
        self checkDoublePrecisionSerieVsFloat: self trigonometricSerie forFunction: #tan
3✔
846
]
3✔
847

848
{ #category : #'testing-hyperbolic' }
849
PMArbitraryPrecisionFloatTest >> testTanh [
3✔
850
        <timeout: 10 "seconds">
3✔
851
        self checkDoublePrecisionSerie: self hyperbolicSerie forFunction: #tanh
3✔
852
]
3✔
853

854
{ #category : #'testing-trigonometry' }
855
PMArbitraryPrecisionFloatTest >> testVeryLargeCos [
3✔
856
        <timeout: 10 "seconds">
3✔
857
        self checkDoublePrecisionSerie: self largeTrigonometricSerie forFunction: #cos
3✔
858
]
3✔
859

860
{ #category : #'testing-trigonometry' }
861
PMArbitraryPrecisionFloatTest >> testVeryLargeSin [
3✔
862
        <timeout: 10 "seconds">
3✔
863
        self checkDoublePrecisionSerie: self largeTrigonometricSerie forFunction: #sin
3✔
864
]
3✔
865

866
{ #category : #'testing-trigonometry' }
867
PMArbitraryPrecisionFloatTest >> testVeryLargeTan [
3✔
868
        <timeout: 10 "seconds">
3✔
869
        self checkDoublePrecisionSerie: self largeTrigonometricSerie forFunction: #tan
3✔
870
]
3✔
871

872
{ #category : #'testing-arithmetic' }
873
PMArbitraryPrecisionFloatTest >> testZeroOne [
3✔
874

3✔
875
        self assert: (312 asArbitraryPrecisionFloatNumBits: 53) one equals: 1.
3✔
876
        self assert: (312 asArbitraryPrecisionFloatNumBits: 24) zero isZero.
3✔
877

3✔
878
        self assert: (312 asArbitraryPrecisionFloatNumBits: 53) one asInteger equals: 1.
3✔
879
        self assert: (312 asArbitraryPrecisionFloatNumBits: 24) zero asInteger isZero
3✔
880
]
3✔
881

882
{ #category : #'testing-trigonometry' }
883
PMArbitraryPrecisionFloatTest >> trigonometricSerie [
3✔
884
        ^(-720 to: 720) collect: [:i | i asFloat degreesToRadians]
3✔
885
]
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc