on Sun Jan 15 2017, Nate Cook <natecook-AT-gmail.com> wrote:

> Excited to see this getting closer!
>
>> On Jan 14, 2017, at 7:41 PM, Dave Abrahams via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> 
>> on Sat Jan 14 2017, Benjamin Spratling <swift-evolution@swift.org
>> <mailto:swift-evolution@swift.org>> wrote:
>> 
>>> I notice the BinaryInteger's func word(at n: Int) -> UInt function
>>> expects a 2's complement representation.  Do you expect that "BigInt"
>>> will be implemented with 2's complement?  
>> 
>> Ah, this is an excellent question, excellently phrased!
>> 
>> We designed it so BigInt could use 2's complement (see
>> DoubleWidth<Int64>, which works that way), which should be faster than
>> sign-magnitude...
>> 
>> BUT: I hadn't really considered that if existing bignum libraries use
>> sign-magnitude, we'll want to be able to efficiently use their
>> representations, so we need to make sure the protocols don't force those
>> representations to be inefficient.
>> 
>>> As a nonmutating function, I would think any implementation from a 1's
>>> complement big int would result in O(n^2) unless the BigInt were
>>> designed with scratch space where it could store the intermediate
>>> values of that representation.  
>> 
>> Oh... you mean that word(at:) itself would be linear, and thus
>> algorithms that iterate the words linearly would be O(N^2)...  yuck.
>> 
>> So far, the only algorithm we have using word(at:) is this one, and
>> https://github.com/apple/swift/blob/new-integer-protocols/stdlib/public/core/Integers.swift.gyb#L2191
>>  
>> <https://github.com/apple/swift/blob/new-integer-protocols/stdlib/public/core/Integers.swift.gyb#L2191>
>> presumably we could adapt it to sign-magnitude by expanding the
>> BinaryInteger protocol with a static var that indicates which
>> representation is used.
>> 
>>  enum Representation { 
>>    twosComplement, signMagnitude, /*onesComplement?*/ 
>>  }
>>  static var representation: Representation { get }
>> 
>> Now, the other algorithms that I can anticipate would use word(at:) are
>> basically... the ones you'd have to implement to build BigInt, so I
>> guess this change would be OK.
>> 
>> Supporting sign-magnitude complicates generic programming with these
>> protocols, though, so I want to be really sure we need to do this before
>> we take the plunge.
>>
>>> I only ask because just last week I was designing an arbitrary-width
>>> float type in 1's complement, well, really I kept the sign bit in a
>>> separate Bool.  
>> 
>> Sounds like sign-magnitude rather than 1's complement if I remember my
>> complements correctly.
>> 
>>> Of course, I recognize the value of being able to write integer init
>>> code from a 2's complement representation, I'm just curious if there's
>>> a way to allow this function to be more efficient for alternate
>>> representations.
>>> 
>>> I love that there's a DoubleWidth type, having coded some arbitrary
>>> precision arithmetic, that's always a downer going from generic code
>>> to having to pick a specific "big enough" result type.
>>> 
>>> I'm glad the % operator got moved.  It really did stand out as not
>>> part of floating points.
>>> 
>>> Trailing zeros looks like a sensible optimization.
>>> 
>>> I agree with moving the shift operators, I like that you've called out
>>> the notion of an infinite shift.  
>> 
>> I don't think we ever meant to say anything about infinite shifts!
>> 
>>> I can't say I fully understood the use of the separate mask vs. smart
>>> shift operators, but I'll take another read in the next few days and
>>> see if I understand why they exist.
>> 
>> You're not alone it appears.  We need to clarify that in the text,
>> obviously.  The smart shift operators are there to give you sensible
>> semantics without undefined behavior or traps in the cases that have
>> logically computable answers.  The masking shifts are there for
>> performance in the rare cases where smart shifting with a non-literal
>> shift amount introduces non-negligible overheads (testing and branching
>> to handle overshifts and negative shift amounts).  
>> 
>> Obviously you have to know that the masking behavior is benign in your
>> use case when using masking shifts in an operation.  I made the mistake
>> of using a masking shift to optimize some code the other day where the
>> shift amount could be equal to the full width of the value being
>> shifted.  I ended up widening the LHS before doing the shift and then
>> truncating back to the width, but that's only because I was writing
>> performance-critical code.  The smart shift would have “just worked.”
>> 
>>> I know this PR does not address the BitInt implementation, but do you
>>> have one?
>> 
>> I know someone that implemented one... using sign-magnitude, actually,
>> and his word(at:) implementation has the linear cost problem.  I'll ask
>> him to post a link.
>
> Link: 
> https://github.com/natecook1000/swift/blob/nc-bigint/test/Prototypes/BigInt.swift
>
> This is just a proof of concept BigInt implementation—there's not much
> in the way of optimization going on, and it's a little out of date. It
> does use sign-magnitude, so the word(at:) implementation is O(n) on
> each call due to this bit:
>
> https://github.com/natecook1000/swift/blob/nc-bigint/test/Prototypes/BigInt.swift#L571-L576
>
> The only other question I have from looking at this again is whether
> perhaps BinaryInteger should have a toString(radix:uppercase:) method,
> since arbitrary precision types may be able to optimize significantly
> for different bases. The prototype at the link doesn't do this, but a
> hex string (or any factor of 2 base?) should be far cheaper to
> generate than the general case that uses repeated division. 

Seems to me that we can make the same optimization for any integer
type. I don't see why we need to inject this into the protocol.  What
am I missing?

> Without that, a BigInt type doesn't have any way to customize the
> generic String<T>(_:radix:uppercase:) initializer.
>
> -Nate
>
>>> I'm glad to see this moving forward.
>>> 
>>> -Ben Spratling
>>> 
>>>> On Jan 14, 2017, at 2:00 AM, Rien via swift-evolution 
>>>> <swift-evolution@swift.org> wrote:
>>>> 
>>>> +1
>>>> 
>>>> Any change of including “ranged integers”?
>>>> I.e. an integer with a value that must fit in a predefined range?
>>>> 
>>>> Regards,
>>>> Rien
>>>> 
>>>> Site: http://balancingrock.nl
>>>> Blog: http://swiftrien.blogspot.com
>>>> Github: http://github.com/Swiftrien
>>>> Project: http://swiftfire.nl
>>>> 
>>>> 
>>>> 
>>>> 
>>>>> On 13 Jan 2017, at 21:47, Max Moiseev via swift-evolution 
>>>>> <swift-evolution@swift.org> wrote:
>>>>> 
>>>>> Hi everyone,
>>>>> 
>>>>> Back in June 2016 we discussed the new design of the integer types for 
>>>>> the standard library. It even resulted in acceptance of SE-0104 for Swift 
>>>>> 3. Unfortunately we were not able to implement it in time for the release.
>>>>> 
>>>>> But it was not forgotten, although, as time went by, a few changes needed 
>>>>> to be made in order to reflect the current state of the language.
>>>>> Without further introduction, please welcome the refined proposal to make 
>>>>> integers in Swift more suitable for generic programming.
>>>>> 
>>>>> Available in this gist 
>>>>> https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c and also 
>>>>> inlined below.
>>>>> 
>>>>> Max
>>>>> 
>>>>> Protocol-oriented integers (take 2)
>>>>> 
>>>>>   • Proposal: SE-NNNN
>>>>>   • Authors: Dave Abrahams, Maxim Moiseev
>>>>>   • Review Manager: TBD
>>>>>   • Status: Awaiting review
>>>>>   • Bug: SR-3196
>>>>>   • Previous Proposal: SE-0104
>>>>> Introduction
>>>>> 
>>>>> This proposal is an evolution of SE-0104. The goal is still to clean up 
>>>>> Swifts integer APIs and make them more useful for generic programming.
>>>>> 
>>>>> The language has evolved in ways that affect integers APIs since the time 
>>>>> the original proposal was approved for Swift 3. We also attempted to 
>>>>> implement the proposed model in the standard library and found that some 
>>>>> essential APIs were missing, whereas others could be safely removed.
>>>>> 
>>>>> Major changes to the APIs introduced by this proposal (as compared to 
>>>>> SE-0104) are listed in a dedicated section.
>>>>> 
>>>>> Motivation
>>>>> 
>>>>> Swift's integer protocols don't currently provide a suitable basis for 
>>>>> generic programming. See this blog post for an example of an attempt to 
>>>>> implement a generic algorithm over integers.
>>>>> 
>>>>> The way the Arithmetic protocol is defined, it does not generalize to 
>>>>> floating point numbers and also slows down compilation by requiring every 
>>>>> concrete type to provide an implementation of arithmetic operators, thus 
>>>>> polluting the overload set.
>>>>> 
>>>>> Converting from one integer type to another is performed using the 
>>>>> concept of the 'maximum width integer' (see MaxInt), which is an 
>>>>> artificial limitation. The very existence of MaxInt makes it unclear what 
>>>>> to do should someone implement Int256, for example.
>>>>> 
>>>>> Another annoying problem is the inability to use integers of different 
>>>>> types in comparison and bit-shift operations. For example, the following 
>>>>> snippets won't compile:
>>>>> 
>>>>> var x: Int8 = 42
>>>>> let y = 1
>>>>> let z = 0
>>>>> 
>>>>> 
>>>>> x 
>>>>> <<= y   // error: binary operator '<<=' cannot be applied to operands of 
>>>>> type 'Int8' and 'Int'
>>>>> if x > z { ... }  // error: binary operator '>' cannot be applied to 
>>>>> operands of type 'Int8' and 'Int'
>>>>> Currently, bit-shifting a negative number of (or too many) bits causes a 
>>>>> trap on some platforms, which makes low-level bit manipulations 
>>>>> needlessly dangerous and unpredictable.
>>>>> 
>>>>> Finally, the current design predates many of the improvements that came 
>>>>> since Swift 1, and hasn't been revised since then.
>>>>> 
>>>>> Proposed solution
>>>>> 
>>>>> We propose a new model that does not have above mentioned problems and is 
>>>>> more easily extensible.
>>>>> 
>>>>>               +--------------+  +-------------+
>>>>>       +------>+  Arithmetic  |  | Comparable  |
>>>>>       |       |   (+,-,*,/)  |  | (==,<,>,...)|
>>>>>       |       +-------------++  +---+---------+
>>>>>       |                     ^       ^
>>>>> +-------+------------+        |       |
>>>>> |  SignedArithmetic  |      +-+-------+-----------+
>>>>> |     (unary -)      |      |    BinaryInteger    |
>>>>> +------+-------------+      |(words,%,bitwise,...)|
>>>>>      ^                    ++---+-----+----------+
>>>>>      |         +-----------^   ^     ^---------------+
>>>>>      |         |               |                     |
>>>>> +------+---------++    +---------+---------------+  +--+----------------+
>>>>> |  SignedInteger  |    |  FixedWidthInteger      |  |  UnsignedInteger  |
>>>>> |                 |    |(endianness,overflow,...)|  |                   |
>>>>> +---------------+-+    +-+--------------------+--+  +-+-----------------+
>>>>>               ^        ^                    ^       ^
>>>>>               |        |                    |       |
>>>>>               |        |                    |       |
>>>>>              ++--------+-+                +-+-------+-+
>>>>>              |Int family |-+              |UInt family|-+
>>>>>              +-----------+ |              +-----------+ |
>>>>>                +-----------+                +-----------+
>>>>> 
>>>>> There are several benefits provided by this model over the old one:
>>>>> 
>>>>>   • It allows mixing integer types in generic functions.
>>>>> 
>>>>> The possibility to initialize instances of any concrete integer type with 
>>>>> values of any other concrete integer type enables writing functions that 
>>>>> operate on more than one type conforming to BinaryInteger, such as 
>>>>> heterogeneous comparisons or bit shifts, described later.
>>>>> 
>>>>>   • It removes the overload resolution overhead.
>>>>> 
>>>>> Arithmetic and bitwise operations can now be defined as generic operators 
>>>>> on protocols. This approach significantly reduces the number of overloads 
>>>>> for those operations, which used to be defined for every single concrete 
>>>>> integer type.
>>>>> 
>>>>>   • It enables protocol sharing between integer and floating point types.
>>>>> 
>>>>> Note the exclusion of the % operation from Arithmetic. Its behavior for 
>>>>> floating point numbers is sufficiently different from the one for 
>>>>> integers that using it in generic context would lead to confusion. The 
>>>>> FloatingPoint protocol introduced by SE-0067 should now refine 
>>>>> SignedArithmetic.
>>>>> 
>>>>>   • It makes future extensions possible.
>>>>> 
>>>>> The proposed model eliminates the 'largest integer type' concept 
>>>>> previously used to interoperate between integer types (see toIntMax in 
>>>>> the current model) and instead provides access to machine words. It also 
>>>>> introduces thedoubleWidthMultiply, doubleWidthDivide, and 
>>>>> quotientAndRemainder methods. Together these changes can be used to 
>>>>> provide an efficient implementation of bignums that would be hard to 
>>>>> achieve otherwise.
>>>>> 
>>>>> The implementation of proposed model in the standard library is available 
>>>>> in the new-integer-protocols branch.
>>>>> 
>>>>> A note on bit shifts
>>>>> 
>>>>> This proposal introduces the concepts of smart shifts and masking shifts.
>>>>> 
>>>>> The semantics of shift operations are often undefined in under- or 
>>>>> over-shift cases. Smart shifts, implemented by >> and <<, are designed to 
>>>>> address this problem and always behave in a well defined way, as shown in 
>>>>> the examples below:
>>>>> 
>>>>>   • x << -2 is equivalent to x >> 2
>>>>> 
>>>>>   • (1 as UInt8) >> 42) will evaluate to 0
>>>>> 
>>>>>   • (-128 as Int8) >> 42) will evaluate to 0xff or -1
>>>>> 
>>>>> In most scenarios, the right hand operand is a literal constant, and 
>>>>> branches for handling under- and over-shift cases can be optimized away. 
>>>>> For other cases, this proposal provides masking shifts, implemented by 
>>>>> &>> and &<<. A masking shift logically preprocesses the right hand 
>>>>> operand by masking its bits to produce a value in the range 0...(x-1) 
>>>>> where x is the number of bits in the left hand operand. On most 
>>>>> architectures this masking is already performed by the CPU's shift 
>>>>> instructions and has no cost. Both kinds of shift avoid undefined 
>>>>> behavior and produce uniform semantics across architectures.
>>>>> 
>>>>> Detailed design
>>>>> 
>>>>> What's new since SE-0104
>>>>> 
>>>>>   • SE-0091 removed the necessity to dispatch generic operators through 
>>>>> special methods.
>>>>> 
>>>>> All operators are now declared by protocols as static funcs.
>>>>> 
>>>>>   • Standard Library no longer provides + and - operators for Strideable 
>>>>> types.
>>>>> 
>>>>> They were problematic, as one could have written mixed-type code like let 
>>>>> x: Int64 = 42; x += (1 as Int), which would compile, but shouldn't. 
>>>>> Besides, since the Stride of an unsigned type is signed, Standard Library 
>>>>> had to implement a hack to make code like let x: UInt = 42; x += (1 as 
>>>>> Int) ambiguous. These operators were only necessary because they made 
>>>>> advancing collection indices convenient, which is no longer the case 
>>>>> since the introduction of the new indexing model in Swift 3.
>>>>> 
>>>>>   • Shifts and other bitwise operations were moved from FixedWidthInteger 
>>>>> to BinaryInteger.
>>>>> 
>>>>> Left shift operation on an unbounded integer should infinitely extend the 
>>>>> number, and never drop set bits when they reach the most significant 
>>>>> position in the underlying representation.
>>>>> 
>>>>>   • BitwiseOperations protocol was deprecated.
>>>>> 
>>>>> We believe there are no useful entities that support bitwise operations, 
>>>>> but at the same time are not binary integers.
>>>>> 
>>>>>   • minimumSignedRepresentationBitWidth property was removed.
>>>>> 
>>>>>   • trailingZeros property was added to the BinaryInteger protocol.
>>>>> 
>>>>> leadingZeros and popcount properties are still defined by the 
>>>>> FixedWidthInteger protocol.
>>>>> 
>>>>>   • Endian-converting initializers and properties were added to the 
>>>>> FixedWidthInteger protocol.
>>>>> 
>>>>>   • Standard library introduces the new type DoubleWidth<T>.
>>>>> 
>>>>> See this section for more details.
>>>>> 
>>>>> Protocols
>>>>> 
>>>>> Arithmetic
>>>>> 
>>>>> The Arithmetic protocol declares binary arithmetic operators – such as +, 
>>>>> -, and * — and their mutating counterparts.
>>>>> 
>>>>> It provides a suitable basis for arithmetic on scalars such as integers 
>>>>> and floating point numbers.
>>>>> 
>>>>> Both mutating and non-mutating operations are declared in the protocol, 
>>>>> however only the mutating ones are required, as default implementations 
>>>>> of the non-mutating ones are provided by a protocol extension.
>>>>> 
>>>>> The Magnitude associated type is able to hold the absolute value of any 
>>>>> possible value of Self. Concrete types do not have to provide a type 
>>>>> alias for it, as it can be inferred from the magnitude property. This 
>>>>> property can be useful in operations that are simpler to implement in 
>>>>> terms of unsigned values, for example, printing a value of an integer, 
>>>>> which is just printing a '-' character in front of an absolute value.
>>>>> 
>>>>> Please note that for ordinary work, the magnitude property should not be 
>>>>> preferred to the abs(_) function, whose return value is of the same type 
>>>>> as its argument.
>>>>> 
>>>>> 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?<T : BinaryInteger>(exactly source
>>>>> : T)
>>>>> 
>>>>> 
>>>>> /// 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
>>>>> }
>>>>> 
>>>>> 
>>>>> /// Returns the sum of the two given values.
>>>>> ///
>>>>> /// The sum of `lhs` and `rhs` must be representable in the same type. In 
>>>>> the
>>>>> /// following example, the result of `100 + 200` is greater than the 
>>>>> maximum
>>>>> /// representable `Int8` value:
>>>>> ///
>>>>> ///     let x: Int8 = 10 + 21
>>>>> ///     // x == 31
>>>>> ///     let y: Int8 = 100 + 121
>>>>> ///     // Overflow error
>>>>> static func +(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> 
>>>>> /// Adds the given value to this value in place.
>>>>> ///
>>>>> /// For example:
>>>>> ///
>>>>> ///     var x = 15
>>>>> ///     y += 7
>>>>> ///     // y == 22
>>>>> static func +=(_ lhs: inout Self, rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// Returns the difference of the two given values.
>>>>> ///
>>>>> /// The difference of `lhs` and `rhs` must be representable in the same 
>>>>> type.
>>>>> /// In the following example, the result of `10 - 21` is less than zero, 
>>>>> the
>>>>> /// minimum representable `UInt` value:
>>>>> ///
>>>>> ///     let x: UInt = 21 - 10
>>>>> ///     // x == 11
>>>>> ///     let y: UInt = 10 - 21
>>>>> ///     // Overflow error
>>>>> static func -(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> 
>>>>> /// Subtracts the given value from this value in place.
>>>>> ///
>>>>> /// For example:
>>>>> ///
>>>>> ///     var x = 15
>>>>> ///     y -= 7
>>>>> ///     // y == 8
>>>>> static func -=(_ lhs: inout Self, rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// Returns the product of the two given values.
>>>>> ///
>>>>> /// The product of `lhs` and `rhs` must be representable in the same 
>>>>> type. In
>>>>> /// the following example, the result of `10 * 50` is greater than the
>>>>> /// maximum representable `Int8` value.
>>>>> ///
>>>>> ///     let x: Int8 = 10 * 5
>>>>> ///     // x == 50
>>>>> ///     let y: Int8 = 10 * 50
>>>>> ///     // Overflow error
>>>>> static func *(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> 
>>>>> /// Multiples this value by the given value in place.
>>>>> ///
>>>>> /// For example:
>>>>> ///
>>>>> ///     var x = 15
>>>>> ///     y *= 7
>>>>> ///     // y == 105
>>>>> static func *=(_ lhs: inout Self, rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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
>>>>> static func /(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> 
>>>>> /// Divides this value by the given value in place.
>>>>> ///
>>>>> /// For example:
>>>>> ///
>>>>> ///     var x = 15
>>>>> ///     y /= 7
>>>>> ///     // y == 2
>>>>> static func /=(_ lhs: inout Self, rhs: Self
>>>>> )
>>>>> }
>>>>> 
>>>>> 
>>>>> extension Arithmetic
>>>>> {
>>>>> 
>>>>> public init() { self = 0
>>>>> }
>>>>> 
>>>>> 
>>>>> public static prefix func + (x: Self) -> Self
>>>>> {
>>>>> 
>>>>> return
>>>>> x
>>>>> }
>>>>> }
>>>>> 
>>>>> SignedArithmetic
>>>>> 
>>>>> The SignedArithmetic protocol is for numbers that can be negated.
>>>>> 
>>>>> public protocol SignedArithmetic : Arithmetic 
>>>>> {
>>>>> 
>>>>> /// Returns the additive inverse of this value.
>>>>> ///
>>>>> ///     let x = 21
>>>>> ///     let y = -x
>>>>> ///     // y == -21
>>>>> ///
>>>>> /// - Returns: The additive inverse of this value.
>>>>> ///
>>>>> /// - SeeAlso: `negate()`
>>>>> 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
>>>>> ///
>>>>> /// - SeeAlso: The unary minus operator (`-`).
>>>>> mutating func negate
>>>>> ()
>>>>> }
>>>>> 
>>>>> 
>>>>> extension SignedArithmetic
>>>>> {
>>>>> 
>>>>> public static prefix func - (_ operand: Self) -> Self
>>>>> {
>>>>> 
>>>>> var result =
>>>>> operand
>>>>>   result.
>>>>> negate
>>>>> ()
>>>>> 
>>>>> return
>>>>> result
>>>>> }
>>>>> 
>>>>> 
>>>>> public mutating func negate
>>>>> () {
>>>>> 
>>>>> self = Self() - self
>>>>> 
>>>>> }
>>>>> }
>>>>> 
>>>>> BinaryInteger
>>>>> 
>>>>> The BinaryInteger protocol is the basis for all the integer types 
>>>>> provided by the standard library.
>>>>> 
>>>>> This protocol adds a few new initializers. Two of them allow to create 
>>>>> integers from floating point numbers, others support construction from 
>>>>> instances of any type conforming to BinaryInteger, using different 
>>>>> strategies:
>>>>> 
>>>>>   • Initialize Self with the value, provided that the value is 
>>>>> representable. The precondition should be satisfied by the caller.
>>>>> 
>>>>>   • Extend or truncate the value to fit into Self
>>>>> 
>>>>>   • Clamp the value to the representable range of Self
>>>>> 
>>>>> BinaryInteger also declares bitwise and shift operators.
>>>>> 
>>>>> 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?<T : FloatingPoint>(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<T : FloatingPoint>(_ 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<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(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<T : BinaryInteger>(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<T : BinaryInteger>(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 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.trailingZeros == 3
>>>>> var trailingZeros: Int { get
>>>>> }
>>>>> 
>>>>> 
>>>>> /// Returns the remainder of dividing the first value by the second.
>>>>> ///
>>>>> /// The result 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
>>>>> ///
>>>>> /// - Parameters:
>>>>> ///   - lhs: The value to divide.
>>>>> ///   - rhs: The value to divide `lhs` by. `rhs` must not be zero.
>>>>> static func %(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> 
>>>>> /// Replaces this value with the remainder of itself divided by the given
>>>>> /// value. For example:
>>>>> ///
>>>>> ///     var x = 15
>>>>> ///     x %= 7
>>>>> ///     // x == 1
>>>>> ///
>>>>> /// - Parameter rhs: The value to divide this value by. `rhs` must not be
>>>>> ///   zero.
>>>>> ///
>>>>> /// - SeeAlso: `remainder(dividingBy:)`
>>>>> static func %=(_ lhs: inout Self, _ rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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
>>>>> 
>>>>> 
>>>>> 
>>>>> /// 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 & y             // 0b00000100
>>>>> static func &(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> static func &=(_ lhs: inout Self, _ rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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 | y             // 0b00001111
>>>>> static func |(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> static func |=(_ lhs: inout Self, _ rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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 ^ y             // 0b00001011
>>>>> static func ^(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> static func ^=(_ lhs: inout Self, _ rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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 shift an 8-bit, unsigned integer by 2, the shift
>>>>> /// amount requires no masking.
>>>>> ///
>>>>> ///     let x: UInt8 = 30                 // 0b00011110
>>>>> ///     let y = x &>> 2
>>>>> ///     // y == 7                         // 0b00000111
>>>>> ///
>>>>> /// However, if you shift it by 11, it 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
>>>>> ///
>>>>> /// Relationship to the Right Shift Operator
>>>>> /// ----------------------------------------
>>>>> ///
>>>>> /// The masking right shift operator 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...<bitWidth`, the operation is equivalent to using the right shift
>>>>> /// operator.
>>>>> ///
>>>>> ///     let x: UInt8 = 30                 // 0b00011110
>>>>> ///     let y1 = x &>> 2
>>>>> ///     // y1 == 7                        // 0b00000111
>>>>> ///     let y2 = x >> 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 &>> 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..<bitWidth`, it is masked to produce a
>>>>> ///   value within that range.
>>>>> /// - Returns: The result of shifting this value by the masked `rhs` to 
>>>>> the
>>>>> ///   right.
>>>>> ///
>>>>> /// - SeeAlso: `&<<`, `>>`
>>>>> static func &>>(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> static func &>>=(_ lhs: inout Self, _ rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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 shift an 8-bit, unsigned integer by 2, the shift
>>>>> /// amount requires no masking.
>>>>> ///
>>>>> ///     let x: UInt8 = 30                 // 0b00011110
>>>>> ///     let y = x &>> 2
>>>>> ///     // y == 120                       // 0b01111000
>>>>> ///
>>>>> /// However, if you shift it by 11, it first bitmasks `rhs` to `3`, and 
>>>>> then
>>>>> /// uses that masked value as the number of bits to shift `x`.
>>>>> ///
>>>>> ///     let z = x &<< 11
>>>>> ///     // z == 240                       // 0b11110000
>>>>> ///
>>>>> /// Relationship to the Left Shift Operator
>>>>> /// ---------------------------------------
>>>>> ///
>>>>> /// The masking left shift operator 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...<bitWidth`, the operation is equivalent to using the left shift
>>>>> /// operator.
>>>>> ///
>>>>> ///     let x: UInt8 = 30                 // 0b00011110
>>>>> ///     let y1 = x &<< 2
>>>>> ///     // y1 == 120                      // 0b01111000
>>>>> ///     let y2 = x << 2
>>>>> ///     // y2 == 120                      // 0b01111000
>>>>> ///
>>>>> /// The left 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 &<< 11
>>>>> ///     // z1 == 240                      // 0b11110000
>>>>> ///     let z2 = x << 11
>>>>> ///     // z2 == 0                        // 0b00000000
>>>>> ///
>>>>> /// - Parameter rhs: The number of bits to shift this value to the left. 
>>>>> If
>>>>> ///   `rhs` is outside the range `0..<bitWidth`, it is masked to produce a
>>>>> ///   value within that range.
>>>>> /// - Returns: The result of shifting this value by the masked `rhs` to 
>>>>> the
>>>>> ///   left.
>>>>> ///
>>>>> /// - SeeAlso: `&>>`, `<<`
>>>>> static func &<<(_ lhs: Self, _ rhs: Self) -> Self
>>>>> 
>>>>> 
>>>>> static func &<<=(_ lhs: inout Self, _ rhs: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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
>>>>> 
>>>>> }
>>>>> 
>>>>> FixedWidthInteger
>>>>> 
>>>>> The FixedWidthInteger protocol adds the notion of endianness as well as 
>>>>> static properties for type bounds and bit width.
>>>>> 
>>>>> The WithOverflow family of methods is used in default implementations of 
>>>>> mutating arithmetic methods (see the Arithmetic protocol). Having these 
>>>>> methods allows the library to provide both bounds-checked and masking 
>>>>> implementations of arithmetic operations, without duplicating code.
>>>>> 
>>>>> The doubleWidthMultiply and doubleWidthDivide methods are necessary 
>>>>> building blocks to implement support for integer types of a greater width 
>>>>> such as arbitrary-precision integers.
>>>>> 
>>>>> public protocol FixedWidthInteger : BinaryInteger 
>>>>> {
>>>>> 
>>>>> /// 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
>>>>> }
>>>>> 
>>>>> 
>>>>> /// Returns the sum of this value and the given value along with a flag
>>>>> /// indicating whether overflow occurred in the operation.
>>>>> ///
>>>>> /// - Parameter other: The value to add to this value.
>>>>> /// - Returns: A tuple containing the result of the addition along with a
>>>>> ///   flag indicating whether overflow occurred. If the `overflow` 
>>>>> component
>>>>> ///   is `.none`, the `partialValue` component contains the entire sum. If
>>>>> ///   the `overflow` component is `.overflow`, an overflow occurred and 
>>>>> the
>>>>> ///   `partialValue` component contains the truncated sum of this value 
>>>>> and
>>>>> ///   `other`.
>>>>> ///
>>>>> /// - SeeAlso: `+`
>>>>> func addingWithOverflow(_ other: Self
>>>>> )
>>>>> 
>>>>> -> (partialValue: Self, overflow
>>>>> : ArithmeticOverflow)
>>>>> 
>>>>> 
>>>>> /// Returns the difference of this value and the given value along with a
>>>>> /// flag indicating whether overflow occurred in the operation.
>>>>> ///
>>>>> /// - Parameter other: The value to subtract from this value.
>>>>> /// - Returns: A tuple containing the result of the subtraction along 
>>>>> with a
>>>>> ///   flag indicating whether overflow occurred. If the `overflow` 
>>>>> component
>>>>> ///   is `.none`, the `partialValue` component contains the entire
>>>>> ///   difference. If the `overflow` component is `.overflow`, an overflow
>>>>> ///   occurred and the `partialValue` component contains the truncated
>>>>> ///   result of `other` subtracted from this value.
>>>>> ///
>>>>> /// - SeeAlso: `-`
>>>>> func subtractingWithOverflow(_ other: Self
>>>>> )
>>>>> 
>>>>> -> (partialValue: Self, overflow
>>>>> : ArithmeticOverflow)
>>>>> 
>>>>> 
>>>>> /// Returns the product of this value and the given value along with a 
>>>>> flag
>>>>> /// indicating whether overflow occurred in the operation.
>>>>> ///
>>>>> /// - Parameter other: The value to multiply by this value.
>>>>> /// - Returns: A tuple containing the result of the multiplication along 
>>>>> with
>>>>> ///   a flag indicating whether overflow occurred. If the `overflow`
>>>>> ///   component is `.none`, the `partialValue` component contains the 
>>>>> entire
>>>>> ///   product. If the `overflow` component is `.overflow`, an overflow
>>>>> ///   occurred and the `partialValue` component contains the truncated
>>>>> ///   product of this value and `other`.
>>>>> ///
>>>>> /// - SeeAlso: `*`, `doubleWidthMultiply(_:_:)`
>>>>> func multipliedWithOverflow(by other: Self
>>>>> )
>>>>> 
>>>>> -> (partialValue: Self, overflow
>>>>> : ArithmeticOverflow)
>>>>> 
>>>>> 
>>>>> /// Returns the quotient of dividing this value by the given value along 
>>>>> with
>>>>> /// a flag indicating whether overflow occurred in the operation.
>>>>> ///
>>>>> /// For a value `x`, if zero is passed as `other`, the result is
>>>>> /// `(x, .overflow)`.
>>>>> ///
>>>>> /// - Parameter other: The value to divide this value by.
>>>>> /// - Returns: A tuple containing the result of the division along with a
>>>>> ///   flag indicating whether overflow occurred. If the `overflow` 
>>>>> component
>>>>> ///   is `.none`, the `partialValue` component contains the entire 
>>>>> quotient.
>>>>> ///   If the `overflow` component is `.overflow`, an overflow occurred and
>>>>> ///   the `partialValue` component contains the truncated quotient.
>>>>> ///
>>>>> /// - SeeAlso: `/`, `doubleWidthDivide(_:_:)`
>>>>> func dividedWithOverflow(by other: Self
>>>>> )
>>>>> 
>>>>> -> (partialValue: Self, overflow
>>>>> : ArithmeticOverflow)
>>>>> 
>>>>> 
>>>>> /// 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
>>>>> )
>>>>> 
>>>>> 
>>>>> /// 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
>>>>> /// - SeeAlso: `BinaryInteger.trailingZeros`
>>>>> var leadingZeros: Int { get
>>>>> }
>>>>> 
>>>>> 
>>>>> /// Creates an integer from its big-endian representation, changing the
>>>>> /// byte order if necessary.
>>>>> init(bigEndian value: Self
>>>>> )
>>>>> 
>>>>> 
>>>>> /// Creates an integer from its little-endian representation, changing the
>>>>> /// byte order if necessary.
>>>>> 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`.
>>>>> ///
>>>>> /// - SeeAlso: `littleEndian`
>>>>> 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`.
>>>>> ///
>>>>> /// - SeeAlso: `bigEndian`
>>>>> var littleEndian: Self { get
>>>>> }
>>>>> 
>>>>> 
>>>>> /// A representation of this integer with the byte order swapped.
>>>>> var byteSwapped: Self { get
>>>>> }
>>>>> }
>>>>> 
>>>>> Auxiliary protocols
>>>>> 
>>>>> public protocol UnsignedInteger : BinaryInteger 
>>>>> {
>>>>> 
>>>>> associatedtype Magnitude : BinaryInteger
>>>>> 
>>>>> }
>>>>> 
>>>>> public protocol SignedInteger : BinaryInteger, SignedArithmetic 
>>>>> {
>>>>> 
>>>>> associatedtype Magnitude : BinaryInteger
>>>>> 
>>>>> }
>>>>> 
>>>>> DoubleWidth
>>>>> 
>>>>> The DoubleWidth<T> type allows to create wider fixed-width integer types 
>>>>> from the ones available in the standard library.
>>>>> 
>>>>> Standard library currently provides fixed-width integer types of up to 64 
>>>>> bits. A value of DoubleWidth<Int64> will double the range of the 
>>>>> underlying type and implement all the FixedWidthInteger requirements. 
>>>>> Please note though that the implementation will not necessarily be the 
>>>>> most efficient one, so it would not be a good idea to use 
>>>>> DoubleWidth<Int32>instead of a built-in Int64.
>>>>> 
>>>>> Extra operators
>>>>> 
>>>>> In addition to the operators described in the protocols section, we also 
>>>>> provide a few extensions that are not protocol requirements:
>>>>> 
>>>>> Heterogeneous shifts
>>>>> 
>>>>> extension BinaryInteger
>>>>> {
>>>>> 
>>>>> // Masking shifts
>>>>> static func &>>  <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Self
>>>>> 
>>>>> 
>>>>> static func &>>= <Other : BinaryInteger>(lhs: inout Self, rhs
>>>>> : Other)
>>>>> 
>>>>> static func &<<  <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Self
>>>>> 
>>>>> 
>>>>> static func &<<= <Other : BinaryInteger>(lhs: inout Self, rhs
>>>>> : Other)
>>>>> 
>>>>> 
>>>>> // 'Smart' shifts
>>>>> static func >>  <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Self
>>>>> 
>>>>> 
>>>>> static func >>= <Other : BinaryInteger>(lhs: inout Self, rhs
>>>>> : Other)
>>>>> 
>>>>> static func <<  <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Self
>>>>> 
>>>>> 
>>>>> static func <<= <Other : BinaryInteger>(lhs: inout Self, rhs
>>>>> : Other)
>>>>> }
>>>>> 
>>>>> Heterogeneous equality and comparison
>>>>> 
>>>>> extension BinaryInteger
>>>>> {
>>>>> 
>>>>> // Equality
>>>>> static func == <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool
>>>>> 
>>>>> 
>>>>> static func != <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool
>>>>> 
>>>>> 
>>>>> 
>>>>> // Comparison
>>>>> static func <  <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool
>>>>> 
>>>>> 
>>>>> static func <= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool
>>>>> 
>>>>> 
>>>>> static func >  <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool
>>>>> 
>>>>> 
>>>>> static func >= <Other : BinaryInteger>(lhs: Self, rhs: Other) -> Bool
>>>>> 
>>>>> }
>>>>> 
>>>>> Masking arithmetic
>>>>> 
>>>>> public func &* <T: FixedWidthInteger>(lhs: T, rhs: T) ->
>>>>> T
>>>>> 
>>>>> public func &- <T: FixedWidthInteger>(lhs: T, rhs: T) ->
>>>>> T
>>>>> 
>>>>> public func &+ <T: FixedWidthInteger>(lhs: T, rhs: T) -> T
>>>>> Non-goals
>>>>> 
>>>>> This proposal:
>>>>> 
>>>>>   • DOES NOT solve the integer promotion problem, which would allow 
>>>>> mixed-type arithmetic. However, we believe that it is an important step 
>>>>> in the right direction.
>>>>> 
>>>>>   • DOES NOT include the implementation of a BigInt type, but allows it 
>>>>> to be implemented in the future.
>>>>> 
>>>>> Source compatibility
>>>>> 
>>>>> The proposed change is designed to be as non-breaking as possible, and it 
>>>>> has been proven that it does not break code on concrete integer types. 
>>>>> However, there are still a few API breaking changes in the realm of 
>>>>> generic code:
>>>>> 
>>>>>   • Integer protocols in Swift up to and including version 3 were not 
>>>>> particularly useful for generic programming, but were rather a means of 
>>>>> sharing implementation between conforming types. Therefore we believe the 
>>>>> amount of code that relied on these protocols is relatively small. The 
>>>>> breakage can be further reduced by introducing proper aliases for the 
>>>>> removed protocols with deprecation warnings.
>>>>> 
>>>>>   • Deprecation of the BitwiseOperations protocol. We find it hard to 
>>>>> imagine a type that conforms to this protocol, but is not a binary 
>>>>> integer type.
>>>>> 
>>>>>   • Addition of 'smart' shifts will change the behavior of existing code. 
>>>>> It will still compile, but will be potentially less performant due to 
>>>>> extra logic involved. In a case, where this becomes a problem, newly 
>>>>> introduced masking shift operators can be used instead. Unfortunately, 
>>>>> performance characteristics of the code cannot be statically checked, and 
>>>>> thus migration cannot be provided.
>>>>> 
>>>>> 
>>>>> _______________________________________________
>>>>> swift-evolution mailing list
>>>>> swift-evolution@swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>>> 
>>>> 
>>>> _______________________________________________
>>>> swift-evolution mailing list
>>>> swift-evolution@swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>>> _______________________________________________
>>> swift-evolution mailing list
>>> swift-evolution@swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> 
>> -- 
>> -Dave
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution@swift.org <mailto:swift-evolution@swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
>> <https://lists.swift.org/mailman/listinfo/swift-evolution>

-- 
-Dave
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to