# [SE-0225] Implementation of isMultiple for BinaryInteger. #18689

Merged
merged 2 commits into from Sep 4, 2018
+82 −6
Merged

# [SE-0225] Implementation of isMultiple for BinaryInteger.#18689

Commits
Show all changes
2 commits
Select commit Hold shift + click to select a range
Filter file types
Failed to load files and symbols.

#### Just for now

 @@ -110,6 +110,10 @@ extension MockBinaryInteger : BinaryInteger { var trailingZeroBitCount: Int { return _value.trailingZeroBitCount } func isMultiple(of other: MockBinaryInteger) -> Bool { return _value.isMultiple(of: other._value) } static func + ( lhs: MockBinaryInteger, rhs: MockBinaryInteger
 @@ -1151,6 +1151,21 @@ public protocol BinaryInteger : func quotientAndRemainder(dividingBy rhs: Self) -> (quotient: Self, remainder: Self) /// Returns true if this value is a multiple of `other`, and false otherwise. /// /// For two integers a and b, a is a multiple of b if there exists a third /// integer q such that a = q*b. For example, 6 is a multiple of 3, because /// 6 = 2*3, and zero is a multiple of everything, because 0 = 0*x, for any /// integer x. /// /// Two edge cases are worth particular attention: /// - `x.isMultiple(of: 0)` is `true` if `x` is zero and `false` otherwise. /// - `T.min.isMultiple(of: -1)` is `true` for signed integer `T`, even /// though the quotient `T.min / -1` is not representable in type `T`. /// /// - Parameter other: the value to test. func isMultiple(of other: Self) -> Bool /// Returns `-1` if this value is negative and `1` if it's positive; /// otherwise, `0`. /// @@ -2755,6 +2770,16 @@ extension FixedWidthInteger { lhs = _nonMaskingRightShift(lhs, shift) } @inlinable public func isMultiple(of other: Self) -> Bool { // Nothing but zero is a multiple of zero. if other == 0 { return self == 0 } // Special case to avoid overflow on .min / -1 for signed types. if Self.isSigned && other == -1 { return true } // Having handled those special cases, this is safe. return self % other == 0 } @inlinable // FIXME(sil-serialize-all) @inline(__always) public static func _nonMaskingRightShift(_ lhs: Self, _ rhs: Int) -> Self {
 @@ -23,9 +23,8 @@ func test8(_: ((Int, Int)) -> Int) {} test8 { (_, _) -> Int in 2 } test8 { (x, y) in x } func isEven(_ x: Int) -> Bool { return x % 2 == 0 } let items = Array(zip(0..<10, 0..<10)) _ = items.filter { (_, x) in isEven(x) } _ = items.filter { (_, x) in x.isMultiple(of: 2) } _ = items.filter { _ in true } func toString(indexes: Int?...) -> String {
 @@ -729,6 +729,11 @@ public struct _BigInt : let r = x._internalDivide(by: rhs) return (x, r) } public func isMultiple(of other: _BigInt) -> Bool { if other == 0 { return self == 0 } return self % other == 0 } public static func &=(lhs: inout _BigInt, rhs: _BigInt) { var lhsTemp = lhs._dataAsTwosComplement() @@ -1867,3 +1872,9 @@ BigIntBitTests.test("words") { } runAllTests() BigIntTests.test("isMultiple") { // Test that these do not crash. expectTrue((0 as _BigInt).isMultiple(of: 0)) expectFalse((1 as _BigInt).isMultiple(of: 0)) }
@@ -39,8 +39,7 @@ import StdlibUnittest
/// integer type. Nesting `DoubleWidth` instances, in particular, may result in
/// undesirable performance.
public struct DoubleWidth<Base : FixedWidthInteger>
where Base.Magnitude : UnsignedInteger,
Base.Words : Collection, Base.Magnitude.Words : Collection {
where Base.Words : Collection, Base.Magnitude.Words : Collection {

#### stephentyrone Aug 14, 2018

Author Member

An unrelated PR a few weeks ago removed the need for the `.Magnitude : UnsignedInteger` conformance. Removing it to get rid of warning in tests.

public typealias High = Base
public typealias Low = Base.Magnitude
@@ -282,7 +281,7 @@ extension DoubleWidth.Words: Collection {

public func index(after i: Index) -> Index {
switch i._value {
case let .low(li) where Base.bitWidth < UInt.bitWidth:
case .low where Base.bitWidth < UInt.bitWidth:

#### stephentyrone Aug 14, 2018

Author Member

This change is also just cleaning up some noise.

return Index(.high(_high.endIndex))
case let .low(li):
let next = _low.index(after: li)
@@ -1004,6 +1003,19 @@ dwTests.test("DivideMinByMinusOne") {
_ = f(Int1024.min)
}

dwTests.test("isMultiple") {
func isMultipleTest<T: FixedWidthInteger>(type: T.Type) {
expectTrue(T.min.isMultiple(of: 2))
expectFalse(T.max.isMultiple(of: 10))
// Test that these do not crash.
expectTrue((0 as T).isMultiple(of: 0))
expectFalse((1 as T).isMultiple(of: 0))
expectTrue(T.min.isMultiple(of: 0 &- 1))
}
isMultipleTest(type: Int128.self)
isMultipleTest(type: UInt128.self)
}

dwTests.test("MultiplyMinByMinusOne") {
func f(_ x: Int1024) -> Int1024 {
return x * -1
@@ -148,6 +148,10 @@ extension MockBinaryInteger : BinaryInteger {
return _value.trailingZeroBitCount
}

func isMultiple(of other: MockBinaryInteger<T>) -> Bool {
return _value.isMultiple(of: other._value)
}

static func + (
lhs: MockBinaryInteger<T>, rhs: MockBinaryInteger<T>
) -> MockBinaryInteger<T> {
@@ -560,7 +564,7 @@ tests.test("truncatingIfNeeded") {

tests.test("Parsing/LosslessStringConvertible") {
func _toArray<T: LosslessStringConvertible>(_ text: String) -> [T] {
return text.split(separator: " ").map { T(String(\$0)) }.flatMap { \$0 }
return text.split(separator: " ").map { T(String(\$0)) }.compactMap { \$0 }

#### stephentyrone Aug 14, 2018

Author Member

Minor update to silence warning while we're here.

}

expectEqualSequence([1, 2, 3], _toArray("1 2 3") as [Int])
@@ -798,6 +802,27 @@ tests.test("DivideMinByMinusOne") {
_ = f(Int.min)
}

tests.test("isMultiple") {
func isMultipleTest<T: FixedWidthInteger>(type: T.Type) {
expectTrue(T.min.isMultiple(of: 2))
expectFalse(T.max.isMultiple(of: 10))
// Test that these do not crash.
expectTrue((0 as T).isMultiple(of: 0))
expectFalse((1 as T).isMultiple(of: 0))
expectTrue(T.min.isMultiple(of: 0 &- 1))
}
isMultipleTest(type: Int.self)
isMultipleTest(type: Int8.self)
isMultipleTest(type: Int16.self)
isMultipleTest(type: Int32.self)
isMultipleTest(type: Int64.self)
isMultipleTest(type: UInt.self)
isMultipleTest(type: UInt8.self)
isMultipleTest(type: UInt16.self)
isMultipleTest(type: UInt32.self)
isMultipleTest(type: UInt64.self)
}

tests.test("MultiplyMinByMinusOne") {
func f(_ x: Int) -> Int {
return x * -1
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.