From f2ea697566a41ce3a7da5f27cba8ddceca3aba21 Mon Sep 17 00:00:00 2001 From: Xiaodi Wu Date: Sat, 5 Aug 2017 17:19:05 -0500 Subject: [PATCH] Update generic algorithms for changes to SE-0104 --- Sources/IntegerAlgorithms.swift | 42 +++++++++----------- Sources/PRNG.swift | 7 ++-- Tests/NumericAnnexTests/FactoringTests.swift | 18 ++++----- 3 files changed, 30 insertions(+), 37 deletions(-) diff --git a/Sources/IntegerAlgorithms.swift b/Sources/IntegerAlgorithms.swift index 858336d..91b9c80 100644 --- a/Sources/IntegerAlgorithms.swift +++ b/Sources/IntegerAlgorithms.swift @@ -51,8 +51,8 @@ extension BinaryInteger { while shift >= 0 { result *= 2 let temporary = 2 * result + 1 - if temporary <= x &>> shift { - x -= temporary &<< shift + if temporary <= x >> shift { + x -= temporary << shift result += 1 } shift -= 2 @@ -77,8 +77,8 @@ extension UnsignedInteger { while shift >= 0 { result *= 2 let temporary = 3 * result * (result + 1) + 1 - if temporary <= x &>> shift { - x -= temporary &<< shift + if temporary <= x >> shift { + x -= temporary << shift result += 1 } shift -= 3 @@ -99,20 +99,20 @@ extension UnsignedInteger { var a = a, b = b, shift = 0 as Self while ((a | b) & 1) == 0 { - a &>>= 1 - b &>>= 1 + a >>= 1 + b >>= 1 shift += 1 } // Now, shift is equal to log2(k), where k is the greatest power of 2 // dividing a and b. - while (a & 1) == 0 { a &>>= 1 } // Now, a is odd. + while (a & 1) == 0 { a >>= 1 } // Now, a is odd. repeat { - while (b & 1) == 0 { b &>>= 1 } // Now, b is odd. + while (b & 1) == 0 { b >>= 1 } // Now, b is odd. if a > b { swap(&a, &b) } // Now, a < b. b -= a } while b != 0 // Restore common factors of 2. - return a &<< shift + return a << shift } /// Returns the least common multiple of `a` and `b`. @@ -132,8 +132,8 @@ extension UnsignedInteger where Self : FixedWidthInteger { /// Returns the least common multiple of `a` and `b` and a flag to indicate /// whether overflow occurred during the operation. public static func lcmReportingOverflow(_ a: Self, _ b: Self) - -> (partialValue: Self, overflow: ArithmeticOverflow) { - if a == 0 || b == 0 { return (partialValue: 0, overflow: .none) } + -> (partialValue: Self, overflow: Bool) { + if a == 0 || b == 0 { return (0, false) } return (a / .gcd(a, b)).multipliedReportingOverflow(by: b) } @@ -192,25 +192,19 @@ where Self : FixedWidthInteger, /// Returns the greatest common divisor of `a` and `b` and a flag to indicate /// whether overflow occurred during the operation. public static func gcdReportingOverflow(_ a: Self, _ b: Self) - -> (partialValue: Self, overflow: ArithmeticOverflow) { - let t = Self(extendingOrTruncating: Magnitude.gcd(a.magnitude, b.magnitude)) - return ( - partialValue: t, - overflow: ArithmeticOverflow(t < 0) - ) + -> (partialValue: Self, overflow: Bool) { + let t = Self(truncatingIfNeeded: Magnitude.gcd(a.magnitude, b.magnitude)) + return (t, t < 0) } // @_transparent // @_inlineable /// Returns the least common multiple of `a` and `b` and a flag to indicate /// whether overflow occurred during the operation. public static func lcmReportingOverflow(_ a: Self, _ b: Self) - -> (partialValue: Self, overflow: ArithmeticOverflow) { + -> (partialValue: Self, overflow: Bool) { let (t, overflow) = Magnitude.lcmReportingOverflow(a.magnitude, b.magnitude) - let u = Self(extendingOrTruncating: t) - return ( - partialValue: u, - overflow: ArithmeticOverflow(overflow == .overflow || u < 0) - ) + let u = Self(truncatingIfNeeded: t) + return (u, overflow || u < 0) } // @_transparent // @_inlineable @@ -219,6 +213,6 @@ where Self : FixedWidthInteger, public static func lcmFullWidth(_ a: Self, _ b: Self) -> (high: Self, low: Self.Magnitude) { let t = Magnitude.lcmFullWidth(a.magnitude, b.magnitude) - return (high: Self(t.high), low: t.low) + return (Self(t.high), t.low) } } diff --git a/Sources/PRNG.swift b/Sources/PRNG.swift index 164cdcc..16b1746 100644 --- a/Sources/PRNG.swift +++ b/Sources/PRNG.swift @@ -169,7 +169,7 @@ extension PRNG { bitCount == T.bitWidth { // It is an awkward way of spelling `next()`, but it is necessary. guard let next = first(where: { _ in true }) else { fatalError() } - return T(extendingOrTruncating: next) + return T(truncatingIfNeeded: next) } let (quotient, remainder) = @@ -179,15 +179,14 @@ extension PRNG { // Call `next()` at least `quotient` times. for i in 0..> (Element.bitWidth - remainder) temporary += - T(extendingOrTruncating: next & mask) &<< (randomBitWidth * quotient) + T(truncatingIfNeeded: next & mask) &<< (randomBitWidth * quotient) } return temporary } diff --git a/Tests/NumericAnnexTests/FactoringTests.swift b/Tests/NumericAnnexTests/FactoringTests.swift index ba928bb..af116f5 100644 --- a/Tests/NumericAnnexTests/FactoringTests.swift +++ b/Tests/NumericAnnexTests/FactoringTests.swift @@ -11,7 +11,7 @@ class FactoringTests : XCTestCase { XCTAssertEqual(Int.gcd(24, 60), 12) XCTAssertEqual(Int.gcd(42, 56), 14) - XCTAssertTrue(Int8.gcdReportingOverflow(-128, -128).overflow == .overflow) + XCTAssertTrue(Int8.gcdReportingOverflow(-128, -128).overflow) // Test special values. XCTAssertEqual(UInt.gcd(0, 42), 42) @@ -29,12 +29,12 @@ class FactoringTests : XCTestCase { XCTAssertEqual(Int8.lcmFullWidth(33, 48).high, 2) XCTAssertEqual(Int8.lcmFullWidth(33, 48).low, 16) XCTAssertEqual(Int8.lcmReportingOverflow(33, 48).partialValue, 16) - XCTAssertTrue(Int8.lcmReportingOverflow(33, 48).overflow == .overflow) + XCTAssertTrue(Int8.lcmReportingOverflow(33, 48).overflow) XCTAssertEqual(UInt8.lcmFullWidth(33, 48).high, 2) XCTAssertEqual(UInt8.lcmFullWidth(33, 48).low, 16) XCTAssertEqual(UInt8.lcmReportingOverflow(33, 48).partialValue, 16) - XCTAssertTrue(UInt8.lcmReportingOverflow(33, 48).overflow == .overflow) + XCTAssertTrue(UInt8.lcmReportingOverflow(33, 48).overflow) // Test special values. XCTAssertEqual(UInt.lcm(0, 42), 0) @@ -44,32 +44,32 @@ class FactoringTests : XCTestCase { XCTAssertEqual(Int8.lcmFullWidth(0, 42).high, 0) XCTAssertEqual(Int8.lcmFullWidth(0, 42).low, 0) XCTAssertEqual(Int8.lcmReportingOverflow(0, 42).partialValue, 0) - XCTAssertTrue(Int8.lcmReportingOverflow(0, 42).overflow == .none) + XCTAssertFalse(Int8.lcmReportingOverflow(0, 42).overflow) XCTAssertEqual(Int8.lcmFullWidth(42, 0).high, 0) XCTAssertEqual(Int8.lcmFullWidth(42, 0).low, 0) XCTAssertEqual(Int8.lcmReportingOverflow(42, 0).partialValue, 0) - XCTAssertTrue(Int8.lcmReportingOverflow(42, 0).overflow == .none) + XCTAssertFalse(Int8.lcmReportingOverflow(42, 0).overflow) XCTAssertEqual(Int8.lcmFullWidth(0, 0).high, 0) XCTAssertEqual(Int8.lcmFullWidth(0, 0).low, 0) XCTAssertEqual(Int8.lcmReportingOverflow(0, 0).partialValue, 0) - XCTAssertTrue(Int8.lcmReportingOverflow(0, 0).overflow == .none) + XCTAssertFalse(Int8.lcmReportingOverflow(0, 0).overflow) XCTAssertEqual(UInt8.lcmFullWidth(0, 42).high, 0) XCTAssertEqual(UInt8.lcmFullWidth(0, 42).low, 0) XCTAssertEqual(UInt8.lcmReportingOverflow(0, 42).partialValue, 0) - XCTAssertTrue(UInt8.lcmReportingOverflow(0, 42).overflow == .none) + XCTAssertFalse(UInt8.lcmReportingOverflow(0, 42).overflow) XCTAssertEqual(UInt8.lcmFullWidth(42, 0).high, 0) XCTAssertEqual(UInt8.lcmFullWidth(42, 0).low, 0) XCTAssertEqual(UInt8.lcmReportingOverflow(42, 0).partialValue, 0) - XCTAssertTrue(UInt8.lcmReportingOverflow(42, 0).overflow == .none) + XCTAssertFalse(UInt8.lcmReportingOverflow(42, 0).overflow) XCTAssertEqual(UInt8.lcmFullWidth(0, 0).high, 0) XCTAssertEqual(UInt8.lcmFullWidth(0, 0).low, 0) XCTAssertEqual(UInt8.lcmReportingOverflow(0, 0).partialValue, 0) - XCTAssertTrue(UInt8.lcmReportingOverflow(0, 0).overflow == .none) + XCTAssertFalse(UInt8.lcmReportingOverflow(0, 0).overflow) } static var allTests = [