-
Notifications
You must be signed in to change notification settings - Fork 34
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
Compact systematic display of values #51
Conversation
Maybe instead of |
It occurs to me that if we generated all typealiases (and yes, now I think they can be typealiases rather than consts), it would "only" be approx 256 exports. That's a lot, but perhaps not so many so as to make it untenable. |
Can they be type aliases and be in the suffix form? I was thinking of having a major that would generate the const in the users namespace, but I like the idea of just generating most of them ;) (What about Uint128 based ones ;)) |
80e602a
to
be32eff
Compare
OK, an update here (I think this implementation is "complete"). The proposal is to print julia> Fixed{Int16,7}(1.23)
1.227Q⁸₇ Here we're using the Q notation, where 8 is the number of magnitude bits and 7 the number of fractional bits. Note that 8+7=15, leaving one bit for the sign. I am not printing this as Likewise, we'd print julia> UFixed{UInt16,7}(1.23)
1.228U⁹₇ 9 is the number of magnitude bits, and again 7 is the number of fractional bits; the In this implementation, these are typealiases for the actual type, and we export all possible typealiases up to 64 bits. I also (somewhat unconventionally) define Another consequence is that On balance I like this proposal; the alternative is to print values as |
In general I really like this, but the super and subscripts can be hard to read. I program in a font-size of 14, but even then it is not clearly visible. But +1 for more compact printing, but this will also require a prominent explanation in the readme. |
Any good ideas for how to handle this without using super/subscripts? At the cost of an extra character, we could indicate the split with an additional unicode character. Perhaps |
you didn't entirely make up the U: "In addition, the letter U can be prefixed to the Q to indicate an unsigned value, such as UQ1.15, indicating values from 0.0 to +1.99997." (from the wiki article you linked). |
what are the consequences of exporting so many names? |
there is a convention to use B for byte (8 bits), W for word (16), D for double (32) and Q for quad (64). so one alternative to super/sub-scripts would be to say use |
True, but the normalization is still different. What they mean by julia> 0xffff/0x8000
1.999969482421875 whereas julia> typemax(UFixed{UInt16,15})
2.00003U¹₁₅ is equal to In case this confuses you, the easy way to remember why we have this distinction is like this:
and so |
The B, W, D, Q suggestion is quite interesting. I was trying to pick something close to "standard" notation, but it's clear that standards don't cover all of our needs, so we are going to have to strike out on our own somewhat. |
I don't think it's terrible. It just seems like a lot for a small package. By comparison, |
if you decide to go with BWDQ, i'd suggest instead to prepend with U for unsigned instead of S for signed, to mirror UInt and Int. |
I would reserve @timholy we could do a soft-rename in this case. Let's start using |
another alternative requiring little explanation would be |
@vchuravy, In that case, @bjarthur, I agree that being more explicit has some merits, but it's still pretty long compared to some of the choices we've been discussing. N9x7 (where x is to be determined) is only 4 characters, compared to 8 for UInt16F7. One thing your example does convince me of, though, is that maybe it wouldn't be so terrible to use a roman character for So perhaps |
No, I agree there won't be a signed variant of I am having a hard time deciding between:
and:
I find the first one easier to read, but the second one is more succinct (but requires more mental effort to parse) |
I also initially went with the equivalent of Q8f4, and still find that somewhat more intuitive. But one fairly big problem is that's inconsistent with the conventional notation: https://en.wikipedia.org/wiki/Fixed-point_arithmetic#Notation. (I know they don't use f, but perhaps that's a small detail.) Also, I think you have the opposite meaning of the number after the f that I've been using. I'm literally copying the value of |
ah I just made a mistake for |
I took the liberty of editing it to |
i'm fine with the second block. it's short, and similar to two standards (the wiki link and floating point). re. such a large namespace. perhaps we export just the even numbers of fractional bits? |
OK, updated. For now I'm exporting all types, rather than just the even ones. Two final questions:
|
be32eff
to
3e7e0c1
Compare
print(io, typechar(X)) | ||
f = nbitsfrac(X) | ||
m = sizeof(X)*8-f-signbits(X) | ||
print(io, m, 'f', f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be more performant to combine these two print
s into one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be, I'll do that.
Fixed16, | ||
UFixed8, | ||
U8, | ||
UFixed10, | ||
UFixed12, | ||
UFixed14, | ||
UFixed16, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we deprecate UFixed16
and friends?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think so. Fixed16 too?
# literal constructor constants | ||
U16, | ||
# Q and U typealiases are exported in separate source files | ||
# literal constructor constants | ||
uf8, | ||
uf10, | ||
uf12, | ||
uf14, | ||
uf16, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deprecate uf16
and friends too?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could, but those exist for a different reason---they are "repr
constructors"---that's not covered by anything else:
julia> 0xc2uf8
0.761N0f8
julia> 0.761N0f8
0.761N0f8
julia> 0xc2N0f8
ERROR: InexactError()
in *(::UInt8, ::Type{FixedPointNumbers.UFixed{UInt8,8}}) at /home/tim/.julia/v0.5/FixedPointNumbers/src/FixedPointNumbers.jl:63
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i don't think the casual user of julia would find this intuitive. is there nothing to be done that would make that work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we really don't like these, perhaps we should get rid of them.
But 0xc2N0f8
or N0f8(0xc2)
can never work as I think you're intending without causing absolute chaos. See JuliaGraphics/ColorTypes.jl#49 (comment). We need to firmly keep in mind the distinction between value and representation of that value, and generally one should just ignore the representation and think about the number in terms of its value. 0xc2 = 194
is far beyond the reach of a number representable with an N0f8
, so if the constructor doesn't throw an error you've got a big problem.
I think the key is to (1) reliably throw errors when the user tries something that's not allowed (we didn't do that before #48 because of arithmetic overflow), and (2) provide better error messages that actually coach users through how to think about this/fix problems, along the lines of #49 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, maybe I'll deprecate 0xc2uf8
in favor of reinterpret(N0f8, 0xc2)
. Reasonable? Forcing people to use reinterpret
explicitly might help clarify everyone's thinking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
doh! i was getting confused between value and representation just as you describe.
deprecating uf8
in favor of reinterpret
sounds great.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've confused myself so many times I've lost track. But I think we're moving towards a solution that will be easier to keep straight!
typealias UFixed8 UFixed{UInt8,8} | ||
typealias UFixed10 UFixed{UInt16,10} | ||
typealias UFixed12 UFixed{UInt16,12} | ||
typealias UFixed14 UFixed{UInt16,14} | ||
typealias UFixed16 UFixed{UInt16,16} | ||
typealias U16 UFixed{UInt16,16} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UFixed{UInt16,16}
is already aliased as N0f16
. i think that's short enough, and having another nomenclature would just add confusion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I largely agree with this. But should we apply the same logic to U8
? In the Colors/Images world, we use RGB{U8}
all the time. That would become RGB{N0f8}
, which is not bad, but a little more to remember. (Probably I'm just not used to it, though.)
I also think it's valid to decide to keep U8 but ditch U16. Basically, I am persuadable to any outcome on this point 😄.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, i'd suggest ditch U8
too. it's bad enough that signed fixed point ints are scaled differently than unsigned ones. we don't need multiple ways to specify the latter to make it even more confusing. N0f8
is already a huge improvement over the status quo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The U8 notation is pretty intuitive for someone coming from an image processing background since most packages use the general datatypes defined in their languages as the base Image type unlike Images.jl where we have FixedPointNumbers to abstract that out and give us one less thing to worry about 😄
If we are going to remove U8 and friends, then we need to support it with good documentation in the Images.jl packages (explaining how FixedPointNumbers works, why it helps and the notation). This does seem like a big change though so if you could also have a big warning message when you deprecate U8 (something that explains how to use the Nxfy notation too) it will really help users. Apart from this, I like the new implementation and even if there is a bit of a learning curve to it, I guess its worth it in the long run 😄
scaledual | ||
|
||
reinterpret(x::FixedPoint) = x.i | ||
|
||
# construction using the (approximate) intended value, i.e., 0.8U⁰₈ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't forget to change this comment to match whatever format we finally decide on
9a908e7
to
1aa2ba9
Compare
OK, I've rebased this and addressed review comments. I've deprecated everything in sight, but there's a chance we'll want to rethink some of these (particularly the Also note: I added a shell script in the (new) |
Current coverage is 82.58% (diff: 47.82%)@@ master #51 diff @@
==========================================
Files 3 4 +1
Lines 164 178 +14
Methods 0 0
Messages 0 0
Branches 0 0
==========================================
+ Hits 145 147 +2
- Misses 19 31 +12
Partials 0 0
|
i believe ColorTypes.jl will have to be changed once this PR is merged to typealias U8 to N0f8 |
If you use |
223772d
to
fdf5506
Compare
Heads-up @vchuravy, this will happen over the weekend. (ref #51 (comment)) |
This rename reflects the nature of `UFixed` it is not just a unsigned fixpoint number type (for that you can use `Fixed{T<:Unsigned}`), but rather a number type that is normalised to a specific `one`.
Rename UFixed to Normed
Bam. Let the chaos begin. |
Note: this proposal has been updated, please skip ahead to #51 (comment)
This introduces value printing of the following form:
Moreover, for
UFixed8
,UFixed10
, ..., the same sequence of characters is interpreted as a constant that allows values to be reconstructed:This has pros and cons:
T
andf
. Or some way of modifying julia's parser.