Update generic algorithms for changes to SE-0104
This commit is contained in:
parent
cef815d55c
commit
f2ea697566
|
@ -51,8 +51,8 @@ extension BinaryInteger {
|
||||||
while shift >= 0 {
|
while shift >= 0 {
|
||||||
result *= 2
|
result *= 2
|
||||||
let temporary = 2 * result + 1
|
let temporary = 2 * result + 1
|
||||||
if temporary <= x &>> shift {
|
if temporary <= x >> shift {
|
||||||
x -= temporary &<< shift
|
x -= temporary << shift
|
||||||
result += 1
|
result += 1
|
||||||
}
|
}
|
||||||
shift -= 2
|
shift -= 2
|
||||||
|
@ -77,8 +77,8 @@ extension UnsignedInteger {
|
||||||
while shift >= 0 {
|
while shift >= 0 {
|
||||||
result *= 2
|
result *= 2
|
||||||
let temporary = 3 * result * (result + 1) + 1
|
let temporary = 3 * result * (result + 1) + 1
|
||||||
if temporary <= x &>> shift {
|
if temporary <= x >> shift {
|
||||||
x -= temporary &<< shift
|
x -= temporary << shift
|
||||||
result += 1
|
result += 1
|
||||||
}
|
}
|
||||||
shift -= 3
|
shift -= 3
|
||||||
|
@ -99,20 +99,20 @@ extension UnsignedInteger {
|
||||||
|
|
||||||
var a = a, b = b, shift = 0 as Self
|
var a = a, b = b, shift = 0 as Self
|
||||||
while ((a | b) & 1) == 0 {
|
while ((a | b) & 1) == 0 {
|
||||||
a &>>= 1
|
a >>= 1
|
||||||
b &>>= 1
|
b >>= 1
|
||||||
shift += 1
|
shift += 1
|
||||||
}
|
}
|
||||||
// Now, shift is equal to log2(k), where k is the greatest power of 2
|
// Now, shift is equal to log2(k), where k is the greatest power of 2
|
||||||
// dividing a and b.
|
// 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 {
|
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.
|
if a > b { swap(&a, &b) } // Now, a < b.
|
||||||
b -= a
|
b -= a
|
||||||
} while b != 0
|
} while b != 0
|
||||||
// Restore common factors of 2.
|
// Restore common factors of 2.
|
||||||
return a &<< shift
|
return a << shift
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the least common multiple of `a` and `b`.
|
/// 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
|
/// Returns the least common multiple of `a` and `b` and a flag to indicate
|
||||||
/// whether overflow occurred during the operation.
|
/// whether overflow occurred during the operation.
|
||||||
public static func lcmReportingOverflow(_ a: Self, _ b: Self)
|
public static func lcmReportingOverflow(_ a: Self, _ b: Self)
|
||||||
-> (partialValue: Self, overflow: ArithmeticOverflow) {
|
-> (partialValue: Self, overflow: Bool) {
|
||||||
if a == 0 || b == 0 { return (partialValue: 0, overflow: .none) }
|
if a == 0 || b == 0 { return (0, false) }
|
||||||
return (a / .gcd(a, b)).multipliedReportingOverflow(by: b)
|
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
|
/// Returns the greatest common divisor of `a` and `b` and a flag to indicate
|
||||||
/// whether overflow occurred during the operation.
|
/// whether overflow occurred during the operation.
|
||||||
public static func gcdReportingOverflow(_ a: Self, _ b: Self)
|
public static func gcdReportingOverflow(_ a: Self, _ b: Self)
|
||||||
-> (partialValue: Self, overflow: ArithmeticOverflow) {
|
-> (partialValue: Self, overflow: Bool) {
|
||||||
let t = Self(extendingOrTruncating: Magnitude.gcd(a.magnitude, b.magnitude))
|
let t = Self(truncatingIfNeeded: Magnitude.gcd(a.magnitude, b.magnitude))
|
||||||
return (
|
return (t, t < 0)
|
||||||
partialValue: t,
|
|
||||||
overflow: ArithmeticOverflow(t < 0)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @_transparent // @_inlineable
|
// @_transparent // @_inlineable
|
||||||
/// Returns the least common multiple of `a` and `b` and a flag to indicate
|
/// Returns the least common multiple of `a` and `b` and a flag to indicate
|
||||||
/// whether overflow occurred during the operation.
|
/// whether overflow occurred during the operation.
|
||||||
public static func lcmReportingOverflow(_ a: Self, _ b: Self)
|
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 (t, overflow) = Magnitude.lcmReportingOverflow(a.magnitude, b.magnitude)
|
||||||
let u = Self(extendingOrTruncating: t)
|
let u = Self(truncatingIfNeeded: t)
|
||||||
return (
|
return (u, overflow || u < 0)
|
||||||
partialValue: u,
|
|
||||||
overflow: ArithmeticOverflow(overflow == .overflow || u < 0)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @_transparent // @_inlineable
|
// @_transparent // @_inlineable
|
||||||
|
@ -219,6 +213,6 @@ where Self : FixedWidthInteger,
|
||||||
public static func lcmFullWidth(_ a: Self, _ b: Self)
|
public static func lcmFullWidth(_ a: Self, _ b: Self)
|
||||||
-> (high: Self, low: Self.Magnitude) {
|
-> (high: Self, low: Self.Magnitude) {
|
||||||
let t = Magnitude.lcmFullWidth(a.magnitude, b.magnitude)
|
let t = Magnitude.lcmFullWidth(a.magnitude, b.magnitude)
|
||||||
return (high: Self(t.high), low: t.low)
|
return (Self(t.high), t.low)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,7 +169,7 @@ extension PRNG {
|
||||||
bitCount == T.bitWidth {
|
bitCount == T.bitWidth {
|
||||||
// It is an awkward way of spelling `next()`, but it is necessary.
|
// It is an awkward way of spelling `next()`, but it is necessary.
|
||||||
guard let next = first(where: { _ in true }) else { fatalError() }
|
guard let next = first(where: { _ in true }) else { fatalError() }
|
||||||
return T(extendingOrTruncating: next)
|
return T(truncatingIfNeeded: next)
|
||||||
}
|
}
|
||||||
|
|
||||||
let (quotient, remainder) =
|
let (quotient, remainder) =
|
||||||
|
@ -179,15 +179,14 @@ extension PRNG {
|
||||||
// Call `next()` at least `quotient` times.
|
// Call `next()` at least `quotient` times.
|
||||||
for i in 0..<quotient {
|
for i in 0..<quotient {
|
||||||
guard let next = first(where: { $0 <= max }) else { fatalError() }
|
guard let next = first(where: { $0 <= max }) else { fatalError() }
|
||||||
temporary +=
|
temporary += T(truncatingIfNeeded: next) &<< (randomBitWidth * i)
|
||||||
T(extendingOrTruncating: next) &<< (randomBitWidth * i)
|
|
||||||
}
|
}
|
||||||
// If `remainder != 0`, call `next()` at least one more time.
|
// If `remainder != 0`, call `next()` at least one more time.
|
||||||
if remainder != 0 {
|
if remainder != 0 {
|
||||||
guard let next = first(where: { $0 <= max }) else { fatalError() }
|
guard let next = first(where: { $0 <= max }) else { fatalError() }
|
||||||
let mask = Element.max &>> (Element.bitWidth - remainder)
|
let mask = Element.max &>> (Element.bitWidth - remainder)
|
||||||
temporary +=
|
temporary +=
|
||||||
T(extendingOrTruncating: next & mask) &<< (randomBitWidth * quotient)
|
T(truncatingIfNeeded: next & mask) &<< (randomBitWidth * quotient)
|
||||||
}
|
}
|
||||||
return temporary
|
return temporary
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ class FactoringTests : XCTestCase {
|
||||||
XCTAssertEqual(Int.gcd(24, 60), 12)
|
XCTAssertEqual(Int.gcd(24, 60), 12)
|
||||||
XCTAssertEqual(Int.gcd(42, 56), 14)
|
XCTAssertEqual(Int.gcd(42, 56), 14)
|
||||||
|
|
||||||
XCTAssertTrue(Int8.gcdReportingOverflow(-128, -128).overflow == .overflow)
|
XCTAssertTrue(Int8.gcdReportingOverflow(-128, -128).overflow)
|
||||||
|
|
||||||
// Test special values.
|
// Test special values.
|
||||||
XCTAssertEqual(UInt.gcd(0, 42), 42)
|
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).high, 2)
|
||||||
XCTAssertEqual(Int8.lcmFullWidth(33, 48).low, 16)
|
XCTAssertEqual(Int8.lcmFullWidth(33, 48).low, 16)
|
||||||
XCTAssertEqual(Int8.lcmReportingOverflow(33, 48).partialValue, 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).high, 2)
|
||||||
XCTAssertEqual(UInt8.lcmFullWidth(33, 48).low, 16)
|
XCTAssertEqual(UInt8.lcmFullWidth(33, 48).low, 16)
|
||||||
XCTAssertEqual(UInt8.lcmReportingOverflow(33, 48).partialValue, 16)
|
XCTAssertEqual(UInt8.lcmReportingOverflow(33, 48).partialValue, 16)
|
||||||
XCTAssertTrue(UInt8.lcmReportingOverflow(33, 48).overflow == .overflow)
|
XCTAssertTrue(UInt8.lcmReportingOverflow(33, 48).overflow)
|
||||||
|
|
||||||
// Test special values.
|
// Test special values.
|
||||||
XCTAssertEqual(UInt.lcm(0, 42), 0)
|
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).high, 0)
|
||||||
XCTAssertEqual(Int8.lcmFullWidth(0, 42).low, 0)
|
XCTAssertEqual(Int8.lcmFullWidth(0, 42).low, 0)
|
||||||
XCTAssertEqual(Int8.lcmReportingOverflow(0, 42).partialValue, 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).high, 0)
|
||||||
XCTAssertEqual(Int8.lcmFullWidth(42, 0).low, 0)
|
XCTAssertEqual(Int8.lcmFullWidth(42, 0).low, 0)
|
||||||
XCTAssertEqual(Int8.lcmReportingOverflow(42, 0).partialValue, 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).high, 0)
|
||||||
XCTAssertEqual(Int8.lcmFullWidth(0, 0).low, 0)
|
XCTAssertEqual(Int8.lcmFullWidth(0, 0).low, 0)
|
||||||
XCTAssertEqual(Int8.lcmReportingOverflow(0, 0).partialValue, 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).high, 0)
|
||||||
XCTAssertEqual(UInt8.lcmFullWidth(0, 42).low, 0)
|
XCTAssertEqual(UInt8.lcmFullWidth(0, 42).low, 0)
|
||||||
XCTAssertEqual(UInt8.lcmReportingOverflow(0, 42).partialValue, 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).high, 0)
|
||||||
XCTAssertEqual(UInt8.lcmFullWidth(42, 0).low, 0)
|
XCTAssertEqual(UInt8.lcmFullWidth(42, 0).low, 0)
|
||||||
XCTAssertEqual(UInt8.lcmReportingOverflow(42, 0).partialValue, 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).high, 0)
|
||||||
XCTAssertEqual(UInt8.lcmFullWidth(0, 0).low, 0)
|
XCTAssertEqual(UInt8.lcmFullWidth(0, 0).low, 0)
|
||||||
XCTAssertEqual(UInt8.lcmReportingOverflow(0, 0).partialValue, 0)
|
XCTAssertEqual(UInt8.lcmReportingOverflow(0, 0).partialValue, 0)
|
||||||
XCTAssertTrue(UInt8.lcmReportingOverflow(0, 0).overflow == .none)
|
XCTAssertFalse(UInt8.lcmReportingOverflow(0, 0).overflow)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var allTests = [
|
static var allTests = [
|
||||||
|
|
Loading…
Reference in New Issue