Skip to content

Commit 1f08182

Browse files
committed
Add min/maxRepresentableNumber functions to SignedNumberRepresentation
1 parent 8ad5b46 commit 1f08182

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

Sources/SignedNumberRepresentation.swift

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,74 @@
44
// See LICENSE for license information
55

66
public enum SignedNumberRepresentation {
7+
78
case signMagnitude
89
case oneComplementNegatives
910
case twoComplementNegatives
1011
case biased(bias: Int)
1112
case radixNegativeTwo
13+
14+
// Generally speaking, there is a natural limit of the maximum and minimum values that Swift's Int type can hold.
15+
// So when the bitsCount matches the bit width of the Int type we need to be careful.
16+
17+
public func minRepresentableNumber(bitsCount: Int) -> Int {
18+
precondition(bitsCount > 0)
19+
20+
switch self {
21+
case .signMagnitude:
22+
fallthrough
23+
case .oneComplementNegatives:
24+
return bitsCount == Int.bitWidth ? Int.min : -(1 << (bitsCount - 1) - 1)
25+
case .twoComplementNegatives:
26+
// Technically, we don't need to be extremely careful in the 2's-complement case, since it is the
27+
// representation used internally by Swift, however, in practice, we still get arithmetic overflow
28+
// in the bitsCount == Int.bitWidth case, if we use the formula, so we check for this case specifically.
29+
return bitsCount == Int.bitWidth ? Int.min : -(1 << (bitsCount - 1))
30+
case .biased(let bias):
31+
precondition(bias >= 0)
32+
return -bias
33+
case .radixNegativeTwo:
34+
if bitsCount == Int.bitWidth {
35+
return Int.min
36+
}
37+
// Minimum corresponds to all of the odd bits being set.
38+
var result = 0
39+
var mult = 2
40+
for _ in stride(from: 1, to: bitsCount, by: 2) {
41+
result -= mult
42+
mult *= 4
43+
}
44+
return result
45+
}
46+
}
47+
48+
public func maxRepresentableNumber(bitsCount: Int) -> Int {
49+
precondition(bitsCount > 0)
50+
51+
switch self {
52+
case .signMagnitude:
53+
fallthrough
54+
case .oneComplementNegatives:
55+
fallthrough
56+
case .twoComplementNegatives:
57+
return bitsCount == Int.bitWidth ? Int.max : 1 << (bitsCount - 1) - 1
58+
case .biased(let bias):
59+
precondition(bias >= 0)
60+
return bitsCount == Int.bitWidth ? Int.max - bias : (1 << bitsCount) - 1 - bias
61+
case .radixNegativeTwo:
62+
var result = 0
63+
var mult = 1
64+
for _ in stride(from: 0, to: bitsCount, by: 2) {
65+
result += mult
66+
let (newMult, overflow) = mult.multipliedReportingOverflow(by: 4)
67+
if overflow {
68+
// This means that we reached the Int.max limit.
69+
break
70+
}
71+
mult = newMult
72+
}
73+
return result
74+
}
75+
}
76+
1277
}

0 commit comments

Comments
 (0)