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