Skip to content

Commit f45342c

Browse files
authored
Shrink integers using midpoint function
1 parent a02e1cd commit f45342c

File tree

2 files changed

+19
-31
lines changed

2 files changed

+19
-31
lines changed

Sources/PropertyBased/Shrink+Integer.swift

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,52 +13,40 @@ extension Shrink {
1313
public typealias Element = IntegerType
1414

1515
@usableFromInline var current: IntegerType
16-
@usableFromInline var leap: IntegerType
17-
18-
@usableFromInline let isSubtracting: Bool
19-
20-
/// The first value in the sequence.
21-
@usableFromInline let first: IntegerType
2216
/// Stop the sequence when reaching the end. Do not yield this value.
2317
@usableFromInline let end: IntegerType
2418

2519
@usableFromInline init(from: IntegerType, bound: IntegerType) {
26-
first = bound
2720
current = bound
2821
end = from
29-
isSubtracting = bound > from
30-
31-
let newLeap: (partialValue: IntegerType, overflow: Bool)
32-
if isSubtracting {
33-
newLeap = (bound / 2).subtractingReportingOverflow(from / 2)
34-
} else {
35-
newLeap = (from / 2).subtractingReportingOverflow(bound / 2)
36-
}
37-
leap = !newLeap.overflow ? newLeap.partialValue : .max / 2
3822
}
3923

4024
public mutating func next() -> IntegerType? {
41-
let hasReachedEnd = isSubtracting ? current <= end : current >= end
42-
guard !hasReachedEnd, leap > 0 else {
25+
guard current != end else {
4326
return nil
4427
}
45-
4628
defer {
47-
if isSubtracting {
48-
current -= leap
49-
} else {
50-
current += leap
51-
}
52-
}
53-
if current != first {
54-
leap /= 2
29+
let next = current.midpoint(towards: end)
30+
current = current != next ? next : end
5531
}
5632
return current
5733
}
5834
}
5935
}
6036

6137
extension FixedWidthInteger {
38+
39+
// Adapted from https://github.com/apple/swift-numerics/pull/293
40+
@inlinable func midpoint(towards other: Self) -> Self {
41+
// Isolate bits in a + b with weight 2, and those with weight 1
42+
let twos = self & other
43+
let ones = self ^ other
44+
let floor = twos &+ ones >> 1
45+
let frac = ones & 1
46+
47+
return floor &+ (self < other ? frac : 0)
48+
}
49+
6250
/// Get a shrinking sequence that shrinks this value to a specific value.
6351
/// - Parameter bound: The value to shrink towards.
6452
/// - Returns: A new sequence.

Tests/PropertyBasedTests/ShrinkTests+Array.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ import Testing
5959
[3, 10, 25],
6060
[4, 0, 25],
6161
[4, 5, 25],
62-
[4, 7, 25],
6362
[4, 8, 25],
63+
[4, 9, 25],
6464
[4, 10, 0],
65-
[4, 10, 12],
66-
[4, 10, 18],
67-
[4, 10, 21],
65+
[4, 10, 13],
66+
[4, 10, 19],
6867
[4, 10, 22],
68+
[4, 10, 24],
6969
]
7070

7171
#expect(actual == expected)

0 commit comments

Comments
 (0)