1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
|
discard """
targets: "c cpp js"
matrix:"; -d:danger"
"""
# xxx: there should be a test with `-d:nimTmathCase2 -d:danger --passc:-ffast-math`,
# but it requires disabling certain lines with `when not defined(nimTmathCase2)`
import std/math
# Function for approximate comparison of floats
proc `==~`(x, y: float): bool = abs(x - y) < 1e-9
template main() =
block:
when not defined(js):
# check for no side effect annotation
proc mySqrt(num: float): float {.noSideEffect.} =
# xxx unused
sqrt(num)
# check gamma function
doAssert gamma(5.0) == 24.0 # 4!
doAssert almostEqual(gamma(0.5), sqrt(PI))
doAssert almostEqual(gamma(-0.5), -2 * sqrt(PI))
doAssert lgamma(1.0) == 0.0 # ln(1.0) == 0.0
doAssert almostEqual(lgamma(0.5), 0.5 * ln(PI))
doAssert erf(6.0) > erf(5.0)
doAssert erfc(6.0) < erfc(5.0)
block: # sgn() tests
doAssert sgn(1'i8) == 1
doAssert sgn(1'i16) == 1
doAssert sgn(1'i32) == 1
doAssert sgn(1'i64) == 1
doAssert sgn(1'u8) == 1
doAssert sgn(1'u16) == 1
doAssert sgn(1'u32) == 1
doAssert sgn(1'u64) == 1
doAssert sgn(-12342.8844'f32) == -1
doAssert sgn(123.9834'f64) == 1
doAssert sgn(0'i32) == 0
doAssert sgn(0'f32) == 0
doAssert sgn(-0.0'f64) == 0
doAssert sgn(NegInf) == -1
doAssert sgn(Inf) == 1
doAssert sgn(NaN) == 0
block: # fac() tests
when nimvm: discard
else:
try:
discard fac(-1)
except AssertionDefect:
discard
doAssert fac(0) == 1
doAssert fac(1) == 1
doAssert fac(2) == 2
doAssert fac(3) == 6
doAssert fac(4) == 24
doAssert fac(5) == 120
block: # floorMod/floorDiv
doAssert floorDiv(8, 3) == 2
doAssert floorMod(8, 3) == 2
doAssert floorDiv(8, -3) == -3
doAssert floorMod(8, -3) == -1
doAssert floorDiv(-8, 3) == -3
doAssert floorMod(-8, 3) == 1
doAssert floorDiv(-8, -3) == 2
doAssert floorMod(-8, -3) == -2
doAssert floorMod(8.0, -3.0) == -1.0
doAssert floorMod(-8.5, 3.0) == 0.5
block: # euclDiv/euclMod
doAssert euclDiv(8, 3) == 2
doAssert euclMod(8, 3) == 2
doAssert euclDiv(8, -3) == -2
doAssert euclMod(8, -3) == 2
doAssert euclDiv(-8, 3) == -3
doAssert euclMod(-8, 3) == 1
doAssert euclDiv(-8, -3) == 3
doAssert euclMod(-8, -3) == 1
doAssert euclMod(8.0, -3.0) == 2.0
doAssert euclMod(-8.5, 3.0) == 0.5
doAssert euclDiv(9, 3) == 3
doAssert euclMod(9, 3) == 0
doAssert euclDiv(9, -3) == -3
doAssert euclMod(9, -3) == 0
doAssert euclDiv(-9, 3) == -3
doAssert euclMod(-9, 3) == 0
doAssert euclDiv(-9, -3) == 3
doAssert euclMod(-9, -3) == 0
block: # splitDecimal() tests
doAssert splitDecimal(54.674).intpart == 54.0
doAssert splitDecimal(54.674).floatpart ==~ 0.674
doAssert splitDecimal(-693.4356).intpart == -693.0
doAssert splitDecimal(-693.4356).floatpart ==~ -0.4356
doAssert splitDecimal(0.0).intpart == 0.0
doAssert splitDecimal(0.0).floatpart == 0.0
block: # trunc tests for vcc
doAssert trunc(-1.1) == -1
doAssert trunc(1.1) == 1
doAssert trunc(-0.1) == -0
doAssert trunc(0.1) == 0
# special case
doAssert classify(trunc(1e1000000)) == fcInf
doAssert classify(trunc(-1e1000000)) == fcNegInf
when not defined(nimTmathCase2):
doAssert classify(trunc(0.0/0.0)) == fcNan
doAssert classify(trunc(0.0)) == fcZero
# trick the compiler to produce signed zero
let
f_neg_one = -1.0
f_zero = 0.0
f_nan = f_zero / f_zero
doAssert classify(trunc(f_neg_one*f_zero)) == fcNegZero
doAssert trunc(-1.1'f32) == -1
doAssert trunc(1.1'f32) == 1
doAssert trunc(-0.1'f32) == -0
doAssert trunc(0.1'f32) == 0
doAssert classify(trunc(1e1000000'f32)) == fcInf
doAssert classify(trunc(-1e1000000'f32)) == fcNegInf
when not defined(nimTmathCase2):
doAssert classify(trunc(f_nan.float32)) == fcNan
doAssert classify(trunc(0.0'f32)) == fcZero
block: # log
doAssert log(4.0, 3.0) ==~ ln(4.0) / ln(3.0)
doAssert log2(8.0'f64) == 3.0'f64
doAssert log2(4.0'f64) == 2.0'f64
doAssert log2(2.0'f64) == 1.0'f64
doAssert log2(1.0'f64) == 0.0'f64
doAssert classify(log2(0.0'f64)) == fcNegInf
doAssert log2(8.0'f32) == 3.0'f32
doAssert log2(4.0'f32) == 2.0'f32
doAssert log2(2.0'f32) == 1.0'f32
doAssert log2(1.0'f32) == 0.0'f32
doAssert classify(log2(0.0'f32)) == fcNegInf
block: # cumsum
block: # cumsum int seq return
let counts = [1, 2, 3, 4]
doAssert counts.cumsummed == @[1, 3, 6, 10]
let empty: seq[int] = @[]
doAssert empty.cumsummed == @[]
block: # cumsum float seq return
let counts = [1.0, 2.0, 3.0, 4.0]
doAssert counts.cumsummed == @[1.0, 3.0, 6.0, 10.0]
let empty: seq[float] = @[]
doAssert empty.cumsummed == @[]
block: # cumsum int in-place
var counts = [1, 2, 3, 4]
counts.cumsum
doAssert counts == [1, 3, 6, 10]
var empty: seq[int] = @[]
empty.cumsum
doAssert empty == @[]
block: # cumsum float in-place
var counts = [1.0, 2.0, 3.0, 4.0]
counts.cumsum
doAssert counts == [1.0, 3.0, 6.0, 10.0]
var empty: seq[float] = @[]
empty.cumsum
doAssert empty == @[]
block: # ^ compiles for valid types
doAssert: compiles(5 ^ 2)
doAssert: compiles(5.5 ^ 2)
doAssert: compiles(5.5 ^ 2.int8)
doAssert: compiles(5.5 ^ 2.uint)
doAssert: compiles(5.5 ^ 2.uint8)
doAssert: not compiles(5.5 ^ 2.2)
block: # isNaN
doAssert NaN.isNaN
doAssert not Inf.isNaN
doAssert isNaN(Inf - Inf)
doAssert not isNaN(0.0)
doAssert not isNaN(3.1415926)
doAssert not isNaN(0'f32)
block: # signbit
doAssert not signbit(0.0)
doAssert signbit(-0.0)
doAssert signbit(-0.1)
doAssert not signbit(0.1)
doAssert not signbit(Inf)
doAssert signbit(-Inf)
doAssert not signbit(NaN)
let x1 = NaN
let x2 = -NaN
let x3 = -x1
doAssert isNaN(x1)
doAssert isNaN(x2)
doAssert isNaN(x3)
doAssert not signbit(x1)
doAssert signbit(x2)
doAssert signbit(x3)
block: # copySign
doAssert copySign(10.0, 1.0) == 10.0
doAssert copySign(10.0, -1.0) == -10.0
doAssert copySign(-10.0, -1.0) == -10.0
doAssert copySign(-10.0, 1.0) == 10.0
doAssert copySign(float(10), -1.0) == -10.0
doAssert copySign(10.0'f64, 1.0) == 10.0
doAssert copySign(10.0'f64, -1.0) == -10.0
doAssert copySign(-10.0'f64, -1.0) == -10.0
doAssert copySign(-10.0'f64, 1.0) == 10.0
doAssert copySign(10'f64, -1.0) == -10.0
doAssert copySign(10.0'f32, 1.0) == 10.0
doAssert copySign(10.0'f32, -1.0) == -10.0
doAssert copySign(-10.0'f32, -1.0) == -10.0
doAssert copySign(-10.0'f32, 1.0) == 10.0
doAssert copySign(10'f32, -1.0) == -10.0
doAssert copySign(Inf, -1.0) == -Inf
doAssert copySign(-Inf, 1.0) == Inf
doAssert copySign(Inf, 1.0) == Inf
doAssert copySign(-Inf, -1.0) == -Inf
doAssert copySign(Inf, 0.0) == Inf
doAssert copySign(Inf, -0.0) == -Inf
doAssert copySign(-Inf, 0.0) == Inf
doAssert copySign(-Inf, -0.0) == -Inf
doAssert copySign(1.0, -0.0) == -1.0
doAssert copySign(0.0, -0.0) == -0.0
doAssert copySign(-1.0, 0.0) == 1.0
doAssert copySign(10.0, 0.0) == 10.0
doAssert copySign(-1.0, NaN) == 1.0
doAssert copySign(10.0, NaN) == 10.0
doAssert copySign(NaN, NaN).isNaN
doAssert copySign(-NaN, NaN).isNaN
doAssert copySign(NaN, -NaN).isNaN
doAssert copySign(-NaN, -NaN).isNaN
doAssert copySign(NaN, 0.0).isNaN
doAssert copySign(NaN, -0.0).isNaN
doAssert copySign(-NaN, 0.0).isNaN
doAssert copySign(-NaN, -0.0).isNaN
doAssert copySign(-1.0, NaN) == 1.0
doAssert copySign(-1.0, -NaN) == -1.0
doAssert copySign(1.0, copySign(NaN, -1.0)) == -1.0
block: # almostEqual
doAssert almostEqual(3.141592653589793, 3.1415926535897936)
doAssert almostEqual(1.6777215e7'f32, 1.6777216e7'f32)
doAssert almostEqual(Inf, Inf)
doAssert almostEqual(-Inf, -Inf)
doAssert not almostEqual(Inf, -Inf)
doAssert not almostEqual(-Inf, Inf)
doAssert not almostEqual(Inf, NaN)
doAssert not almostEqual(NaN, NaN)
block: # round
block: # Round to 0 decimal places
doAssert round(54.652) == 55.0
doAssert round(54.352) == 54.0
doAssert round(-54.652) == -55.0
doAssert round(-54.352) == -54.0
doAssert round(0.0) == 0.0
doAssert 1 / round(0.0) == Inf
doAssert 1 / round(-0.0) == -Inf
doAssert round(Inf) == Inf
doAssert round(-Inf) == -Inf
doAssert round(NaN).isNaN
doAssert round(-NaN).isNaN
doAssert round(-0.5) == -1.0
doAssert round(0.5) == 1.0
doAssert round(-1.5) == -2.0
doAssert round(1.5) == 2.0
doAssert round(-2.5) == -3.0
doAssert round(2.5) == 3.0
doAssert round(2.5'f32) == 3.0'f32
doAssert round(2.5'f64) == 3.0'f64
block: # func round*[T: float32|float64](x: T, places: int): T
doAssert round(54.345, 0) == 54.0
template fn(x) =
doAssert round(x, 2).almostEqual 54.35
doAssert round(x, 2).almostEqual 54.35
doAssert round(x, -1).almostEqual 50.0
doAssert round(x, -2).almostEqual 100.0
doAssert round(x, -3).almostEqual 0.0
fn(54.346)
fn(54.346'f32)
block: # abs
doAssert 1.0 / abs(-0.0) == Inf
doAssert 1.0 / abs(0.0) == Inf
doAssert -1.0 / abs(-0.0) == -Inf
doAssert -1.0 / abs(0.0) == -Inf
doAssert abs(0.0) == 0.0
doAssert abs(0.0'f32) == 0.0'f32
doAssert abs(Inf) == Inf
doAssert abs(-Inf) == Inf
doAssert abs(NaN).isNaN
doAssert abs(-NaN).isNaN
block: # classify
doAssert classify(0.3) == fcNormal
doAssert classify(-0.3) == fcNormal
doAssert classify(5.0e-324) == fcSubnormal
doAssert classify(-5.0e-324) == fcSubnormal
doAssert classify(0.0) == fcZero
doAssert classify(-0.0) == fcNegZero
doAssert classify(NaN) == fcNan
doAssert classify(0.3 / 0.0) == fcInf
doAssert classify(Inf) == fcInf
doAssert classify(-0.3 / 0.0) == fcNegInf
doAssert classify(-Inf) == fcNegInf
block: # sum
let empty: seq[int] = @[]
doAssert sum(empty) == 0
doAssert sum([1, 2, 3, 4]) == 10
doAssert sum([-4, 3, 5]) == 4
block: # prod
let empty: seq[int] = @[]
doAssert prod(empty) == 1
doAssert prod([1, 2, 3, 4]) == 24
doAssert prod([-4, 3, 5]) == -60
doAssert almostEqual(prod([1.5, 3.4]), 5.1)
let x: seq[float] = @[]
doAssert prod(x) == 1.0
block: # clamp range
doAssert clamp(10, 1..5) == 5
doAssert clamp(3, 1..5) == 3
doAssert clamp(5, 1..5) == 5
doAssert clamp(42.0, 1.0 .. 3.1415926535) == 3.1415926535
doAssert clamp(NaN, 1.0 .. 2.0).isNaN
doAssert clamp(-Inf, -Inf .. -1.0) == -Inf
type A = enum a0, a1, a2, a3, a4, a5
doAssert a1.clamp(a2..a4) == a2
doAssert clamp((3, 0), (1, 0) .. (2, 9)) == (2, 9)
block: # edge cases
doAssert sqrt(-4.0).isNaN
doAssert ln(0.0) == -Inf
doAssert ln(-0.0) == -Inf
doAssert ln(-12.0).isNaN
doAssert log10(0.0) == -Inf
doAssert log10(-0.0) == -Inf
doAssert log10(-12.0).isNaN
doAssert log2(0.0) == -Inf
doAssert log2(-0.0) == -Inf
doAssert log2(-12.0).isNaN
when nimvm: discard
else:
doAssert frexp(0.0) == (0.0, 0)
doAssert frexp(-0.0) == (-0.0, 0)
doAssert classify(frexp(-0.0)[0]) == fcNegZero
when not defined(js):
doAssert gamma(0.0) == Inf
doAssert gamma(-0.0) == -Inf
doAssert gamma(-1.0).isNaN
doAssert lgamma(0.0) == Inf
doAssert lgamma(-0.0) == Inf
doAssert lgamma(-1.0) == Inf
when nimvm: discard
else:
var exponent: cint
doAssert c_frexp(0.0, exponent) == 0.0
doAssert c_frexp(-0.0, exponent) == -0.0
doAssert classify(c_frexp(-0.0, exponent)) == fcNegZero
static: main()
main()
|