//===--- Integers.swift.gyb -----------------------------------*- swift -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://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 # 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 = { 'Arithmetic' : [ 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='*'), struct(operator='/', name='divided', firstArg='by', llvmName='div', kind='/'), ], 'BinaryInteger' : [ 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', llvmName=lambda s:['lshr','ashr'][s]), struct( operator='&<<', nonMaskingOperator='<<', description='left shift', 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. public typealias IntMax = ${IntMax} /// The largest native unsigned integer type. public typealias UIntMax = ${UIntMax} infix operator &<< : BitwiseShiftPrecedence infix operator &<<= : AssignmentPrecedence infix operator &>> : BitwiseShiftPrecedence infix operator &>>= : AssignmentPrecedence //===----------------------------------------------------------------------===// //===--- Bits for the Stdlib ----------------------------------------------===// //===----------------------------------------------------------------------===// // FIXME(integers): This should go in the stdlib separately, probably. extension ExpressibleByIntegerLiteral where Self : _ExpressibleByBuiltinIntegerLiteral { @_transparent public init(integerLiteral value: Self) { self = value } } //===----------------------------------------------------------------------===// //===--- Documentation Helpers --------------------------------------------===// //===----------------------------------------------------------------------===// %{ def operationComment(operator): comments = { '+': """\ /// Returns the sum of this value and the given value. /// /// This method serves as the basis for the addition operator (`+`). For /// example: /// /// let x = 15 /// print(x.adding(7)) /// // Prints "22" /// print(x + 7) /// // Prints "22" /// /// - Parameter rhs: The value to add to this value. /// - Returns: The sum of this value and `rhs`. /// /// - SeeAlso: `add(_:)` """, '-': """\ /// Returns the difference of this value and the given value. /// /// This method serves as the basis for the subtraction operator (`-`). For /// example: /// /// let x = 15 /// print(x.subtracting(7)) /// // Prints "8" /// print(x - 7) /// // Prints "8" /// /// - Parameter rhs: The value to subtract from this value. /// - Returns: The difference of this value and `rhs`. /// /// - SeeAlso: `subtract(_:)` """, '*': """\ /// Returns the product of this value and the given value. /// /// This method serves as the basis for the multiplication operator (`*`). /// For example: /// /// let x = 15 /// print(x.multiplied(by: 7)) /// // Prints "105" /// print(x * 7) /// // Prints "105" /// /// - Parameter rhs: The value to multiply by this value. /// - Returns: The product of this value and `rhs`. /// /// - SeeAlso: `multiply(by:)` """, '/': """\ /// Returns the quotient of dividing this value by the given value. /// /// This method serves as the basis for the division operator (`/`). For /// example: /// /// let x = 15 /// print(x.divided(by: 7)) /// // Prints "2" /// print(x / 7) /// // Prints "2" /// /// - Parameter rhs: The value to divide this value by. `rhs` must not be /// zero. /// - Returns: The quotient of dividing this value by `rhs`. /// /// - SeeAlso: `divide(by:)` """, '%': """\ /// Returns the remainder of dividing this value by the given value. /// /// This method serves as the basis for the remainder operator (`%`). For /// example: /// /// let x = 15 /// print(x.remainder(dividingBy: 7)) /// // Prints "1" /// print(x % 7) /// // Prints "1" /// /// - Parameter rhs: The value to divide this value by. `rhs` must not be /// zero. /// - Returns: The remainder of dividing this value by `rhs`. /// /// - SeeAlso: `formRemainder(dividingBy:)` """, '&': """\ /// Returns the result of performing a bitwise AND operation on this value /// and the given value. /// /// 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.bitwiseAnd(y) // 0b00000100 /// /// This method serves as the basis for the bitwise AND operator (`&`). /// /// - Parameter rhs: The value to perform the bitwise AND with this value. /// - Returns: A new value with each bit set to `1` where this value and /// `rhs` both have bits set to `1`. """, '|': """\ /// Returns the result of performing a bitwise OR operation on this value and /// the given value. /// /// 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.bitwiseOr(y) // 0b00001111 /// /// This method serves as the basis for the bitwise OR operator (`|`). /// /// - Parameter rhs: The value to perform the bitwise OR with this value. /// - Returns: A new value with each bit set to `1` where this value, `rhs`, /// or both have bits set to `1`. """, '^': """\ /// Returns the result of performing a bitwise XOR operation on this value /// and the given value. /// /// 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.bitwiseXor(y) // 0b00001011 /// /// This method serves as the basis for the bitwise XOR operator (`^`). /// /// - Parameter rhs: The value to perform the bitwise XOR with this value. /// - Returns: A new value with each bit set to `1` where either this value /// or `rhs`, but not both, have bits set to `1`. """, '&>>': """\ /// Returns the result of shifting this value's binary representation the /// specified number of digits to the right. /// /// In a *masking shift*, the bit pattern of the value passed as `rhs` is /// masked to produce a value between zero and the bit width of `lhs`. The /// shift is performed using this masked value. Masking shifts require more /// care to use correctly than a traditional bit shift, but are likely to be /// more efficient when used with shift amounts that are not compile-time /// constants. On most architectures, a masking shift compiles down to a /// single instruction. /// /// For example, if you pass `2` to the `maskingShiftRight(_:)` method on an /// 8-bit, unsigned integer, the shift amount requires no masking. /// /// let x: UInt8 = 30 // 0b00011110 /// let y = x.maskingShiftRight(2) /// // y == 7 // 0b00000111 /// /// However, if you pass `11` as `rhs`, the method first bitmasks `rhs` to /// `3`, and then uses that masked value as the number of bits to shift `x`. /// /// let z = x.maskingShiftRight(11) /// // z == 3 // 0b00000011 /// /// This method serves as the basis for the masking right shift operator /// (`&>>`). /// /// let y3 = x &>> 11 /// // y3 == 3 /// /// Relationship to the Right Shift Operator /// ---------------------------------------- /// /// The `maskingShiftRight(_:)` method handles attempted overshifts and /// undershifts differently from the right shift operator (`>>`). When the /// value passed as `rhs` in a masking shift is within the range /// `0...> 2 /// // y2 == 7 // 0b00000111 /// /// The right shift operator does not mask its right-hand-side argument, so /// passing `11` as `rhs` shifts all the bits of `x` to zero. /// /// let z1 = x.maskingShiftRight(11) /// // z1 == 240 // 0b00000011 /// let z2 = x >> 11 /// // z2 == 0 // 0b00000000 /// /// - Parameter rhs: The number of bits to shift this value to the right. If /// `rhs` is outside the range `0..>`, `>>`, `maskingShiftLeft(_:)` """, '&<<': """\ /// Returns the result of shifting this value's binary representation the /// specified number of digits to the left. /// /// In a *masking shift*, the bit pattern of the value passed as `rhs` is /// masked to produce a value between zero and the bit width of `lhs`. The /// shift is performed using this masked value. Masking shifts require more /// care to use correctly than a traditional bit shift, but are likely to be /// more efficient when used with shift amounts that are not compile-time /// constants. On most architectures, a masking shift compiles down to a /// single instruction. /// /// For example, if you pass `2` to the `maskingShiftLeft(_:)` method on an /// 8-bit, unsigned integer, the shift amount requires no masking. /// /// let x: UInt8 = 30 // 0b00011110 /// let y = x.maskingShiftLeft(2) /// // y == 120 // 0b01111000 /// /// However, if you pass `11` as `rhs`, the method first bitmasks `rhs` to /// `3`, and then uses that masked value as the number of bits to shift `x`. /// /// let z = x.maskingShiftLeft(11) /// // z == 240 // 0b11110000 /// /// This method serves as the basis for the masking left shift operator /// (`&<<`). /// /// let y3 = x &<< 11 /// // y3 == 240 /// /// Relationship to the Left Shift Operator /// --------------------------------------- /// /// The `maskingShiftLeft(_:)` method handles attempted overshifts and /// undershifts differently from the left shift operator (`<<`). When the /// value passed as `rhs` in a masking shift is within the range /// `0...>': """\ /// 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 `&>>` operator performs a *masking shift*, where the value passed as /// `rhs` is masked to produce a value in the range `0..> 2 /// // y == 7 // 0b00000111 /// /// However, if you use `11` as `rhs`, the operation first bitmasks `rhs` to /// `3`, and then uses that masked value as the number of bits to shift `x`. /// /// let z = x &>> 11 /// // 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..>`, `&<<` """, '&<<': """\ /// 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 `&<<` operator performs a *masking shift*, where the value used as /// `rhs` is masked to produce a value in the range `0..>` """, '>>': """\ /// 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. /// /// - SeeAlso: `<<` """, '<<': """\ /// 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. /// /// - SeeAlso: `>>` """, } return comments[operator] }% //===----------------------------------------------------------------------===// //===--- Arithmetic -------------------------------------------------------===// //===----------------------------------------------------------------------===// /// A type that supports binary arithmetic operators, such as `+`, `-`, and /// `*`, and their mutating counterparts. /// /// The `Arithmetic` 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 `Arithmetic` protocol as a generic constraint. /// /// The following example declares a method that calculates the total of any /// sequence with `Arithmetic` elements. /// /// extension Sequence where Iterator.Element: Arithmetic { /// func sum() -> Iterator.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 Arithmetic Protocol /// ===================================== /// /// To add `Arithmetic` protocol conformance to your own custom type, implement /// the required mutating methods. Extensions to `Arithmetic` provide default /// implementations for the protocol's nonmutating methods based on the /// mutating variants. public protocol Arithmetic : 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 floating-point value to convert to an integer. init?(exactly source: T) // FIXME(ABI)#44 (Recursive Protocol Constraints): should be just Arithmetic /// A type that can represent the absolute value of any possible value of the /// conforming type. associatedtype Magnitude : Equatable, ExpressibleByIntegerLiteral /// The magnitude of this value. /// /// For any numeric value `x`, `x.magnitude` is the absolute value of `x`. /// You can use the `magnitude` property in operations that are simpler to /// implement in terms of unsigned values, such as printing the value of an /// integer, which is just printing a '-' character in front of an absolute /// value. /// /// let x = -200 /// // x.magnitude == 200 /// /// The global `abs(_:)` function provides more familiar syntax when you need /// to find an absolute value. In addition, because `abs(_:)` always returns /// a value of the same type, even in a generic context, using the function /// instead of the `magnitude` property is encouraged. /// /// - SeeAlso: `abs(_:)` var magnitude: Magnitude { get } % for x in binaryArithmetic['Arithmetic']: // defaulted using an in-place counterpart, but can be used as an // optimization hook ${operatorComment(x.operator)} // FIXME(integers): revisit the doc comment static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self // implementation hook ${mutatingOperationComment(x.operator)} // FIXME(integers): revisit the doc comment static func ${x.operator}=(_ lhs: inout Self, rhs: Self) % end } extension Arithmetic { @_transparent public init() { self = 0 } } % for Protocol in ['Arithmetic', 'BinaryInteger', 'FloatingPoint']: % # Explicitly providing these operations for BinaryInteger and FloatingPoint % # protocols because Strideable conformance creates ambiguity if the % # operationsare only defined for Arithmetic extension ${Protocol} { % if Protocol in ['Arithmetic', 'FloatingPoint']: % ops = binaryArithmetic['Arithmetic'] % else: % ops = binaryArithmetic['Arithmetic'] + binaryArithmetic['BinaryInteger'] % for x in ops: % callLabel = x.firstArg + ': ' if not x.firstArg == '_' else '' ${operationComment(x.operator)} // FIXME(integers): revisit the doc comment @_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 `SignedArithmetic` protocol extends the operations defined by the /// `Arithmetic` protocol to include a value's additive inverse. /// /// Conforming to the SignedArithmetic Protocol /// =========================================== /// /// Because the `SignedArithmetic` 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 SignedArithmetic : Arithmetic { // FIXME(integers): turn negate() into a static prefix func -(_:) /// Returns the additive inverse of this value. /// /// This method serves as the basis for the unary minus operator (prefixed /// `-`). For example: /// /// let x = 21 /// let y = x.negated() /// // y == -21 /// /// - Returns: The additive inverse of this value. /// /// - SeeAlso: `negate()` func negated() -> 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 /// /// - SeeAlso: `negated()` mutating func negate() } extension SignedArithmetic { @_transparent public func negated() -> Self { var result = self result.negate() return result } @_transparent public mutating func negate() { self = Self() - self } } /// Returns the absolute value of the given number. /// /// - Parameter x: A signed number. /// - Returns: The absolute value of `x`. @_transparent public func abs(_ x: T) -> T where T.Magnitude == T { return x.magnitude } /* /// Returns the absolute value of the given number. /// /// The absolute value of `x` must be representable in the same type. In /// particular, the absolute value of a signed, fixed-width integer type's /// minimum cannot be represented. /// /// let x = Int8.min /// // x == -128 /// let y = abs(x) /// // Overflow error /// /// - Parameter x: A signed number. /// - Returns: The absolute value of `x`. public func abs(_ x: T) -> T { return x < 0 ? x.negated() : x } */ //===----------------------------------------------------------------------===// //===--- Arithmetic operators ---------------------------------------------===// //===----------------------------------------------------------------------===// extension SignedArithmetic { @_transparent public static prefix func - (x: Self) -> Self { return x.negated() } } extension Arithmetic { @_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(127) /// /// 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(extendingOrTruncating:)` 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(extendingOrTruncating: q) // truncate 'q' to fit in 8 bits /// // r == 82 /// // == 0b01010010 /// /// let s = Int16(extendingOrTruncating: s) // extend 'r' to fill 16 bits /// // s == 82 /// // == 0b00000000_01010010 /// /// Any padding is performed by *sign-extending* the passed value. When /// nonnegative integers are extended, the result is padded with zeroes. When /// negative integers are extended, the result is padded with ones. This /// example shows several extending conversions of a negative value---note /// that negative values are sign-extended even when converting to an unsigned /// type. /// /// let t: Int8 = -100 /// // t == -100 /// // t's binary representation == 0b10011100 /// /// let u = UInt8(extendingOrTruncating: t) /// // u == 156 /// // u's binary representation == 0b10011100 /// /// let v = Int16(extendingOrTruncating: t) /// // v == -100 /// // v's binary representation == 0b11111111_10011100 /// /// let w = UInt16(extendingOrTruncating: 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 : Comparable, Hashable, Arithmetic, CustomStringConvertible, Strideable { /// 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?(exactly source: T) /// Creates an integer from the given floating-point value, truncating any /// fractional part. /// /// Truncating the fractional part of `source` is equivalent to rounding /// 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 truncation, 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 truncation. init(_ source: T) /// Creates an 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(_ 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(extendingOrTruncating: 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(extendingOrTruncating: 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(extendingOrTruncating: w) /// // x == -21 /// // 'x' has a binary representation of 11111111_11101011 /// let y = UInt16(extendingOrTruncating: w) /// // y == 65515 /// // 'y' has a binary representation of 11111111_11101011 /// /// - Parameter source: An integer to convert to this type. init(extendingOrTruncating 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(clamping source: T) /// Returns the n-th word, counting from the least significant to most /// significant, of this value's binary representation. /// /// The `word(at:)` method returns negative values in two's complement /// representation, regardless of a type's underlying implementation. If `n` /// is greater than the number of words in this value's current /// representation, the result is `0` for positive numbers and `~0` for /// negative numbers. /// /// - Parameter n: The word to return, counting from the least significant to /// most significant. `n` must be greater than or equal to zero. /// - Returns: An word-sized, unsigned integer with the bit pattern of the /// n-th word of this value. func word(at n: Int) -> UInt /// The number of bits in the current binary representation of this value. /// /// This property is a constant for instances of fixed-width integer /// types. var bitWidth : Int { get } /// The number of bits required to represent this value in a signed type /// using two's complement representation. /// /// The value of this property is always at least 1. var minimumSignedRepresentationBitWidth: Int { get } % for x in binaryArithmetic['BinaryInteger']: // defaulted using an in-place counterpart, but can be used as an // optimization hook ${operatorComment(x.operator)} // FIXME(integers): revisit the doc comment static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self // implementation hook ${mutatingOperationComment(x.operator)} // FIXME(integers): revisit the doc commenl static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self) % 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 { public init?(exactly source: T) { // FIXME(integers): implement fatalError() return nil } @_transparent public func signum() -> Self { if self < 0 { return -1 } if self > 0 { return 1 } return 0 } /// The number of words used for the current binary representation of this /// value. /// /// This property is a constant for instances of fixed-width integer types. @_transparent public var countRepresentedWords: Int { return (self.bitWidth + ${word_bits} - 1) / ${word_bits} } public func quotientAndRemainder(dividingBy rhs: Self) -> (quotient: Self, remainder: Self) { return (self / rhs, self % rhs) } } // Strideable conformance extension BinaryInteger { // FIXME(ABI): using Int as the return type is wrong. @_transparent public func distance(to other: Self) -> Int { let distance = other - self if let result = Int(exactly: distance) { return result } _preconditionFailure("Distance is not representable in Int") } // FIXME(ABI): using Int as the parameter type is wrong. @_transparent public func advanced(by n: Int) -> Self { var advanced: Int = Int(self) advanced += n if let result = Self(exactly: advanced) { return result } _preconditionFailure("The result of advanced(by:) is not representable") } } //===----------------------------------------------------------------------===// //===--- Homogeneous comparison -------------------------------------------===// //===----------------------------------------------------------------------===// // FIXME(integers): without this overload enums don't compile with the // following error: "error: no overload of '==' for Int" // /// Returns a Boolean value indicating whether the two given values are equal. /// /// - Parameters: /// - lhs: An integer to compare. /// - rhs: Another integer to compare. @_transparent public func == (lhs: Int, rhs: Int) -> Bool { return lhs.isEqual(to: rhs) } //===----------------------------------------------------------------------===// //===--- 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. @_transparent public static func == < Other : BinaryInteger >(lhs: Self, rhs: Other) -> Bool { return (lhs > 0) == (rhs > 0) && Self(extendingOrTruncating: rhs) == lhs && Other(extendingOrTruncating: lhs) == rhs } /// Returns a Boolean value indicating whether the two given values are not /// equal. /// /// You can check the inequality of instances of any `BinaryInteger` types /// using the not-equal-to operator (`!=`). For example, you can test /// whether the first `UInt8` value in a string's UTF-8 encoding is not /// equal to the first `UInt32` value in its Unicode scalar view: /// /// let gameName = "Red Light, Green Light" /// if let firstUTF8 = gameName.utf8.first, /// let firstScalar = gameName.unicodeScalars.first?.value { /// print("First code values are different: \(firstUTF8 != firstScalar)") /// } /// // Prints "First code values are different: false" /// /// - Parameters: /// - lhs: An integer to compare. /// - rhs: Another integer to compare. @_transparent public static func != < Other : BinaryInteger >(lhs: Self, rhs: Other) -> Bool { return !(lhs == rhs) } /// Returns a Boolean value indicating whether the value of the first /// argument is less than that of the second argument. /// /// You can compare instances of any `BinaryInteger` types using the /// less-than operator (`<`), even if the two instances are of different /// types. /// /// - Parameters: /// - lhs: An integer to compare. /// - rhs: Another integer to compare. @_transparent public static func < (lhs: Self, rhs: Other) -> Bool { let lhsSign = lhs < (0 as Self) ? -1 : lhs > (0 as Self) ? 1 : 0 let rhsSign = rhs < (0 as Other) ? -1 : rhs > (0 as Other) ? 1 : 0 if lhsSign != rhsSign { return lhsSign < rhsSign } // if we get here, lhs and rhs have the same sign. If they're // negative, then T and U are both signed types, and one of them can // represent values of the other type. Otherwise, lhs and rhs are // positive, and one of T, U may be signed and the other unsigned. // In this case, we can conceptually subtract 1 from the bitWidth of // any signed type, and either the resulting bitWidths are the same // or one can represent every value of the other. let rT = Self(extendingOrTruncating: rhs) // Can we round-trip rhs through T? if Other(extendingOrTruncating: rT) == rhs { return lhs < rT } return Other(extendingOrTruncating: lhs) < rhs } /// Returns a Boolean value indicating whether the value of the first /// argument is less than or equal to that of the second argument. /// /// You can compare instances of any `BinaryInteger` types using the /// less-than-or-equal-to operator (`<=`), even if the two instances are of /// different types. /// /// - Parameters: /// - lhs: An integer to compare. /// - rhs: Another integer to compare. @_transparent //@inine(__always) public static func <= (lhs: Self, rhs: Other) -> Bool { return !(rhs < lhs) } /// Returns a Boolean value indicating whether the value of the first /// argument is greater than or equal to that of the second argument. /// /// You can compare instances of any `BinaryInteger` types using the /// greater-than-or-equal-to operator (`>=`), even if the two instances are /// of different types. /// /// - Parameters: /// - lhs: An integer to compare. /// - rhs: Another integer to compare. @_transparent //@inline(__always) public static func >= (lhs: Self, rhs: Other) -> Bool { return !(lhs < rhs) } /// Returns a Boolean value indicating whether the value of the first /// argument is greater than that of the second argument. /// /// You can compare instances of any `BinaryInteger` types using the /// greater-than operator (`>`), even if the two instances are of different /// types. /// /// - Parameters: /// - lhs: An integer to compare. /// - rhs: Another integer to compare. @_transparent //@inline(__always) public static func > (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 infinte // recursion. // // (T, T) -> Bool // (T, U) -> Bool // // so we define: // // (T, T) -> Bool // //===----------------------------------------------------------------------===// extension BinaryInteger { @_transparent public static func != (lhs: Self, rhs: Self) -> Bool { return !(lhs == rhs) } @inline(__always) public static func <= (lhs: Self, rhs: Self) -> Bool { return !(rhs < lhs) } @inline(__always) public static func >= (lhs: Self, rhs: Self) -> Bool { return !(lhs < rhs) } @inline(__always) public static func > (lhs: Self, rhs: Self) -> Bool { return rhs < lhs } } //===----------------------------------------------------------------------===// //===--- FixedWidthInteger ------------------------------------------------===// //===----------------------------------------------------------------------===// /// An indicator of whether an arithmetic operation overflowed. /// /// Some arithmetic operations on fixed-width integers return an /// `ArithmeticOverflow` instance to indicate whether an overflow has /// occurred. For example, adding `UInt8.max` to itself results in a value that /// can't be represented by an `UInt8` instance without overflowing. /// /// let x = UInt8.max /// // x == 255 /// let (y, overflow) = x.addingWithOverflow(x) /// // y == 254 /// // overflow == ArithmeticOverflow.overflow public enum ArithmeticOverflow { @_transparent public init(_ overflow: Bool) { self = overflow ? .overflow : .none } /// An indication that no overflow occured in the operation. case none /// An indication that an overflow did occur in the operation. case overflow } /// An integer type that uses a fixed size for every instance. /// /// The `FixedWidthInteger` protocol adds binary bitwise operations, bit /// 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 Swift.stride(from: 0, to: Self.bitWidth, by: 8) { /// let wordValue = UInt8(extendingOrTruncating: self >> i) /// let word = String(wordValue, radix: 2) /// let padding = String(repeating: "0", /// count: 8 - word.characters.count) /// result.append(padding + word) /// } /// 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 the generic `squared` function, which accepts an /// instance `x` of any fixed-width integer type. The function uses the /// `multipliedWithOverflow(by:)` method to multiply `x` by itself and check /// whether the result is too large to represent in the same type. /// /// func squared(_ x: T) -> T? { /// let (result, overflow) = x.multipliedWithOverflow(by: x) /// guard overflow == .none else { /// return nil /// } /// return result /// } /// /// let (x, y): (Int8, Int8) = (10, 100) /// print(squared(x)) /// // Prints "Optional(100)" /// 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 `WithOverflow` 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 // FIXME(integers): remove this along with the BitwiseOperations protocol , BitwiseOperations { /// 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 value. /// /// 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['Arithmetic']: ${overflowOperationComment(x.operator)} func ${x.name}WithOverflow( ${x.firstArg} rhs: Self ) -> (partialValue: Self, overflow: ArithmeticOverflow) % end % for x in binaryBitwise + maskingShifts: ${operationComment(x.operator)} // FIXME(integers): revisit the doc comment static func ${x.operator}(_ lhs: Self, _ rhs: Self) -> Self % end /// Returns a tuple containing the high and low parts of the result of /// multiplying its arguments. /// /// Use this method to calculate the full result of a product that would /// otherwise overflow. Unlike traditional truncating multiplication, the /// `doubleWidthMultiply(_:_:)` method returns both the `high` and `low` /// parts of the product of `lhs` and `rhs`. 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 = UInt8.doubleWidthMultiply(100, 20) /// // 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` components of the `result` tuple /// 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 /// /// - Parameters: /// - lhs: A value to multiply. /// - rhs: Another value to multiply. /// - Returns: A tuple containing the high and low parts of the result of /// multiplying `lhs` and `rhs`. /// /// - SeeAlso: `multipliedWithOverflow(by:)` static func doubleWidthMultiply(_ lhs: Self, _ rhs: Self) -> (high: Self, low: Magnitude) /// Returns a tuple containing the quotient and remainder of dividing the /// first argument by the second. /// /// The resulting quotient must be representable within the bounds of the /// type. If the quotient of dividing `lhs` by `rhs` is too large to /// represent in the type, a runtime error may occur. /// /// - Parameters: /// - lhs: A tuple containing the high and low parts of a double-width /// integer. The `high` component of the tuple carries the sign, if the /// type is signed. /// - rhs: The integer to divide into `lhs`. /// - Returns: A tuple containing the quotient and remainder of `lhs` divided /// by `rhs`. static func doubleWidthDivide( _ lhs: (high: Self, low: Magnitude), _ rhs: Self) -> (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.popcount == 5 var popcount: 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.leadingZeros == 3 var leadingZeros: Int { get } } // FIXME(integers): this conformance should be removed along with the // BitwiseOperations protocol extension FixedWidthInteger { /// An instance where every bit is set to zero. public static var allZeros: Self { return 0 } } //===----------------------------------------------------------------------===// //===--- Operators on FixedWidthInteger -----------------------------------===// //===----------------------------------------------------------------------===// extension FixedWidthInteger { @inline(__always) public static prefix func ~ (x: Self) -> Self { return 0 &- x &- 1 } % for x in maskingShifts: @_transparent public static func ${x.operator}= (lhs: inout Self, rhs: Self) { lhs = lhs ${x.operator} rhs } ${operatorComment(x.operator)} public static func ${x.operator} < Other : BinaryInteger >(lhs: Self, rhs: Other) -> Self { return lhs ${x.operator} Self(extendingOrTruncating: rhs) } @_transparent public static func ${x.operator}= < Other : BinaryInteger >(lhs: inout Self, rhs: Other) { lhs = lhs ${x.operator} rhs } ${operatorComment(x.nonMaskingOperator)} @_transparent public static func ${x.nonMaskingOperator} < Other : BinaryInteger >(lhs: Self, rhs: Other) -> Self { let shift = rhs < -Self.bitWidth ? -Self.bitWidth : rhs > Self.bitWidth ? Self.bitWidth : Int(rhs) return lhs ${x.nonMaskingOperator} shift } //===----------------------------------------------------------------------===// //=== "Smart ${x.description}", supporting overshifts and negative shifts -===// //===----------------------------------------------------------------------===// ${operatorComment(x.nonMaskingOperator)} @_transparent public static func ${x.nonMaskingOperator} (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(extendingOrTruncating: rhs) } return overshift${'LR'['R' in x.nonMaskingOperator]} } if _slowPath(rhs <= -Self.bitWidth) { return overshift${'RL'['R' in x.nonMaskingOperator]} } return lhs ${x.operator.translate(maketrans('<>', '><'))} -rhs } @_transparent public static func ${x.nonMaskingOperator}= (lhs: inout Self, rhs: Self) { lhs = lhs ${x.nonMaskingOperator} rhs } @_transparent public static func ${x.nonMaskingOperator}= < Other : BinaryInteger >(lhs: inout Self, rhs: Other) { lhs = lhs ${x.nonMaskingOperator} rhs } % end # maskingShifts } extension FixedWidthInteger { public init(clamping source: Other) { if _slowPath(source < Self.min) { self = Self.min } else if _slowPath(source > Self.max) { self = Self.max } else { self = Self(extendingOrTruncating: source) } } % for x in binaryArithmetic['Arithmetic']: % callLabel = x.firstArg + ': ' if not x.firstArg == '_' else '' // FIXME(integers): penging optimizer work on handling the case where the // boolean value is wrapped into a two-case enum and then immediately // unwrapped. // Uncomment this block and remove the corresponding one from the concrete // types once the optimizer is ready. #if false @_transparent public static func ${x.operator}=(_ lhs: inout Self, _ rhs: Self) { let (result, overflow) = lhs.${x.name}WithOverflow(${callLabel}rhs) _precondition(overflow == .none, "Overflow in ${x.operator}=") lhs = result } #endif // end of FIXME(integers) ${unsafeOperationComment(x.operator)} @_transparent public func unsafe${capitalize(x.name)}(${x.firstArg} other: Self) -> Self { let (result, overflow) = self.${x.name}WithOverflow(${callLabel}other) if (overflow != .none) { if (_isDebugAssertConfiguration()) { _preconditionFailure("overflow in unsafe${capitalize(x.name)}") } else { Builtin.conditionallyUnreachable() } } return result } % end @_transparent public init(extendingOrTruncating source: T) { if Self.bitWidth <= ${word_bits} { self = Self.init(_truncatingBits: source.word(at: 0)) } else { var result: Self = source < (0 as T) ? ~0 : 0 // start with the most significant word var n = source.countRepresentedWords while n >= 0 { // masking is OK here because this we have already ensured // that Self.bitWidth > ${word_bits}. Not masking results in // infinite recursion. result &<<= ${word_bits} result |= Self(_truncatingBits: source.word(at: n)) n -= 1 } self = result } } @_transparent public // transparent static var _highBitIndex: Self { return Self.init(_truncatingBits: UInt(Self.bitWidth._value) &- 1) } public static func doubleWidthDivide( _ lhs: (high: Self, low: Magnitude), _ rhs: Self) -> (quotient: Self, remainder: Self) { fatalError() } % for x in [op for ops in binaryArithmetic.values() for op in ops]: % callLabel = x.firstArg + ': ' if not x.firstArg == '_' else '' % if x.kind != '/': ${operatorComment('&' + x.operator)} public static func &${x.operator} (lhs: Self, rhs: Self) -> Self { return lhs.${x.name}WithOverflow(${callLabel}rhs).partialValue } % end % end } //===----------------------------------------------------------------------===// //===--- UnsignedInteger --------------------------------------------------===// //===----------------------------------------------------------------------===// /// An integer type that can represent only nonnegative values. public protocol UnsignedInteger : BinaryInteger { associatedtype Magnitude : 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. /// /// - SeeAlso: `abs(_:)` @_transparent public var magnitude: Self { return self } @_transparent public static var isSigned: Bool { return false } public var description: String { if self == 0 { return "0" } let ascii0 = 48 var buf: [UnicodeScalar] = [] var x = self repeat { let r = x % 10 x /= 10 buf.append( UnicodeScalar( ascii0 + Int(UInt(extendingOrTruncating: r)._value))!) } while x != 0 return String(buf.reversed().lazy.map { Character($0) }) } } extension UnsignedInteger where Self : FixedWidthInteger { @_transparent public init(_ source: T) { _precondition(source >= 0, "negative value is not representable") // FIXME(integers): uncomment the check when the ctlz instruction gets the // necessary optimizations. /*let requiredBits = source.minimumSignedRepresentationBitWidth - 1*/ /*_precondition(requiredBits <= Self.bitWidth,*/ /*"Not enough bits to represent an unsigned value")*/ self.init(extendingOrTruncating: source) } @_transparent public init?(exactly source: T) { _precondition(source >= 0, "Negative value is not representable") let requiredBits = source.minimumSignedRepresentationBitWidth - 1 if requiredBits > Self.bitWidth { return nil } self.init(extendingOrTruncating: source) } @_transparent public static var max: Self { return ~0 } @_transparent public static var min: Self { return 0 } } //===----------------------------------------------------------------------===// //===--- SignedInteger ----------------------------------------------------===// //===----------------------------------------------------------------------===// /// An integer type that can represent both positive and negative values. public protocol SignedInteger : BinaryInteger, SignedArithmetic { associatedtype Magnitude : BinaryInteger } extension SignedInteger { public var description: String { let base = String(describing: magnitude) return self < 0 ? "-" + base : base } @_transparent public static var isSigned: Bool { return true } } extension SignedInteger where Self : FixedWidthInteger { @_transparent public init(_ source: T) { // FIXME(integers): uncomment the check when the ctlz instruction gets the // necessary optimizations. /*let requiredBits = source.minimumSignedRepresentationBitWidth*/ /*_precondition(*/ /*requiredBits <= Self.bitWidth,*/ /*"Not enough bits to represent a signed value")*/ self.init(extendingOrTruncating: source) } @_transparent public init?(exactly source: T) { let requiredBits = source.minimumSignedRepresentationBitWidth if requiredBits > Self.bitWidth { return nil } self.init(extendingOrTruncating: source) } @_transparent public static var max: Self { return ~min } @_transparent public static var min: Self { return -1 &<< 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' @_fixed_layout public struct ${Self} : FixedWidthInteger, ${Unsigned}Integer, _ExpressibleByBuiltinIntegerLiteral { @_transparent public init(_builtinIntegerLiteral x: _MaxBuiltinIntegerType) { _value = Builtin.truncOrBitCast_${IntLiteral}_Int${bits}(x) Builtin.condfail( Builtin.cmp_ne_${IntLiteral}( Builtin.${z}extOrBitCast_Int${bits}_${IntLiteral}( _value), x)) } /// Creates a new instance with the same memory representation as the given /// value. /// /// This initializer does not perform any range or overflow checking. The the /// resulting instance may not have the same numeric value as /// `bitPattern`---it is only guaranteed to use the same pattern of bits in /// its binary representation. /// /// - Parameter x: A value to use as the source of the new instance's binary /// representation. @_transparent public init(bitPattern x: ${OtherSelf}) { _value = x._value } % 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 public init(_ source: ${FloatType}) { _precondition(source.isFinite, "") // FIXME(integers): message _precondition(source > ${str(lower)}.0, "") // FIXME(integers): message _precondition(source < ${str(upper)}.0, "") // FIXME(integers): message self._value = Builtin.fpto${u}i_FPIEEE${FloatBits}_${BuiltinName}(source._value) } % if FloatType == 'Float80': #endif % end % end // FIXME(integers): workaround for a problem where enums don't compile without // `== (Int, Int)` // % if Self in ['Int']: @_transparent public func isEqual(to other: ${Self}) -> Bool { return Bool(Builtin.cmp_eq_Int${bits}(_value, other._value)) } % else: @_transparent public static func == (lhs: ${Self}, rhs: ${Self}) -> Bool { return Bool(Builtin.cmp_eq_Int${bits}(lhs._value, rhs._value)) } % end @_transparent public static func < (lhs: ${Self}, rhs: ${Self}) -> Bool { return Bool(Builtin.cmp_${u}lt_Int${bits}(lhs._value, rhs._value)) } // FIXME(integers): penging optimizer work on handling the case where the // boolean value is wrapped into a two-case enum and then immediately // unwrapped. // See corresponding definitions in the FixedWidthInteger extension. % for x in binaryArithmetic['Arithmetic']: @_transparent public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) { let (result, overflow) = % if x.kind == '/': (Builtin.${u}${x.llvmName}_Int${bits}(lhs._value, rhs._value), false._value) % else: // !!! This implementation is incorrect for division and modulo, as it does // not catch division by zero. Builtin.${u}${x.llvmName}_with_overflow_Int${bits}( lhs._value, rhs._value, true._value) % end Builtin.condfail(overflow) lhs = ${Self}(result) } % end // end of FIXME(integers) % for x in [op for ops in binaryArithmetic.values() for op in ops]: @_transparent public func ${x.name}WithOverflow( ${x.firstArg} other: ${Self} ) -> (partialValue: ${Self}, overflow: ArithmeticOverflow) { % if x.kind == '/': // No LLVM primitives for checking overflow of division // operations, so we check manually. if _slowPath( other == 0 ${'|| self == %s.min && other == -1' % Self if signed else ''} ) { return (partialValue: self, overflow: .overflow) } 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: ArithmeticOverflow(Bool(overflow))) } % end @_transparent public static func %=(_ lhs: inout ${Self}, _ rhs: ${Self}) { if _slowPath(rhs == 0) { preconditionFailure("Remainder of division by zero") } let (newStorage, _) = ( Builtin.${u}rem_Int${bits}(lhs._value, rhs._value), false._value) lhs = ${Self}(newStorage) } @_transparent public init(_ _value: Builtin.Int${bits}) { self._value = _value } // FIXME(integers): in order to remove this, the simd.swift.gyb should be // updated @_transparent public init(_bits: Builtin.Int${bits}) { self._value = _bits } % for x in binaryBitwise: @_transparent public static func ${x.operator}(_ lhs: ${Self}, _ rhs: ${Self}) -> ${Self} { return ${Self}( Builtin.${x.llvmName}_Int${bits}(lhs._value, rhs._value)) } @_transparent public static func ${x.operator}=(_ lhs: inout ${Self}, _ rhs: ${Self}) { lhs = lhs ${x.operator} rhs } % end % for x in maskingShifts: @_transparent public static func ${x.operator}(_ lhs: ${Self}, _ rhs: ${Self}) -> ${Self} { let rhs_ = rhs & ${Self}._highBitIndex return ${Self}( Builtin.${x.llvmName(signed)}_Int${bits}(lhs._value, rhs_._value)) } % end @_transparent public static var bitWidth : Int { return ${bits} } public var bitWidth: Int { return ${bits} } @_transparent public var minimumSignedRepresentationBitWidth: Int { % if signed: let x = self < 0 ? ~self : self return (x == 0) ? 1 : (${Self}.bitWidth - x.leadingZeros + 1) % else: return (self == 0) ? 1 : (${Self}.bitWidth - self.leadingZeros + 1) % end } @_transparent public var leadingZeros: Int { return Int( ${Self}( Builtin.int_ctlz_Int${bits}(self._value, false._value) )._lowUWord._value) } @_transparent public var popcount: Int { return Int( ${Self}( Builtin.int_ctpop_Int${bits}(self._value) )._lowUWord._value) } @_transparent public func word(at n: Int) -> UInt { _precondition(n >= 0, "Negative word index") if _fastPath(n < countRepresentedWords) { let shift = UInt(n._value) &* ${word_bits} let bitWidth = UInt(self.bitWidth._value) _sanityCheck(shift < bitWidth) return (self &>> ${Self}(_truncatingBits: shift))._lowUWord } % if signed: return self < 0 ? ~0 : 0 % else: return 0 % end } @_transparent public // transparent var _lowUWord: UInt { % truncOrExt = z + 'ext' if bits <= word_bits else 'trunc' return UInt( Builtin.${truncOrExt}OrBitCast_Int${bits}_Int${word_bits}(_value) ) } @_transparent public // transparent init(_truncatingBits bits: UInt) { % truncOrExt = 'zext' if bits > word_bits else 'trunc' self.init( Builtin.${truncOrExt}OrBitCast_Int${word_bits}_Int${bits}(bits._value)) } % if signed: public typealias Magnitude = U${Self} @_transparent public var magnitude: U${Self} { let base = U${Self}(_value) return self < 0 ? ~base + 1 : base } % end % dbits = bits*2 public static func doubleWidthMultiply(_ self_: ${Self}, _ other: ${Self}) -> (high: ${Self}, low: ${Self}.Magnitude) { 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: UInt8 = ${bits} let shifted = Builtin.ashr_Int${dbits}(res, Builtin.zextOrBitCast_Int8_Int${dbits}(shift._value)) let high = ${Self}(Builtin.truncOrBitCast_Int${dbits}_Int${bits}(shifted)) return (high: high, low: low) } % if bits > 8: /// Creates an integer from its big-endian representation, changing the /// byte order if necessary. @_transparent public init(bigEndian value: ${Self}) { #if _endian(big) self = value #else self = ${Self}(Builtin.int_bswap_${BuiltinName}(value._value) ) #endif } /// Creates an integer from its little-endian representation, changing the /// byte order if necessary. @_transparent public init(littleEndian value: ${Self}) { #if _endian(little) self = value #else self = ${Self}(Builtin.int_bswap_${BuiltinName}(value._value) ) #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`. /// /// - SeeAlso: `littleEndian` public var bigEndian: ${Self} { #if _endian(big) return self #else return ${Self}(Builtin.int_bswap_${BuiltinName}(_value)) #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`. /// /// - SeeAlso: `bigEndian` public var littleEndian: ${Self} { #if _endian(little) return self #else return ${Self}(Builtin.int_bswap_${BuiltinName}(_value)) #endif } /// A representation of this integer with the byte order swapped. public var byteSwapped: ${Self} { return ${Self}(Builtin.int_bswap_${BuiltinName}(_value)) } % end // Implementation details public var _value: Builtin.Int${bits} % if self_type.is_word: @_transparent public // @testable init(_ _v: Builtin.Word) { % if BuiltinName == 'Int32': self._value = Builtin.truncOrBitCast_Word_Int32(_v) % elif BuiltinName == 'Int64': self._value = Builtin.zextOrBitCast_Word_Int64(_v) % end } @_transparent public // @testable var _builtinWordValue: Builtin.Word { % if BuiltinName == 'Int32': return Builtin.zextOrBitCast_Int32_Word(_value) % elif BuiltinName == 'Int64': return Builtin.truncOrBitCast_Int64_Word(_value) % end } % end @available(*, unavailable, message: "Use initializers instead") public func to${U}IntMax() -> ${U}IntMax { fatalError("Unavailable function") } } %# end of concrete type: ${Self} extension ${Self} { // FIXME(integers): implement me in a less terrible way public init(_ source: T) { % for (FloatType, FloatBits) in [ % ('Float', 32), ('Double', 64), ('Float80', 80)]: % if FloatType == 'Float80': #if !os(Windows) && (arch(i386) || arch(x86_64)) % end if source is ${FloatType} { self.init(source as! ${FloatType}) return } % if FloatType == 'Float80': #endif % end % end _preconditionFailure("Conversion is not supported") } } extension ${Self} : Hashable { /// The integer's hash value. /// /// The hash value is not guaranteed to be stable across different /// invocations of the same program. Do not persist the hash value across /// program runs. public var hashValue: Int { @inline(__always) get { % if bits <= word_bits and signed: // Sign extend the value. return Int(self) % elif bits <= word_bits and not signed: // Sign extend the value. return Int(${OtherSelf}(bitPattern: self)) % elif bits == word_bits * 2: // We have twice as many bits as we need to return. return Int(extendingOrTruncating: self) ^ Int(extendingOrTruncating: self &>> 32) % else: _Unimplemented() % end } } } // Create an ambiguity when indexing or slicing // Range[OfStrideable]<${Self}> outside a generic context. See // Range.swift for details. extension ${Self} { public typealias _DisabledRangeIndex = ${Self} } % for src_type in all_integer_types(word_bits): % srcBits = src_type.bits % srcSigned = src_type.is_signed % Src = src_type.stdlib_name % if should_define_truncating_bit_pattern_init(src_ty=src_type, dst_ty=self_type): extension ${Self} { /// Creates a new instance with the same bitwise representation as the least /// significant bits of the given value. /// /// This initializer performs no range or overflow checking. The resulting /// instance may have a different numeric value from `source`. /// /// - Parameter source: An integer to use as the source of the new value's /// bit pattern. @available(swift, obsoleted: 4.0, renamed: "init(extendingOrTruncating:)") @_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 % if signed: // TODO: Consider removing the underscore. /// Returns the argument and specifies that the value is not negative. /// It has only an effect if the argument is a load or call. @_transparent public func _assumeNonNegative(_ x: ${Self}) -> ${Self} { _sanityCheck(x >= 0) return ${Self}(Builtin.assumeNonNegative_${BuiltinName}(x._value)) } % end #if false // FIXME(integers): resolving the ambiguity. Should be gone along with the // BitwiseOperations protocol % for x in binaryBitwise: @_transparent public func ${x.operator}= < T : BitwiseOperations >(lhs: inout T, rhs: T) where T : FixedWidthInteger { lhs = lhs ${x.operator} rhs } % end #endif //===--- end of FIXME(integers) -------------------------------------------===// //===----------------------------------------------------------------------===// // FIXME(integers): short term solution until the overload resolution is fast // with the generic arithmetic operators. #if false extension ${Self} { // Operations with potentially-static overflow checking // // FIXME: must use condfail in these operators, rather than // overflowChecked, pending so that we don't // foil static checking for numeric overflows. % for op in ['+', '*', '-', '/', '%']: @available(swift, obsoleted: 4.0) @_transparent public static func ${op} (lhs: ${Self}, rhs: ${Self}) -> ${Self} { var lhs = lhs lhs ${op}= rhs return lhs } % end } #endif //===--- end of FIXME(integers) -------------------------------------------===// % end # end of concrete FixedWidthInteger section // FIXME(integers): inline manually everywhere /// 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 { /// 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`. public func numericCast(_ x: T) -> U { return U(x) } // FIXME(integers): switch to using `FixedWidthInteger.unsafeAdding` internal func _unsafePlus(_ lhs: Int, _ rhs: Int) -> Int { #if INTERNAL_CHECKS_ENABLED return lhs + rhs #else return lhs &+ rhs #endif } // FIXME(integers): switch to using `FixedWidthInteger.unsafeSubtracting` internal func _unsafeMinus(_ lhs: Int, _ rhs: Int) -> Int { #if INTERNAL_CHECKS_ENABLED return lhs - rhs #else return lhs &- rhs #endif } // FIXME(integers): switch to using `FixedWidthInteger.unsafeMultiplied(by:)` internal func _unsafeMultiply(_ lhs: Int, _ rhs: Int) -> Int { #if INTERNAL_CHECKS_ENABLED return lhs * rhs #else return lhs &* rhs #endif } // FIXME(integers): test more of these. // FIXME: should maybe be BinaryInteger & Arithmetic, but prevents it @available(*, unavailable, renamed: "Arithmetic") public typealias _IntegerArithmeticType = Arithmetic @available(*, unavailable, renamed: "Arithmetic") public typealias IntegerArithmeticType = Arithmetic @available(*, unavailable, renamed: "SignedArithmetic") public typealias SignedNumberType = SignedArithmetic @available(*, unavailable, renamed: "SignedInteger") public typealias SignedIntegerType = SignedInteger @available(*, unavailable, renamed: "UnsignedInteger") public typealias UnsignedIntegerType = SignedArithmetic @available(*, unavailable, renamed: "SignedArithmetic") public typealias AbsoluteValuable = SignedArithmetic @available(*, unavailable, renamed: "FixedWidthInteger") public typealias _IntegerType = FixedWidthInteger @available(*, unavailable, renamed: "FixedWidthInteger") public typealias IntegerType = FixedWidthInteger @available(*, unavailable, renamed: "SignedInteger") public typealias _SignedIntegerType = SignedInteger