blob: 73a66b09ba082a33cef685eec949c1760cee16cf [file] [log] [blame]
//===--- 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: