| //===--- Integers.swift.gyb -----------------------------------*- swift -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| %{ |
| # |
| # Utility code for later in this template |
| # |
| |
| from SwiftIntTypes import all_integer_types, int_max_bits, should_define_truncating_bit_pattern_init |
| from SwiftFloatingPointTypes import getFtoIBounds |
| |
| from string import maketrans, capitalize |
| from itertools import chain |
| |
| # Number of bits in the Builtin.Word type |
| word_bits = int(CMAKE_SIZEOF_VOID_P) * 8 |
| |
| # Number of bits in integer literals. |
| builtinIntLiteralBits = 2048 |
| IntLiteral = 'Int%s' % builtinIntLiteralBits |
| |
| class struct(object): |
| def __init__(self, **kw): |
| self.__dict__ = kw |
| def __repr__(self): |
| return 'struct(%r)' % self.__dict__ |
| |
| binaryArithmetic = { |
| 'Numeric' : [ |
| struct(operator='+', name='adding', firstArg='_', llvmName='add', kind='+'), |
| struct(operator='-', name='subtracting', firstArg='_', llvmName='sub', kind='-'), |
| struct(operator='*', name='multiplied', firstArg='by', llvmName='mul', kind='*'), |
| ], |
| 'BinaryInteger' : [ |
| struct(operator='/', name='divided', firstArg='by', llvmName='div', kind='/'), |
| struct(operator='%', name='remainder', firstArg='dividingBy', llvmName='rem', kind='/'), |
| ], |
| } |
| |
| binaryBitwise = [ |
| struct(operator='&', llvmName='and'), |
| struct(operator='|', llvmName='or'), |
| struct(operator='^', llvmName='xor'), |
| ] |
| |
| maskingShifts = [ |
| struct( |
| operator='&>>', nonMaskingOperator='>>', description='right shift', |
| helper='_nonMaskingRightShift', |
| llvmName=lambda s:['lshr','ashr'][s]), |
| struct( |
| operator='&<<', nonMaskingOperator='<<', description='left shift', |
| helper='_nonMaskingLeftShift', |
| llvmName=lambda _: 'shl'), |
| ] |
| |
| IntMax = 'Int%s' % int_max_bits |
| UIntMax = 'UInt%s' % int_max_bits |
| }% |
| |
| // FIXME(integers): remove these two aliases |
| /// The largest native signed integer type. |
| @available(swift, obsoleted: 4.0, renamed: "${IntMax}") |
| public typealias IntMax = ${IntMax} |
| /// The largest native unsigned integer type. |
| @available(swift, obsoleted: 4.0, renamed: "${UIntMax}") |
| public typealias UIntMax = ${UIntMax} |
| |
| //===----------------------------------------------------------------------===// |
| //===--- Bits for the Stdlib ----------------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| // FIXME(integers): This should go in the stdlib separately, probably. |
| extension ExpressibleByIntegerLiteral |
| where Self : _ExpressibleByBuiltinIntegerLiteral { |
| @_transparent |
| public init(integerLiteral value: Self) { |
| self = value |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| //===--- Operator Documentation -------------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| %{ |
| |
| # documentation for binary operators: +, -, <<, &, etc |
| def operatorComment(operator, fixedWidth): |
| comments = { |
| '+': """\ |
| /// Adds two values and produces their sum. |
| /// |
| /// The addition operator (`+`) calculates the sum of its two arguments. For |
| /// example: |
| /// |
| /// 1 + 2 // 3 |
| /// -10 + 15 // 5 |
| /// -15 + -5 // -20 |
| /// 21.5 + 3.25 // 24.75 |
| /// |
| /// You cannot use `+` with arguments of different types. To add values of |
| /// different types, convert one of the values to the other value's type. |
| /// |
| /// let x: Int8 = 21 |
| /// let y: Int = 1000000 |
| /// Int(x) + y // 1000021 |
| /// |
| """ + ("""\ |
| /// The sum of the two arguments must be representable in the arguments' |
| /// type. In the following example, the result of `21 + 120` is greater than |
| /// the maximum representable `Int8` value: |
| /// |
| /// x + 120 // Overflow error |
| /// |
| /// - Note: Overflow checking is not performed in `-Ounchecked` builds. |
| /// |
| /// If you want to opt out of overflow checking and ignore any overflow, use |
| /// the overflow addition operator (`&+`). |
| /// |
| /// x &+ 120 // -115 |
| /// |
| """ if fixedWidth else '') + """\ |
| /// - Parameters: |
| /// - lhs: The first value to add. |
| /// - rhs: The second value to add. |
| """, |
| '-': """\ |
| /// Subtracts one value from another and produces their difference. |
| /// |
| /// The subtraction operator (`-`) calculates the difference of its two |
| /// arguments. For example: |
| /// |
| /// 8 - 3 // 5 |
| /// -10 - 5 // -15 |
| /// 100 - -5 // 105 |
| /// 10.5 - 100.0 // -89.5 |
| /// |
| /// You cannot use `-` with arguments of different types. To subtract values |
| /// of different types, convert one of the values to the other value's type. |
| /// |
| /// let x: UInt8 = 21 |
| /// let y: UInt = 1000000 |
| /// y - UInt(x) // 999979 |
| /// |
| """ + ("""\ |
| /// The difference of the two arguments must be representable in the |
| /// arguments' type. In the following example, the result of `21 - 50` is |
| /// less than zero, the minimum representable `UInt8` value: |
| /// |
| /// x - 50 // Overflow error |
| /// |
| /// - Note: Overflow checking is not performed in `-Ounchecked` builds. |
| /// |
| /// If you want to opt out of overflow checking and ignore any overflow, use |
| /// the overflow subtraction operator (`&-`). |
| /// |
| /// x &- 50 // 227 |
| /// |
| """ if fixedWidth else '') + """\ |
| /// - Parameters: |
| /// - lhs: A numeric value. |
| /// - rhs: The value to subtract from `lhs`. |
| """, |
| '*': """\ |
| /// Multiplies two values and produces their product. |
| /// |
| /// The multiplication operator (`*`) calculates the product of its two |
| /// arguments. For example: |
| /// |
| /// 2 * 3 // 6 |
| /// 100 * 21 // 2100 |
| /// -10 * 15 // -150 |
| /// 3.5 * 2.25 // 7.875 |
| /// |
| /// You cannot use `*` with arguments of different types. To multiply values |
| /// of different types, convert one of the values to the other value's type. |
| /// |
| /// let x: Int8 = 21 |
| /// let y: Int = 1000000 |
| /// Int(x) * y // 21000000 |
| /// |
| """ + ("""\ |
| /// The product of the two arguments must be representable in the arguments' |
| /// type. In the following example, the result of `21 * 21` is greater than |
| /// the maximum representable `Int8` value: |
| /// |
| /// x * 21 // Overflow error |
| /// |
| /// - Note: Overflow checking is not performed in `-Ounchecked` builds. |
| /// |
| /// If you want to opt out of overflow checking and ignore any overflow, use |
| /// the overflow multiplication operator (`&*`). |
| /// |
| /// x &* 21 // -115 |
| /// |
| """ if fixedWidth else '') + """\ |
| /// - Parameters: |
| /// - lhs: The first value to multiply. |
| /// - rhs: The second value to multiply. |
| """, |
| '/': """\ |
| /// Returns the quotient of dividing the first value by the second. |
| /// |
| /// For integer types, any remainder of the division is discarded. |
| /// |
| /// let x = 21 / 5 |
| /// // x == 4 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to divide. |
| /// - rhs: The value to divide `lhs` by. `rhs` must not be zero. |
| """, |
| '%': """\ |
| /// Returns the remainder of dividing the first value by the second. |
| /// |
| /// The result of the modulo operator (`%`) has the same sign as `lhs` and is |
| /// less than `rhs.magnitude`. |
| /// |
| /// let x = 22 % 5 |
| /// // x == 2 |
| /// let y = 22 % -5 |
| /// // y == 2 |
| /// let z = -22 % -5 |
| /// // z == -2 |
| /// |
| /// For any two integers `a` and `b`, their quotient `q`, and their remainder |
| /// `r`, `a == b * q + r`. |
| /// |
| /// - Parameters: |
| /// - lhs: The value to divide. |
| /// - rhs: The value to divide `lhs` by. `rhs` must not be zero. |
| """, |
| '&+': """\ |
| /// Returns the sum of the two given values, discarding any overflow. |
| /// |
| /// The masking addition operator (`&+`) silently discards any overflow that |
| /// occurs during the operation. In the following example, the sum of `100` |
| /// and `121` is greater than the maximum representable `Int8` value, so the |
| /// result is the overflowed value: |
| /// |
| /// let x: Int8 = 10 &+ 21 |
| /// // x == 31 |
| /// let y: Int8 = 100 &+ 121 |
| /// // y == -35 (after overflow) |
| /// |
| /// - Parameters: |
| /// - lhs: The first value to add. |
| /// - rhs: The second value to add. |
| """, |
| '&-': """\ |
| /// Returns the difference of the two given values, discarding any overflow. |
| /// |
| /// The masking subtraction operator (`&-`) silently discards any overflow |
| /// that occurs during the operation. In the following example, the |
| /// difference of `10` and `21` is less than zero, the minimum representable |
| /// `UInt` value, so the result is the overflowed value: |
| /// |
| /// let x: UInt8 = 21 &- 10 |
| /// // x == 11 |
| /// let y: UInt8 = 10 &- 21 |
| /// // y == 245 (after overflow) |
| /// |
| /// - Parameters: |
| /// - lhs: A numeric value. |
| /// - rhs: The value to subtract from `lhs`. |
| """, |
| '&*': """\ |
| /// Returns the product of the two given values, discarding any overflow. |
| /// |
| /// The masking multiplication operator (`&*`) silently discards any overflow |
| /// that occurs during the operation. In the following example, the product |
| /// of `10` and `50` is greater than the maximum representable `Int8` value, |
| /// so the result is the overflowed value: |
| /// |
| /// let x: Int8 = 10 &* 5 |
| /// // x == 50 |
| /// let y: Int8 = 10 &* 50 |
| /// // y == -12 (after overflow) |
| /// |
| /// - Parameters: |
| /// - lhs: The first value to multiply. |
| /// - rhs: The second value to multiply. |
| """, |
| '&': """\ |
| /// Returns the result of performing a bitwise AND operation on the two given |
| /// values. |
| /// |
| /// A bitwise AND operation results in a value that has each bit set to `1` |
| /// where *both* of its arguments have that bit set to `1`. For example: |
| /// |
| /// let x: UInt8 = 5 // 0b00000101 |
| /// let y: UInt8 = 14 // 0b00001110 |
| /// let z = x & y // 0b00000100 |
| /// |
| /// - Parameters: |
| /// - lhs: An integer value. |
| /// - rhs: Another integer value. |
| """, |
| '|': """\ |
| /// Returns the result of performing a bitwise OR operation on the two given |
| /// values. |
| /// |
| /// A bitwise OR operation results in a value that has each bit set to `1` |
| /// where *one or both* of its arguments have that bit set to `1`. For |
| /// example: |
| /// |
| /// let x: UInt8 = 5 // 0b00000101 |
| /// let y: UInt8 = 14 // 0b00001110 |
| /// let z = x | y // 0b00001111 |
| /// |
| /// - Parameters: |
| /// - lhs: An integer value. |
| /// - rhs: Another integer value. |
| """, |
| '^': """\ |
| /// Returns the result of performing a bitwise XOR operation on the two given |
| /// values. |
| /// |
| /// A bitwise XOR operation, also known as an exclusive OR operation, results |
| /// in a value that has each bit set to `1` where *one or the other but not |
| /// both* of its arguments had that bit set to `1`. For example: |
| /// |
| /// let x: UInt8 = 5 // 0b00000101 |
| /// let y: UInt8 = 14 // 0b00001110 |
| /// let z = x ^ y // 0b00001011 |
| /// |
| /// - Parameters: |
| /// - lhs: An integer value. |
| /// - rhs: Another integer value. |
| """, |
| '&>>': """\ |
| /// Returns the result of shifting a value's binary representation the |
| /// specified number of digits to the right, masking the shift amount to the |
| /// type's bit width. |
| /// |
| /// The masking right shift operator (`&>>`) performs a *masking shift*, |
| /// where the value passed as `rhs` is masked to produce a value in the |
| /// range `0..<lhs.bitWidth`. The shift is performed using this masked |
| /// value. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the shift amount requires no masking. |
| /// |
| /// let x: UInt8 = 30 // 0b00011110 |
| /// let y = x &>> 2 |
| /// // y == 7 // 0b00000111 |
| /// |
| /// However, if you use `19` as `rhs`, the operation first bitmasks `rhs` to |
| /// `3`, and then uses that masked value as the number of bits to shift `lhs`. |
| /// |
| /// let z = x &>> 19 |
| /// // z == 3 // 0b00000011 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the right. If `rhs` is |
| /// outside the range `0..<lhs.bitWidth`, it is masked to produce a |
| /// value within that range. |
| """, |
| '&<<': """\ |
| /// Returns the result of shifting a value's binary representation the |
| /// specified number of digits to the left, masking the shift amount to the |
| /// type's bit width. |
| /// |
| /// The masking left shift operator (`&<<`) performs a *masking shift*, where |
| /// the value used as `rhs` is masked to produce a value in the range |
| /// `0..<lhs.bitWidth`. The shift is performed using this masked value. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the shift amount requires no masking. |
| /// |
| /// let x: UInt8 = 30 // 0b00011110 |
| /// let y = x &<< 2 |
| /// // y == 120 // 0b01111000 |
| /// |
| /// However, if you pass `19` as `rhs`, the method first bitmasks `rhs` to |
| /// `3`, and then uses that masked value as the number of bits to shift `lhs`. |
| /// |
| /// let z = x &<< 19 |
| /// // z == 240 // 0b11110000 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the left. If `rhs` is |
| /// outside the range `0..<lhs.bitWidth`, it is masked to produce a |
| /// value within that range. |
| """, |
| '>>': """\ |
| /// Returns the result of shifting a value's binary representation the |
| /// specified number of digits to the right. |
| /// |
| /// The `>>` operator performs a *smart shift*, which defines a result for a |
| /// shift of any value. |
| /// |
| /// - Using a negative value for `rhs` performs a left shift using |
| /// `abs(rhs)`. |
| /// - Using a value for `rhs` that is greater than or equal to the bit width |
| /// of `lhs` is an *overshift*. An overshift results in `-1` for a |
| /// negative value of `lhs` or `0` for a nonnegative value. |
| /// - Using any other value for `rhs` performs a right shift on `lhs` by that |
| /// amount. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the value is shifted right by two bits. |
| /// |
| /// let x: UInt8 = 30 // 0b00011110 |
| /// let y = x >> 2 |
| /// // y == 7 // 0b00000111 |
| /// |
| /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits |
| /// are set to zero. |
| /// |
| /// let z = x >> 11 |
| /// // z == 0 // 0b00000000 |
| /// |
| /// Using a negative value as `rhs` is the same as performing a left shift |
| /// using `abs(rhs)`. |
| /// |
| /// let a = x >> -3 |
| /// // a == 240 // 0b11110000 |
| /// let b = x << 3 |
| /// // b == 240 // 0b11110000 |
| /// |
| /// Right shift operations on negative values "fill in" the high bits with |
| /// ones instead of zeros. |
| /// |
| /// let q: Int8 = -30 // 0b11100010 |
| /// let r = q >> 2 |
| /// // r == -8 // 0b11111000 |
| /// |
| /// let s = q >> 11 |
| /// // s == -1 // 0b11111111 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the right. |
| """, |
| '<<': """\ |
| /// Returns the result of shifting a value's binary representation the |
| /// specified number of digits to the left. |
| /// |
| /// The `<<` operator performs a *smart shift*, which defines a result for a |
| /// shift of any value. |
| /// |
| /// - Using a negative value for `rhs` performs a right shift using |
| /// `abs(rhs)`. |
| /// - Using a value for `rhs` that is greater than or equal to the bit width |
| /// of `lhs` is an *overshift*, resulting in zero. |
| /// - Using any other value for `rhs` performs a left shift on `lhs` by that |
| /// amount. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the value is shifted left by two bits. |
| /// |
| /// let x: UInt8 = 30 // 0b00011110 |
| /// let y = x << 2 |
| /// // y == 120 // 0b01111000 |
| /// |
| /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits |
| /// are set to zero. |
| /// |
| /// let z = x << 11 |
| /// // z == 0 // 0b00000000 |
| /// |
| /// Using a negative value as `rhs` is the same as performing a right shift |
| /// with `abs(rhs)`. |
| /// |
| /// let a = x << -3 |
| /// // a == 3 // 0b00000011 |
| /// let b = x >> 3 |
| /// // b == 3 // 0b00000011 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the left. |
| """, |
| } |
| return comments[operator] |
| |
| # documentation for assignment operators: +=, -=, <<=, etc |
| def assignmentOperatorComment(operator, fixedWidth): |
| comments = { |
| '+': """\ |
| /// Adds two values and stores the result in the left-hand-side variable. |
| /// |
| """ + ("""\ |
| /// The sum of the two arguments must be representable in the arguments' |
| /// type. In the following example, the result of `21 + 120` is greater than |
| /// the maximum representable `Int8` value: |
| /// |
| /// var x: Int8 = 21 |
| /// x += 120 |
| /// // Overflow error |
| /// |
| /// - Note: Overflow checking is not performed in `-Ounchecked` builds. |
| /// |
| """ if fixedWidth else '') + """\ |
| /// - Parameters: |
| /// - lhs: The first value to add. |
| /// - rhs: The second value to add. |
| """, |
| '-': """\ |
| /// Subtracts the second value from the first and stores the difference in the |
| /// left-hand-side variable. |
| /// |
| """ + ("""\ |
| /// The difference of the two arguments must be representable in the |
| /// arguments' type. In the following example, the result of `21 - 50` is |
| /// less than zero, the minimum representable `UInt8` value: |
| /// |
| /// var x: UInt8 = 21 |
| /// x - 50 |
| /// // Overflow error |
| /// |
| /// - Note: Overflow checking is not performed in `-Ounchecked` builds. |
| /// |
| """ if fixedWidth else '') + """\ |
| /// - Parameters: |
| /// - lhs: A numeric value. |
| /// - rhs: The value to subtract from `lhs`. |
| """, |
| '*': """\ |
| /// Multiplies two values and stores the result in the left-hand-side |
| /// variable. |
| /// |
| """ + ("""\ |
| /// The product of the two arguments must be representable in the arguments' |
| /// type. In the following example, the result of `21 * 21` is greater than |
| /// the maximum representable `Int8` value: |
| /// |
| /// var x: Int8 = 21 |
| /// x * 21 |
| /// // Overflow error |
| /// |
| /// - Note: Overflow checking is not performed in `-Ounchecked` builds. |
| /// |
| """ if fixedWidth else '') + """\ |
| /// - Parameters: |
| /// - lhs: The first value to multiply. |
| /// - rhs: The second value to multiply. |
| """, |
| '/': """\ |
| /// Divides the first value by the second and stores the quotient in the |
| /// left-hand-side variable. |
| /// |
| /// For integer types, any remainder of the division is discarded. |
| /// |
| /// var x = 21 |
| /// x /= 5 |
| /// // x == 4 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to divide. |
| /// - rhs: The value to divide `lhs` by. `rhs` must not be zero. |
| """, |
| '%': """\ |
| /// Divides the first value by the second and stores the remainder in the |
| /// left-hand-side variable. |
| /// |
| /// The result has the same sign as `lhs` and is less than `rhs.magnitude`. |
| /// |
| /// var x = 22 |
| /// x %= 5 |
| /// // x == 2 |
| /// |
| /// var y = 22 |
| /// y %= -5 |
| /// // y == 2 |
| /// |
| /// var z = -22 |
| /// z %= -5 |
| /// // z == -2 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to divide. |
| /// - rhs: The value to divide `lhs` by. `rhs` must not be zero. |
| """, |
| '&': """\ |
| /// Stores the result of performing a bitwise AND operation on the two given |
| /// values in the left-hand-side variable. |
| /// |
| /// A bitwise AND operation results in a value that has each bit set to `1` |
| /// where *both* of its arguments have that bit set to `1`. For example: |
| /// |
| /// var x: UInt8 = 5 // 0b00000101 |
| /// let y: UInt8 = 14 // 0b00001110 |
| /// x &= y // 0b00000100 |
| /// |
| /// - Parameters: |
| /// - lhs: An integer value. |
| /// - rhs: Another integer value. |
| """, |
| '|': """\ |
| /// Stores the result of performing a bitwise OR operation on the two given |
| /// values in the left-hand-side variable. |
| /// |
| /// A bitwise OR operation results in a value that has each bit set to `1` |
| /// where *one or both* of its arguments have that bit set to `1`. For |
| /// example: |
| /// |
| /// var x: UInt8 = 5 // 0b00000101 |
| /// let y: UInt8 = 14 // 0b00001110 |
| /// x |= y // 0b00001111 |
| /// |
| /// - Parameters: |
| /// - lhs: An integer value. |
| /// - rhs: Another integer value. |
| """, |
| '^': """\ |
| /// Stores the result of performing a bitwise XOR operation on the two given |
| /// values in the left-hand-side variable. |
| /// |
| /// A bitwise XOR operation, also known as an exclusive OR operation, results |
| /// in a value that has each bit set to `1` where *one or the other but not |
| /// both* of its arguments had that bit set to `1`. For example: |
| /// |
| /// var x: UInt8 = 5 // 0b00000101 |
| /// let y: UInt8 = 14 // 0b00001110 |
| /// x ^= y // 0b00001011 |
| /// |
| /// - Parameters: |
| /// - lhs: An integer value. |
| /// - rhs: Another integer value. |
| """, |
| '&>>': """\ |
| /// Calculates the result of shifting a value's binary representation the |
| /// specified number of digits to the right, masking the shift amount to the |
| /// type's bit width, and stores the result in the left-hand-side variable. |
| /// |
| /// The `&>>=` operator performs a *masking shift*, where the value passed as |
| /// `rhs` is masked to produce a value in the range `0..<lhs.bitWidth`. The |
| /// shift is performed using this masked value. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the shift amount requires no masking. |
| /// |
| /// var x: UInt8 = 30 // 0b00011110 |
| /// x &>>= 2 |
| /// // x == 7 // 0b00000111 |
| /// |
| /// However, if you use `19` as `rhs`, the operation first bitmasks `rhs` to |
| /// `3`, and then uses that masked value as the number of bits to shift `lhs`. |
| /// |
| /// var y: UInt8 = 30 // 0b00011110 |
| /// y &>>= 19 |
| /// // y == 3 // 0b00000011 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the right. If `rhs` is |
| /// outside the range `0..<lhs.bitWidth`, it is masked to produce a |
| /// value within that range. |
| """, |
| '&<<': """\ |
| /// Returns the result of shifting a value's binary representation the |
| /// specified number of digits to the left, masking the shift amount to the |
| /// type's bit width, and stores the result in the left-hand-side variable. |
| /// |
| /// The `&<<=` operator performs a *masking shift*, where the value used as |
| /// `rhs` is masked to produce a value in the range `0..<lhs.bitWidth`. The |
| /// shift is performed using this masked value. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the shift amount requires no masking. |
| /// |
| /// var x: UInt8 = 30 // 0b00011110 |
| /// x &<<= 2 |
| /// // x == 120 // 0b01111000 |
| /// |
| /// However, if you pass `19` as `rhs`, the method first bitmasks `rhs` to |
| /// `3`, and then uses that masked value as the number of bits to shift `lhs`. |
| /// |
| /// var y: UInt8 = 30 // 0b00011110 |
| /// y &<<= 19 |
| /// // y == 240 // 0b11110000 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the left. If `rhs` is |
| /// outside the range `0..<lhs.bitWidth`, it is masked to produce a |
| /// value within that range. |
| """, |
| '>>': """\ |
| /// Stores the result of shifting a value's binary representation the |
| /// specified number of digits to the right in the left-hand-side variable. |
| /// |
| /// The `>>=` operator performs a *smart shift*, which defines a result for a |
| /// shift of any value. |
| /// |
| /// - Using a negative value for `rhs` performs a left shift using |
| /// `abs(rhs)`. |
| /// - Using a value for `rhs` that is greater than or equal to the bit width |
| /// of `lhs` is an *overshift*. An overshift results in `-1` for a |
| /// negative value of `lhs` or `0` for a nonnegative value. |
| /// - Using any other value for `rhs` performs a right shift on `lhs` by that |
| /// amount. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the value is shifted right by two bits. |
| /// |
| /// var x: UInt8 = 30 // 0b00011110 |
| /// x >>= 2 |
| /// // x == 7 // 0b00000111 |
| /// |
| /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits |
| /// are set to zero. |
| /// |
| /// var y: UInt8 = 30 // 0b00011110 |
| /// y >>= 11 |
| /// // y == 0 // 0b00000000 |
| /// |
| /// Using a negative value as `rhs` is the same as performing a left shift |
| /// using `abs(rhs)`. |
| /// |
| /// var a: UInt8 = 30 // 0b00011110 |
| /// a >>= -3 |
| /// // a == 240 // 0b11110000 |
| /// |
| /// var b: UInt8 = 30 // 0b00011110 |
| /// b <<= 3 |
| /// // b == 240 // 0b11110000 |
| /// |
| /// Right shift operations on negative values "fill in" the high bits with |
| /// ones instead of zeros. |
| /// |
| /// var q: Int8 = -30 // 0b11100010 |
| /// q >>= 2 |
| /// // q == -8 // 0b11111000 |
| /// |
| /// var r: Int8 = -30 // 0b11100010 |
| /// r >>= 11 |
| /// // r == -1 // 0b11111111 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the right. |
| """, |
| '<<': """\ |
| /// Stores the result of shifting a value's binary representation the |
| /// specified number of digits to the left in the left-hand-side variable. |
| /// |
| /// The `<<` operator performs a *smart shift*, which defines a result for a |
| /// shift of any value. |
| /// |
| /// - Using a negative value for `rhs` performs a right shift using |
| /// `abs(rhs)`. |
| /// - Using a value for `rhs` that is greater than or equal to the bit width |
| /// of `lhs` is an *overshift*, resulting in zero. |
| /// - Using any other value for `rhs` performs a left shift on `lhs` by that |
| /// amount. |
| /// |
| /// The following example defines `x` as an instance of `UInt8`, an 8-bit, |
| /// unsigned integer type. If you use `2` as the right-hand-side value in an |
| /// operation on `x`, the value is shifted left by two bits. |
| /// |
| /// var x: UInt8 = 30 // 0b00011110 |
| /// x <<= 2 |
| /// // x == 120 // 0b01111000 |
| /// |
| /// If you use `11` as `rhs`, `x` is overshifted such that all of its bits |
| /// are set to zero. |
| /// |
| /// var y: UInt8 = 30 // 0b00011110 |
| /// y <<= 11 |
| /// // y == 0 // 0b00000000 |
| /// |
| /// Using a negative value as `rhs` is the same as performing a right shift |
| /// with `abs(rhs)`. |
| /// |
| /// var a: UInt8 = 30 // 0b00011110 |
| /// a <<= -3 |
| /// // a == 3 // 0b00000011 |
| /// |
| /// var b: UInt8 = 30 // 0b00011110 |
| /// b >>= 3 |
| /// // b == 3 // 0b00000011 |
| /// |
| /// - Parameters: |
| /// - lhs: The value to shift. |
| /// - rhs: The number of bits to shift `lhs` to the left. |
| """, |
| } |
| return comments[operator] |
| |
| # documentation for overflow-calculating arithmetic methods, indexed |
| # by the related operator: |
| # + addingReportingOverflow(_:) |
| # - subtractingReportingOverflow(_:) |
| # * multiplyingReportingOverflow(_:) |
| # / dividedReportingOverflow(by:) |
| # % remainderReportingOverflow(dividingBy:) |
| def overflowOperationComment(operator): |
| comments = { |
| '+': """\ |
| /// Returns the sum of this value and the given value along with a flag |
| /// indicating whether overflow occurred in the operation. |
| /// |
| /// - Parameter rhs: The value to add to this value. |
| /// - Returns: A tuple containing the result of the addition along with a |
| /// Boolean value indicating whether overflow occurred. If the `overflow` |
| /// component 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`. |
| """, |
| '-': """\ |
| /// Returns the difference of this value and the given value along with a |
| /// flag indicating whether overflow occurred in the operation. |
| /// |
| /// - 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 `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. |
| """, |
| '*': """\ |
| /// Returns the product of this value and the given value along with a flag |
| /// indicating whether overflow occurred in the operation. |
| /// |
| /// - Parameter rhs: The value to multiply by this value. |
| /// - Returns: A tuple containing the result of the multiplication along with |
| /// a Boolean value indicating whether overflow occurred. If the `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`. |
| """, |
| '/': """\ |
| /// Returns the quotient of dividing this value by the given value along with |
| /// 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, true)`. |
| /// |
| /// - Parameter rhs: The value to divide this value by. |
| /// - Returns: A tuple containing the result of the division along with a |
| /// Boolean value indicating whether overflow occurred. If the `overflow` |
| /// component 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. |
| """, |
| '%': """\ |
| // FIXME(integers): the comment is for division instead of remainder |
| /// Returns the remainder of dividing this value by the given value along |
| /// with 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, true)`. |
| /// |
| /// - Parameter rhs: The value to divide this value by. |
| /// - Returns: A tuple containing the result of the division along with a |
| /// Boolean value indicating whether overflow occurred. If the `overflow` |
| /// component 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. |
| """, |
| } |
| return comments[operator] |
| |
| # documentation for "unsafe" arithmetic methods, indexed by the related |
| # operator: |
| # + unsafeAdding(_:) |
| # - unsafeSubtracting(_:) |
| # * unsafeMultiplying(_:) |
| # / unsafeDividing(by:) |
| def unsafeOperationComment(operator): |
| comments = { |
| '+': """\ |
| /// Returns the sum of this value and the given value without checking for |
| /// arithmetic overflow. |
| /// |
| /// If an arithmetic overflow occurs, the behavior is undefined. Use this |
| /// function only to avoid the cost of overflow checking when you are sure |
| /// that the operation won't overflow. |
| /// |
| /// - Parameter rhs: The value to add to this value. |
| /// - Returns: The sum of this value and `rhs`. |
| """, |
| '-': """\ |
| /// Returns the difference of this value and the given value without checking |
| /// for arithmetic overflow. |
| /// |
| /// If an arithmetic overflow occurs, the behavior is undefined. Use this |
| /// function only to avoid the cost of overflow checking when you are sure |
| /// that the operation won't overflow. |
| /// |
| /// - Parameter rhs: The value to subtract from this value. |
| /// - Returns: The difference of this value and `rhs`. |
| """, |
| '*': """\ |
| /// Returns the product of this value and the given value without checking |
| /// for arithmetic overflow. |
| /// |
| /// If an arithmetic overflow occurs, the behavior is undefined. Use this |
| /// function only to avoid the cost of overflow checking when you are sure |
| /// that the operation won't overflow. |
| /// |
| /// - Parameter rhs: The value to multiply by this value. |
| /// - Returns: The difference of this value and `rhs`. |
| """, |
| '/': """\ |
| /// Returns the quotient of dividing this value by the given value without |
| /// checking for arithmetic overflow. |
| /// |
| /// If an arithmetic overflow occurs, the behavior is undefined. Use this |
| /// function only to avoid the cost of overflow checking when you are sure |
| /// that the operation won't overflow. |
| /// |
| /// - Parameter rhs: The value to divide this value by. |
| /// - Returns: The quotient of dividing this value by `rhs`. |
| """, |
| } |
| return comments[operator] |
| |
| }% |
| |
| //===----------------------------------------------------------------------===// |
| //===--- Numeric ----------------------------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| /// Declares methods backing binary arithmetic operators--such as `+`, `-` and |
| /// `*`--and their mutating counterparts. |
| /// |
| /// The `Numeric` protocol provides a suitable basis for arithmetic on |
| /// scalar values, such as integers and floating-point numbers. You can write |
| /// generic methods that operate on any numeric type in the standard library |
| /// by using the `Numeric` protocol as a generic constraint. |
| /// |
| /// The following example declares a method that calculates the total of any |
| /// sequence with `Numeric` elements. |
| /// |
| /// extension Sequence where Element: Numeric { |
| /// func sum() -> Element { |
| /// return reduce(0, +) |
| /// } |
| /// } |
| /// |
| /// The `sum()` method is now available on any sequence or collection with |
| /// numeric values, whether it is an array of `Double` or a countable range of |
| /// `Int`. |
| /// |
| /// let arraySum = [1.1, 2.2, 3.3, 4.4, 5.5].sum() |
| /// // arraySum == 16.5 |
| /// |
| /// let rangeSum = (1..<10).sum() |
| /// // rangeSum == 45 |
| /// |
| /// Conforming to the Numeric Protocol |
| /// ===================================== |
| /// |
| /// To add `Numeric` protocol conformance to your own custom type, implement |
| /// the required mutating methods. Extensions to `Numeric` provide default |
| /// implementations for the protocol's nonmutating methods based on the |
| /// mutating variants. |
| public protocol Numeric : Equatable, ExpressibleByIntegerLiteral { |
| /// Creates a new instance from the given integer, if it can be represented |
| /// exactly. |
| /// |
| /// If the value passed as `source` is not representable exactly, the result |
| /// is `nil`. In the following example, the constant `x` is successfully |
| /// created from a value of `100`, while the attempt to initialize the |
| /// constant `y` from `1_000` fails because the `Int8` type can represent |
| /// `127` at maximum: |
| /// |
| /// let x = Int8(exactly: 100) |
| /// // x == Optional(100) |
| /// let y = Int8(exactly: 1_000) |
| /// // y == nil |
| /// |
| /// - Parameter source: A value to convert to this type. |
| init?<T : BinaryInteger>(exactly source: T) |
| |
| // FIXME(ABI)#44 (Recursive Protocol Constraints): should be just |
| // Numeric, Comparable |
| /// A type that can represent the absolute value of any possible value of the |
| /// conforming type. |
| associatedtype Magnitude : Comparable, ExpressibleByIntegerLiteral |
| |
| /// The magnitude of this value. |
| /// |
| /// For any numeric value `x`, `x.magnitude` is the absolute value of `x`. |
| /// You can use the `magnitude` property in operations that are simpler to |
| /// implement in terms of unsigned values, such as printing the value of an |
| /// integer, which is just printing a '-' character in front of an absolute |
| /// value. |
| /// |
| /// let x = -200 |
| /// // x.magnitude == 200 |
| /// |
| /// The global `abs(_:)` function provides more familiar syntax when you need |
| /// to find an absolute value. In addition, because `abs(_:)` always returns |
| /// a value of the same type, even in a generic context, using the function |
| /// instead of the `magnitude` property is encouraged. |
| var magnitude: Magnitude { get } |
| |
| % for x in binaryArithmetic['Numeric']: |
| // defaulted using an in-place counterpart, but can be used as an |
| // optimization hook |
| ${operatorComment(x.operator, False)} |
| static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self |
| |
| // implementation hook |
| ${assignmentOperatorComment(x.operator, False)} |
| static func ${x.operator}=(_ lhs: inout Self, rhs: Self) |
| % end |
| } |
| |
| % # FIXME(integers): uncomment once the compilation time improves. |
| % # Don't forget to remove similar definitions from concrete integer types, |
| % # floating point types, CGFloat, and Decimal in Foundation. |
| % for Protocol in []: # !!! FIXME !!! ['Numeric', 'BinaryInteger', 'FloatingPoint']: |
| % # Explicitly providing these operations for BinaryInteger and FloatingPoint |
| % # protocols because Strideable conformance creates ambiguity if the |
| % # operations are only defined for Numeric |
| extension ${Protocol} { |
| % if Protocol in ['Numeric', 'FloatingPoint']: |
| % ops = binaryArithmetic['Numeric'] |
| % else: |
| % ops = binaryArithmetic['Numeric'] + binaryArithmetic['BinaryInteger'] |
| % for x in ops: |
| % callLabel = x.firstArg + ': ' if not x.firstArg == '_' else '' |
| ${operatorComment(x.operator, False)} |
| @_transparent |
| public static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self { |
| var lhs = lhs |
| lhs ${x.operator}= rhs |
| return lhs |
| } |
| % end |
| } |
| % end |
| |
| /// A type that can represent both positive and negative values. |
| /// |
| /// The `SignedNumeric` protocol extends the operations defined by the |
| /// `Numeric` protocol to include a value's additive inverse. |
| /// |
| /// Conforming to the SignedNumeric Protocol |
| /// =========================================== |
| /// |
| /// Because the `SignedNumeric` protocol provides default implementations of |
| /// both of its required methods, you don't need to do anything beyond |
| /// declaring conformance to the protocol and ensuring that the values of your |
| /// type support negation. To customize your type's implementation, provide |
| /// your own mutating `negate()` method. |
| public protocol SignedNumeric : Numeric { |
| /// Returns the additive inverse of the specified value. |
| /// |
| /// The negation operator (prefix `-`) returns the additive inverse of its |
| /// argument. |
| /// |
| /// let x = 21 |
| /// let y = -x |
| /// // y == -21 |
| /// |
| /// The resulting value must be representable in the same type as the |
| /// argument. In particular, negating a signed, fixed-width integer type's |
| /// minimum results in a value that cannot be represented. |
| /// |
| /// let z = -Int8.min |
| /// // Overflow error |
| /// |
| /// - Returns: The additive inverse of this value. |
| static prefix func - (_ operand: Self) -> Self |
| |
| /// Replaces this value with its additive inverse. |
| /// |
| /// The following example uses the `negate()` method to negate the value of |
| /// an integer `x`: |
| /// |
| /// var x = 21 |
| /// x.negate() |
| /// // x == -21 |
| mutating func negate() |
| } |
| |
| extension SignedNumeric { |
| /// Returns the additive inverse of the specified value. |
| /// |
| /// The negation operator (prefix `-`) returns the additive inverse of its |
| /// argument. |
| /// |
| /// let x = 21 |
| /// let y = -x |
| /// // y == -21 |
| /// |
| /// The resulting value must be representable in the same type as the |
| /// argument. In particular, negating a signed, fixed-width integer type's |
| /// minimum results in a value that cannot be represented. |
| /// |
| /// let z = -Int8.min |
| /// // Overflow error |
| /// |
| /// - Returns: The additive inverse of the argument. |
| @_transparent |
| public static prefix func - (_ operand: Self) -> Self { |
| var result = operand |
| result.negate() |
| return result |
| } |
| |
| /// Replaces this value with its additive inverse. |
| /// |
| /// The following example uses the `negate()` method to negate the value of |
| /// an integer `x`: |
| /// |
| /// var x = 21 |
| /// x.negate() |
| /// // x == -21 |
| @_transparent |
| public mutating func negate() { |
| self = 0 - self |
| } |
| } |
| |
| |
| /// Returns the absolute value of the given number. |
| /// |
| /// - Parameter x: A signed number. |
| /// - Returns: The absolute value of `x`. |
| @_transparent |
| public func abs<T : SignedNumeric>(_ x: T) -> T |
| where T.Magnitude == T { |
| return x.magnitude |
| } |
| |
| /// Returns the absolute value of the given number. |
| /// |
| /// The absolute value of `x` must be representable in the same type. In |
| /// particular, the absolute value of a signed, fixed-width integer type's |
| /// minimum cannot be represented. |
| /// |
| /// let x = Int8.min |
| /// // x == -128 |
| /// let y = abs(x) |
| /// // Overflow error |
| /// |
| /// - Parameter x: A signed number. |
| /// - Returns: The absolute value of `x`. |
| public func abs<T : SignedNumeric & Comparable>(_ x: T) -> T { |
| return x < 0 ? -x : x |
| } |
| |
| extension Numeric { |
| /// Returns the given number unchanged. |
| /// |
| /// You can use the unary plus operator (`+`) to provide symmetry in your |
| /// code for positive numbers when also using the unary minus operator. |
| /// |
| /// let x = -21 |
| /// let y = +21 |
| /// // x == -21 |
| /// // y == 21 |
| /// |
| /// - Returns: The given argument without any changes. |
| @_transparent |
| public static prefix func + (x: Self) -> Self { |
| return x |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| //===--- BinaryInteger ----------------------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| /// An integer type with a binary representation. |
| /// |
| /// The `BinaryInteger` protocol is the basis for all the integer types |
| /// provided by the standard library. All of the standard library's integer |
| /// types, such as `Int` and `UInt32`, conform to `BinaryInteger`. |
| /// |
| /// Converting Between Numeric Types |
| /// ================================ |
| /// |
| /// You can create new instances of a type that conforms to the `BinaryInteger` |
| /// protocol from a floating-point number or another binary integer of any |
| /// type. The `BinaryInteger` protocol provides initializers for four |
| /// different kinds of conversion. |
| /// |
| /// Range-Checked Conversion |
| /// ------------------------ |
| /// |
| /// You use the default `init(_:)` initializer to create a new instance when |
| /// you're sure that the value passed is representable in the new type. For |
| /// example, an instance of `Int16` can represent the value `500`, so the |
| /// first conversion in the code sample below succeeds. That same value is too |
| /// large to represent as an `Int8` instance, so the second conversion fails, |
| /// triggering a runtime error. |
| /// |
| /// let x: Int = 500 |
| /// let y = Int16(x) |
| /// // y == 500 |
| /// |
| /// let z = Int8(x) |
| /// // Error: Not enough bits to represent... |
| /// |
| /// When you create a binary integer from a floating-point value using the |
| /// default initializer, the value is rounded toward zero before the range is |
| /// checked. In the following example, the value `127.75` is rounded to `127`, |
| /// which is representable by the `Int8` type. `128.25` is rounded to `128`, |
| /// which is not representable as an `Int8` instance, triggering a runtime |
| /// error. |
| /// |
| /// let e = Int8(127.75) |
| /// // e == 127 |
| /// |
| /// let f = Int8(128.25) |
| /// // Error: Double value cannot be converted... |
| /// |
| /// |
| /// Exact Conversion |
| /// ---------------- |
| /// |
| /// Use the `init?(exactly:)` initializer to create a new instance after |
| /// checking whether the passed value is representable. Instead of trapping on |
| /// out-of-range values, using the failable `exact` initializer results in |
| /// `nil`. |
| /// |
| /// let x = Int16(exactly: 500) |
| /// // x == Optional(500) |
| /// |
| /// let y = Int8(exactly: 500) |
| /// // y == nil |
| /// |
| /// When converting floating-point values, the `init?(exact:)` initializer |
| /// checks both that the passed value has no fractional part and that the |
| /// value is representable in the resulting type. |
| /// |
| /// let e = Int8(exactly: 23.0) // integral value, representable |
| /// // e == Optional(23) |
| /// |
| /// let f = Int8(exactly: 23.75) // fractional value, representable |
| /// // f == nil |
| /// |
| /// let g = Int8(exactly: 500.0) // integral value, nonrepresentable |
| /// // g == nil |
| /// |
| /// Clamping Conversion |
| /// ------------------- |
| /// |
| /// Use the `init(clamping:)` initializer to create a new instance of a binary |
| /// integer type where out-of-range values are clamped to the representable |
| /// range of the type. For a type `T`, the resulting value is in the range |
| /// `T.min...T.max`. |
| /// |
| /// let x = Int16(clamping: 500) |
| /// // x == 500 |
| /// |
| /// let y = Int8(clamping: 500) |
| /// // y == 127 |
| /// |
| /// let z = UInt8(clamping: -500) |
| /// // z == 0 |
| /// |
| /// Bit Pattern Conversion |
| /// ---------------------- |
| /// |
| /// Use the `init(truncatingIfNeeded:)` initializer to create a new instance |
| /// with the same bit pattern as the passed value, extending or truncating the |
| /// value's representation as necessary. Note that the value may not be |
| /// preserved, particularly when converting between signed to unsigned integer |
| /// types or when the destination type has a smaller bit width than the source |
| /// type. The following example shows how extending and truncating work for |
| /// nonnegative integers: |
| /// |
| /// let q: Int16 = 850 |
| /// // q == 0b00000011_01010010 |
| /// |
| /// let r = Int8(truncatingIfNeeded: q) // truncate 'q' to fit in 8 bits |
| /// // r == 82 |
| /// // == 0b01010010 |
| /// |
| /// let s = Int16(truncatingIfNeeded: s) // extend 'r' to fill 16 bits |
| /// // s == 82 |
| /// // == 0b00000000_01010010 |
| /// |
| /// Any padding is performed by *sign-extending* the passed value. When |
| /// nonnegative integers are extended, the result is padded with zeroes. When |
| /// negative integers are extended, the result is padded with ones. This |
| /// example shows several extending conversions of a negative value---note |
| /// that negative values are sign-extended even when converting to an unsigned |
| /// type. |
| /// |
| /// let t: Int8 = -100 |
| /// // t == -100 |
| /// // t's binary representation == 0b10011100 |
| /// |
| /// let u = UInt8(truncatingIfNeeded: t) |
| /// // u == 156 |
| /// // u's binary representation == 0b10011100 |
| /// |
| /// let v = Int16(truncatingIfNeeded: t) |
| /// // v == -100 |
| /// // v's binary representation == 0b11111111_10011100 |
| /// |
| /// let w = UInt16(truncatingIfNeeded: t) |
| /// // w == 65436 |
| /// // w's binary representation == 0b11111111_10011100 |
| /// |
| /// |
| /// Comparing Across Integer Types |
| /// ============================== |
| /// |
| /// You can use relational operators, such as the less-than and equal-to |
| /// operators (`<` and `==`), to compare instances of different binary integer |
| /// types. The following example compares instances of the `Int`, `UInt`, and |
| /// `UInt8` types: |
| /// |
| /// let x: Int = -23 |
| /// let y: UInt = 1_000 |
| /// let z: UInt8 = 23 |
| /// |
| /// if x < y { |
| /// print("\(x) is less than \(y).") |
| /// } |
| /// // Prints "-23 is less than 1000." |
| /// |
| /// if z > x { |
| /// print("\(z) is greater than \(x).") |
| /// } |
| /// // Prints "23 is greater than -23." |
| public protocol BinaryInteger : |
| Hashable, Numeric, CustomStringConvertible, Strideable |
| where Magnitude : BinaryInteger, Magnitude.Magnitude == Magnitude |
| { |
| /// A Boolean value indicating whether this type is a signed integer type. |
| /// |
| /// *Signed* integer types can represent both positive and negative values. |
| /// *Unsigned* integer types can represent only nonnegative values. |
| static var isSigned: Bool { get } |
| |
| /// Creates an integer from the given floating-point value, if it can be |
| /// represented exactly. |
| /// |
| /// If the value passed as `source` is not representable exactly, the result |
| /// is `nil`. In the following example, the constant `x` is successfully |
| /// created from a value of `21.0`, while the attempt to initialize the |
| /// constant `y` from `21.5` fails: |
| /// |
| /// let x = Int(exactly: 21.0) |
| /// // x == Optional(21) |
| /// let y = Int(exactly: 21.5) |
| /// // y == nil |
| /// |
| /// - Parameter source: A floating-point value to convert to an integer. |
| init?<T : BinaryFloatingPoint>(exactly source: T) |
| |
| /// Creates an integer from the given floating-point value, rounding toward |
| /// zero. |
| /// |
| /// Any fractional part of the value passed as `source` is removed, rounding |
| /// the value toward zero. |
| /// |
| /// let x = Int(21.5) |
| /// // x == 21 |
| /// let y = Int(-21.5) |
| /// // y == -21 |
| /// |
| /// If `source` is outside the bounds of this type after rounding toward |
| /// zero, a runtime error may occur. |
| /// |
| /// let z = UInt(-21.5) |
| /// // Error: ...the result would be less than UInt.min |
| /// |
| /// - Parameter source: A floating-point value to convert to an integer. |
| /// `source` must be representable in this type after rounding toward |
| /// zero. |
| init<T : BinaryFloatingPoint>(_ source: T) |
| |
| /// Creates a new instance from the given integer. |
| /// |
| /// If the value passed as `source` is not representable in this type, a |
| /// runtime error may occur. |
| /// |
| /// let x = -500 as Int |
| /// let y = Int32(x) |
| /// // y == -500 |
| /// |
| /// // -500 is not representable as a 'UInt32' instance |
| /// let z = UInt32(x) |
| /// // Error |
| /// |
| /// - Parameter source: An integer to convert. `source` must be representable |
| /// in this type. |
| init<T : BinaryInteger>(_ source: T) |
| |
| /// Creates a new instance from the bit pattern of the given instance by |
| /// sign-extending or truncating to fit this type. |
| /// |
| /// When the bit width of `T` (the type of `source`) is equal to or greater |
| /// than this type's bit width, the result is the truncated |
| /// least-significant bits of `source`. For example, when converting a |
| /// 16-bit value to an 8-bit type, only the lower 8 bits of `source` are |
| /// used. |
| /// |
| /// let p: Int16 = -500 |
| /// // 'p' has a binary representation of 11111110_00001100 |
| /// let q = Int8(truncatingIfNeeded: p) |
| /// // q == 12 |
| /// // 'q' has a binary representation of 00001100 |
| /// |
| /// When the bit width of `T` is less than this type's bit width, the result |
| /// is *sign-extended* to fill the remaining bits. That is, if `source` is |
| /// negative, the result is padded with ones; otherwise, the result is |
| /// padded with zeros. |
| /// |
| /// let u: Int8 = 21 |
| /// // 'u' has a binary representation of 00010101 |
| /// let v = Int16(truncatingIfNeeded: u) |
| /// // v == 21 |
| /// // 'v' has a binary representation of 00000000_00010101 |
| /// |
| /// let w: Int8 = -21 |
| /// // 'w' has a binary representation of 11101011 |
| /// let x = Int16(truncatingIfNeeded: w) |
| /// // x == -21 |
| /// // 'x' has a binary representation of 11111111_11101011 |
| /// let y = UInt16(truncatingIfNeeded: w) |
| /// // y == 65515 |
| /// // 'y' has a binary representation of 11111111_11101011 |
| /// |
| /// - Parameter source: An integer to convert to this type. |
| init<T : BinaryInteger>(truncatingIfNeeded source: T) |
| |
| /// Creates a new instance with the representable value that's closest to the |
| /// given integer. |
| /// |
| /// If the value passed as `source` is greater than the maximum representable |
| /// value in this type, the result is the type's `max` value. If `source` is |
| /// less than the smallest representable value in this type, the result is |
| /// the type's `min` value. |
| /// |
| /// In this example, `x` is initialized as an `Int8` instance by clamping |
| /// `500` to the range `-128...127`, and `y` is initialized as a `UInt` |
| /// instance by clamping `-500` to the range `0...UInt.max`. |
| /// |
| /// let x = Int8(clamping: 500) |
| /// // x == 127 |
| /// // x == Int8.max |
| /// |
| /// let y = UInt(clamping: -500) |
| /// // y == 0 |
| /// |
| /// - Parameter source: An integer to convert to this type. |
| init<T : BinaryInteger>(clamping source: T) |
| |
| // FIXME: Should be `Words : Collection where Words.Element == UInt` |
| // See <rdar://problem/31798916> for why it isn't. |
| /// A type that represents the words of a binary integer. |
| /// |
| /// The `Words` type must conform to the `Collection` protocol with an |
| /// `Element` type of `UInt`. |
| associatedtype Words : Sequence where Words.Element == UInt |
| |
| /// A collection containing the words of this value's binary |
| /// representation, in order from the least significant to most significant. |
| /// |
| /// Negative values are returned in two's complement representation, |
| /// regardless of the type's underlying implementation. |
| var words: Words { get } |
| |
| /// The least significant word in this value's binary representation. |
| var _lowWord: UInt { get } |
| |
| /// The number of bits in the current binary representation of this value. |
| /// |
| /// This property is a constant for instances of fixed-width integer |
| /// types. |
| var bitWidth : Int { get } |
| |
| /// The number of trailing zeros in this value's binary representation. |
| /// |
| /// For example, in a fixed-width integer type with a `bitWidth` value of 8, |
| /// the number -8 has three trailing zeros. |
| /// |
| /// let x = Int8(bitPattern: 0b1111_1000) |
| /// // x == -8 |
| /// // x.trailingZeroBitCount == 3 |
| var trailingZeroBitCount: Int { get } |
| |
| % for x in chain(*binaryArithmetic.values()): |
| // defaulted using an in-place counterpart, but can be used as an |
| // optimization hook |
| ${operatorComment(x.operator, False)} |
| static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self |
| |
| // implementation hook |
| ${assignmentOperatorComment(x.operator, False)} |
| static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self) |
| % end |
| |
| /// Returns the inverse of the bits set in the argument. |
| /// |
| /// The bitwise NOT operator (`~`) is a prefix operator that returns a value |
| /// in which all the bits of its argument are flipped: Bits that are `1` in |
| /// the argument are `0` in the result, and bits that are `0` in the argument |
| /// are `1` in the result. This is equivalent to the inverse of a set. For |
| /// example: |
| /// |
| /// let x: UInt8 = 5 // 0b00000101 |
| /// let notX = ~x // 0b11111010 |
| /// |
| /// Performing a bitwise NOT operation on 0 returns a value with every bit |
| /// set to `1`. |
| /// |
| /// let allOnes = ~UInt8.min // 0b11111111 |
| /// |
| /// - Complexity: O(1). |
| static prefix func ~ (_ x: Self) -> Self |
| |
| % for x in binaryBitwise: |
| ${operatorComment(x.operator, False)} |
| static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self |
| |
| ${assignmentOperatorComment(x.operator, False)} |
| static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self) |
| % end |
| |
| % for x in maskingShifts: |
| ${operatorComment(x.nonMaskingOperator, False)} |
| static func ${x.nonMaskingOperator}<RHS: BinaryInteger>( |
| _ lhs: Self, _ rhs: RHS |
| ) -> Self |
| |
| ${assignmentOperatorComment(x.nonMaskingOperator, False)} |
| static func ${x.nonMaskingOperator}=<RHS: BinaryInteger>( |
| _ lhs: inout Self, _ rhs: RHS) |
| % end |
| |
| /// Returns the quotient and remainder of this value divided by the given |
| /// value. |
| /// |
| /// Use this method to calculate the quotient and remainder of a division at |
| /// the same time. |
| /// |
| /// let x = 1_000_000 |
| /// let (q, r) = x.quotientAndRemainder(dividingBy: 933) |
| /// // q == 1071 |
| /// // r == 757 |
| /// |
| /// - Parameter rhs: The value to divide this value by. |
| /// - Returns: A tuple containing the quotient and remainder of this value |
| /// divided by `rhs`. |
| func quotientAndRemainder(dividingBy rhs: Self) |
| -> (quotient: Self, remainder: Self) |
| |
| /// Returns `-1` if this value is negative and `1` if it's positive; |
| /// otherwise, `0`. |
| /// |
| /// - Returns: The sign of this number, expressed as an integer of the same |
| /// type. |
| func signum() -> Self |
| } |
| |
| extension BinaryInteger { |
| @_transparent |
| public init() { |
| self = 0 |
| } |
| |
| @_transparent |
| public func signum() -> Self { |
| return (self > (0 as Self) ? 1 : 0) - (self < (0 as Self) ? 1 : 0) |
| } |
| |
| @_transparent |
| public var _lowWord: UInt { |
| var it = words.makeIterator() |
| return it.next() ?? 0 |
| } |
| |
| /// Returns the quotient and remainder of this value divided by the given |
| /// value. |
| /// |
| /// Use this method to calculate the quotient and remainder of a division at |
| /// the same time. |
| /// |
| /// let x = 1_000_000 |
| /// let (q, r) = x.quotientAndRemainder(dividingBy: 933) |
| /// // q == 1071 |
| /// // r == 757 |
| /// |
| /// - Parameter rhs: The value to divide this value by. |
| /// - Returns: A tuple containing the quotient and remainder of this value |
| /// divided by `rhs`. |
| public func quotientAndRemainder(dividingBy rhs: Self) |
| -> (quotient: Self, remainder: Self) { |
| return (self / rhs, self % rhs) |
| } |
| |
| % for x in binaryBitwise: |
| |
| // Homogeneous |
| ${operatorComment(x.operator, False)} |
| @_transparent |
| public static func ${x.operator} (lhs: Self, rhs: Self) -> Self { |
| var lhs = lhs |
| lhs ${x.operator}= rhs |
| return lhs |
| } |
| |
| % end |
| |
| % for x in maskingShifts: |
| // Heterogeneous non-masking shift in terms of shift-assignment |
| ${operatorComment(x.nonMaskingOperator, False)} |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_inlineable |
| public static func ${x.nonMaskingOperator}<RHS: BinaryInteger>( |
| _ lhs: Self, _ rhs: RHS |
| ) -> Self { |
| var r = lhs |
| r ${x.nonMaskingOperator}= rhs |
| return r |
| } |
| % end |
| |
| } |
| |
| // Strideable conformance |
| extension BinaryInteger { |
| // FIXME(ABI): using Int as the return type is wrong. |
| @_transparent |
| public func distance(to other: Self) -> Int { |
| let distance = other - self |
| if let result = Int(exactly: distance) { |
| return result |
| } |
| _preconditionFailure("Distance is not representable in Int") |
| } |
| |
| // FIXME(ABI): using Int as the parameter type is wrong. |
| @_transparent |
| public func advanced(by n: Int) -> Self { |
| var advanced: Int = Int(self) |
| advanced += n |
| if let result = Self(exactly: advanced) { |
| return result |
| } |
| _preconditionFailure("The result of advanced(by:) is not representable") |
| } |
| } |
| |
| extension Int { |
| // FIXME(ABI): using Int as the return type is wrong. |
| @_transparent |
| public func distance(to other: Int) -> Int { |
| return other - self |
| } |
| |
| // FIXME(ABI): using Int as the parameter type is wrong. |
| @_transparent |
| public func advanced(by n: Int) -> Int { |
| return self + n |
| } |
| } |
| |
| |
| //===----------------------------------------------------------------------===// |
| //===--- Heterogeneous comparison -----------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| extension BinaryInteger { |
| /// Returns a Boolean value indicating whether the two given values are |
| /// equal. |
| /// |
| /// You can check the equality of instances of any `BinaryInteger` types |
| /// using the equal-to operator (`==`). For example, you can test whether |
| /// the first `UInt8` value in a string's UTF-8 encoding is equal to the |
| /// first `UInt32` value in its Unicode scalar view: |
| /// |
| /// let gameName = "Red Light, Green Light" |
| /// if let firstUTF8 = gameName.utf8.first, |
| /// let firstScalar = gameName.unicodeScalars.first?.value { |
| /// print("First code values are equal: \(firstUTF8 == firstScalar)") |
| /// } |
| /// // Prints "First code values are equal: true" |
| /// |
| /// - Parameters: |
| /// - lhs: An integer to compare. |
| /// - rhs: Another integer to compare. |
| @inline(__always) |
| public static func == < |
| Other : BinaryInteger |
| >(lhs: Self, rhs: Other) -> Bool { |
| let lhsNegative = Self.isSigned && lhs < (0 as Self) |
| let rhsNegative = Other.isSigned && rhs < (0 as Other) |
| |
| if lhsNegative != rhsNegative { return false } |
| |
| // Here we know the values are of the same sign. |
| // |
| // There are a few possible scenarios from here: |
| // |
| // 1. Both values are negative |
| // - If one value is strictly wider than the other, then it is safe to |
| // convert to the wider type. |
| // - If the values are of the same width, it does not matter which type we |
| // choose to convert to as the values are already negative, and thus |
| // include the sign bit if two's complement representation already. |
| // 2. Both values are non-negative |
| // - If one value is strictly wider than the other, then it is safe to |
| // convert to the wider type. |
| // - If the values are of the same width, than signedness matters, as not |
| // unsigned types are 'wider' in a sense they don't need to 'waste' the |
| // sign bit. Therefore it is safe to convert to the unsigned type. |
| |
| if lhs.bitWidth < rhs.bitWidth { |
| return Other(truncatingIfNeeded: lhs) == rhs |
| } |
| if lhs.bitWidth > rhs.bitWidth { |
| return lhs == Self(truncatingIfNeeded: rhs) |
| } |
| |
| if Self.isSigned { |
| return Other(truncatingIfNeeded: lhs) == rhs |
| } |
| return lhs == Self(truncatingIfNeeded: rhs) |
| } |
| |
| /// Returns a Boolean value indicating whether the two given values are not |
| /// equal. |
| /// |
| /// You can check the inequality of instances of any `BinaryInteger` types |
| /// using the not-equal-to operator (`!=`). For example, you can test |
| /// whether the first `UInt8` value in a string's UTF-8 encoding is not |
| /// equal to the first `UInt32` value in its Unicode scalar view: |
| /// |
| /// let gameName = "Red Light, Green Light" |
| /// if let firstUTF8 = gameName.utf8.first, |
| /// let firstScalar = gameName.unicodeScalars.first?.value { |
| /// print("First code values are different: \(firstUTF8 != firstScalar)") |
| /// } |
| /// // Prints "First code values are different: false" |
| /// |
| /// - Parameters: |
| /// - lhs: An integer to compare. |
| /// - rhs: Another integer to compare. |
| @_transparent |
| public static func != < |
| Other : BinaryInteger |
| >(lhs: Self, rhs: Other) -> Bool { |
| return !(lhs == rhs) |
| } |
| |
| /// Returns a Boolean value indicating whether the value of the first |
| /// argument is less than that of the second argument. |
| /// |
| /// You can compare instances of any `BinaryInteger` types using the |
| /// less-than operator (`<`), even if the two instances are of different |
| /// types. |
| /// |
| /// - Parameters: |
| /// - lhs: An integer to compare. |
| /// - rhs: Another integer to compare. |
| @inline(__always) |
| public static func < <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool { |
| let lhsNegative = Self.isSigned && lhs < (0 as Self) |
| let rhsNegative = Other.isSigned && rhs < (0 as Other) |
| if lhsNegative != rhsNegative { return lhsNegative } |
| |
| if lhs == (0 as Self) && rhs == (0 as Other) { return false } |
| |
| // if we get here, lhs and rhs have the same sign. If they're negative, |
| // then Self and Other are both signed types, and one of them can represent |
| // values of the other type. Otherwise, lhs and rhs are positive, and one |
| // of Self, Other may be signed and the other unsigned. |
| |
| let rhsAsSelf = Self(truncatingIfNeeded: rhs) |
| let rhsAsSelfNegative = rhsAsSelf < (0 as Self) |
| |
| |
| // Can we round-trip rhs through Other? |
| if Other(truncatingIfNeeded: rhsAsSelf) == rhs && |
| // This additional check covers the `Int8.max < (128 as UInt8)` case. |
| // Since the types are of the same width, init(truncatingIfNeeded:) |
| // will result in a simple bitcast, so that rhsAsSelf would be -128, and |
| // `lhs < rhsAsSelf` will return false. |
| // We basically guard against that bitcast by requiring rhs and rhsAsSelf |
| // to be the same sign. |
| rhsNegative == rhsAsSelfNegative { |
| return lhs < rhsAsSelf |
| } |
| |
| return Other(truncatingIfNeeded: lhs) < rhs |
| } |
| |
| /// Returns a Boolean value indicating whether the value of the first |
| /// argument is less than or equal to that of the second argument. |
| /// |
| /// You can compare instances of any `BinaryInteger` types using the |
| /// less-than-or-equal-to operator (`<=`), even if the two instances are of |
| /// different types. |
| /// |
| /// - Parameters: |
| /// - lhs: An integer to compare. |
| /// - rhs: Another integer to compare. |
| @_transparent |
| //@inline(__always) |
| public static func <= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool { |
| return !(rhs < lhs) |
| } |
| |
| /// Returns a Boolean value indicating whether the value of the first |
| /// argument is greater than or equal to that of the second argument. |
| /// |
| /// You can compare instances of any `BinaryInteger` types using the |
| /// greater-than-or-equal-to operator (`>=`), even if the two instances are |
| /// of different types. |
| /// |
| /// - Parameters: |
| /// - lhs: An integer to compare. |
| /// - rhs: Another integer to compare. |
| @_transparent |
| //@inline(__always) |
| public static func >= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool { |
| return !(lhs < rhs) |
| } |
| |
| /// Returns a Boolean value indicating whether the value of the first |
| /// argument is greater than that of the second argument. |
| /// |
| /// You can compare instances of any `BinaryInteger` types using the |
| /// greater-than operator (`>`), even if the two instances are of different |
| /// types. |
| /// |
| /// - Parameters: |
| /// - lhs: An integer to compare. |
| /// - rhs: Another integer to compare. |
| @_transparent |
| //@inline(__always) |
| public static func > <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool { |
| return rhs < lhs |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| //===--- Ambiguity breakers -----------------------------------------------===// |
| // These two versions of the operators are not ordered with respect to one |
| // another, but the compiler choses the second one, and that results in infinite |
| // recursion. |
| // |
| // <T : Comparable>(T, T) -> Bool |
| // <T : BinaryInteger, U : BinaryInteger>(T, U) -> Bool |
| // |
| // so we define: |
| // |
| // <T : BinaryInteger>(T, T) -> Bool |
| // |
| //===----------------------------------------------------------------------===// |
| |
| extension BinaryInteger { |
| @_transparent |
| public static func != (lhs: Self, rhs: Self) -> Bool { |
| return !(lhs == rhs) |
| } |
| |
| @inline(__always) |
| public static func <= (lhs: Self, rhs: Self) -> Bool { |
| return !(rhs < lhs) |
| } |
| |
| @inline(__always) |
| public static func >= (lhs: Self, rhs: Self) -> Bool { |
| return !(lhs < rhs) |
| } |
| |
| @inline(__always) |
| public static func > (lhs: Self, rhs: Self) -> Bool { |
| return rhs < lhs |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| //===--- FixedWidthInteger ------------------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| /// An integer type that uses a fixed size for every instance. |
| /// |
| /// The `FixedWidthInteger` protocol adds binary bitwise operations, bit |
| /// shifts, and overflow handling to the operations supported by the |
| /// `BinaryInteger` protocol. |
| /// |
| /// Use the `FixedWidthInteger` protocol as a constraint or extension point |
| /// when writing operations that depend on bit shifting, performing bitwise |
| /// operations, catching overflows, or having access to the maximum or minimum |
| /// representable value of a type. For example, the following code provides a |
| /// `binaryString` property on every fixed-width integer that represents the |
| /// number's binary representation, split into 8-bit chunks. |
| /// |
| /// extension FixedWidthInteger { |
| /// var binaryString: String { |
| /// var result: [String] = [] |
| /// for i in 0..<(Self.bitWidth / 8) { |
| /// let byte = UInt8(truncatingIfNeeded: self >> (i * 8)) |
| /// let byteString = String(byte, radix: 2) |
| /// let padding = String(repeating: "0", |
| /// count: 8 - byteString.count) |
| /// result.append(padding + byteString) |
| /// } |
| /// return "0b" + result.reversed().joined(separator: "_") |
| /// } |
| /// } |
| /// |
| /// print(Int16.max.binaryString) |
| /// // Prints "0b01111111_11111111" |
| /// print((101 as UInt8).binaryString) |
| /// // Prints "0b11001001" |
| /// |
| /// The `binaryString` implementation uses the static `bitWidth` property and |
| /// the right shift operator (`<<`), both of which are available to any type |
| /// that conforms to the `FixedWidthInteger` protocol. |
| /// |
| /// The next example declares a generic `squared` function, which accepts an |
| /// instance `x` of any fixed-width integer type. The function uses the |
| /// `multipliedReportingOverflow(by:)` method to multiply `x` by itself and |
| /// check whether the result is too large to represent in the same type. |
| /// |
| /// func squared<T: FixedWidthInteger>(_ x: T) -> T? { |
| /// let (result, overflow) = x.multipliedReportingOverflow(by: x) |
| /// if overflow { |
| /// return nil |
| /// } |
| /// return result |
| /// } |
| /// |
| /// let (x, y): (Int8, Int8) = (9, 123) |
| /// print(squared(x)) |
| /// // Prints "Optional(81)" |
| /// print(squared(y)) |
| /// // Prints "nil" |
| /// |
| /// Conforming to the FixedWidthInteger Protocol |
| /// ============================================ |
| /// |
| /// To make your own custom type conform to the `FixedWidthInteger` protocol, |
| /// declare the required initializers, properties, and methods. The required |
| /// methods that are suffixed with `ReportingOverflow` serve as the |
| /// customization points for arithmetic operations. When you provide just those |
| /// methods, the standard library provides default implementations for all |
| /// other arithmetic methods and operators. |
| public protocol FixedWidthInteger : |
| BinaryInteger, LosslessStringConvertible, _BitwiseOperations |
| where Magnitude : FixedWidthInteger |
| { |
| /// The number of bits used for the underlying binary representation of |
| /// values of this type. |
| /// |
| /// An unsigned, fixed-width integer type can represent values from 0 through |
| /// `(2 ** bitWidth) - 1`, where `**` is exponentiation. A signed, |
| /// fixed-width integer type can represent values from |
| /// `-(2 ** (bitWidth - 1))` through `(2 ** (bitWidth - 1)) - 1`. For example, |
| /// the `Int8` type has a `bitWidth` value of 8 and can store any integer in |
| /// the range `-128...127`. |
| static var bitWidth : Int { get } |
| |
| /// The maximum representable integer in this type. |
| /// |
| /// For unsigned integer types, this value is `(2 ** bitWidth) - 1`, where |
| /// `**` is exponentiation. For signed integer types, this value is |
| /// `(2 ** (bitWidth - 1)) - 1`. |
| static var max: Self { get } |
| |
| /// The minimum representable integer in this type. |
| /// |
| /// For unsigned integer types, this value is always `0`. For signed integer |
| /// types, this value is `-(2 ** (bitWidth - 1))`, where `**` is |
| /// exponentiation. |
| static var min: Self { get } |
| |
| % for x in binaryArithmetic['Numeric'] + binaryArithmetic['BinaryInteger']: |
| ${overflowOperationComment(x.operator)} |
| func ${x.name}ReportingOverflow( |
| ${x.firstArg} rhs: Self |
| ) -> (partialValue: Self, overflow: Bool) |
| % end |
| |
| /// Returns a tuple containing the high and low parts of the result of |
| /// multiplying this value by the given value. |
| /// |
| /// Use this method to calculate the full result of a product that would |
| /// otherwise overflow. Unlike traditional truncating multiplication, the |
| /// `multipliedFullWidth(by:)` method returns a tuple |
| /// containing both the `high` and `low` parts of the product of this value and |
| /// `other`. The following example uses this method to multiply two `UInt8` |
| /// values that normally overflow when multiplied: |
| /// |
| /// let x: UInt8 = 100 |
| /// let y: UInt8 = 20 |
| /// let result = x.multipliedFullWidth(by: y) |
| /// // result.high == 0b00000111 |
| /// // result.low == 0b11010000 |
| /// |
| /// The product of `x` and `y` is 2000, which is too large to represent in a |
| /// `UInt8` instance. The `high` and `low` properties of the `result` value |
| /// represent 2000 when concatenated to form a double-width integer; that |
| /// is, using `result.high` as the high byte and `result.low` as the low byte |
| /// of a `UInt16` instance. |
| /// |
| /// let z = UInt16(result.high) << 8 | UInt16(result.low) |
| /// // z == 2000 |
| /// |
| /// - Parameter other: The value to multiply this value by. |
| /// - Returns: A tuple containing the high and low parts of the result of |
| /// multiplying this value and `other`. |
| func multipliedFullWidth(by other: Self) -> (high: Self, low: Self.Magnitude) |
| // FIXME(integers): figure out how to return DoubleWidth<Self> |
| |
| /// Returns a tuple containing the quotient and remainder of dividing the |
| /// given value by this value. |
| /// |
| /// The resulting quotient must be representable within the bounds of the |
| /// type. If the quotient of dividing `dividend` by this value is too large |
| /// to represent in the type, a runtime error may occur. |
| /// |
| /// - Parameter dividend: A tuple containing the high and low parts of a |
| /// double-width integer. The `high` component of the value carries the |
| /// sign, if the type is signed. |
| /// - Returns: A tuple containing the quotient and remainder of `dividend` |
| /// divided by this value. |
| func dividingFullWidth(_ dividend: (high: Self, low: Self.Magnitude)) |
| -> (quotient: Self, remainder: Self) |
| |
| init(_truncatingBits bits: UInt) |
| |
| /// The number of bits equal to 1 in this value's binary representation. |
| /// |
| /// For example, in a fixed-width integer type with a `bitWidth` value of 8, |
| /// the number *31* has five bits equal to *1*. |
| /// |
| /// let x: Int8 = 0b0001_1111 |
| /// // x == 31 |
| /// // x.nonzeroBitCount == 5 |
| var nonzeroBitCount: Int { get } |
| |
| /// The number of leading zeros in this value's binary representation. |
| /// |
| /// For example, in a fixed-width integer type with a `bitWidth` value of 8, |
| /// the number *31* has three leading zeros. |
| /// |
| /// let x: Int8 = 0b0001_1111 |
| /// // x == 31 |
| /// // x.leadingZeroBitCount == 3 |
| var leadingZeroBitCount: Int { get } |
| |
| /// Creates an integer from its big-endian representation, changing the byte |
| /// order if necessary. |
| /// |
| /// - Parameter value: A value to use as the big-endian representation of the |
| /// new integer. |
| init(bigEndian value: Self) |
| |
| /// Creates an integer from its little-endian representation, changing the |
| /// byte order if necessary. |
| /// |
| /// - Parameter value: A value to use as the little-endian representation of |
| /// the new integer. |
| init(littleEndian value: Self) |
| |
| /// The big-endian representation of this integer. |
| /// |
| /// If necessary, the byte order of this value is reversed from the typical |
| /// byte order of this integer type. On a big-endian platform, for any |
| /// integer `x`, `x == x.bigEndian`. |
| var bigEndian: Self { get } |
| |
| /// The little-endian representation of this integer. |
| /// |
| /// If necessary, the byte order of this value is reversed from the typical |
| /// byte order of this integer type. On a little-endian platform, for any |
| /// integer `x`, `x == x.littleEndian`. |
| var littleEndian: Self { get } |
| |
| /// A representation of this integer with the byte order swapped. |
| var byteSwapped: Self { get } |
| |
| % for x in maskingShifts: |
| ${operatorComment(x.operator, False)} |
| static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self |
| |
| ${assignmentOperatorComment(x.operator, False)} |
| static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self) |
| % end |
| |
| } |
| |
| extension FixedWidthInteger { |
| /// The empty bitset. |
| /// |
| /// The `allZeros` static property is the [identity element][] for bitwise OR |
| /// and XOR operations and the [fixed point][] for bitwise AND operations. |
| /// For example: |
| /// |
| /// let x: UInt8 = 5 // 0b00000101 |
| /// |
| /// // Identity |
| /// x | .allZeros // 0b00000101 |
| /// x ^ .allZeros // 0b00000101 |
| /// |
| /// // Fixed point |
| /// x & .allZeros // 0b00000000 |
| /// |
| /// [identity element]:http://en.wikipedia.org/wiki/Identity_element |
| /// [fixed point]:http://en.wikipedia.org/wiki/Fixed_point_(mathematics) |
| @available(swift, deprecated: 3.1, obsoleted: 4.0, message: "Use 0") |
| public static var allZeros: Self { return 0 } |
| |
| /// The number of bits in the binary representation of this value. |
| @_inlineable |
| public var bitWidth: Int { return Self.bitWidth } |
| |
| /// Creates an integer from its little-endian representation, changing the |
| /// byte order if necessary. |
| /// |
| /// - Parameter value: A value to use as the little-endian representation of |
| /// the new integer. |
| public init(littleEndian value: Self) { |
| #if _endian(little) |
| self = value |
| #else |
| self = value.byteSwapped |
| #endif |
| } |
| |
| /// Creates an integer from its big-endian representation, changing the byte |
| /// order if necessary. |
| /// |
| /// - Parameter value: A value to use as the big-endian representation of the |
| /// new integer. |
| public init(bigEndian value: Self) { |
| #if _endian(big) |
| self = value |
| #else |
| self = value.byteSwapped |
| #endif |
| } |
| |
| /// The little-endian representation of this integer. |
| /// |
| /// If necessary, the byte order of this value is reversed from the typical |
| /// byte order of this integer type. On a little-endian platform, for any |
| /// integer `x`, `x == x.littleEndian`. |
| public var littleEndian: Self { |
| #if _endian(little) |
| return self |
| #else |
| return byteSwapped |
| #endif |
| } |
| |
| /// The big-endian representation of this integer. |
| /// |
| /// If necessary, the byte order of this value is reversed from the typical |
| /// byte order of this integer type. On a big-endian platform, for any |
| /// integer `x`, `x == x.bigEndian`. |
| public var bigEndian: Self { |
| #if _endian(big) |
| return self |
| #else |
| return byteSwapped |
| #endif |
| } |
| |
| % for x in maskingShifts: |
| |
| // Homogeneous masking shift |
| ${operatorComment(x.operator, False)} |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_transparent |
| public static func ${x.operator} (lhs: Self, rhs: Self) -> Self { |
| var lhs = lhs |
| lhs ${x.operator}= rhs |
| return lhs |
| } |
| |
| |
| // Heterogeneous masking shift |
| ${operatorComment(x.operator, False)} |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_inlineable |
| public static func ${x.operator} < |
| Other : BinaryInteger |
| >(lhs: Self, rhs: Other) -> Self { |
| return lhs ${x.operator} Self(truncatingIfNeeded: rhs) |
| } |
| |
| // Heterogeneous masking shift assignment |
| ${assignmentOperatorComment(x.operator, False)} |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_transparent |
| public static func ${x.operator}= < |
| Other : BinaryInteger |
| >(lhs: inout Self, rhs: Other) { |
| lhs = lhs ${x.operator} rhs |
| } |
| |
| % end |
| } |
| |
| //===----------------------------------------------------------------------===// |
| //===--- Operators on FixedWidthInteger -----------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| extension FixedWidthInteger { |
| /// Returns the inverse of the bits set in the argument. |
| /// |
| /// The bitwise NOT operator (`~`) is a prefix operator that returns a value |
| /// in which all the bits of its argument are flipped: Bits that are `1` in |
| /// the argument are `0` in the result, and bits that are `0` in the argument |
| /// are `1` in the result. This is equivalent to the inverse of a set. For |
| /// example: |
| /// |
| /// let x: UInt8 = 5 // 0b00000101 |
| /// let notX = ~x // 0b11111010 |
| /// |
| /// Performing a bitwise NOT operation on 0 returns a value with every bit |
| /// set to `1`. |
| /// |
| /// let allOnes = ~UInt8.min // 0b11111111 |
| /// |
| /// - Complexity: O(1). |
| @_transparent |
| public static prefix func ~ (x: Self) -> Self { |
| return 0 &- x &- 1 |
| } |
| |
| % for x in maskingShifts: |
| |
| //===----------------------------------------------------------------------===// |
| //=== "Smart ${x.description}", supporting overshifts and negative shifts -===// |
| //===----------------------------------------------------------------------===// |
| |
| ${operatorComment(x.nonMaskingOperator, True)} |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_transparent |
| public static func ${x.nonMaskingOperator} < |
| Other : BinaryInteger |
| >(lhs: Self, rhs: Other) -> Self { |
| var lhs = lhs |
| ${x.helper}Generic(&lhs, rhs) |
| return lhs |
| } |
| |
| @_transparent |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| public static func ${x.nonMaskingOperator}= < |
| Other : BinaryInteger |
| >(lhs: inout Self, rhs: Other) { |
| ${x.helper}Generic(&lhs, rhs) |
| } |
| |
| @_transparent |
| public static func ${x.helper}Generic < |
| Other : BinaryInteger |
| >(_ lhs: inout Self, _ rhs: Other) { |
| let shift = rhs < -Self.bitWidth ? -Self.bitWidth |
| : rhs > Self.bitWidth ? Self.bitWidth |
| : Int(rhs) |
| lhs = ${x.helper}(lhs, shift) |
| } |
| |
| % reversedOperator = x.operator.translate(maketrans('<>', '><')) |
| % isRightShift = '>' in x.operator |
| @inline(__always) |
| public static func ${x.helper}(_ lhs: Self, _ rhs: Int) -> Self { |
| let overshiftR = Self.isSigned ? lhs &>> (Self.bitWidth - 1) : 0 |
| let overshiftL: Self = 0 |
| if _fastPath(rhs >= 0) { |
| if _fastPath(rhs < Self.bitWidth) { |
| return lhs ${x.operator} Self(truncatingIfNeeded: rhs) |
| } |
| return overshift${'LR'[isRightShift]} |
| } |
| |
| if _slowPath(rhs <= -Self.bitWidth) { |
| return overshift${'RL'[isRightShift]} |
| } |
| return lhs ${reversedOperator} -rhs |
| } |
| |
| % end # maskingShifts |
| } |
| |
| extension FixedWidthInteger { |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| public // @testable |
| static func _convert<Source : BinaryFloatingPoint>( |
| from source: Source |
| ) -> (value: Self?, exact: Bool) { |
| guard _fastPath(!source.isZero) else { return (0, true) } |
| guard _fastPath(source.isFinite) else { return (nil, false) } |
| guard Self.isSigned || source > 0 else { return (nil, false) } |
| let exponent = source.exponent |
| if _slowPath(Self.bitWidth <= exponent) { return (nil, false) } |
| let minBitWidth = source.significandWidth |
| let isExact = (minBitWidth <= exponent) |
| let bitPattern = source.significandBitPattern |
| // `RawSignificand.bitWidth` is not available if `RawSignificand` does not |
| // conform to `FixedWidthInteger`; we can compute this value as follows if |
| // `source` is finite: |
| let bitWidth = minBitWidth &+ bitPattern.trailingZeroBitCount |
| let shift = exponent - Source.Exponent(bitWidth) |
| // Use `Self.Magnitude` to prevent sign extension if `shift < 0`. |
| let shiftedBitPattern = Self.Magnitude.bitWidth > bitWidth |
| ? Self.Magnitude(truncatingIfNeeded: bitPattern) << shift |
| : Self.Magnitude(truncatingIfNeeded: bitPattern << shift) |
| if _slowPath(Self.isSigned && Self.bitWidth &- 1 == exponent) { |
| return source < 0 && shiftedBitPattern == 0 |
| ? (Self.min, isExact) |
| : (nil, false) |
| } |
| let magnitude = ((1 as Self.Magnitude) << exponent) | shiftedBitPattern |
| return ( |
| Self.isSigned && source < 0 ? 0 &- Self(magnitude) : Self(magnitude), |
| isExact) |
| } |
| |
| /// Creates an integer from the given floating-point value, rounding toward |
| /// zero. Any fractional part of the value passed as `source` is removed. |
| /// |
| /// let x = Int(21.5) |
| /// // x == 21 |
| /// let y = Int(-21.5) |
| /// // y == -21 |
| /// |
| /// If `source` is outside the bounds of this type after rounding toward |
| /// zero, a runtime error may occur. |
| /// |
| /// let z = UInt(-21.5) |
| /// // Error: ...the result would be less than UInt.min |
| /// |
| /// - Parameter source: A floating-point value to convert to an integer. |
| /// `source` must be representable in this type after rounding toward |
| /// zero. |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @inline(__always) |
| public init<T : BinaryFloatingPoint>(_ source: T) { |
| guard let value = Self._convert(from: source).value else { |
| fatalError(""" |
| \(T.self) value cannot be converted to \(Self.self) because it is \ |
| infinite or NaN, or because the result would be greater than \ |
| \(Self.self).max or less than \(Self.self).min |
| """) |
| } |
| self = value |
| } |
| |
| /// Creates an integer from the given floating-point value, if it can be |
| /// represented exactly. |
| /// |
| /// If the value passed as `source` is not representable exactly, the result |
| /// is `nil`. In the following example, the constant `x` is successfully |
| /// created from a value of `21.0`, while the attempt to initialize the |
| /// constant `y` from `21.5` fails: |
| /// |
| /// let x = Int(exactly: 21.0) |
| /// // x == Optional(21) |
| /// let y = Int(exactly: 21.5) |
| /// // y == nil |
| /// |
| /// - Parameter source: A floating-point value to convert to an integer. |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @inline(__always) |
| public init?<T : BinaryFloatingPoint>(exactly source: T) { |
| let (temporary, exact) = Self._convert(from: source) |
| guard exact, let value = temporary else { |
| return nil |
| } |
| self = value |
| } |
| |
| /// Creates a new instance with the representable value that's closest to the |
| /// given integer. |
| /// |
| /// If the value passed as `source` is greater than the maximum representable |
| /// value in this type, the result is the type's `max` value. If `source` is |
| /// less than the smallest representable value in this type, the result is |
| /// the type's `min` value. |
| /// |
| /// In this example, `x` is initialized as an `Int8` instance by clamping |
| /// `500` to the range `-128...127`, and `y` is initialized as a `UInt` |
| /// instance by clamping `-500` to the range `0...UInt.max`. |
| /// |
| /// let x = Int8(clamping: 500) |
| /// // x == 127 |
| /// // x == Int8.max |
| /// |
| /// let y = UInt(clamping: -500) |
| /// // y == 0 |
| /// |
| /// - Parameter source: An integer to convert to this type. |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| public init<Other : BinaryInteger>(clamping source: Other) { |
| if _slowPath(source < Self.min) { |
| self = Self.min |
| } |
| else if _slowPath(source > Self.max) { |
| self = Self.max |
| } |
| else { self = Self(truncatingIfNeeded: source) } |
| } |
| |
| % for x in binaryArithmetic['Numeric'] + binaryArithmetic["BinaryInteger"][:1]: |
| % callLabel = x.firstArg + ': ' if not x.firstArg == '_' else '' |
| // FIXME(integers): pending optimizer work on handling the case where the |
| // boolean value is wrapped into a two-case enum and then immediately |
| // unwrapped. <rdar://problem/29004429> |
| // Uncomment this block and remove the corresponding one from the concrete |
| // types once the optimizer is ready. |
| #if false |
| ${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, "Overflow in ${x.operator}=") |
| lhs = result |
| } |
| #endif |
| // end of FIXME(integers) |
| |
| ${unsafeOperationComment(x.operator)} |
| @_transparent |
| public func unsafe${capitalize(x.name)}(${x.firstArg} other: Self) -> Self { |
| let (result, overflow) = self.${x.name}ReportingOverflow(${callLabel}other) |
| |
| if overflow { |
| if (_isDebugAssertConfiguration()) { |
| _preconditionFailure("Overflow in unsafe${capitalize(x.name)}") |
| } |
| else { |
| Builtin.conditionallyUnreachable() |
| } |
| } |
| return result |
| } |
| % end |
| |
| /// Creates a new instance from the bit pattern of the given instance by |
| /// truncating or sign-extending if needed to fit this type. |
| /// |
| /// When the bit width of `T` (the type of `source`) is equal to or greater |
| /// than this type's bit width, the result is the truncated |
| /// least-significant bits of `source`. For example, when converting a |
| /// 16-bit value to an 8-bit type, only the lower 8 bits of `source` are |
| /// used. |
| /// |
| /// let p: Int16 = -500 |
| /// // 'p' has a binary representation of 11111110_00001100 |
| /// let q = Int8(truncatingIfNeeded: p) |
| /// // q == 12 |
| /// // 'q' has a binary representation of 00001100 |
| /// |
| /// When the bit width of `T` is less than this type's bit width, the result |
| /// is *sign-extended* to fill the remaining bits. That is, if `source` is |
| /// negative, the result is padded with ones; otherwise, the result is |
| /// padded with zeros. |
| /// |
| /// let u: Int8 = 21 |
| /// // 'u' has a binary representation of 00010101 |
| /// let v = Int16(truncatingIfNeeded: u) |
| /// // v == 21 |
| /// // 'v' has a binary representation of 00000000_00010101 |
| /// |
| /// let w: Int8 = -21 |
| /// // 'w' has a binary representation of 11101011 |
| /// let x = Int16(truncatingIfNeeded: w) |
| /// // x == -21 |
| /// // 'x' has a binary representation of 11111111_11101011 |
| /// let y = UInt16(truncatingIfNeeded: w) |
| /// // y == 65515 |
| /// // 'y' has a binary representation of 11111111_11101011 |
| /// |
| /// - Parameter source: An integer to convert to this type. |
| @inline(__always) |
| public init<T : BinaryInteger>(truncatingIfNeeded source: T) { |
| if Self.bitWidth <= ${word_bits} { |
| self = Self.init(_truncatingBits: source._lowWord) |
| } |
| else { |
| let neg = source < (0 as T) |
| var result: Self = neg ? ~0 : 0 |
| var shift: Self = 0 |
| let width = Self(_truncatingBits: Self.bitWidth._lowWord) |
| for word in source.words { |
| guard shift < width else { break } |
| // Masking shift is OK here because we have already ensured |
| // that shift < Self.bitWidth. Not masking results in |
| // infinite recursion. |
| result ^= Self(_truncatingBits: neg ? ~word : word) &<< shift |
| shift += ${word_bits} |
| } |
| self = result |
| } |
| } |
| |
| @_transparent |
| public // transparent |
| static var _highBitIndex: Self { |
| return Self.init(_truncatingBits: UInt(Self.bitWidth._value) &- 1) |
| } |
| |
| % for x in chain(*binaryArithmetic.values()): |
| % callLabel = x.firstArg + ': ' if not x.firstArg == '_' else '' |
| % if x.kind != '/': |
| ${operatorComment('&' + x.operator, True)} |
| @_transparent |
| public static func &${x.operator} (lhs: Self, rhs: Self) -> Self { |
| return lhs.${x.name}ReportingOverflow(${callLabel}rhs).partialValue |
| } |
| % end |
| % end |
| } |
| |
| //===----------------------------------------------------------------------===// |
| //===--- UnsignedInteger --------------------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| /// An integer type that can represent only nonnegative values. |
| public protocol UnsignedInteger : BinaryInteger { } |
| |
| extension UnsignedInteger { |
| /// The magnitude of this value. |
| /// |
| /// Every unsigned integer is its own magnitude, so for any value `x`, |
| /// `x == x.magnitude`. |
| /// |
| /// The global `abs(_:)` function provides more familiar syntax when you need |
| /// to find an absolute value. In addition, because `abs(_:)` always returns |
| /// a value of the same type, even in a generic context, using the function |
| /// instead of the `magnitude` property is encouraged. |
| @_transparent |
| public var magnitude: Self { return self } |
| |
| /// A Boolean value indicating whether this type is a signed integer type. |
| /// |
| /// This property is always `false` for unsigned integer types. |
| @_transparent |
| public static var isSigned: Bool { return false } |
| |
| /// A textual representation of this value. |
| public var description: String { |
| if self.bitWidth <= ${word_bits} { |
| return _uint64ToString(UInt64(truncatingIfNeeded: self)) |
| } |
| if self == (0 as Self) { |
| return "0" |
| } |
| return renderNonZeroDescription() |
| } |
| |
| // FIXME(integers): perhaps a faster implementation is possible |
| @_transparent |
| internal func renderNonZeroDescription() -> String { |
| let ascii0 = 48 |
| var buf: [Unicode.Scalar] = [] |
| |
| var x = self |
| repeat { |
| let r = x % 10 |
| x /= 10 |
| buf.append( |
| Unicode.Scalar( |
| ascii0 + Int(UInt(truncatingIfNeeded: r)._value))!) |
| } |
| while x != (0 as Self) |
| return String(buf.reversed().lazy.map { Character($0) }) |
| } |
| } |
| |
| extension UnsignedInteger where Self : FixedWidthInteger { |
| /// Creates a new instance from the given integer. |
| /// |
| /// Use this initializer to convert from another integer type when you know |
| /// the value is within the bounds of this type. Passing a value that can't |
| /// be represented in this type results in a runtime error. |
| /// |
| /// In the following example, the constant `y` is successfully created from |
| /// `x`, an `Int` instance with a value of `100`. Because the `Int8` type |
| /// can represent `127` at maximum, the attempt to create `z` with a value |
| /// of `1000` results in a runtime error. |
| /// |
| /// let x = 100 |
| /// let y = Int8(x) |
| /// // y == 100 |
| /// let z = Int8(x * 10) |
| /// // Error: Not enough bits to represent the given value |
| /// |
| /// - Parameter source: A value to convert to this type of integer. The value |
| /// passed as `source` must be representable in this type. |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @inline(__always) |
| public init<T : BinaryInteger>(_ source: T) { |
| // This check is potentially removable by the optimizer |
| if T.isSigned { |
| _precondition(source >= (0 as T), "Negative value is not representable") |
| } |
| // This check is potentially removable by the optimizer |
| if source.bitWidth >= Self.bitWidth { |
| _precondition(source <= Self.max, |
| "Not enough bits to represent a signed value") |
| } |
| self.init(truncatingIfNeeded: source) |
| } |
| |
| /// Creates a new instance from the given integer, if it can be represented |
| /// exactly. |
| /// |
| /// If the value passed as `source` is not representable exactly, the result |
| /// is `nil`. In the following example, the constant `x` is successfully |
| /// created from a value of `100`, while the attempt to initialize the |
| /// constant `y` from `1_000` fails because the `Int8` type can represent |
| /// `127` at maximum: |
| /// |
| /// let x = Int8(exactly: 100) |
| /// // x == Optional(100) |
| /// let y = Int8(exactly: 1_000) |
| /// // y == nil |
| /// |
| /// - Parameter source: A value to convert to this type of integer. |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @inline(__always) |
| public init?<T : BinaryInteger>(exactly source: T) { |
| // This check is potentially removable by the optimizer |
| if T.isSigned && source < (0 as T) { |
| return nil |
| } |
| // The width check can be eliminated by the optimizer |
| if source.bitWidth >= Self.bitWidth && |
| source > Self.max { |
| return nil |
| } |
| self.init(truncatingIfNeeded: source) |
| } |
| |
| /// The maximum representable integer in this type. |
| /// |
| /// For unsigned integer types, this value is `(2 ** bitWidth) - 1`, where |
| /// `**` is exponentiation. |
| @_transparent |
| public static var max: Self { |
| return ~0 |
| } |
| |
| /// The minimum representable integer in this type. |
| /// |
| /// For unsigned integer types, this value is always `0`. |
| @_transparent |
| public static var min: Self { |
| return 0 |
| } |
| } |
| |
| |
| //===----------------------------------------------------------------------===// |
| //===--- SignedInteger ----------------------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| /// An integer type that can represent both positive and negative values. |
| public protocol SignedInteger : BinaryInteger, SignedNumeric { |
| // These requirements are for the source code compatibility with Swift 3 |
| static func _maskingAdd(_ lhs: Self, _ rhs: Self) -> Self |
| static func _maskingSubtract(_ lhs: Self, _ rhs: Self) -> Self |
| } |
| |
| extension SignedInteger { |
| /// A textual representation of this value. |
| public var description: String { |
| if self.bitWidth <= ${word_bits} { |
| return _int64ToString(Int64(truncatingIfNeeded: self)) |
| } |
| |
| let base = magnitude.description |
| return self < (0 as Self) ? "-" + base : base |
| } |
| |
| /// A Boolean value indicating whether this type is a signed integer type. |
| /// |
| /// This property is always `true` for signed integer types. |
| @_transparent |
| public static var isSigned: Bool { return true } |
| } |
| |
| extension SignedInteger where Self : FixedWidthInteger { |
| /// Creates a new instance from the given integer. |
| /// |
| /// Use this initializer to convert from another integer type when you know |
| /// the value is within the bounds of this type. Passing a value that can't |
| /// be represented in this type results in a runtime error. |
| /// |
| /// In the following example, the constant `y` is successfully created from |
| /// `x`, an `Int` instance with a value of `100`. Because the `Int8` type |
| /// can represent `127` at maximum, the attempt to create `z` with a value |
| /// of `1000` results in a runtime error. |
| /// |
| /// let x = 100 |
| /// let y = Int8(x) |
| /// // y == 100 |
| /// let z = Int8(x * 10) |
| /// // Error: Not enough bits to represent the given value |
| /// |
| /// - Parameter source: A value to convert to this type of integer. The value |
| /// passed as `source` must be representable in this type. |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @inline(__always) |
| public init<T : BinaryInteger>(_ source: T) { |
| // This check is potentially removable by the optimizer |
| if T.isSigned && source.bitWidth > Self.bitWidth { |
| _precondition(source >= Self.min, |
| "Not enough bits to represent a signed value") |
| } |
| // This check is potentially removable by the optimizer |
| if (source.bitWidth > Self.bitWidth) || |
| (source.bitWidth == Self.bitWidth && !T.isSigned) { |
| _precondition(source <= Self.max, |
| "Not enough bits to represent a signed value") |
| } |
| self.init(truncatingIfNeeded: source) |
| } |
| |
| /// Creates a new instance from the given integer, if it can be represented |
| /// exactly. |
| /// |
| /// If the value passed as `source` is not representable exactly, the result |
| /// is `nil`. In the following example, the constant `x` is successfully |
| /// created from a value of `100`, while the attempt to initialize the |
| /// constant `y` from `1_000` fails because the `Int8` type can represent |
| /// `127` at maximum: |
| /// |
| /// let x = Int8(exactly: 100) |
| /// // x == Optional(100) |
| /// let y = Int8(exactly: 1_000) |
| /// // y == nil |
| /// |
| /// - Parameter source: A value to convert to this type of integer. |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @inline(__always) |
| public init?<T : BinaryInteger>(exactly source: T) { |
| // This check is potentially removable by the optimizer |
| if T.isSigned && source.bitWidth > Self.bitWidth && source < Self.min { |
| return nil |
| } |
| // The width check can be eliminated by the optimizer |
| if (source.bitWidth > Self.bitWidth || |
| (source.bitWidth == Self.bitWidth && !T.isSigned)) && |
| source > Self.max { |
| return nil |
| } |
| self.init(truncatingIfNeeded: source) |
| } |
| |
| /// The maximum representable integer in this type. |
| /// |
| /// For signed integer types, this value is `(2 ** (bitWidth - 1)) - 1`, |
| /// where `**` is exponentiation. |
| @_transparent |
| public static var max: Self { |
| return ~min |
| } |
| |
| /// The minimum representable integer in this type. |
| /// |
| /// For signed integer types, this value is `-(2 ** (bitWidth - 1))`, where |
| /// `**` is exponentiation. |
| @_transparent |
| public static var min: Self { |
| return (-1 as Self) &<< Self._highBitIndex |
| } |
| } |
| |
| |
| //===----------------------------------------------------------------------===// |
| //===--- Concrete FixedWidthIntegers --------------------------------------===// |
| //===----------------------------------------------------------------------===// |
| |
| % for self_type in all_integer_types(word_bits): |
| % bits = self_type.bits |
| % signed = self_type.is_signed |
| % BuiltinName = self_type.builtin_name |
| % Self = self_type.stdlib_name |
| % OtherSelf = self_type.get_opposite_signedness().stdlib_name |
| % Unsigned = 'Signed' if signed else 'Unsigned' |
| % u = 's' if signed else 'u' |
| % U = 'U' if signed else '' |
| % z = 's' if signed else 'z' |
| |
| % Article = 'An' if bits == 8 else 'A' |
| % if self_type.is_word: |
| /// ${'A ' if signed else 'An un'}signed integer value type. |
| /// |
| /// On 32-bit platforms, `${Self}` is the same size as `${Self}32`, and |
| /// on 64-bit platforms, `${Self}` is the same size as `${Self}64`. |
| % else: |
| /// ${Article} ${bits}-bit ${'' if signed else 'un'}signed integer value |
| /// type. |
| % end |
| @_fixed_layout |
| public struct ${Self} |
| : FixedWidthInteger, ${Unsigned}Integer, |
| _ExpressibleByBuiltinIntegerLiteral { |
| |
| @_transparent |
| public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) { |
| _value = Builtin.s_to_${u}_checked_trunc_${IntLiteral}_${BuiltinName}(x).0 |
| } |
| |
| /// Creates a new instance with the same memory representation as the given |
| /// value. |
| /// |
| /// This initializer does not perform any range or overflow checking. The the |
| /// resulting instance may not have the same numeric value as |
| /// `bitPattern`---it is only guaranteed to use the same pattern of bits in |
| /// its binary representation. |
| /// |
| /// - Parameter x: A value to use as the source of the new instance's binary |
| /// representation. |
| @_transparent |
| public init(bitPattern x: ${OtherSelf}) { |
| _value = x._value |
| } |
| |
| % if Self in ['Int32', 'Int64']: |
| % Floating = {32 : 'Float', 64 : 'Double'}[bits] |
| @available(*, unavailable, |
| message: "Please use ${Self}(bitPattern: ${OtherSelf}) in combination with ${Floating}.bitPattern property.") |
| public init(bitPattern x: ${Floating}) { |
| Builtin.unreachable() |
| } |
| % end |
| |
| % for (FloatType, FloatBits) in [ |
| % ('Float', 32), ('Double', 64), ('Float80', 80)]: |
| % (lower, upper) = getFtoIBounds(floatBits=FloatBits, intBits=int(bits), signed=signed) |
| |
| % if FloatType == 'Float80': |
| #if !os(Windows) && (arch(i386) || arch(x86_64)) |
| % end |
| |
| /// Creates an integer from the given floating-point value, rounding toward |
| /// zero. |
| /// |
| /// Any fractional part of the value passed as `source` is removed, rounding |
| /// the value toward zero. |
| /// |
| /// let x = Int(21.5) |
| /// // x == 21 |
| /// let y = Int(-21.5) |
| /// // y == -21 |
| /// |
| /// If `source` is outside the bounds of this type after rounding toward |
| /// zero, a runtime error may occur. |
| /// |
| /// let z = UInt(-21.5) |
| /// // Error: ...the result would be less than UInt.min |
| /// |
| /// - Parameter source: A floating-point value to convert to an integer. |
| /// `source` must be representable in this type after rounding toward |
| /// zero. |
| @_transparent |
| public init(_ source: ${FloatType}) { |
| _precondition(source.isFinite, |
| "${FloatType} value cannot be converted to ${Self} because it is either infinite or NaN") |
| _precondition(source > ${str(lower)}.0, |
| "${FloatType} value cannot be converted to ${Self} because the result would be less than ${Self}.min") |
| _precondition(source < ${str(upper)}.0, |
| "${FloatType} value cannot be converted to ${Self} because the result would be greater than ${Self}.max") |
| self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value) |
| } |
| |
| /// Creates an integer from the given floating-point value, if it can be |
| /// represented exactly. |
| /// |
| /// If the value passed as `source` is not representable exactly, the result |
| /// is `nil`. In the following example, the constant `x` is successfully |
| /// created from a value of `21.0`, while the attempt to initialize the |
| /// constant `y` from `21.5` fails: |
| /// |
| /// let x = Int(exactly: 21.0) |
| /// // x == Optional(21) |
| /// let y = Int(exactly: 21.5) |
| /// // y == nil |
| /// |
| /// - Parameter source: A floating-point value to convert to an integer. |
| @_transparent |
| public init?(exactly source: ${FloatType}) { |
| self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value) |
| if ${FloatType}(self) != source { |
| return nil |
| } |
| } |
| |
| % if FloatType == 'Float80': |
| #endif |
| % end |
| |
| % end |
| |
| @_transparent |
| public static func == (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.cmp_eq_Int${bits}(lhs._value, rhs._value)) |
| } |
| |
| @_transparent |
| public static func < (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return Bool(Builtin.cmp_${u}lt_Int${bits}(lhs._value, rhs._value)) |
| } |
| |
| // FIXME(integers): pending optimizer work on handling the case where the |
| // boolean value is wrapped into a two-case enum and then immediately |
| // unwrapped. <rdar://problem/29004429> |
| // See corresponding definitions in the FixedWidthInteger extension. |
| % for x in binaryArithmetic['Numeric'] + binaryArithmetic["BinaryInteger"][:1]: |
| ${assignmentOperatorComment(x.operator, True)} |
| @_transparent |
| public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) { |
| % if x.kind == '/': |
| // No LLVM primitives for checking overflow of division |
| // operations, so we check manually. |
| if _slowPath(rhs == (0 as ${Self})) { |
| _preconditionFailure("Remainder of or division by zero") |
| } |
| % if signed: |
| if _slowPath( |
| ${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)} |
| ) { |
| _preconditionFailure("Overflow in remainder of or division") |
| } |
| % end |
| let (result, overflow) = |
| (Builtin.${u}${x.llvmName}_Int${bits}(lhs._value, rhs._value), |
| false._value) |
| % else: |
| let (result, overflow) = |
| Builtin.${u}${x.llvmName}_with_overflow_Int${bits}( |
| lhs._value, rhs._value, true._value) |
| % end |
| Builtin.condfail(overflow) |
| lhs = ${Self}(result) |
| } |
| % end |
| // end of FIXME(integers) |
| |
| % for x in chain(*binaryArithmetic.values()): |
| |
| ${overflowOperationComment(x.operator)} |
| @_transparent |
| public func ${x.name}ReportingOverflow( |
| ${x.firstArg} other: ${Self} |
| ) -> (partialValue: ${Self}, overflow: Bool) { |
| |
| % if x.kind == '/': |
| // No LLVM primitives for checking overflow of division |
| // operations, so we check manually. |
| if _slowPath( |
| other == (0 as ${Self}) |
| ${'|| self == %s.min && other == (-1 as %s)' % (Self, Self) if signed else ''} |
| ) { |
| return (partialValue: self, overflow: true) |
| } |
| |
| let (newStorage, overflow) = ( |
| Builtin.${u}${x.llvmName}_Int${bits}(self._value, other._value), |
| false._value) |
| |
| % else: |
| |
| let (newStorage, overflow) |
| = Builtin.${u}${x.llvmName}_with_overflow_Int${bits}( |
| self._value, other._value, false._value) |
| % end |
| |
| return ( |
| partialValue: ${Self}(newStorage), |
| overflow: Bool(overflow)) |
| } |
| % end |
| |
| ${assignmentOperatorComment('%', True)} |
| @_transparent |
| public static func %=(_ lhs: inout ${Self}, _ rhs: ${Self}) { |
| // No LLVM primitives for checking overflow of division |
| // operations, so we check manually. |
| if _slowPath(rhs == (0 as ${Self})) { |
| _preconditionFailure("Remainder of division by zero") |
| } |
| % if signed: |
| if _slowPath( |
| ${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)} |
| ) { |
| _preconditionFailure("Overflow in remainder of division") |
| } |
| % end |
| |
| let (newStorage, _) = ( |
| Builtin.${u}rem_Int${bits}(lhs._value, rhs._value), |
| false._value) |
| lhs = ${Self}(newStorage) |
| } |
| |
| @_transparent |
| public init(_ _value: Builtin.Int${bits}) { |
| self._value = _value |
| } |
| |
| // FIXME(integers): in order to remove this, the simd.swift.gyb should be |
| // updated |
| @_transparent |
| public init(_bits: Builtin.Int${bits}) { |
| self._value = _bits |
| } |
| |
| % for x in binaryBitwise: |
| ${assignmentOperatorComment(x.operator, True)} |
| @_transparent |
| public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) { |
| lhs = ${Self}(Builtin.${x.llvmName}_Int${bits}(lhs._value, rhs._value)) |
| } |
| % end |
| |
| % for x in maskingShifts: |
| |
| ${assignmentOperatorComment(x.operator, True)} |
| @_transparent |
| public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) { |
| let rhs_ = rhs & ${bits - 1} |
| lhs = ${Self}( |
| Builtin.${x.llvmName(signed)}_Int${bits}(lhs._value, rhs_._value)) |
| } |
| |
| % end |
| |
| /// The number of bits used for the underlying binary representation of |
| /// values of this type. |
| /// |
| % if self_type.is_word: |
| /// The bit width of ${Article.lower()} `${Self}` instance is 32 on 32-bit |
| /// platforms and 64 on 64-bit platforms. |
| % else: |
| /// The bit width of ${Article.lower()} `${Self}` instance is ${bits}. |
| % end |
| @_transparent |
| public static var bitWidth : Int { return ${bits} } |
| |
| /// The number of leading zeros in this value's binary representation. |
| /// |
| /// For example, in an integer type with a `bitWidth` value of 8, |
| /// the number *31* has three leading zeros. |
| /// |
| /// let x: Int8 = 0b0001_1111 |
| /// // x == 31 |
| /// // x.leadingZeroBitCount == 3 |
| @_transparent |
| public var leadingZeroBitCount: Int { |
| return Int( |
| ${Self}( |
| Builtin.int_ctlz_Int${bits}(self._value, false._value) |
| )._lowWord._value) |
| } |
| |
| /// The number of trailing zeros in this value's binary representation. |
| /// |
| /// For example, the number *-8* has three trailing zeros. |
| /// |
| /// let x = Int8(bitPattern: 0b1111_1000) |
| /// // x == -8 |
| /// // x.trailingZeroBitCount == 3 |
| @_transparent |
| public var trailingZeroBitCount: Int { |
| return Int( |
| ${Self}( |
| Builtin.int_cttz_Int${bits}(self._value, false._value) |
| )._lowWord._value) |
| } |
| |
| /// The number of bits equal to 1 in this value's binary representation. |
| /// |
| /// For example, in a fixed-width integer type with a `bitWidth` value of 8, |
| /// the number *31* has five bits equal to *1*. |
| /// |
| /// let x: Int8 = 0b0001_1111 |
| /// // x == 31 |
| /// // x.nonzeroBitCount == 5 |
| @_transparent |
| public var nonzeroBitCount: Int { |
| return Int( |
| ${Self}( |
| Builtin.int_ctpop_Int${bits}(self._value) |
| )._lowWord._value) |
| } |
| |
| // FIXME should be RandomAccessCollection |
| public struct Words : BidirectionalCollection { |
| public typealias Indices = CountableRange<Int> |
| public typealias SubSequence = BidirectionalSlice<${Self}.Words> |
| |
| var _value: ${Self} |
| |
| public init(_ value: ${Self}) { |
| self._value = value |
| } |
| |
| public var count: Int { |
| return (${bits} + ${word_bits} - 1) / ${word_bits} |
| } |
| |
| public var startIndex: Int { return 0 } |
| |
| public var endIndex: Int { return count } |
| |
| public var indices: Indices { return startIndex ..< endIndex } |
| |
| @_transparent |
| public func index(after i: Int) -> Int { return i + 1 } |
| |
| @_transparent |
| public func index(before i: Int) -> Int { return i - 1 } |
| |
| public subscript(position: Int) -> UInt { |
| get { |
| _precondition(position >= 0, "Negative word index") |
| _precondition(position < endIndex, "Word index out of range") |
| let shift = UInt(position._value) &* ${word_bits} |
| _sanityCheck(shift < UInt(_value.bitWidth._value)) |
| return (_value &>> ${Self}(_truncatingBits: shift))._lowWord |
| } |
| } |
| } |
| |
| /// A collection containing the words of this value's binary |
| /// representation, in order from the least significant to most significant. |
| % if signed: |
| /// |
| /// Negative values are returned in two's complement representation, |
| /// regardless of the type's underlying implementation. |
| % end |
| @_transparent |
| public var words: Words { |
| return Words(self) |
| } |
| |
| @_transparent |
| public // transparent |
| var _lowWord: UInt { |
| % truncOrExt = z + 'ext' if bits <= word_bits else 'trunc' |
| return UInt( |
| Builtin.${truncOrExt}OrBitCast_Int${bits}_Int${word_bits}(_value) |
| ) |
| } |
| |
| @_transparent |
| public // transparent |
| init(_truncatingBits bits: UInt) { |
| % truncOrExt = 'zext' if bits > word_bits else 'trunc' |
| self.init( |
| Builtin.${truncOrExt}OrBitCast_Int${word_bits}_Int${bits}(bits._value)) |
| } |
| |
| public typealias Magnitude = ${U}${Self} |
| |
| % if signed: |
| /// The magnitude of this value. |
| /// |
| /// For any numeric value `x`, `x.magnitude` is the absolute value of `x`. |
| /// You can use the `magnitude` property in operations that are simpler to |
| /// implement in terms of unsigned values, such as printing the value of an |
| /// integer, which is just printing a '-' character in front of an absolute |
| /// value. |
| /// |
| /// let x = -200 |
| /// // x.magnitude == 200 |
| /// |
| /// The global `abs(_:)` function provides more familiar syntax when you need |
| /// to find an absolute value. In addition, because `abs(_:)` always returns |
| /// a value of the same type, even in a generic context, using the function |
| /// instead of the `magnitude` property is encouraged. |
| @_transparent |
| public var magnitude: U${Self} { |
| let base = U${Self}(_value) |
| return self < (0 as ${Self}) ? ~base + 1 : base |
| } |
| % end |
| |
| % dbits = bits*2 |
| /// Returns a tuple containing the high and low parts of the result of |
| /// multiplying this value by the given value. |
| /// |
| /// Use this method to calculate the full result of a product that would |
| /// otherwise overflow. Unlike traditional truncating multiplication, the |
| /// `multipliedFullWidth(by:)` method returns a tuple |
| /// containing both the `high` and `low` parts of the product of this value and |
| /// `other`. The following example uses this method to multiply two `UInt8` |
| /// values that normally overflow when multiplied: |
| /// |
| /// let x: UInt8 = 100 |
| /// let y: UInt8 = 20 |
| /// let result = x.multipliedFullWidth(by: y) |
| /// // result.high == 0b00000111 |
| /// // result.low == 0b11010000 |
| /// |
| /// The product of `x` and `y` is 2000, which is too large to represent in a |
| /// `UInt8` instance. The `high` and `low` properties of the `result` value |
| /// represent 2000 when concatenated to form a double-width integer; that |
| /// is, using `result.high` as the high byte and `result.low` as the low byte |
| /// of a `UInt16` instance. |
| /// |
| /// let z = UInt16(result.high) << 8 | UInt16(result.low) |
| /// // z == 2000 |
| /// |
| /// - Parameter other: The value to multiply this value by. |
| /// - Returns: A tuple containing the high and low parts of the result of |
| /// multiplying this value and `other`. |
| public func multipliedFullWidth(by other: ${Self}) |
| -> (high: ${Self}, low: ${Self}.Magnitude) { |
| // FIXME(integers): tests |
| % # 128 bit types are not provided by the 32-bit LLVM |
| % if word_bits == 32 and bits == 64: |
| // FIXME(integers): implement |
| fatalError("Operation is not supported") |
| % else: |
| let lhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(self._value) |
| let rhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(other._value) |
| |
| let res = Builtin.mul_Int${dbits}(lhs_, rhs_) |
| let low = ${Self}.Magnitude(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(res)) |
| let shift = Builtin.zextOrBitCast_Int8_Int${dbits}(UInt8(${bits})._value) |
| let shifted = Builtin.ashr_Int${dbits}(res, shift) |
| let high = ${Self}(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(shifted)) |
| return (high: high, low: low) |
| % end |
| } |
| |
| /// Returns a tuple containing the quotient and remainder of dividing the |
| /// given value by this value. |
| /// |
| /// The resulting quotient must be representable within the bounds of the |
| /// type. If the quotient of dividing `dividend` by this value is too large |
| /// to represent in the type, a runtime error may occur. |
| /// |
| /// - Parameter dividend: A tuple containing the high and low parts of a |
| /// double-width integer. The `high` component of the value carries the |
| /// sign, if the type is signed. |
| /// - Returns: A tuple containing the quotient and remainder of `dividend` |
| /// divided by this value. |
| public func dividingFullWidth( |
| _ dividend: (high: ${Self}, low: ${Self}.Magnitude) |
| ) -> (quotient: ${Self}, remainder: ${Self}) { |
| // FIXME(integers): tests |
| % # 128 bit types are not provided by the 32-bit LLVM |
| % #if word_bits == 32 and bits == 64: |
| % if bits == 64: |
| let lhs = DoubleWidth<${Self}>(dividend) |
| let rhs = DoubleWidth<${Self}>(self) |
| |
| let (quotient, remainder) = lhs.quotientAndRemainder(dividingBy: rhs) |
| // FIXME(integers): check for high words in quotient and remainder |
| return (${Self}(quotient.low), ${Self}(remainder.low)) |
| % else: |
| // FIXME(integers): handle division by zero and overflows |
| _precondition(self != 0, "Division by zero") |
| let lhsHigh = Builtin.${z}ext_Int${bits}_Int${dbits}(dividend.high._value) |
| let shift = Builtin.zextOrBitCast_Int8_Int${dbits}(UInt8(${bits})._value) |
| let lhsHighShifted = Builtin.shl_Int${dbits}(lhsHigh, shift) |
| let lhsLow = Builtin.zext_Int${bits}_Int${dbits}(dividend.low._value) |
| let lhs_ = Builtin.or_Int${dbits}(lhsHighShifted, lhsLow) |
| let rhs_ = Builtin.${z}ext_Int${bits}_Int${dbits}(self._value) |
| |
| let quotient_ = Builtin.${u}div_Int${dbits}(lhs_, rhs_) |
| let remainder_ = Builtin.${u}rem_Int${dbits}(lhs_, rhs_) |
| |
| let quotient = ${Self}( |
| Builtin.truncOrBitCast_Int${dbits}_Int${bits}(quotient_)) |
| let remainder = ${Self}( |
| Builtin.truncOrBitCast_Int${dbits}_Int${bits}(remainder_)) |
| |
| return (quotient: quotient, remainder: remainder) |
| % end |
| } |
| |
| /// A representation of this integer with the byte order swapped. |
| @_transparent |
| public var byteSwapped: ${Self} { |
| % if bits <= 8: |
| return self |
| % else: |
| return ${Self}(Builtin.int_bswap_${BuiltinName}(_value)) |
| % end |
| } |
| |
| // Implementation details |
| |
| public var _value: Builtin.Int${bits} |
| |
| % if self_type.is_word: |
| @_transparent |
| public // @testable |
| init(_ _v: Builtin.Word) { |
| % if BuiltinName == 'Int32': |
| self._value = Builtin.truncOrBitCast_Word_Int32(_v) |
| % elif BuiltinName == 'Int64': |
| self._value = Builtin.zextOrBitCast_Word_Int64(_v) |
| % end |
| } |
| |
| @_transparent |
| public // @testable |
| var _builtinWordValue: Builtin.Word { |
| % if BuiltinName == 'Int32': |
| return Builtin.zextOrBitCast_Int32_Word(_value) |
| % elif BuiltinName == 'Int64': |
| return Builtin.truncOrBitCast_Int64_Word(_value) |
| % end |
| } |
| % end |
| |
| @available(swift, obsoleted: 4.0, message: "Use initializers instead") |
| public func to${U}IntMax() -> ${U}Int64 { |
| return numericCast(self) |
| } |
| |
| @available(swift, obsoleted: 4, message: "Use bitWidth instead.") |
| public static var _sizeInBits: ${Self} { return ${bits} } |
| |
| @available(swift, obsoleted: 4) |
| public static var _sizeInBytes: ${Self} { return ${bits}/8 } |
| |
| /// Returns `-1` if this value is negative and `1` if it's positive; |
| /// otherwise, `0`. |
| /// |
| /// - Returns: The sign of this number, expressed as an integer of the same |
| /// type. |
| @inline(__always) |
| public func signum() -> ${Self} { |
| let isPositive = ${Self}(Builtin.zext_Int1_Int${bits}( |
| (self > (0 as ${Self}))._value)) |
| return isPositive | (self &>> ${bits - 1}) |
| } |
| } |
| %# end of concrete type: ${Self} |
| |
| extension ${Self} : Hashable { |
| /// The integer's hash value. |
| /// |
| /// The hash value is not guaranteed to be stable across different |
| /// invocations of the same program. Do not persist the hash value across |
| /// program runs. |
| public var hashValue: Int { |
| @inline(__always) |
| get { |
| % if bits <= word_bits and signed: |
| // Sign extend the value. |
| return Int(self) |
| % elif bits <= word_bits and not signed: |
| // Sign extend the value. |
| return Int(${OtherSelf}(bitPattern: self)) |
| % elif bits == word_bits * 2: |
| // We have twice as many bits as we need to return. |
| return |
| Int(truncatingIfNeeded: self) ^ |
| Int(truncatingIfNeeded: self &>> 32) |
| % else: |
| _Unimplemented() |
| % end |
| } |
| } |
| } |
| |
| |
| // Create an ambiguity when indexing or slicing |
| // Range[OfStrideable]<${Self}> outside a generic context. See |
| // Range.swift for details. |
| extension ${Self} { |
| public typealias _DisabledRangeIndex = ${Self} |
| } |
| |
| |
| % for src_type in all_integer_types(word_bits): |
| % srcBits = src_type.bits |
| % srcSigned = src_type.is_signed |
| % Src = src_type.stdlib_name |
| % if should_define_truncating_bit_pattern_init(src_ty=src_type, dst_ty=self_type): |
| extension ${Self} { |
| /// Creates a new instance with the same bitwise representation as the least |
| /// significant bits of the given value. |
| /// |
| /// This initializer performs no range or overflow checking. The resulting |
| /// instance may have a different numeric value from `source`. |
| /// |
| /// - Parameter source: An integer to use as the source of the new value's |
| /// bit pattern. |
| @available(swift, obsoleted: 4.0, renamed: "init(truncatingIfNeeded:)") |
| @_transparent |
| public init(truncatingBitPattern source: ${Src}) { |
| let src = source._value |
| % if self_type.bits == src_type.bits: |
| let dstNotWord = src |
| % else: |
| let dstNotWord = Builtin.trunc_Int${srcBits}_Int${bits}(src) |
| % end |
| self._value = dstNotWord |
| } |
| } |
| % end |
| % end |
| |
| |
| // FIXME(integers): this section here is to help the typechecker, |
| // as it seems to have problems with a pattern where the nonmutating operation |
| // is defined on a protocol in terms of a mutating one that is itself defined |
| // on concrete types. |
| extension ${Self} { |
| |
| % for x in binaryBitwise + maskingShifts + list(chain(*binaryArithmetic.values())): |
| |
| ${operatorComment(x.operator, True)} |
| @_transparent |
| public static func ${x.operator}(_ lhs: ${Self}, _ rhs: ${Self}) -> ${Self} { |
| var lhs = lhs |
| lhs ${x.operator}= rhs |
| return lhs |
| } |
| |
| % end |
| |
| % for op in maskingShifts: |
| |
| ${operatorComment(x.operator, True)} |
| @available(swift, obsoleted: 4) |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_transparent |
| public static func ${op.nonMaskingOperator}( |
| lhs: ${Self}, rhs: ${Self} |
| ) -> ${Self} { |
| var lhs = lhs |
| ${op.helper}Generic(&lhs, rhs) |
| return lhs |
| } |
| |
| ${assignmentOperatorComment(x.operator, True)} |
| @available(swift, obsoleted: 4) |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_transparent |
| public static func ${op.nonMaskingOperator}=( |
| lhs: inout ${Self}, rhs: ${Self} |
| ) { |
| ${op.helper}Generic(&lhs, rhs) |
| } |
| |
| % end |
| } |
| |
| |
| % if signed: |
| // TODO: Consider removing the underscore. |
| /// Returns the argument and specifies that the value is not negative. |
| /// It has only an effect if the argument is a load or call. |
| @_transparent |
| public func _assumeNonNegative(_ x: ${Self}) -> ${Self} { |
| _sanityCheck(x >= (0 as ${Self})) |
| return ${Self}(Builtin.assumeNonNegative_${BuiltinName}(x._value)) |
| } |
| % end |
| |
| //===--- end of FIXME(integers) -------------------------------------------===// |
| |
| % end # end of concrete FixedWidthInteger section |
| |
| |
| /// Returns the given integer as the equivalent value in a different integer |
| /// type. |
| /// |
| /// The `numericCast(_:)` function traps on overflow in `-O` and `-Onone` |
| /// builds. |
| /// |
| /// You can use `numericCast(_:)` to convert a value when the destination type |
| /// can be inferred from the context. In the following example, the |
| /// `random(in:)` function uses `numericCast(_:)` twice to convert the |
| /// argument and return value of the `arc4random_uniform(_:)` function to the |
| /// appropriate type. |
| /// |
| /// func random(in range: Range<Int>) -> Int { |
| /// return numericCast(arc4random_uniform(numericCast(range.count))) |
| /// + range.lowerBound |
| /// } |
| /// |
| /// let number = random(in: -10...<10) |
| /// // number == -3, perhaps |
| /// |
| /// - Parameter x: The integer to convert, and instance of type `T`. |
| /// - Returns: The value of `x` converted to type `U`. |
| @_transparent |
| public func numericCast<T : BinaryInteger, U : BinaryInteger>(_ x: T) -> U { |
| return U(x) |
| } |
| |
| // FIXME(integers): switch to using `FixedWidthInteger.unsafeAdding` |
| internal func _unsafePlus(_ lhs: Int, _ rhs: Int) -> Int { |
| #if INTERNAL_CHECKS_ENABLED |
| return lhs + rhs |
| #else |
| return lhs &+ rhs |
| #endif |
| } |
| |
| // FIXME(integers): switch to using `FixedWidthInteger.unsafeSubtracting` |
| internal func _unsafeMinus(_ lhs: Int, _ rhs: Int) -> Int { |
| #if INTERNAL_CHECKS_ENABLED |
| return lhs - rhs |
| #else |
| return lhs &- rhs |
| #endif |
| } |
| |
| // Swift 3 compatibility APIs |
| |
| @available(swift, obsoleted: 4, renamed: "BinaryInteger") |
| public typealias Integer = BinaryInteger |
| |
| @available(swift, obsoleted: 4, renamed: "BinaryInteger") |
| public typealias IntegerArithmetic = BinaryInteger |
| |
| @available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.") |
| public typealias SignedNumber = SignedNumeric & Comparable |
| |
| @available(swift, obsoleted: 4, message: "Please use 'SignedNumeric & Comparable' instead.") |
| public typealias AbsoluteValuable = SignedNumeric & Comparable |
| |
| @available(swift, obsoleted: 4, renamed: "SignedInteger") |
| public typealias _SignedInteger = SignedInteger |
| |
| extension SignedNumeric where Self : Comparable { |
| @available(swift, obsoleted: 4, message: "Please use the 'abs(_:)' free function.") |
| @_transparent |
| public static func abs(_ x: Self) -> Self { |
| return Swift.abs(x) |
| } |
| } |
| |
| @available(swift, obsoleted: 4) |
| extension BinaryInteger { |
| @available(swift, obsoleted: 4) |
| public func toIntMax() -> Int64 { |
| return Int64(self) |
| } |
| } |
| |
| extension UnsignedInteger { |
| @available(swift, obsoleted: 4) |
| public func toUIntMax() -> UInt64 { |
| return UInt64(self) |
| } |
| } |
| |
| // FIXME(integers): These overloads allow expressions like the following in |
| // Swift 3 compatibility mode: |
| // let x = 1 << i32 |
| // f(i32: x) |
| // At the same time, since they are obsolete in Swift 4, this will not cause |
| // `u8 << -1` to fail due to an overflow in an unsigned value. |
| extension FixedWidthInteger { |
| |
| % for op in maskingShifts: |
| |
| @available(swift, obsoleted: 4) |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_transparent |
| public static func ${op.nonMaskingOperator}( |
| lhs: Self, rhs: Self |
| ) -> Self { |
| var lhs = lhs |
| ${op.helper}Generic(&lhs, rhs) |
| return lhs |
| } |
| |
| @available(swift, obsoleted: 4) |
| @_semantics("optimize.sil.specialize.generic.partial.never") |
| @_transparent |
| public static func ${op.nonMaskingOperator}=( |
| lhs: inout Self, rhs: Self |
| ) { |
| ${op.helper}Generic(&lhs, rhs) |
| } |
| |
| % end |
| |
| } |
| |
| %{ |
| overflowingOps = [ |
| ('add', 'adding', ''), |
| ('subtract', 'subtracting', ''), |
| ('multiply', 'multiplied', 'by:'), |
| ('divide', 'divided', 'by:'), |
| ('remainder', 'remainder', 'dividingBy:'), |
| ] |
| }% |
| |
| extension FixedWidthInteger { |
| % for oldPrefix, newPrefix, argLabel in overflowingOps: |
| @available(swift, obsoleted: 4, message: "Use ${newPrefix}ReportingOverflow(${argLabel or '_:'}) instead.") |
| @_transparent |
| public static func ${oldPrefix}WithOverflow( |
| _ lhs: Self, _ rhs: Self |
| ) -> (Self, overflow: Bool) { |
| let (partialValue, overflow) = |
| lhs.${newPrefix}ReportingOverflow(${argLabel} rhs) |
| return (partialValue, overflow: overflow) |
| } |
| |
| % end |
| } |
| |
| extension BinaryInteger { |
| % for oldPrefix, newPrefix, argLabel in overflowingOps: |
| @available(swift, obsoleted: 3.2, |
| message: "Please use FixedWidthInteger protocol as a generic constraint and ${newPrefix}ReportingOverflow(${argLabel or '_:'}) method instead.") |
| public static func ${oldPrefix}WithOverflow( |
| _ lhs: Self, _ rhs: Self |
| ) -> (Self, overflow: Bool) { |
| fatalError("Unavailable") |
| } |
| % end |
| } |
| |
| // FIXME(integers): Absence of &+ causes ambiguity in the code like the |
| // following: |
| // func f<T : SignedInteger>(_ x: T, _ y: T) { |
| // var _ = (x &+ (y - 1)) < x |
| // } |
| // Compiler output: |
| // error: ambiguous reference to member '-' |
| // var _ = (x &+ (y - 1)) < x |
| // ^ |
| % maskingOpsSwift3 = [ |
| % ('&+', '_maskingAdd', 'adding'), |
| % ('&-', '_maskingSubtract', 'subtracting')] |
| extension SignedInteger { |
| % for (op, helper, _) in maskingOpsSwift3: |
| public static func ${helper}(_ lhs: Self, _ rhs: Self) -> Self { |
| fatalError("Should be overridden in a more specific type") |
| } |
| |
| @available(swift, obsoleted: 4.0, |
| message: "Please use 'FixedWidthInteger' instead of 'SignedInteger' to get '${op}' in generic code.") |
| public static func ${op} (lhs: Self, rhs: Self) -> Self { |
| return ${helper}(lhs, rhs) |
| } |
| % end |
| } |
| |
| extension SignedInteger where Self : FixedWidthInteger { |
| % for (op, helper, action) in maskingOpsSwift3: |
| // This overload is supposed to break the ambiguity between the |
| // implementations on SignedInteger and FixedWidthInteger |
| public static func ${op} (lhs: Self, rhs: Self) -> Self { |
| return ${helper}(lhs, rhs) |
| } |
| @_transparent |
| public static func ${helper}(_ lhs: Self, _ rhs: Self) -> Self { |
| return lhs.${action}ReportingOverflow(rhs).partialValue |
| } |
| % end |
| } |