Skip to content

Commit d3d91b8

Browse files
committed
Add per-source-file tests for authoritative Binary64 and Binary32 implementations
Completes 1:1 test file mapping following INCITS 4-1986 pattern: - IEEE_754.Binary64 Tests.swift: Tests for authoritative Binary64 implementation - IEEE_754.Binary32 Tests.swift: Tests for authoritative Binary32 implementation Each file tests: - Constants (byteSize, bitSize, exponentBits, significandBits, exponentBias, maxExponent) - Authoritative serialization (bytes(from:endianness:)) - Authoritative deserialization (value(from:endianness:)) - Special values (NaN, ±0 with sign preservation) - Byte count validation - Endianness handling Tests increased from 48 to 80 across 22 suites. All tests passing.
1 parent 529b284 commit d3d91b8

File tree

2 files changed

+302
-0
lines changed

2 files changed

+302
-0
lines changed
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// IEEE_754.Binary32 Tests.swift
2+
// swift-ieee-754
3+
//
4+
// Tests for IEEE 754 Binary32 (authoritative implementation)
5+
6+
import Testing
7+
@testable import IEEE_754
8+
9+
@Suite("IEEE_754.Binary32 - Constants")
10+
struct Binary32ConstantsTests {
11+
@Test func `byte size is 4`() {
12+
#expect(IEEE_754.Binary32.byteSize == 4)
13+
}
14+
15+
@Test func `bit size is 32`() {
16+
#expect(IEEE_754.Binary32.bitSize == 32)
17+
}
18+
19+
@Test func `sign bits is 1`() {
20+
#expect(IEEE_754.Binary32.signBits == 1)
21+
}
22+
23+
@Test func `exponent bits is 8`() {
24+
#expect(IEEE_754.Binary32.exponentBits == 8)
25+
}
26+
27+
@Test func `significand bits is 23`() {
28+
#expect(IEEE_754.Binary32.significandBits == 23)
29+
}
30+
31+
@Test func `exponent bias is 127`() {
32+
#expect(IEEE_754.Binary32.exponentBias == 127)
33+
}
34+
35+
@Test func `max exponent is 255`() {
36+
#expect(IEEE_754.Binary32.maxExponent == 255)
37+
}
38+
39+
@Test func `bit layout sums to 32`() {
40+
let total = IEEE_754.Binary32.signBits +
41+
IEEE_754.Binary32.exponentBits +
42+
IEEE_754.Binary32.significandBits
43+
#expect(total == 32, "Sign + exponent + significand bits should equal 32")
44+
}
45+
}
46+
47+
@Suite("IEEE_754.Binary32 - Authoritative serialization")
48+
struct Binary32SerializationTests {
49+
@Test(arguments: [
50+
Float(3.14159),
51+
Float(2.71828),
52+
Float(1.41421),
53+
Float(0.0),
54+
Float(-0.0),
55+
Float(1.0),
56+
Float(-1.0),
57+
Float.infinity,
58+
-Float.infinity,
59+
Float.pi,
60+
])
61+
func `bytes(from:) produces correct byte count`(value: Float) {
62+
let bytes = IEEE_754.Binary32.bytes(from: value)
63+
#expect(bytes.count == 4, "Binary32 should always produce 4 bytes")
64+
}
65+
66+
@Test(arguments: [Float(3.14), Float(2.718), Float(1.414), Float(42.0)])
67+
func `bytes(from:) with different endianness`(value: Float) {
68+
let little = IEEE_754.Binary32.bytes(from: value, endianness: .little)
69+
let big = IEEE_754.Binary32.bytes(from: value, endianness: .big)
70+
71+
#expect(little.count == 4, "Little endian should produce 4 bytes")
72+
#expect(big.count == 4, "Big endian should produce 4 bytes")
73+
#expect(little != big, "Different endianness should produce different byte order")
74+
#expect(little == big.reversed(), "Big endian should be reverse of little")
75+
}
76+
}
77+
78+
@Suite("IEEE_754.Binary32 - Authoritative deserialization")
79+
struct Binary32DeserializationTests {
80+
@Test(arguments: [
81+
Float(3.14159),
82+
Float(2.71828),
83+
Float(1.41421),
84+
Float(0.0),
85+
Float(1.0),
86+
Float(-1.0),
87+
Float.infinity,
88+
-Float.infinity,
89+
])
90+
func `value(from:) round-trip`(original: Float) {
91+
let bytes = IEEE_754.Binary32.bytes(from: original)
92+
let restored = IEEE_754.Binary32.value(from: bytes)
93+
94+
#expect(restored == original, "\(original) should round-trip through Binary32")
95+
}
96+
97+
@Test func `value(from:) with wrong byte count returns nil`() {
98+
#expect(IEEE_754.Binary32.value(from: []) == nil, "Empty array should return nil")
99+
#expect(IEEE_754.Binary32.value(from: [UInt8](repeating: 0, count: 3)) == nil, "3 bytes should return nil")
100+
#expect(IEEE_754.Binary32.value(from: [UInt8](repeating: 0, count: 5)) == nil, "5 bytes should return nil")
101+
}
102+
103+
@Test func `value(from:) with exactly 4 bytes succeeds`() {
104+
let bytes = [UInt8](repeating: 0, count: 4)
105+
let result = IEEE_754.Binary32.value(from: bytes)
106+
107+
#expect(result != nil, "4 bytes should succeed")
108+
#expect(result == 0.0, "All-zero bytes should decode to 0.0")
109+
}
110+
111+
@Test(arguments: [Float(3.14), Float(2.718), Float(1.414)])
112+
func `value(from:) respects endianness`(value: Float) {
113+
let littleBytes = IEEE_754.Binary32.bytes(from: value, endianness: .little)
114+
let bigBytes = IEEE_754.Binary32.bytes(from: value, endianness: .big)
115+
116+
let fromLittle = IEEE_754.Binary32.value(from: littleBytes, endianness: .little)
117+
let fromBig = IEEE_754.Binary32.value(from: bigBytes, endianness: .big)
118+
119+
#expect(fromLittle == value, "Little endian round-trip should work")
120+
#expect(fromBig == value, "Big endian round-trip should work")
121+
122+
// Mismatched endianness should fail
123+
let wrongLittle = IEEE_754.Binary32.value(from: bigBytes, endianness: .little)
124+
let wrongBig = IEEE_754.Binary32.value(from: littleBytes, endianness: .big)
125+
126+
#expect(wrongLittle != value, "Mismatched endianness should fail")
127+
#expect(wrongBig != value, "Mismatched endianness should fail")
128+
}
129+
}
130+
131+
@Suite("IEEE_754.Binary32 - Special values")
132+
struct Binary32SpecialValuesTests {
133+
@Test func `NaN round-trip`() {
134+
let nan = Float.nan
135+
let bytes = IEEE_754.Binary32.bytes(from: nan)
136+
let restored = IEEE_754.Binary32.value(from: bytes)
137+
138+
#expect(restored?.isNaN == true, "NaN should round-trip as NaN")
139+
}
140+
141+
@Test(arguments: [Float(0.0), Float(-0.0)])
142+
func `zero with sign preservation`(value: Float) {
143+
let bytes = IEEE_754.Binary32.bytes(from: value)
144+
let restored = IEEE_754.Binary32.value(from: bytes)
145+
146+
#expect(restored == value, "Zero should round-trip")
147+
if value.sign == .minus {
148+
#expect(restored?.sign == .minus, "Negative zero should preserve sign")
149+
}
150+
}
151+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
// IEEE_754.Binary64 Tests.swift
2+
// swift-ieee-754
3+
//
4+
// Tests for IEEE 754 Binary64 (authoritative implementation)
5+
6+
import Testing
7+
@testable import IEEE_754
8+
9+
@Suite("IEEE_754.Binary64 - Constants")
10+
struct Binary64ConstantsTests {
11+
@Test func `byte size is 8`() {
12+
#expect(IEEE_754.Binary64.byteSize == 8)
13+
}
14+
15+
@Test func `bit size is 64`() {
16+
#expect(IEEE_754.Binary64.bitSize == 64)
17+
}
18+
19+
@Test func `sign bits is 1`() {
20+
#expect(IEEE_754.Binary64.signBits == 1)
21+
}
22+
23+
@Test func `exponent bits is 11`() {
24+
#expect(IEEE_754.Binary64.exponentBits == 11)
25+
}
26+
27+
@Test func `significand bits is 52`() {
28+
#expect(IEEE_754.Binary64.significandBits == 52)
29+
}
30+
31+
@Test func `exponent bias is 1023`() {
32+
#expect(IEEE_754.Binary64.exponentBias == 1023)
33+
}
34+
35+
@Test func `max exponent is 2047`() {
36+
#expect(IEEE_754.Binary64.maxExponent == 2047)
37+
}
38+
39+
@Test func `bit layout sums to 64`() {
40+
let total = IEEE_754.Binary64.signBits +
41+
IEEE_754.Binary64.exponentBits +
42+
IEEE_754.Binary64.significandBits
43+
#expect(total == 64, "Sign + exponent + significand bits should equal 64")
44+
}
45+
}
46+
47+
@Suite("IEEE_754.Binary64 - Authoritative serialization")
48+
struct Binary64SerializationTests {
49+
@Test(arguments: [
50+
3.14159265358979323846,
51+
2.71828182845904523536,
52+
1.41421356237309504880,
53+
0.0,
54+
-0.0,
55+
1.0,
56+
-1.0,
57+
Double.infinity,
58+
-Double.infinity,
59+
Double.pi,
60+
])
61+
func `bytes(from:) produces correct byte count`(value: Double) {
62+
let bytes = IEEE_754.Binary64.bytes(from: value)
63+
#expect(bytes.count == 8, "Binary64 should always produce 8 bytes")
64+
}
65+
66+
@Test(arguments: [3.14159, 2.71828, 1.41421, 42.0])
67+
func `bytes(from:) with different endianness`(value: Double) {
68+
let little = IEEE_754.Binary64.bytes(from: value, endianness: .little)
69+
let big = IEEE_754.Binary64.bytes(from: value, endianness: .big)
70+
71+
#expect(little.count == 8, "Little endian should produce 8 bytes")
72+
#expect(big.count == 8, "Big endian should produce 8 bytes")
73+
#expect(little != big, "Different endianness should produce different byte order")
74+
#expect(little == big.reversed(), "Big endian should be reverse of little")
75+
}
76+
}
77+
78+
@Suite("IEEE_754.Binary64 - Authoritative deserialization")
79+
struct Binary64DeserializationTests {
80+
@Test(arguments: [
81+
3.14159265358979323846,
82+
2.71828182845904523536,
83+
1.41421356237309504880,
84+
0.0,
85+
1.0,
86+
-1.0,
87+
Double.infinity,
88+
-Double.infinity,
89+
])
90+
func `value(from:) round-trip`(original: Double) {
91+
let bytes = IEEE_754.Binary64.bytes(from: original)
92+
let restored = IEEE_754.Binary64.value(from: bytes)
93+
94+
#expect(restored == original, "\(original) should round-trip through Binary64")
95+
}
96+
97+
@Test func `value(from:) with wrong byte count returns nil`() {
98+
#expect(IEEE_754.Binary64.value(from: []) == nil, "Empty array should return nil")
99+
#expect(IEEE_754.Binary64.value(from: [UInt8](repeating: 0, count: 7)) == nil, "7 bytes should return nil")
100+
#expect(IEEE_754.Binary64.value(from: [UInt8](repeating: 0, count: 9)) == nil, "9 bytes should return nil")
101+
}
102+
103+
@Test func `value(from:) with exactly 8 bytes succeeds`() {
104+
let bytes = [UInt8](repeating: 0, count: 8)
105+
let result = IEEE_754.Binary64.value(from: bytes)
106+
107+
#expect(result != nil, "8 bytes should succeed")
108+
#expect(result == 0.0, "All-zero bytes should decode to 0.0")
109+
}
110+
111+
@Test(arguments: [3.14159, 2.71828, 1.41421])
112+
func `value(from:) respects endianness`(value: Double) {
113+
let littleBytes = IEEE_754.Binary64.bytes(from: value, endianness: .little)
114+
let bigBytes = IEEE_754.Binary64.bytes(from: value, endianness: .big)
115+
116+
let fromLittle = IEEE_754.Binary64.value(from: littleBytes, endianness: .little)
117+
let fromBig = IEEE_754.Binary64.value(from: bigBytes, endianness: .big)
118+
119+
#expect(fromLittle == value, "Little endian round-trip should work")
120+
#expect(fromBig == value, "Big endian round-trip should work")
121+
122+
// Mismatched endianness should fail
123+
let wrongLittle = IEEE_754.Binary64.value(from: bigBytes, endianness: .little)
124+
let wrongBig = IEEE_754.Binary64.value(from: littleBytes, endianness: .big)
125+
126+
#expect(wrongLittle != value, "Mismatched endianness should fail")
127+
#expect(wrongBig != value, "Mismatched endianness should fail")
128+
}
129+
}
130+
131+
@Suite("IEEE_754.Binary64 - Special values")
132+
struct Binary64SpecialValuesTests {
133+
@Test func `NaN round-trip`() {
134+
let nan = Double.nan
135+
let bytes = IEEE_754.Binary64.bytes(from: nan)
136+
let restored = IEEE_754.Binary64.value(from: bytes)
137+
138+
#expect(restored?.isNaN == true, "NaN should round-trip as NaN")
139+
}
140+
141+
@Test(arguments: [0.0, -0.0])
142+
func `zero with sign preservation`(value: Double) {
143+
let bytes = IEEE_754.Binary64.bytes(from: value)
144+
let restored = IEEE_754.Binary64.value(from: bytes)
145+
146+
#expect(restored == value, "Zero should round-trip")
147+
if value.sign == .minus {
148+
#expect(restored?.sign == .minus, "Negative zero should preserve sign")
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)