Skip to content

Commit 830a815

Browse files
committed
Merge pull request #2883 from apple/stdlib-float-testing
2 parents f45eb9e + 876856c commit 830a815

File tree

4 files changed

+199
-20
lines changed

4 files changed

+199
-20
lines changed

stdlib/private/StdlibUnittest/StdlibUnittest.swift.gyb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,13 @@ public func expectEqual<T : Equatable, U : Equatable>(
143143
expectEqual(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
144144
}
145145

146+
public func expectEqual<T : Equatable, U : Equatable, V : Equatable>(
147+
_ expected: (T, U, V), _ actual: (T, U, V), ${TRACE}) {
148+
expectEqual(expected.0, actual.0, ${trace}, showFrame: false) {$0 == $1}
149+
expectEqual(expected.1, actual.1, ${trace}, showFrame: false) {$0 == $1}
150+
expectEqual(expected.2, actual.2, ${trace}, showFrame: false) {$0 == $1}
151+
}
152+
146153
public func expectationFailure(
147154
_ reason: String,
148155
trace message: String,

stdlib/public/core/FloatingPointTypes.swift.gyb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ builtinIntLiteralBits = 2048
3434
# Mapping from float bits to significand bits
3535
explicitSignificandBits = { 32:24, 64:53, 80:64 }
3636

37-
cFunctionSuffix = { 32:'f', 64:'', 80:'l' }
38-
3937
def allInts():
4038
for bits in allIntBits:
4139
for signed in False, True:

test/1_stdlib/FloatingPoint.swift.gyb

Lines changed: 130 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
// RUN: %S/../../utils/line-directive %t/FloatingPoint.swift -- %target-run %t/a.out
44
// REQUIRES: executable_test
55

6+
%{
7+
from gyb_stdlib_unittest_support import TRACE, stackTrace, trace
8+
}%
9+
610
import Swift
711
import StdlibUnittest
812

9-
1013
#if arch(i386) || arch(x86_64)
1114

1215
struct Float80Bits : Equatable, CustomStringConvertible {
@@ -19,7 +22,7 @@ struct Float80Bits : Equatable, CustomStringConvertible {
1922
}
2023

2124
var description: String {
22-
return "(\(String(signAndExponent, radix: 16)) \(String(significand, radix: 16))))"
25+
return "(\(String(signAndExponent, radix: 16)) \(String(significand, radix: 16)))"
2326
}
2427
}
2528

@@ -51,6 +54,29 @@ extension Float80 {
5154

5255
#endif
5356

57+
% for (FloatTy, BitPatternTy) in [
58+
% ('Float', 'UInt32'),
59+
% ('Double', 'UInt64'),
60+
% ('Float80', 'Float80Bits')
61+
% ]:
62+
% if FloatTy == 'Float80':
63+
#if arch(i386) || arch(x86_64)
64+
% end
65+
func expectBitwiseEqual(
66+
_ expected: ${FloatTy}, _ actual: ${FloatTy}, ${TRACE}
67+
) {
68+
expectEqual(expected.bitPattern, actual.bitPattern, ${trace})
69+
}
70+
func expectBitwiseEqual(
71+
bitPattern expected: ${BitPatternTy}, _ actual: ${FloatTy}, ${TRACE}
72+
) {
73+
expectBitwiseEqual(${FloatTy}(bitPattern: expected), actual, ${trace})
74+
}
75+
% if FloatTy == 'Float80':
76+
#endif
77+
% end
78+
% end
79+
5480
var FloatingPoint = TestSuite("FloatingPoint")
5581

5682
func positiveOne<T: IntegerLiteralConvertible>() -> T {
@@ -65,6 +91,29 @@ FloatingPoint.test("Float/IntegerLiteralConvertible") {
6591
expectEqual(negativeOne(), -1.0 as Float)
6692
}
6793

94+
FloatingPoint.test("Float/FloatLiteralConvertible") {
95+
let x: Float = -0.0
96+
expectBitwiseEqual(bitPattern: 0x8000_0000, x)
97+
}
98+
99+
FloatingPoint.test("Float/staticProperties") {
100+
typealias Ty = Float
101+
// From the FloatingPoint protocol.
102+
expectEqual(2, Ty.radix)
103+
expectBitwiseEqual(bitPattern: 0x7fc0_0000, Ty.nan)
104+
expectBitwiseEqual(bitPattern: 0x7fa0_0000, Ty.signalingNaN)
105+
expectBitwiseEqual(bitPattern: 0x7f80_0000, Ty.infinity)
106+
expectBitwiseEqual(0x1.ffff_fe__p127, Ty.greatestFiniteMagnitude)
107+
expectBitwiseEqual(0x1.921f_b6__p1, Ty.pi)
108+
expectBitwiseEqual(0x1.0p-23, Ty.ulpOfOne)
109+
expectBitwiseEqual(0x1.0p-126, Ty.leastNormalMagnitude)
110+
expectBitwiseEqual(0x1.0p-149, Ty.leastNonzeroMagnitude)
111+
112+
// From the BinaryFloatingPoint protocol.
113+
expectEqual(8, Ty.exponentBitCount)
114+
expectEqual(23, Ty.significandBitCount)
115+
}
116+
68117
// Tests the float and int conversions work correctly. Each case is special.
69118
FloatingPoint.test("Float/UInt8") {
70119
expectEqual(UInt8.min, UInt8(Float(UInt8.min)))
@@ -115,6 +164,29 @@ FloatingPoint.test("Double/IntegerLiteralConvertible") {
115164
expectEqual(negativeOne(), -1.0 as Double)
116165
}
117166

167+
FloatingPoint.test("Double/FloatLiteralConvertible") {
168+
let x: Double = -0.0
169+
expectBitwiseEqual(bitPattern: 0x8000_0000_0000_0000, x)
170+
}
171+
172+
FloatingPoint.test("Double/staticProperties") {
173+
typealias Ty = Double
174+
// From the FloatingPoint protocol.
175+
expectEqual(2, Ty.radix)
176+
expectBitwiseEqual(bitPattern: 0x7ff8_0000_0000_0000, Ty.nan)
177+
expectBitwiseEqual(bitPattern: 0x7ff4_0000_0000_0000, Ty.signalingNaN)
178+
expectBitwiseEqual(bitPattern: 0x7ff0_0000_0000_0000, Ty.infinity)
179+
expectBitwiseEqual(0x1.ffff_ffff_ffff_f__p1023, Ty.greatestFiniteMagnitude)
180+
expectBitwiseEqual(0x1.921f_b544_42d1_8__p1, Ty.pi)
181+
expectBitwiseEqual(0x1.0p-52, Ty.ulpOfOne)
182+
expectBitwiseEqual(0x1.0p-1022, Ty.leastNormalMagnitude)
183+
expectBitwiseEqual(0x1.0p-1074, Ty.leastNonzeroMagnitude)
184+
185+
// From the BinaryFloatingPoint protocol.
186+
expectEqual(11, Ty.exponentBitCount)
187+
expectEqual(52, Ty.significandBitCount)
188+
}
189+
118190
FloatingPoint.test("Double/UInt8") {
119191
expectEqual(UInt8.min, UInt8(Double(UInt8.min)))
120192
expectEqual(UInt8.max, UInt8(Double(UInt8.max)))
@@ -174,37 +246,35 @@ FloatingPoint.test("Double/HashValueZero") {
174246
let floatNextUpDownTests: [(Float, Float)] = [
175247
(.nan, .nan),
176248
(.greatestFiniteMagnitude, .infinity),
177-
(-.infinity, -.greatestFiniteMagnitude),
178-
(0x1.fffffep-1, 1.0), (1.0, 0x1.000002p+0),
179-
(-0x1p-149, -0.0), (0.0, 0x1p-149),
180-
(0x1.effffep-1, 0.96875), (0.96875, 0x1.f00002p-1),
249+
(0x1.ffff_fe__p-1, 1.0), (1.0, 0x1.0000_02__p+0),
250+
(0.0, .leastNonzeroMagnitude),
251+
(0x1.efff_fe__p-1, 0x1.fp-1), (0x1.fp-1, 0x1.f000_02__p-1),
181252
]
182253

183254
FloatingPoint.test("Float.nextUp, .nextDown")
184255
.forEach(in: floatNextUpDownTests) {
185256
(prev, succ) in
186-
expectEqual(succ.bitPattern, prev.nextUp.bitPattern)
187-
expectEqual(prev.bitPattern, succ.nextDown.bitPattern)
188-
expectEqual((-succ).bitPattern, (-prev).nextDown.bitPattern)
189-
expectEqual((-prev).bitPattern, (-succ).nextUp.bitPattern)
257+
expectBitwiseEqual(succ, prev.nextUp)
258+
expectBitwiseEqual(prev, succ.nextDown)
259+
expectBitwiseEqual(-succ, (-prev).nextDown)
260+
expectBitwiseEqual(-prev, (-succ).nextUp)
190261
}
191262

192263
let doubleNextUpDownTests: [(Double, Double)] = [
193264
(.nan, .nan),
194265
(.greatestFiniteMagnitude, .infinity),
195-
(-.infinity, -.greatestFiniteMagnitude),
196-
(0x1.fffffffffffffp-1, 1.0), (1.0, 0x1.0000000000001p+0),
197-
(-0x1p-1074, -0.0), (0.0, 0x1p-1074),
198-
(0x1.effffffffffffp-1, 0.96875), (0.96875, 0x1.f000000000001p-1),
266+
(0x1.ffff_ffff_ffff_fp-1, 1.0), (1.0, 0x1.0000_0000_0000_1p+0),
267+
(0.0, .leastNonzeroMagnitude),
268+
(0x1.efff_ffff_ffff_fp-1, 0x1.fp-1), (0x1.fp-1, 0x1.f000_0000_0000_1p-1),
199269
]
200270

201271
FloatingPoint.test("Double.nextUp, .nextDown")
202272
.forEach(in: doubleNextUpDownTests) {
203273
(prev, succ) in
204-
expectEqual(succ.bitPattern, prev.nextUp.bitPattern)
205-
expectEqual(prev.bitPattern, succ.nextDown.bitPattern)
206-
expectEqual((-succ).bitPattern, (-prev).nextDown.bitPattern)
207-
expectEqual((-prev).bitPattern, (-succ).nextUp.bitPattern)
274+
expectBitwiseEqual(succ, prev.nextUp)
275+
expectBitwiseEqual(prev, succ.nextDown)
276+
expectBitwiseEqual(-succ, (-prev).nextDown)
277+
expectBitwiseEqual(-prev, (-succ).nextUp)
208278
}
209279

210280
#if arch(i386) || arch(x86_64)
@@ -214,13 +284,55 @@ FloatingPoint.test("Float80/IntegerLiteralConvertible") {
214284
expectEqual(negativeOne(), -1.0 as Float80)
215285
}
216286

287+
FloatingPoint.test("Float80/FloatLiteralConvertible") {
288+
let x: Float80 = -0.0
289+
expectBitwiseEqual(bitPattern: Float80Bits(0x8000, 0), x)
290+
}
291+
292+
FloatingPoint.test("Float80/staticProperties") {
293+
typealias Ty = Double
294+
// From the FloatingPoint protocol.
295+
expectEqual(2, Ty.radix)
296+
expectBitwiseEqual(bitPattern: 0x7ff8_0000_0000_0000, Ty.nan)
297+
expectBitwiseEqual(bitPattern: 0x7ff4_0000_0000_0000, Ty.signalingNaN)
298+
expectBitwiseEqual(bitPattern: 0x7ff0_0000_0000_0000, Ty.infinity)
299+
expectBitwiseEqual(0x1.ffff_ffff_ffff_f__p1023, Ty.greatestFiniteMagnitude)
300+
expectBitwiseEqual(0x1.921f_b544_42d1_8__p1, Ty.pi)
301+
expectBitwiseEqual(0x1.0p-52, Ty.ulpOfOne)
302+
expectBitwiseEqual(0x1.0p-1022, Ty.leastNormalMagnitude)
303+
expectBitwiseEqual(0x1.0p-1074, Ty.leastNonzeroMagnitude)
304+
305+
// From the BinaryFloatingPoint protocol.
306+
expectEqual(11, Ty.exponentBitCount)
307+
expectEqual(52, Ty.significandBitCount)
308+
}
309+
217310
FloatingPoint.test("Float80/HashValueZero") {
218311
let zero: Float80 = getFloat80(0.0)
219312
let negativeZero: Float80 = getFloat80(-0.0)
220313
expectNotEqual(zero.bitPattern, negativeZero.bitPattern)
221314
expectEqual(zero.hashValue, negativeZero.hashValue)
222315
}
223316

317+
let float80NextUpDownTests: [(Float80, Float80)] = [
318+
(.nan, .nan),
319+
(.greatestFiniteMagnitude, .infinity),
320+
(0x1.ffff_ffff_ffff_fffep-1, 1.0), (1.0, 0x1.0000_0000_0000_0002p+0),
321+
(0.0, .leastNonzeroMagnitude),
322+
(0x1.efff_ffff_ffff_fffep-1, 0x1.fp-1),
323+
(0x1.fp-1, 0x1.f000_0000_0000_0002p-1),
324+
]
325+
326+
FloatingPoint.test("Float80.nextUp, .nextDown")
327+
.forEach(in: float80NextUpDownTests) {
328+
(prev, succ) in
329+
330+
expectBitwiseEqual(succ, prev.nextUp)
331+
expectBitwiseEqual(prev, succ.nextDown)
332+
expectBitwiseEqual(-succ, (-prev).nextDown)
333+
expectBitwiseEqual(-prev, (-succ).nextUp)
334+
}
335+
224336
#endif
225337

226338
% for FloatSelf in ['Float32', 'Float64']:

validation-test/StdlibUnittest/Assertions.swift.gyb

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,67 @@ AssertionsTestSuite.test("expectEqualsUnordered(Range<T>, [T])") {
162162
% end
163163
}
164164

165+
AssertionsTestSuite.test("expectEqual<T : Equatable>") {
166+
let _0 = MinimalEquatableValue(0)
167+
let _1 = MinimalEquatableValue(1)
168+
169+
expectEqual(_0, _0)
170+
expectEqual(_1, _1)
171+
expectFailure {
172+
expectEqual(_0, _1)
173+
expectEqual(_1, _0)
174+
}
175+
}
176+
177+
AssertionsTestSuite.test("expectEqual<T : Equatable, U : Equatable>") {
178+
let _0 = MinimalEquatableValue(0)
179+
let _1 = MinimalEquatableValue(1)
180+
181+
for a in [_0, _1] {
182+
for b in [_0, _1] {
183+
for c in [_0, _1] {
184+
for d in [_0, _1] {
185+
let lhs = (a, b)
186+
let rhs = (c, d)
187+
if lhs == rhs {
188+
expectEqual(lhs, rhs)
189+
} else {
190+
expectFailure {
191+
expectEqual(lhs, rhs)
192+
}
193+
}
194+
}
195+
}
196+
}
197+
}
198+
}
199+
200+
AssertionsTestSuite.test("expectEqual<T : Equatable, U : Equatable, V : Equatable>") {
201+
let _0 = MinimalEquatableValue(0)
202+
let _1 = MinimalEquatableValue(1)
203+
204+
for a in [_0, _1] {
205+
for b in [_0, _1] {
206+
for c in [_0, _1] {
207+
for d in [_0, _1] {
208+
for e in [_0, _1] {
209+
for f in [_0, _1] {
210+
let lhs = (a, b, c)
211+
let rhs = (d, e, f)
212+
if lhs == rhs {
213+
expectEqual(lhs, rhs)
214+
} else {
215+
expectFailure {
216+
expectEqual(lhs, rhs)
217+
}
218+
}
219+
}
220+
}
221+
}
222+
}
223+
}
224+
}
225+
}
226+
165227
runAllTests()
166228

0 commit comments

Comments
 (0)