| //===--- Integers.swift.gyb -----------------------------------*- swift -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2018 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 |
| |
| 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'), |
| ] |
| |
| #===-----------------------------------------------------------------------===// |
| #===--- 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 wrap the result in case |
| /// of 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 wrap the result in case |
| /// of 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 wrap the result in case |
| /// of 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 remainder operator (`%`) has the same sign as `lhs` and |
| /// has a magnitude 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, wrapping the result in case of |
| /// any overflow. |
| /// |
| /// The overflow addition operator (`&+`) discards any bits that overflow the |
| /// fixed width of the integer type. In the following example, the sum of |
| /// `100` and `121` is greater than the maximum representable `Int8` value, |
| /// so the result is the partial value after discarding the overflowing |
| /// bits. |
| /// |
| /// let x: Int8 = 10 &+ 21 |
| /// // x == 31 |
| /// let y: Int8 = 100 &+ 121 |
| /// // y == -35 (after overflow) |
| /// |
| /// For more about arithmetic with overflow operators, see [Overflow |
| /// Operators][overflow] in *[The Swift Programming Language][tspl]*. |
| /// |
| /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37 |
| /// [tspl]: https://docs.swift.org/swift-book/ |
| /// |
| /// - Parameters: |
| /// - lhs: The first value to add. |
| /// - rhs: The second value to add. |
| """, |
| '&-': """\ |
| /// Returns the difference of the two given values, wrapping the result in |
| /// case of any overflow. |
| /// |
| /// The overflow subtraction operator (`&-`) discards any bits that overflow |
| /// the fixed width of the integer type. In the following example, the |
| /// difference of `10` and `21` is less than zero, the minimum representable |
| /// `UInt` value, so the result is the partial value after discarding the |
| /// overflowing bits. |
| /// |
| /// let x: UInt8 = 21 &- 10 |
| /// // x == 11 |
| /// let y: UInt8 = 10 &- 21 |
| /// // y == 245 (after overflow) |
| /// |
| /// For more about arithmetic with overflow operators, see [Overflow |
| /// Operators][overflow] in *[The Swift Programming Language][tspl]*. |
| /// |
| /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37 |
| /// [tspl]: https://docs.swift.org/swift-book/ |
| /// |
| /// - Parameters: |
| /// - lhs: A numeric value. |
| /// - rhs: The value to subtract from `lhs`. |
| """, |
| '&*': """\ |
| /// Returns the product of the two given values, wrapping the result in case |
| /// of any overflow. |
| /// |
| /// The overflow multiplication operator (`&*`) discards any bits that |
| /// overflow the fixed width of the integer type. In the following example, |
| /// the product of `10` and `50` is greater than the maximum representable |
| /// `Int8` value, so the result is the partial value after discarding the |
| /// overflowing bits. |
| /// |
| /// let x: Int8 = 10 &* 5 |
| /// // x == 50 |
| /// let y: Int8 = 10 &* 50 |
| /// // y == -12 (after overflow) |
| /// |
| /// For more about arithmetic with overflow operators, see [Overflow |
| /// Operators][overflow] in *[The Swift Programming Language][tspl]*. |
| /// |
| /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37 |
| /// [tspl]: https://docs.swift.org/swift-book/ |
| /// |
| /// - 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 |
| /// // z == 4 |
| /// |
| /// - 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 |
| /// // z == 15 |
| /// |
| /// - 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 |
| /// // z == 11 |
| /// |
| /// - 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. |
| /// |
| /// Use the masking right shift operator (`&>>`) when you need to perform a |
| /// shift and are sure that the shift amount is in the range |
| /// `0..<lhs.bitWidth`. Before shifting, the masking right shift operator |
| /// masks the shift to this range. 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 `8` as the shift amount, the method first masks the |
| /// shift amount to zero, and then performs the shift, resulting in no change |
| /// to the original value. |
| /// |
| /// let z = x &>> 8 |
| /// // z == 30 // 0b00011110 |
| /// |
| /// If the bit width of the shifted integer type is a power of two, masking |
| /// is performed using a bitmask; otherwise, masking is performed using a |
| /// modulo operation. |
| /// |
| /// - 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. |
| /// |
| /// Use the masking left shift operator (`&<<`) when you need to perform a |
| /// shift and are sure that the shift amount is in the range |
| /// `0..<lhs.bitWidth`. Before shifting, the masking left shift operator |
| /// masks the shift to this range. 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 use `8` as the shift amount, the method first masks the |
| /// shift amount to zero, and then performs the shift, resulting in no change |
| /// to the original value. |
| /// |
| /// let z = x &<< 8 |
| /// // z == 30 // 0b00011110 |
| /// |
| /// If the bit width of the shifted integer type is a power of two, masking |
| /// is performed using a bitmask; otherwise, masking is performed using a |
| /// modulo operation. |
| /// |
| /// - 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 has a magnitude 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. |
| """, |
| '&+': """\ |
| /// Adds two values and stores the result in the left-hand-side variable, |
| /// wrapping any overflow. |
| /// |
| /// The masking addition assignment operator (`&+=`) silently wraps 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 partial value after discarding the |
| /// overflowing bits. |
| /// |
| /// var x: Int8 = 10 |
| /// x &+= 21 |
| /// // x == 31 |
| /// var y: Int8 = 100 |
| /// y &+= 121 |
| /// // y == -35 (after overflow) |
| /// |
| /// For more about arithmetic with overflow operators, see [Overflow |
| /// Operators][overflow] in *[The Swift Programming Language][tspl]*. |
| /// |
| /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37 |
| /// [tspl]: https://docs.swift.org/swift-book/ |
| /// |
| /// - 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, wrapping any overflow. |
| /// |
| /// The masking subtraction assignment operator (`&-=`) silently wraps 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 result is the partial value after |
| /// discarding the overflowing bits. |
| /// |
| /// var x: Int8 = 21 |
| /// x &-= 10 |
| /// // x == 11 |
| /// var y: UInt8 = 10 |
| /// y &-= 21 |
| /// // y == 245 (after overflow) |
| /// |
| /// For more about arithmetic with overflow operators, see [Overflow |
| /// Operators][overflow] in *[The Swift Programming Language][tspl]*. |
| /// |
| /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37 |
| /// [tspl]: https://docs.swift.org/swift-book/ |
| /// |
| /// - 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, wrapping any overflow. |
| /// |
| /// The masking multiplication assignment operator (`&*=`) silently wraps |
| /// 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 partial value after discarding the |
| /// overflowing bits. |
| /// |
| /// var x: Int8 = 10 |
| /// x &*= 5 |
| /// // x == 50 |
| /// var y: Int8 = 10 |
| /// y &*= 50 |
| /// // y == -12 (after overflow) |
| /// |
| /// For more about arithmetic with overflow operators, see [Overflow |
| /// Operators][overflow] in *[The Swift Programming Language][tspl]*. |
| /// |
| /// [overflow]: https://docs.swift.org/swift-book/LanguageGuide/AdvancedOperators.html#ID37 |
| /// [tspl]: https://docs.swift.org/swift-book/ |
| /// |
| /// - Parameters: |
| /// - lhs: The first value to multiply. |
| /// - rhs: The second value to multiply. |
| """, |
| '&': """\ |
| /// 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(_:) |
| # * multipliedReportingOverflow(by:) |
| # / dividedReportingOverflow(by:) |
| # % remainderReportingOverflow(dividingBy:) |
| def overflowOperationComment(operator): |
| comments = { |
| '+': """\ |
| /// Returns the sum of this value and the given value, along with a Boolean |
| /// value 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 obtained by subtracting the given value from this |
| /// value, along with a Boolean value 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 |
| /// Boolean value 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 |
| /// Boolean value 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 obtained by dividing this value by the given value, |
| /// along with a Boolean value 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 either the truncated quotient |
| /// or, if the quotient is undefined, the dividend. |
| """, |
| '%': """\ |
| /// Returns the remainder after dividing this value by the given value, along |
| /// with a Boolean value indicating whether overflow occurred during division. |
| /// |
| /// Dividing by zero is not an error when using this method. For a value `x`, |
| /// the result of `x.remainderReportingOverflow(dividingBy: 0)` is |
| /// `(x, true)`. |
| /// |
| /// - Parameter rhs: The value to divide this value by. |
| /// - Returns: A tuple containing the result of the operation along with a |
| /// Boolean value indicating whether overflow occurred. If the `overflow` |
| /// component is `false`, the `partialValue` component contains the entire |
| /// remainder. If the `overflow` component is `true`, an overflow occurred |
| /// during division and the `partialValue` component contains either the |
| /// entire remainder or, if the remainder is undefined, the dividend. |
| """, |
| } |
| return comments[operator] |
| |
| # documentation for "unsafe" arithmetic methods, indexed by the related |
| # operator: |
| # + unsafeAdding(_:) |
| # - unsafeSubtracting(_:) |
| # * unsafeMultiplied(by:) |
| # / unsafeDivided(by:) |
| def unsafeOperationComment(operator): |
| comments = { |
| '+': """\ |
| /// Returns the sum of this value and the given value without checking for |
| /// arithmetic overflow. |
| /// |
| /// Use this function only to avoid the cost of overflow checking when you |
| /// are certain that the operation won't overflow. In optimized builds (`-O`) |
| /// the compiler is free to assume that overflow won't occur. Failure to |
| /// satisfy that assumption is a serious programming error and could lead to |
| /// statements being unexpectedly executed or skipped. |
| /// |
| /// In debug builds (`-Onone`) a runtime error is still triggered if the |
| /// operation overflows. |
| /// |
| /// This method is not a synonym for the masking addition operator (`&+`). |
| /// Use that operator instead of this method when you want to discard any |
| /// overflow that results from an addition operation. |
| /// |
| /// - Parameter rhs: The value to add to this value. |
| /// - Returns: The sum of this value and `rhs`. |
| """, |
| '-': """\ |
| /// Returns the difference obtained by subtracting the given value from this |
| /// value without checking for arithmetic overflow. |
| /// |
| /// Use this function only to avoid the cost of overflow checking when you |
| /// are certain that the operation won't overflow. In optimized builds (`-O`) |
| /// the compiler is free to assume that overflow won't occur. Failure to |
| /// satisfy that assumption is a serious programming error and could lead to |
| /// statements being unexpectedly executed or skipped. |
| /// |
| /// In debug builds (`-Onone`) a runtime error is still triggered if the |
| /// operation overflows. |
| /// |
| /// This method is not a synonym for the masking subtraction operator (`&-`). |
| /// Use that operator instead of this method when you want to discard any |
| /// overflow that results from a subtraction operation. |
| /// |
| /// - Parameter rhs: The value to subtract from this value. |
| /// - Returns: The result of subtracting `rhs` from this value. |
| """, |
| '*': """\ |
| /// Returns the product of this value and the given value without checking |
| /// for arithmetic overflow. |
| /// |
| /// Use this function only to avoid the cost of overflow checking when you |
| /// are certain that the operation won't overflow. In optimized builds (`-O`) |
| /// the compiler is free to assume that overflow won't occur. Failure to |
| /// satisfy that assumption is a serious programming error and could lead to |
| /// statements being unexpectedly executed or skipped. |
| /// |
| /// In debug builds (`-Onone`) a runtime error is still triggered if the |
| /// operation overflows. |
| /// |
| /// This method is not a synonym for the masking multiplication operator |
| /// (`&*`). Use that operator instead of this method when you want to discard |
| /// any overflow that results from an addition operation. |
| /// |
| /// - Parameter rhs: The value to multiply by this value. |
| /// - Returns: The product of this value and `rhs`. |
| """, |
| '/': """\ |
| /// Returns the quotient obtained by dividing this value by the given value |
| /// without checking for arithmetic overflow. |
| /// |
| /// Use this function only to avoid the cost of overflow checking when you |
| /// are certain that the operation won't overflow. In optimized builds (`-O`) |
| /// the compiler is free to assume that overflow won't occur. Failure to |
| /// satisfy that assumption is a serious programming error and could lead to |
| /// statements being unexpectedly executed or skipped. |
| /// |
| /// In debug builds (`-Onone`) a runtime error is still triggered if the |
| /// operation overflows. |
| /// |
| /// - Parameter rhs: The value to divide this value by. |
| /// - Returns: The result of dividing this value by `rhs`. |
| """, |
| } |
| return comments[operator] |
| |
| }% |
| |
| //===----------------------------------------------------------------------===// |
| //===--- 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 { |
| |
| /// A type that represents an integer literal. |
| public typealias IntegerLiteralType = ${Self} |
| |
| |
| @_transparent |
| public init(_builtinIntegerLiteral x: Builtin.IntLiteral) { |
| _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 |
| /// 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}) { |
| // The value passed as `source` must not be infinite, NaN, or exceed the |
| // bounds of the integer type; the result of `fptosi` or `fptoui` is |
| // undefined if it overflows. |
| guard source > ${str(lower)}.0 && source < ${str(upper)}.0 else { |
| return nil |
| } |
| guard source == source.rounded(.towardZero) else { |
| return nil |
| } |
| self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value) |
| } |
| |
| % 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)) |
| } |
| |
| // 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( |
| "Division by zero${' in remainder operation' if x.operator == '%' else ''}") |
| } |
| % if signed: |
| if _slowPath( |
| ${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)} |
| ) { |
| _preconditionFailure( |
| "Division results in an overflow${' in remainder operation' if x.operator == '%' else ''}") |
| } |
| % 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 |
| |
| % 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})) { |
| return (partialValue: self, overflow: true) |
| } |
| % if signed: |
| if _slowPath(self == ${Self}.min && other == (-1 as ${Self})) { |
| % partialValue = 'self' if x.operator == '/' else '0' |
| return (partialValue: ${partialValue}, overflow: true) |
| } |
| % end |
| |
| 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( |
| "Division by zero in remainder operation") |
| } |
| % if signed: |
| if _slowPath(${'lhs == %s.min && rhs == (-1 as %s)' % (Self, Self)}) { |
| _preconditionFailure( |
| "Division results in an overflow in remainder operation") |
| } |
| % 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 |
| } |
| |
| % 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) |
| } |
| |
| /// A type that represents the words of this integer. |
| @_fixed_layout |
| public struct Words : RandomAccessCollection { |
| public typealias Indices = Range<Int> |
| public typealias SubSequence = Slice<${Self}.Words> |
| |
| @usableFromInline |
| internal var _value: ${Self} |
| |
| @inlinable |
| public init(_ value: ${Self}) { |
| self._value = value |
| } |
| |
| @inlinable |
| public var count: Int { |
| return (${bits} + ${word_bits} - 1) / ${word_bits} |
| } |
| |
| @inlinable |
| public var startIndex: Int { return 0 } |
| |
| @inlinable |
| public var endIndex: Int { return count } |
| |
| @inlinable |
| 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 } |
| |
| @inlinable |
| 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} |
| _internalInvariant(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)) |
| } |
| |
| /// A type that can represent the absolute value of any possible value of |
| /// this type. |
| 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`. |
| @inlinable |
| 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. |
| @inlinable |
| 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: |
| % # FIXME(integers): uncomment the above after using the right conditional |
| % # compilation block to exclude 64-bit Windows, which does not support |
| % # 128-bit operations |
| fatalError("Operation is not supported") |
| % 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.${z}extOrBitCast_Word_Int64(_v) |
| % end |
| } |
| |
| @_transparent |
| public // @testable |
| var _builtinWordValue: Builtin.Word { |
| % if BuiltinName == 'Int32': |
| return Builtin.${z}extOrBitCast_Int32_Word(_value) |
| % elif BuiltinName == 'Int64': |
| return Builtin.truncOrBitCast_Int64_Word(_value) |
| % end |
| } |
| % end |
| |
| /// 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. |
| @inlinable |
| @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 { |
| /// Hashes the essential components of this value by feeding them into the |
| /// given hasher. |
| /// |
| /// - Parameter hasher: The hasher to use when combining the components |
| /// of this instance. |
| @inlinable |
| public func hash(into hasher: inout Hasher) { |
| hasher._combine(${U}${Self}(_value)) |
| } |
| |
| @inlinable |
| public func _rawHashValue(seed: Int) -> Int { |
| % if bits == 64: |
| return Hasher._hash(seed: seed, UInt64(_value)) |
| % elif bits == word_bits: |
| return Hasher._hash(seed: seed, UInt(_value)) |
| % else: |
| return Hasher._hash( |
| seed: seed, |
| bytes: UInt64(truncatingIfNeeded: ${U}${Self}(_value)), |
| count: ${bits / 8}) |
| % end |
| } |
| } |
| |
| extension ${Self} : _HasCustomAnyHashableRepresentation { |
| // Not @inlinable |
| public func _toCustomAnyHashable() -> AnyHashable? { |
| return AnyHashable(_box: _IntegerAnyHashableBox(self)) |
| } |
| } |
| |
| // 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 |
| |
| @_transparent |
| public static func <= (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return !(rhs < lhs) |
| } |
| |
| @_transparent |
| public static func >= (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return !(lhs < rhs) |
| } |
| |
| @_transparent |
| public static func > (lhs: ${Self}, rhs: ${Self}) -> Bool { |
| return rhs < lhs |
| } |
| } |
| |
| |
| % 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} { |
| _internalInvariant(x >= (0 as ${Self})) |
| return ${Self}(Builtin.assumeNonNegative_${BuiltinName}(x._value)) |
| } |
| % end |
| |
| //===--- end of FIXME(integers) -------------------------------------------===// |
| |
| % end # end of concrete FixedWidthInteger section |
| |
| extension Int { |
| // FIXME(ABI): using Int as the return type is wrong. |
| /// Returns the distance from this value to the given value, expressed as a |
| /// stride. |
| /// |
| /// For two values `x` and `y`, and a distance `n = x.distance(to: y)`, |
| /// `x.advanced(by: n) == y`. |
| /// |
| /// - Parameter other: The value to calculate the distance to. |
| /// - Returns: The distance from this value to `other`. |
| @_transparent |
| public func distance(to other: Int) -> Int { |
| return other - self |
| } |
| |
| // FIXME(ABI): using Int as the parameter type is wrong. |
| /// Returns a value that is offset the specified distance from this value. |
| /// |
| /// Use the `advanced(by:)` method in generic code to offset a value by a |
| /// specified distance. If you're working directly with numeric values, use |
| /// the addition operator (`+`) instead of this method. |
| /// |
| /// For a value `x`, a distance `n`, and a value `y = x.advanced(by: n)`, |
| /// `x.distance(to: y) == n`. |
| /// |
| /// - Parameter n: The distance to advance this value. |
| /// - Returns: A value that is offset from this value by `n`. |
| @_transparent |
| public func advanced(by n: Int) -> Int { |
| return self + n |
| } |
| } |
| |
| // FIXME(integers): switch to using `FixedWidthInteger.unsafeAdding` |
| @_transparent |
| @inlinable |
| 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` |
| @_transparent |
| @inlinable |
| internal func _unsafeMinus(_ lhs: Int, _ rhs: Int) -> Int { |
| #if INTERNAL_CHECKS_ENABLED |
| return lhs - rhs |
| #else |
| return lhs &- rhs |
| #endif |
| } |
| |
| internal struct _IntegerAnyHashableBox< |
| Base: FixedWidthInteger |
| >: _AnyHashableBox { |
| internal let _value: Base |
| |
| internal init(_ value: Base) { |
| self._value = value |
| } |
| |
| internal var _canonicalBox: _AnyHashableBox { |
| // We need to follow NSNumber semantics here; the AnyHashable forms of |
| // integer types holding the same mathematical value should compare equal. |
| // Sign-extend value to a 64-bit integer. This will generate hash conflicts |
| // between, say -1 and UInt.max, but that's fine. |
| if _value < 0 { |
| return _IntegerAnyHashableBox<Int64>(Int64(truncatingIfNeeded: _value)) |
| } |
| return _IntegerAnyHashableBox<UInt64>(UInt64(truncatingIfNeeded: _value)) |
| } |
| |
| internal func _isEqual(to box: _AnyHashableBox) -> Bool? { |
| if Base.self == UInt64.self { |
| guard let box = box as? _IntegerAnyHashableBox<UInt64> else { return nil } |
| return _value == box._value |
| } |
| if Base.self == Int64.self { |
| guard let box = box as? _IntegerAnyHashableBox<Int64> else { return nil } |
| return _value == box._value |
| } |
| _preconditionFailure("self isn't canonical") |
| } |
| |
| internal var _hashValue: Int { |
| _internalInvariant(Base.self == UInt64.self || Base.self == Int64.self, |
| "self isn't canonical") |
| return _value.hashValue |
| } |
| |
| internal func _hash(into hasher: inout Hasher) { |
| _internalInvariant(Base.self == UInt64.self || Base.self == Int64.self, |
| "self isn't canonical") |
| _value.hash(into: &hasher) |
| } |
| |
| internal func _rawHashValue(_seed: Int) -> Int { |
| _internalInvariant(Base.self == UInt64.self || Base.self == Int64.self, |
| "self isn't canonical") |
| return _value._rawHashValue(seed: _seed) |
| } |
| |
| internal var _base: Any { |
| return _value |
| } |
| |
| internal func _unbox<T: Hashable>() -> T? { |
| return _value as? T |
| } |
| |
| internal func _downCastConditional<T>( |
| into result: UnsafeMutablePointer<T> |
| ) -> Bool { |
| guard let value = _value as? T else { return false } |
| result.initialize(to: value) |
| return true |
| } |
| } |
| |
| // ${'Local Variables'}: |
| // eval: (read-only-mode 1) |
| // End: |