Skip to content

Commit

Permalink
[stdlib] Get rid of ArithmeticOverflow type
Browse files Browse the repository at this point in the history
  • Loading branch information
Max Moiseev committed Jul 26, 2017
1 parent 5d47a0d commit 1c3e597
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 94 deletions.
37 changes: 16 additions & 21 deletions stdlib/public/core/DoubleWidth.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -269,25 +269,21 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
% 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)

Expand All @@ -298,7 +294,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
let hadPositiveOverflow = !isNegative &&
DoubleWidth.isSigned && product.leadingZeroBitCount == 0

return (result, ArithmeticOverflow(didCarry || hadPositiveOverflow))
return (result, didCarry || hadPositiveOverflow)
}

public func quotientAndRemainder(dividingBy other: DoubleWidth)
Expand Down Expand Up @@ -350,25 +346,25 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
}

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)
Expand All @@ -384,8 +380,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :
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)
}

Expand All @@ -406,7 +401,7 @@ public struct DoubleWidth<Base : FixedWidthInteger> :

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)
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions stdlib/public/core/IntegerParsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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
}
Expand Down
62 changes: 20 additions & 42 deletions stdlib/public/core/Integers.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -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`.
""",
Expand All @@ -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.
""",
Expand All @@ -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`.
""",
Expand All @@ -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.
""",
'%': """\
Expand All @@ -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.
""",
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1948,7 +1926,7 @@ public enum ArithmeticOverflow {
///
/// func squared<T: FixedWidthInteger>(_ x: T) -> T? {
/// let (result, overflow) = x.multipliedReportingOverflow(by: x)
/// guard overflow == .none else {
/// if overflow {
/// return nil
/// }
/// return result
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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)}")
}
Expand Down Expand Up @@ -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
Expand All @@ -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) = (
Expand All @@ -2685,7 +2663,7 @@ public struct ${Self}

return (
partialValue: ${Self}(newStorage),
overflow: ArithmeticOverflow(Bool(overflow)))
overflow: Bool(overflow))
}
% end

Expand Down Expand Up @@ -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
Expand Down
Loading

0 comments on commit 1c3e597

Please sign in to comment.