-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unsigned ranges with large ("negative") step are (semi)empty #29801
Comments
The - will promote to signed or crash.
Does using reverse(UInt(1):UInt(16)) help?
…On 25 Oct 2018 09:37, "PeterJacko" ***@***.***> wrote:
While signed integers can count backwards,
julia> collect( Int16( 10 ) : -Int16( 1 ) : Int16( 0 ) )
11-element Array{Int16,1}:
10
9
8
7
6
5
4
3
2
1
0
unsigned integers can't :(
julia> collect( UInt16( 10 ) : -UInt16( 1 ) : UInt16( 0 ) )
0-element Array{UInt16,1}
I am using it in a for loop like
for n = UInt16( 10 ) : -UInt16( 1 ) : UInt16( 0 )
...
end
because I need "n" to be of type UInt16 inside the loop (to avoid type
changes, to improve performance).
julia> versioninfo()
Julia Version 1.0.1
Commit 0d71392
<0d71392>
(2018-09-29 19:05 UTC)
Platform Info:
OS: Windows (x86_64-w64-mingw32)
CPU: Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-6.0.0 (ORCJIT, skylake)
Environment:
JULIA_EDITOR = "C:\JuliaPro-1.0.1.1\app-1.29.0\atom.exe" -a
JULIA_NUM_THREADS = 2
JULIA_PKG_SERVER = https://pkg.juliacomputing.com/
JULIA_PKG_TOKEN_PATH = C:\Users\Peter.julia\token.toml
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#29801>, or mute the thread
<https://github.com/notifications/unsubscribe-auth/AMc4te-fQRojtg29N7s2MYodhPq5MjElks5uocy5gaJpZM4X6bVo>
.
|
See also #29576 |
The "-" actually loops through and instead of "-1" gives "65535" (the highest value of UInt16). No, reverse doesn't help: julia> collect(reverse(UInt16(0):UInt16(10))) |
I'd say that one is definitely a bug. What you're saying when you write julia> collect( UInt16( 10 ) : -Int16( 1 ) : UInt16( 0 ) )
11-element Array{UInt16,1}:
0x000a
0x0009
0x0008
0x0007
0x0006
0x0005
0x0004
0x0003
0x0002
0x0001
0x0000 |
Was there ever an exhaustive discussion of the semantics of unsigned ranges? Because one could argue that they should wrap, i.e. unsigned unit ranges should never be empty and should be covariant under addition (add x to both start and stop == add x to each element). |
Oh, well the reverse bug is #29576. Let's use this issue to discuss those overflow semantics — although I'm still searching for others. |
Supporting overflow here could indeed make sense, but there's a bad smell coming from the generic definition of |
Ok, let's have this discussion. Just to be clear: The ultimate judge of desired semantics should be usefulness in practical contexts, not mathematical elegance or consistency. I am going to argue the mathematically consistent model, just for the sake of trying it on; I am honestly very unsure what semantics I would prefer. Consider unitranges of UIntx first. What should it mean for a number Now, step ranges. An natural viewpoint is to consider Now what about length? In order to compute the length, we will need to distinguish between cases. If The fact that we need to do "trickery" is nothing bad; consider the "trickery" performed in On the other hand, many |
I'd argue that both must be considered and weighted against each other. That's why I simply say it's a bad smell — it's just one signal to consider. We in fact do do all sorts of signed/unsigned/negative/positive trickery for length in the case of If you take the stance that In terms of user expectation, I think it's valuable to note that we support translatability (including modN overflow) up until the resulting range straddles a wraparound. That is, julia> (Int8(126):Int8(127)) .+ Int8(0)
126:127
julia> (Int8(126):Int8(127)) .+ Int8(1)
ERROR: InexactError: trunc(Int8, 128)
julia> (Int8(126):Int8(127)) .+ Int8(2)
-128:-127
# -------------------------------------------
julia> (Int8(63):Int8(64)) .* Int8(1)
63:1:64
julia> (Int8(63):Int8(64)) .* Int8(2)
ERROR: InexactError: trunc(Int8, 128)
julia> (Int8(63):Int8(64)) .* Int8(3)
-67:3:-64 I'd argue that More succinctly: |
So it's not in there. The idea of this thing is: We have the set
That is correct, and an unfortunate side-effect of ranges being inclusive on both sides, which is an unfortunate side-effect of one-based indexing. Btw, is the following a new issue or the same? Pointer ranges with negative step do make sense, after all, and there is no wrap happening.
Cf also #29810. I think the example of pointers makes my thinking clearer: The crucial property of ranges is a ternary comparison on the domain, plus an abelian group action of |
Well that's a different operation. We don't do conversions when checking In any case, I'm now convinced we cannot support this meaning. |
But do we want to support |
Yes, that's #29576 — which was immediately marked as a bug. It's an easy fix… I just need to write a few tests and push it. |
I was going to close this, as we already have #29576, but it turns out the OP counter-example is now also broken: julia> @test length( UInt16( 10 ) : -UInt16( 1 ) : UInt16( 0 ) ) == 0
Test Failed at REPL[9]:1
Expression: length(UInt16(10):-(UInt16(1)):UInt16(0)) == 0
Evaluated: 1 == 0
ERROR: There was an error during testing
julia> @test isempty( UInt16( 10 ) : -UInt16( 1 ) : UInt16( 0 ) )
Test Passed
Expression: isempty(UInt16(10):-(UInt16(1)):UInt16(0))
Evaluated: isempty(0x000a:0xffff:0x0009) |
Fixes JuliaLang#29801 (cherry picked from commit b71330d)
While signed integers can count backwards,
unsigned integers can't :(
I am using it in a for loop like
because I need "n" to be of type UInt16 inside the loop (to avoid type changes, to improve performance).
The text was updated successfully, but these errors were encountered: