[swift-evolution] [Discussion] Arbitrary precision integer and float literal protocols

Xiaodi Wu xiaodi.wu at gmail.com
Fri Mar 31 12:08:14 CDT 2017


On Fri, Mar 31, 2017 at 3:45 AM, Brent Royal-Gordon via swift-evolution <
swift-evolution at swift.org> wrote:

> On Mar 30, 2017, at 2:56 PM, David Hart via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> The current protocols ExpressibleByIntegerLiteral and ExpressibleByFloat
> Literal are simple and work well but don't support arbitrary precision
> literal values. Replacing those protocols is a non-goal as they provide a
> simple interface for work well for most cases.
>
> Honestly, I don't think I agree with this. I see no particular reason to
> like our current protocols; they break down as soon as your type gets
> larger than the largest standard library integer/float type, which
> undermines one of their main use cases.
>

Right. I think the existing ones should, if at all possible, be revised to
support arbitrary precision literal values--or at least very, very large
precision literal values (as it can be argued that, even for a BigInt, the
ability to specify a value of arbitrarily many digits as a _literal_ would
be rarely used).


> I've been toying with a different approach in my head for a few weeks. The
> `BinaryInteger` protocol contains the concept of a `words` collection,
> which expresses any integer type as a collection of `UInt`s containing a
> signed two's-compliment representation of the integer. That means any
> `BinaryInteger` already contains code to handle a `words` collection. If we
> made this more exposed in some way, then `ExpressibleByIntegerLiteral`
> could leverage that conformance.
>
> One approach would be to extract the `words` collection into a
> higher-level protocol:
>
> protocol BinaryIntegerSource {
> associatedtype Words: Collection where Iterator.Element == UInt
> var words: Words { get }
> }
>
> Then we could modify `BinaryInteger` to accept this:
>
> protocol BinaryInteger: BinaryIntegerSource {
> ...
> init<T : BinaryIntegerSource>(_ source: T)
> ...
> }
>
> And introduce a new `IntegerLiteral` type which is a
> `BinaryIntegerSource`, but not a `BinaryInteger` (so you can't do
> arithmetic with it):
>
> struct IntegerLiteral: BinaryIntegerSource {
> associatedtype Words = …
> var words: Words { … }
> }
>
> And now, you can say something like:
>
> struct Int128: ExpressibleByIntegerLiteral {
> fileprivate var _value: DoubleWidth<Int64>
> init(integerLiteral value: IntegerLiteral) {
> _value = DoubleWidth(value)
> }
> }
>
> And everything ought to do what it's supposed to. You could still use a
> different type if you didn't need anything larger than, say, `Int`. I don't
> believe this would require any changes to the compiler; `IntegerLiteral`
> could conform to `_ExpressibleByBuiltinIntegerLiteral`, which would allow
> it to represent integers up to the current limit of 1024 bits + 1 sign bit.
>
> (There are a few similar approaches we could take, like exposing an
> `init(words:)` constructor in `BinaryInteger` and having the
> `IntegerLiteral` behave as a `Words` collection, but all of them basically
> involve bootstrapping into `BinaryInteger` through the `Words` type.)
>
> I *think* that the not-yet-implemented `BinaryFloatingPoint.init<
> Source: BinaryFloatingPoint>(_ value: Source)` initializers could be
> leveraged in a similar way—create a `BinaryFloatingPointSource` protocol
> and a `BinaryFloatLiteral` type that conforms to it—but I'm less certain of
> that because I don't really understand how this universal float conversion
> is supposed to work. Plus, the universal float conversion is still just a
> TODO comment right now.
>

Hmm, I wonder if less is more.

First, we will soon have DoubleWidth types in the stdlib, which I would
hope means that they will be useable out of the box as integer literal
types. This would cover a lot of use cases, I'd imagine, as it would
trivially get you 128-bit and 256-bit types. Though they might be less
efficient for arithmetic, they should be perfectly suitable for
initializing a value from a literal.

For larger than 256 bits, could we not recover almost all of the benefits
by exposing Int2048 as an integer literal type? Given that Float80 has not
been abused, I don't think it's the case that offering Int2048 means people
will reach for it to do arithmetic when a smaller type will do.

(This would leave non-binary floats in the lurch, but we're pretty much
> doing that already—try initializing `Decimal` through its
> `ExpressibleByFloatLiteral` conformance sometime and you'll see what I
> mean. I would support changing its name to `ExpressibleByBinaryFloatLitera
> l`.)
>

This is actually one of the greatest deficiencies I see in
`ExpressibleByFloatLiteral`. Here, I would disagree with you and say that
I'd like to see `ExpressibleByFloatLiteral` improved precisely because of
its very poor functionality for `Decimal`. IMO, while saying that floating
point literals are only meant to work in binary would mean that the current
design is "correct," it's unfortunate and unjustifiable that `0.1` doesn't
mean 0.1.

Honestly, I'd even prefer to allow `String` as a floating point literal
type (because after all that's what Decimal is really doing under the hood)
than to just give up on this aspect of float literals altogether. I don't
have a good answer here but I would hate to see this opportunity lost to
fix the deficiency for real.

These leave our current integer and floating-point literal size limits
> (1025-bit signed integers and 80-bit floats) in place, but those are
> implementation details and could be changed. In practice, I very much hope
> the compiler will try to optimize initialization from literals aggressively.
>
> --
> Brent Royal-Gordon
> Architechies
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170331/4b2a91e5/attachment.html>


More information about the swift-evolution mailing list