-
Notifications
You must be signed in to change notification settings - Fork 122
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
Unexpected output #1089
Comments
I suspect this might have to do directly with libBF, as opposed to Cryptol. There seems to be an online calculator at http://numcalc.com. I tried:
which matches Cryptol output, but it is still the wrong output. I've mailed the author of LibBF to see if he has any feedback; but he hasn't responded yet. |
Interesting, this seems to be due to fact that we are using the
so I thought this version might be nicer... I wonder if it is doing that because it is considering 65500 to have "fewer" digits than 65504 but when you parse it back you'd get the same thing. If this is the intended behavior, I find it rather confusing, and maybe we should use the |
I got a response from the author:
So yeah, it seems the number itself is correctly represented, but decimal conversion is busted. |
To be clear, one can argue it is doing the right thing, just not the expected thing. More strongly, perhaps we're expecting a bit too much. As a half-float:
Notice that the above two representations are next-to-each other, i.e., there are no other numbers between them that is exactly representable. In this binade, representable numbers are separated by 32, as evidenced by Given any output from Perhaps there's really nothing to do here, except to note this in the documentation as floats are strangely beasts and full of these sorts of surprises. Calling this a bug seems a bit too harsh. |
I expect the printing functions in Cryptol to be precise; so to the extent this behavior represents a mismatch between expectations and behavior, I think that's a bug. The |
I agree it's a bug, except it is probably our bug rather than upstream, so maybe we should remove that label, and we should just change Cryptol to use |
|
We can actually confirm the 17-16 split in the mapping.
Funny how the first 17 is represented as I'd like to know what the above prints if you get around to changing the printing to the |
@LeventErkok I can give it a go a bit later today. Btw, we are using some Haskell bindings to |
Changing to the
I'm not sure this is exactly what we want either. Maybe we can get precise decimal output somehow. |
That looks correct though. Try running it after |
Oh, right, I forgot it was a separate setting.
This seems like what we'd want. |
Bingo! Looks like BTW, I ran into the following:
I totally understand the error, but surely that's not what you intended to print to the user! |
I think that's #975 |
Ah, my version of Cryptol is 2.9.0 from hackage, that explains it. Thinking a bit more about this though, there seems to be an oddity. Why is the following well typed?
What does Cryptol think the type of those literals are? Clearly, they cannot be |
Yeah, I think that's #1062. I thought it'd be nice to check that literals are exactly representable, but I forgot that we also assume the literals are downward closed so that we don't infer super polymorphic types for long sequences of numbers. If you have ideas, let's comment on that ticket. I think, currently we are thinking of maybe just allowing you to write imprcise literals (in base 10), and have them be rounded in some way. |
Playing a bit more about this, I'm convinced import LibBF (BigFloat)
import qualified LibBF as BF
data FP = FP { fpExponentSize :: Int
, fpSignificandSize :: Int
, fpValue :: BigFloat
}
-- | Show a big float in the base given.
-- NB. Do not be tempted to use BF.showFreeMin below; it produces arguably correct
-- but very confusing results. See <https://github.com/GaloisInc/cryptol/issues/1089>
-- for a discussion of the issues.
bfToString :: Int -> Bool -> FP -> String
bfToString b withPrefix (FP _ sb a)
| BF.bfIsNaN a = "NaN"
| BF.bfIsInf a = if BF.bfIsPos a then "Infinity" else "-Infinity"
| BF.bfIsZero a = if BF.bfIsPos a then "0.0" else "-0.0"
| True = trimZeros $ BF.bfToString b withP a
where opts = BF.showRnd BF.NearEven <> BF.showFree (Just (fromIntegral sb))
withP
| withPrefix = BF.addPrefix <> opts
| True = opts
trimZeros s
| '.' `elem` s = reverse $ case dropWhile (== '0') $ reverse s of
res@('.':_) -> '0' : res
res -> res
| True = s |
I've released a new version of SBV (v8.12), that now supports arbitrary-sized floats. I understand that Cryptol doesn't use SBV for floats currently, and there's probably no real ROI to add support for it; but just in case you want to compare the results to What4 gave you, it might come in handy. It could also be useful in other projects. In particular, there's a new Prelude Data.SBV> satWith z3{crackNum=True} $ \(x :: SFloatingPoint 5 11) -> x .== 65504
Satisfiable. Model:
s0 = 65504 :: FloatingPoint 5 11
1 0
5 43210 9876543210
S -E5-- ---S10----
Binary layout: 0 11110 1111111111
Hex layout: 7BFF
Precision: Half (5 exponent bits, 10 significand bits.)
Sign: Positive
Exponent: 15 (Stored: 30, Bias: 15)
Classification: FP_NORMAL
Binary Value: 0b1.1111111111p15
Octal Value: 0o177740
Decimal Value: 65504
Hex Value: 0xffe0 The implementation uses Iavor's LibBF under the hood. Cheers! |
I don't think this zero-trimming function quite what you want, either. If there is an exponent suffix, I think the function above won't trim the zeros because they appear in the middle of the string. E.g., if I just use the
|
I don't think Did you see otherwise? |
Via GHCi
|
Ah, my bad. Apparently I didn't test it enough. SBV shows the same: Prelude> :m + Data.SBV
Prelude Data.SBV> :set -XDataKinds
Prelude Data.SBV> 1e64 :: SFloatingPoint 11 53
1.0000000000000000e64 :: SFloatingPoint 11 53 Surprisingly, it doesn't do that with larger precision: Prelude Data.SBV> 1e64 :: SFloatingPoint 11 200
10000000000000000000000000000000000000000000000000000000000000000 :: SFloatingPoint 11 200 Same in GHCi:
I'm not sure what sort of logic it's following here.:
I guess it gives up on the In either case you're right; need to do a bit more string-manipulation there to get it cleaner. |
That is very odd. |
has highly counterintuitive results. Instad, use the `showFree` mode, which produces results more accurate to the underlying bit representation. The `showFree` mode often produces unfortunate trailing zeros in decimal representations, so we take some care to trim those out. Fixes #1089
Wondering why
65504
prints as65500
. (It's the maximum representable half-float.) Is this a printing issue, or perhaps something else is going on?The text was updated successfully, but these errors were encountered: