From 1c3e597928aa33a4bb662d120bab8a4d18b1d5d7 Mon Sep 17 00:00:00 2001 From: Max Moiseev Date: Wed, 26 Jul 2017 11:08:00 -0700 Subject: [PATCH] [stdlib] Get rid of ArithmeticOverflow type --- stdlib/public/core/DoubleWidth.swift.gyb | 37 +++++------ stdlib/public/core/IntegerParsing.swift | 4 +- stdlib/public/core/Integers.swift.gyb | 62 ++++++------------- test/Prototypes/BigInt.swift | 41 ++++++------ test/stdlib/Integers.swift.gyb | 6 +- .../FixedPointArithmeticTraps.swift.gyb | 10 +-- 6 files changed, 66 insertions(+), 94 deletions(-) diff --git a/stdlib/public/core/DoubleWidth.swift.gyb b/stdlib/public/core/DoubleWidth.swift.gyb index 0e72c32d1d6ce..92f46f2e3dd37 100644 --- a/stdlib/public/core/DoubleWidth.swift.gyb +++ b/stdlib/public/core/DoubleWidth.swift.gyb @@ -269,25 +269,21 @@ public struct DoubleWidth : % for (operator, name) in [('+', 'adding'), ('-', 'subtracting')]: % highAffectedByLowOverflow = 'Base.max' if operator == '+' else 'Base.min' public func ${name}ReportingOverflow(_ rhs: DoubleWidth) - -> (partialValue: DoubleWidth, overflow: ArithmeticOverflow) { + -> (partialValue: DoubleWidth, overflow: Bool) { let (low, lowOverflow) = _storage.low.${name}ReportingOverflow(rhs._storage.low) let (high, highOverflow) = _storage.high.${name}ReportingOverflow(rhs._storage.high) - let isLowOverflow = lowOverflow == .overflow - let result = (high &${operator} (isLowOverflow ? 1 : 0), low) - let overflow = ArithmeticOverflow( - highOverflow == .overflow || - high == ${highAffectedByLowOverflow} && isLowOverflow - ) - return (partialValue: DoubleWidth(result), - overflow: overflow) + let result = (high &${operator} (lowOverflow ? 1 : 0), low) + let overflow = highOverflow || + high == ${highAffectedByLowOverflow} && lowOverflow + return (partialValue: DoubleWidth(result), overflow: overflow) } % end public func multipliedReportingOverflow( by rhs: DoubleWidth - ) -> (partialValue: DoubleWidth, overflow: ArithmeticOverflow) { + ) -> (partialValue: DoubleWidth, overflow: Bool) { let (carry, product) = multipliedFullWidth(by: rhs) let result = DoubleWidth(truncatingIfNeeded: product) @@ -298,7 +294,7 @@ public struct DoubleWidth : let hadPositiveOverflow = !isNegative && DoubleWidth.isSigned && product.leadingZeroBitCount == 0 - return (result, ArithmeticOverflow(didCarry || hadPositiveOverflow)) + return (result, didCarry || hadPositiveOverflow) } public func quotientAndRemainder(dividingBy other: DoubleWidth) @@ -350,25 +346,25 @@ public struct DoubleWidth : } public func dividedReportingOverflow(by other: DoubleWidth) - -> (partialValue: DoubleWidth, overflow: ArithmeticOverflow) { + -> (partialValue: DoubleWidth, overflow: Bool) { if other == (0 as DoubleWidth) || (DoubleWidth.isSigned && other == (-1 as Int) && self == .min) { - return (self, .overflow) + return (self, true) } - return (quotientAndRemainder(dividingBy: other).quotient, .none) + return (quotientAndRemainder(dividingBy: other).quotient, false) } public func remainderReportingOverflow(dividingBy other: DoubleWidth) - -> (partialValue: DoubleWidth, overflow: ArithmeticOverflow) { + -> (partialValue: DoubleWidth, overflow: Bool) { if other == 0 || (DoubleWidth.isSigned && other == -1 && self == .min) { - return (self, .overflow) + return (self, true) } - return (quotientAndRemainder(dividingBy: other).remainder, .none) + return (quotientAndRemainder(dividingBy: other).remainder, false) } public func multipliedFullWidth(by other: DoubleWidth) @@ -384,8 +380,7 @@ public struct DoubleWidth : func sum(_ x: Low, _ y: Low, _ z: Low) -> (partial: Low, carry: Low) { let (sum1, overflow1) = x.addingReportingOverflow(y) let (sum2, overflow2) = sum1.addingReportingOverflow(z) - let carry: Low = (overflow1 == .overflow ? 1 : 0) + - (overflow2 == .overflow ? 1 : 0) + let carry: Low = (overflow1 ? 1 : 0) + (overflow2 ? 1 : 0) return (sum2, carry) } @@ -406,7 +401,7 @@ public struct DoubleWidth : if isNegative { let (lowComplement, overflow) = (~low).addingReportingOverflow(1) - return (~high + (overflow == .overflow ? 1 : 0), lowComplement) + return (~high + (overflow ? 1 : 0), lowComplement) } else { return (high, low) } @@ -535,7 +530,7 @@ binaryOperators = [ lhs: inout DoubleWidth, rhs: DoubleWidth ) { let (result, overflow) = lhs.${name}ReportingOverflow(${argumentLabel}rhs) - _precondition(overflow == .none, "Overflow in ${operator}=") + _precondition(!overflow, "Overflow in ${operator}=") lhs = result } % end diff --git a/stdlib/public/core/IntegerParsing.swift b/stdlib/public/core/IntegerParsing.swift index 12ff53dbca3c6..4b2985cdb3d92 100644 --- a/stdlib/public/core/IntegerParsing.swift +++ b/stdlib/public/core/IntegerParsing.swift @@ -40,7 +40,7 @@ where Rest.Element : UnsignedInteger { if !positive { let (result0, overflow0) = (0 as Result).subtractingReportingOverflow(result) - guard _fastPath(overflow0 == .none) else { return nil } + guard _fastPath(!overflow0) else { return nil } result = result0 } @@ -51,7 +51,7 @@ where Rest.Element : UnsignedInteger { let (result2, overflow2) = positive ? result1.addingReportingOverflow(d) : result1.subtractingReportingOverflow(d) - guard _fastPath(overflow1 == .none && overflow2 == .none) + guard _fastPath(!overflow1 && !overflow2) else { return nil } result = result2 } diff --git a/stdlib/public/core/Integers.swift.gyb b/stdlib/public/core/Integers.swift.gyb index d1d1444b46d70..0680a1d87b87f 100644 --- a/stdlib/public/core/Integers.swift.gyb +++ b/stdlib/public/core/Integers.swift.gyb @@ -819,8 +819,8 @@ def overflowOperationComment(operator): /// - Parameter rhs: The value to add to this value. /// - Returns: A tuple containing the result of the addition along with a /// flag indicating whether overflow occurred. If the `overflow` component - /// is `.none`, the `partialValue` component contains the entire sum. If - /// the `overflow` component is `.overflow`, an overflow occurred and the + /// is `false`, the `partialValue` component contains the entire sum. If + /// the `overflow` component is `true`, an overflow occurred and the /// `partialValue` component contains the truncated sum of this value and /// `rhs`. """, @@ -831,8 +831,8 @@ def overflowOperationComment(operator): /// - Parameter rhs: The value to subtract from this value. /// - Returns: A tuple containing the result of the subtraction along with a /// flag indicating whether overflow occurred. If the `overflow` component - /// is `.none`, the `partialValue` component contains the entire - /// difference. If the `overflow` component is `.overflow`, an overflow + /// is `false`, the `partialValue` component contains the entire + /// difference. If the `overflow` component is `true`, an overflow /// occurred and the `partialValue` component contains the truncated /// result of `rhs` subtracted from this value. """, @@ -843,8 +843,8 @@ def overflowOperationComment(operator): /// - Parameter rhs: The value to multiply by this value. /// - Returns: A tuple containing the result of the multiplication along with /// a flag indicating whether overflow occurred. If the `overflow` - /// component is `.none`, the `partialValue` component contains the entire - /// product. If the `overflow` component is `.overflow`, an overflow + /// component is `false`, the `partialValue` component contains the entire + /// product. If the `overflow` component is `true`, an overflow /// occurred and the `partialValue` component contains the truncated /// product of this value and `rhs`. """, @@ -853,13 +853,13 @@ def overflowOperationComment(operator): /// a flag indicating whether overflow occurred in the operation. /// /// Dividing by zero is not an error when using this method. For a value `x`, - /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, .overflow)`. + /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, true)`. /// /// - Parameter rhs: The value to divide this value by. /// - Returns: A tuple containing the result of the division along with a /// flag indicating whether overflow occurred. If the `overflow` component - /// is `.none`, the `partialValue` component contains the entire quotient. - /// If the `overflow` component is `.overflow`, an overflow occurred and + /// is `false`, the `partialValue` component contains the entire quotient. + /// If the `overflow` component is `true`, an overflow occurred and /// the `partialValue` component contains the truncated quotient. """, '%': """\ @@ -868,13 +868,13 @@ def overflowOperationComment(operator): /// a flag indicating whether overflow occurred in the operation. /// /// Dividing by zero is not an error when using this method. For a value `x`, - /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, .overflow)`. + /// the result of `x.dividedReportingOverflow(by: 0)` is `(x, true)`. /// /// - Parameter rhs: The value to divide this value by. /// - Returns: A tuple containing the result of the division along with a /// flag indicating whether overflow occurred. If the `overflow` component - /// is `.none`, the `partialValue` component contains the entire quotient. - /// If the `overflow` component is `.overflow`, an overflow occurred and + /// is `false`, the `partialValue` component contains the entire quotient. + /// If the `overflow` component is `true`, an overflow occurred and /// the `partialValue` component contains the truncated quotient. """, } @@ -1883,28 +1883,6 @@ extension BinaryInteger { //===--- FixedWidthInteger ------------------------------------------------===// //===----------------------------------------------------------------------===// -/// An indicator of whether an arithmetic operation overflowed. -/// -/// Some arithmetic operations on fixed-width integers return an -/// `ArithmeticOverflow` instance to indicate whether an overflow has -/// occurred. For example, adding `UInt8.max` to itself results in a value that -/// can't be represented by an `UInt8` instance without overflowing. -/// -/// let x = UInt8.max -/// // x == 255 -/// let (y, overflow) = x.addingReportingOverflow(x) -/// // y == 254 -/// // overflow == ArithmeticOverflow.overflow -@_fixed_layout -public enum ArithmeticOverflow { - @_transparent - public init(_ overflow: Bool) { self = overflow ? .overflow : .none } - /// An indication that no overflow occurred in the operation. - case none - /// An indication that an overflow did occur in the operation. - case overflow -} - /// An integer type that uses a fixed size for every instance. /// /// The `FixedWidthInteger` protocol adds binary bitwise operations, bit @@ -1948,7 +1926,7 @@ public enum ArithmeticOverflow { /// /// func squared(_ x: T) -> T? { /// let (result, overflow) = x.multipliedReportingOverflow(by: x) -/// guard overflow == .none else { +/// if overflow { /// return nil /// } /// return result @@ -2001,7 +1979,7 @@ public protocol FixedWidthInteger : BinaryInteger, _BitwiseOperations ${overflowOperationComment(x.operator)} func ${x.name}ReportingOverflow( ${x.firstArg} rhs: Self - ) -> (partialValue: Self, overflow: ArithmeticOverflow) + ) -> (partialValue: Self, overflow: Bool) % end /// Returns a tuple containing the high and low parts of the result of @@ -2267,7 +2245,7 @@ ${assignmentOperatorComment(x.operator, True)} @_transparent public static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self) { let (result, overflow) = lhs.${x.name}ReportingOverflow(${callLabel}rhs) - _precondition(overflow == .none, "Overflow in ${x.operator}=") + _precondition(!overflow, "Overflow in ${x.operator}=") lhs = result } #endif @@ -2278,7 +2256,7 @@ ${unsafeOperationComment(x.operator)} public func unsafe${capitalize(x.name)}(${x.firstArg} other: Self) -> Self { let (result, overflow) = self.${x.name}ReportingOverflow(${callLabel}other) - if (overflow != .none) { + if overflow { if (_isDebugAssertConfiguration()) { _preconditionFailure("overflow in unsafe${capitalize(x.name)}") } @@ -2660,7 +2638,7 @@ public struct ${Self} @_transparent public func ${x.name}ReportingOverflow( ${x.firstArg} other: ${Self} - ) -> (partialValue: ${Self}, overflow: ArithmeticOverflow) { + ) -> (partialValue: ${Self}, overflow: Bool) { % if x.kind == '/': // No LLVM primitives for checking overflow of division @@ -2669,7 +2647,7 @@ public struct ${Self} other == (0 as ${Self}) ${'|| self == %s.min && other == (-1 as %s)' % (Self, Self) if signed else ''} ) { - return (partialValue: self, overflow: .overflow) + return (partialValue: self, overflow: true) } let (newStorage, overflow) = ( @@ -2685,7 +2663,7 @@ public struct ${Self} return ( partialValue: ${Self}(newStorage), - overflow: ArithmeticOverflow(Bool(overflow))) + overflow: Bool(overflow)) } % end @@ -3230,7 +3208,7 @@ extension FixedWidthInteger { ) -> (Self, overflow: Bool) { let (partialValue, overflow) = lhs.${newPrefix}ReportingOverflow(${argLabel} rhs) - return (partialValue, overflow == .overflow) + return (partialValue, overflow: overflow) } % end diff --git a/test/Prototypes/BigInt.swift b/test/Prototypes/BigInt.swift index a7c92bc9ad6ea..73a7380ddeda0 100644 --- a/test/Prototypes/BigInt.swift +++ b/test/Prototypes/BigInt.swift @@ -24,7 +24,7 @@ extension FixedWidthInteger { func addingFullWidth(_ other: Self) -> (high: Self, low: Self) { let sum = self.addingReportingOverflow(other) - return (sum.overflow == .overflow ? 1 : 0, sum.partialValue) + return (sum.overflow ? 1 : 0, sum.partialValue) } /// Returns the high and low parts of two seqeuential potentially overflowing @@ -33,8 +33,8 @@ extension FixedWidthInteger { (high: Self, low: Self) { let xy = x.addingReportingOverflow(y) let xyz = xy.partialValue.addingReportingOverflow(z) - let high: Self = (xy.overflow == .overflow ? 1 : 0) + - (xyz.overflow == .overflow ? 1 : 0) + let high: Self = (xy.overflow ? 1 : 0) + + (xyz.overflow ? 1 : 0) return (high, xyz.partialValue) } @@ -43,7 +43,7 @@ extension FixedWidthInteger { func subtractingWithBorrow(_ rhs: Self) -> (borrow: Self, partialValue: Self) { let difference = subtractingReportingOverflow(rhs) - return (difference.overflow == .overflow ? 1 : 0, difference.partialValue) + return (difference.overflow ? 1 : 0, difference.partialValue) } /// Returns a tuple containing the value that would be borrowed from a higher @@ -53,8 +53,8 @@ extension FixedWidthInteger { let firstDifference = subtractingReportingOverflow(x) let secondDifference = firstDifference.partialValue.subtractingReportingOverflow(y) - let borrow: Self = (firstDifference.overflow == .overflow ? 1 : 0) + - (secondDifference.overflow == .overflow ? 1 : 0) + let borrow: Self = (firstDifference.overflow ? 1 : 0) + + (secondDifference.overflow ? 1 : 0) return (borrow, secondDifference.partialValue) } } @@ -513,8 +513,7 @@ public struct _BigInt : // 0b11111111 + (0b11111101_____00000010) + 0b11111111 // (0b11111110_____00000001) + 0b11111111 // (0b11111111_____00000000) - _sanityCheck( - product.high.addingReportingOverflow(carry).overflow == .none) + _sanityCheck(!product.high.addingReportingOverflow(carry).overflow) carry = product.high &+ carry } @@ -1302,60 +1301,60 @@ struct Bit : FixedWidthInteger, UnsignedInteger { // Arithmetic Operations / Operators - func _checkOverflow(_ v: UInt8) -> ArithmeticOverflow { + func _checkOverflow(_ v: UInt8) -> Bool { let mask: UInt8 = ~0 << 1 - return v & mask == 0 ? .none : .overflow + return v & mask != 0 } func addingReportingOverflow(_ rhs: Bit) -> - (partialValue: Bit, overflow: ArithmeticOverflow) { + (partialValue: Bit, overflow: Bool) { let result = value &+ rhs.value return (Bit(result & 1), _checkOverflow(result)) } func subtractingReportingOverflow(_ rhs: Bit) -> - (partialValue: Bit, overflow: ArithmeticOverflow) { + (partialValue: Bit, overflow: Bool) { let result = value &- rhs.value return (Bit(result & 1), _checkOverflow(result)) } func multipliedReportingOverflow(by rhs: Bit) -> - (partialValue: Bit, overflow: ArithmeticOverflow) { + (partialValue: Bit, overflow: Bool) { let result = value &* rhs.value - return (Bit(result), .none) + return (Bit(result), false) } func dividedReportingOverflow(by rhs: Bit) -> - (partialValue: Bit, overflow: ArithmeticOverflow) { - return rhs == 0 ? (self, .none) : (self, .overflow) + (partialValue: Bit, overflow: Bool) { + return (self, rhs != 0) } func remainderReportingOverflow(dividingBy rhs: Bit) -> - (partialValue: Bit, overflow: ArithmeticOverflow) { + (partialValue: Bit, overflow: Bool) { fatalError() } static func +=(lhs: inout Bit, rhs: Bit) { let result = lhs.addingReportingOverflow(rhs) - assert(result.overflow == .none, "Addition overflow") + assert(!result.overflow, "Addition overflow") lhs = result.partialValue } static func -=(lhs: inout Bit, rhs: Bit) { let result = lhs.subtractingReportingOverflow(rhs) - assert(result.overflow == .none, "Subtraction overflow") + assert(!result.overflow, "Subtraction overflow") lhs = result.partialValue } static func *=(lhs: inout Bit, rhs: Bit) { let result = lhs.multipliedReportingOverflow(by: rhs) - assert(result.overflow == .none, "Multiplication overflow") + assert(!result.overflow, "Multiplication overflow") lhs = result.partialValue } static func /=(lhs: inout Bit, rhs: Bit) { let result = lhs.dividedReportingOverflow(by: rhs) - assert(result.overflow == .none, "Division overflow") + assert(!result.overflow, "Division overflow") lhs = result.partialValue } diff --git a/test/stdlib/Integers.swift.gyb b/test/stdlib/Integers.swift.gyb index 6d25528ade066..fe93e978874c1 100644 --- a/test/stdlib/Integers.swift.gyb +++ b/test/stdlib/Integers.swift.gyb @@ -87,7 +87,7 @@ func expectEqual( } func expectEqual( - _ expected: (T, ArithmeticOverflow), _ actual: (T, ArithmeticOverflow), + _ expected: (T, Bool), _ actual: (T, Bool), _ message: @autoclosure () -> String = "", stackTrace: SourceLocStack = SourceLocStack(), showFrame: Bool = true, @@ -706,7 +706,7 @@ dwTests.test("Nested") { let (y, o) = x.addingReportingOverflow(1) expectEqual(y, 0) expectTrue(y == (0 as Int)) - expectTrue(o == .overflow) + expectTrue(o) } do { @@ -716,7 +716,7 @@ dwTests.test("Nested") { expectLT(y, 0) expectTrue(y < (0 as Int)) expectTrue(y < (0 as UInt)) - expectTrue(o == .overflow) + expectTrue(o) } expectFalse(UInt1024.isSigned) diff --git a/validation-test/stdlib/FixedPointArithmeticTraps.swift.gyb b/validation-test/stdlib/FixedPointArithmeticTraps.swift.gyb index 4ed2f92f2d4c4..1e8af194591c3 100644 --- a/validation-test/stdlib/FixedPointArithmeticTraps.swift.gyb +++ b/validation-test/stdlib/FixedPointArithmeticTraps.swift.gyb @@ -41,7 +41,7 @@ func expectNoOverflow( } func expectOverflow( - _ res: (partialValue: T, overflow: ArithmeticOverflow), + _ res: (partialValue: T, overflow: Bool), //===--- TRACE boilerplate ----------------------------------------------===// _ message: @autoclosure () -> String = "", showFrame: Bool = true, @@ -49,20 +49,20 @@ func expectOverflow( file: String = #file, line: UInt = #line ) { expectTrue( - res.overflow == .overflow, "expected overflow", + res.overflow, "expected overflow", stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) } func expectNoOverflow( - _ res: (partialValue: T, overflow: ArithmeticOverflow), + _ res: (partialValue: T, overflow: Bool), //===--- TRACE boilerplate ----------------------------------------------===// _ message: @autoclosure () -> String = "", showFrame: Bool = true, stackTrace: SourceLocStack = SourceLocStack(), file: String = #file, line: UInt = #line ) { - expectTrue( - res.overflow == .none, "expected no overflow", + expectFalse( + res.overflow, "expected no overflow", stackTrace: stackTrace.pushIf(showFrame, file: file, line: line)) }