[swift-evolution] [Draft]: Introducing a striding(by:) method on 3.0 ranges

Xiaodi Wu xiaodi.wu at gmail.com
Sun Apr 10 02:13:18 CDT 2016


The iteration counter will be floating point and the iterator will break
down after incrementing by one is no longer exactly representable. It has
been made clear on this list that there is a strong preference that no
floating point stride should degenerate into an infinite loop due to this
issue. Thus, there will be a limit at the time a floating point stride is
created of 2^53 steps (in the case of a Double--some thought is necessary
for a Float). As currently mocked up the logic is whether start + 2^53 *
stride gets you to/through the end. If not, precondition failure.
On Sun, Apr 10, 2016 at 7:41 AM <davesweeris at mac.com> wrote:

> I understand (and agree with) 3/4 of that… Why do we want to prevent
> striding *to* an infinity? I mean, yeah it’ll take a long time to get
> there, but with the new floating point stride code, a floating point value
> will *eventually* “overflow” into infinity (or `iteration += 1` will
> overflow and crash), it’s just that at that point there isn’t a
> straight-forward way to go the other direction anymore.
>
> Actually, striding from an infinity should be ok, too, as long as it’s not
> the actual starting point:
> let x = -Double.infinity ... 0.0 // Big Problems in, um, Non-Little
> Loops… or something… (and apologies to Kurt Russell)
> let x = -Double.infinity <.. 0.0 // starts at `nextafter(start, end)`
> (-1.797693134862316e+308, in this case)
>
> If the infinities are definitely out even as exclusive endpoints, can the
> floating point types get min/max properties like the integer types have?
> let x = Double.min ... Double.max // same as -1.797693134862316e+308 ... 1.797693134862316e+308,
> but way easier to write
> let x = Float.min ... Float.max // same as -3.402823e+38 ... 3.402823e+38
>
> - Dave Sweeris
>
> On Apr 10, 2016, at 12:05 AM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> We will be proposing exactly that which you've put in parentheses, i.e.
> floating point types will get their own strides, and it will be a
> precondition failure to try to stride from or to infinity or nan :)
>
> On Sun, Apr 10, 2016 at 4:47 AM <davesweeris at mac.com> wrote:
>
>> It’s not a matter of floating point error accumulation… At least on my
>> machine, once a Double hits +/-∞, there’s no way that I know of to get back
>> to normal floating point numbers. That is to say, for *all* normal, finite
>> values of x, "-Double.infinity + x" will just return “-inf". If x is to
>> equal Double.infinity, Double.NaN, or Double.quietNaN, then it’ll return
>> “nan” (which, incidentally, will fail the regular equality test… Double.NaN
>> isn’t even equal to itself; I think checking the floating point class is
>> the way to do it).
>>
>> I could easily be missing something, but AFAICT the only way to always
>> get the correct sequence (without splitting the floating point types off
>> into their own thing) is either have a negative stride swap start and end
>> *before* the StrideTo starts generating values (that is, *not* by just
>> calling `.reverse()` on something with a positive stride), or to allow “0
>> ..< -Double.infinity” to be a valid range (with the negative stride being
>> implied).
>>
>> - Dave Sweeris
>>
>> On Apr 9, 2016, at 6:59 PM, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>>
>> Yikes. Not too concerned about the infinite loop issue, as floating point
>> strides when fixed to avoid error accumulation will necessarily enforce a
>> finite number of steps. However, you're talking a regular, not-at-all-lazy
>> Array being returned? That would be not good at all...
>>
>> On Sun, Apr 10, 2016 at 12:29 AM Dave via swift-evolution <
>> swift-evolution at swift.org> wrote:
>>
>>>
>>> On Apr 9, 2016, at 4:33 AM, Haravikk via swift-evolution <
>>> swift-evolution at swift.org> wrote:
>>>
>>> While I’m in favour of the basic idea I think the operator selection is
>>> too complex, and I’m not sure about the need for negative strides. Really
>>> all I want are the following:
>>>
>>> (0 ... 6).striding(by: 2) // [0, 2, 4, 6] x from 0 to 6
>>> (0 ..< 6).striding(by: 2) // [0, 2, 4] x from 0 while <6
>>> (6 ... 0).striding(by: 2) // [6, 4, 2, 0] x from 6 to 0
>>> (6 ..> 0).striding(by: 2) // [6, 4, 2] x from 6 while >0
>>>
>>> Everything else should be coverable either by flipping the order, or
>>> using .reverse(). The main advantage is that there’s only one new operator
>>> to clarify the 6 ..> 0 case, though you could always just reuse the
>>> existing operator if you just interpret it as “x from 6 to, but not
>>> including, 0"
>>>
>>>
>>> `.reverse()` returns an array, though, not a StrideTo<>, which means
>>> it’ll get in an infinite loop on infinite sequences. This works fine:
>>> for i in stride(from: 0.0, to: Double.infinity, by: M_PI) {
>>>     if someTestInvolving(i) { break }
>>>     ...
>>> }
>>>
>>> But this never even starts executing the loop because of the infinite
>>> loop inside `.reverse()`:
>>> for i in stride(from: -Double.infinity, to: 0.0, by: M_PI).reverse() {
>>>     if someTestInvolving(i) { break }
>>>     ...
>>> }
>>>
>>> - Dave Sweeris
>>> _______________________________________________
>>> 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/20160410/bf974bf8/attachment.html>


More information about the swift-evolution mailing list