Stephen Canon wrote that Arithmetic should refine ExpressibleByIntegerLiteral because of certain mathematical properties of rings. In that case, 0 and 1 would just be spelled in that way. Otherwise, +1. On Wed, Jan 25, 2017 at 11:38 Anton Mironov via swift-evolution < swift-evolution@swift.org> wrote:
> Hi everyone, > > I want to suggest a tiny extension to an Arithmetic protocol. It would be > nice to have an additive identity and a multiplicative identity constants. > Basically zero and one. > > ``` > protocol Arithmetic { > /* ... */ > static var zero: Self { get } // additive identity: (value + .zero) == > value > static var one: Self { get } // multiplicative identity: (value * > .one) == value > } > ``` > > These constants will ease implementation of math structures: vectors, > matrices and etc. > I’m sorry if I’m duplicating someone’s suggestion. It is really hard to > search for something in a long thread. > > Thanks, > Anton Mironov > > > On Jan 13, 2017, at 10:47 PM, 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 > <https://github.com/apple/swift-evolution/blob/master/proposals/0104-improved-integers.md> > 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 > <https://gist.github.com/moiseev/0000-even-more-improved-integers.md> > - Authors: Dave Abrahams <https://github.com/dabrahams>, Maxim Moiseev > <https://github.com/moiseev> > - Review Manager: TBD > - Status: Awaiting review > - Bug: SR-3196 <https://bugs.swift.org/browse/SR-3196> > - Previous Proposal: SE-0104 > <https://gist.github.com/moiseev/0104-improved-integers.md> > > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#introduction> > Introduction > > This proposal is an evolution of SE-0104 > <https://gist.github.com/moiseev/0104-improved-integers.md>. 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 <https://gist.github.com/moiseev/0104-improved-integers.md>) are > listed in a dedicated section > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#whats-new-since-se-0104> > . > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#motivation> > Motivation > > Swift's integer protocols don't currently provide a suitable basis for > generic programming. See this blog post > <http://blog.krzyzanowskim.com/2015/03/01/swift_madness_of_generic_integer/> > 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 = 42let y = 1let 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. > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#proposed-solution>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 > <https://gist.github.com/moiseev/0067-floating-point-protocols.md> 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 > <https://github.com/apple/swift/tree/new-integer-protocols>. > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#a-note-on-bit-shifts>A > note on bit shifts > > This proposal introduces the concepts of *smart shifts* and *masking > shifts*. > > The semantics of shift operations are often undefined > <http://llvm.org/docs/LangRef.html#bitwise-binary-operations> 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. > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#detailed-design>Detailed > design > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#whats-new-since-se-0104>What's > new since SE-0104 > > - > > SE-0091 > <https://gist.github.com/moiseev/0091-improving-operators-in-protocols.md> > 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 > <https://gist.github.com/moiseev/0065-collections-move-indices.md> 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 > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#doublewidth> > for > more details. > > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#protocols> > Protocols > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#arithmetic> > 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 > } > } > > > <https://gist.github.com/moiseev/62ffe3c91b66866fdebf6f3fcc7cad8c#signedarithmetic> > 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 > >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution