-
Notifications
You must be signed in to change notification settings - Fork 71
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
add tryinto instances for integer types to floats #900
Conversation
I don't think this is the right approach. All of these types have known bounds, the conversion code should just check if the input value is exactly representable in the output type. Also all of these conversions are infallible, so they should use The ones that are missing are |
@eliaslfox should I start working on this again? |
If you want to. The issue is still open. Does what I said about how to proceed make sense? |
so I should do TryInto from I64, U64, IFix, and UFix? but I dont get this quote “so if a value is within a floats range, but outside the safe range the conversion should fail”. |
Floats have a range of values they can represent, but only some of that range represents numbers exactly. Larger values (or larger negative values) are imprecise. TryInto shouldn't lose precision, so when converting a value a float, if the values is outside the float's "safe range" then the conversion should fail. |
I could be misremembering, but I think the safe range for f64 (our |
Thanks. Can you provide a link to an example where there’s a test to check whether the values are outside the safe range? Thanks here’s there’s a check whether it’s out of range https://github.com/coalton-lang/coalton/blob/main/library/math/conversions.lisp#L182. Is it like that? here’s a stackoverflow answer |
I think @gefjon is right about the ranges. Just check that the value is within (-2^53, 2^53) before coercing to a double float. The stack overflow answer will give confusing results because some values will coerce to floats, but that value plus or minus one won't. This is because some integers above 2^53 can be represented exactly as a double float, but not all of them. See floating point for more information. Also the Coalton code you linked should probably be updated to check integer ranges directly. I'm not sure if erroring when a value is out of range in coerce is guaranteed by the standard. |
@eliaslfox want to take a look at my changes? let me know if I have to make any changes please. thanks |
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.
A couple minor things. Also single-floats should have TryInto U32|I32 Single-Float
.
library/math/conversions.lisp
Outdated
(cl:if (cl:null y) | ||
(Err (cl:concatenate 'string ,integer-name "to " ,float-name " conversion out-of-range")) | ||
(Ok y))) | ||
(Err (cl:concatenate 'string "Given integer" is not within "(-2^" (write-to-string ,pow) ", " "2^" (write-to-string ,pow) ")")))))))) |
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.
Write this as (Err ,(cl:concatenate ...))
so that it runs during macro expansion.
library/math/conversions.lisp
Outdated
(define (tryInto x) | ||
(lisp (Result String ,float) (x) | ||
(cl:if (cl:and (cl:> x (cl:expt -2 ,pow)) (cl:< x (cl:expt 2 ,pow))) | ||
(cl:let ((y (cl:ignore-errors (cl:coerce x (cl:quote ,lisp-float))))) |
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 ignore errors here. The conversion should never fail, and if it does we want to know.
library/math/conversions.lisp
Outdated
@@ -182,5 +182,32 @@ cannot be represented in :TO. These fall into a few categories: | |||
(Err "Integer to Double-Float conversion out-of-range") | |||
(Ok y))))))) | |||
|
|||
(cl:defmacro integer-tryinto-float (integer integer-name lisp-float float float-name pow) |
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.
Have the macro generate a define-instance
without a coalton-toplevel
. Then call the macro inside a toplevel like:
(coalton-toplevel
(integer-tryinto-float ...)
...)
This allows the Coalton compiler to gives better error messages.
library/math/conversions.lisp
Outdated
|
||
|
||
;; Single Float | ||
(integer-tryinto-float I64 "I64" cl:single-float Single-Float "Single-Float" 24) |
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.
You don't need to pass the type names as strings. Symbols can be converted to strings with cl:symbol-name
.
@eliaslfox Ok I have addressed your review |
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.
A couple minor things
library/math/conversions.lisp
Outdated
(Err `,(cl:concatenate 'string "Given integer" "is not within " "(-2^" (write-to-string ,pow) ", " "2^" (write-to-string ,pow) ")"))))))) | ||
|
||
;; Single Float | ||
(coalton-toplevel |
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.
These can all be one coalton-toplevel
library/math/conversions.lisp
Outdated
(define (tryInto x) | ||
(lisp (Result String ,float) (x) | ||
(cl:if (cl:and (cl:> x (cl:expt -2 ,pow)) (cl:< x (cl:expt 2 ,pow))) | ||
(cl:let ((y (cl:coerce x (cl:quote ,lisp-float)))) |
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.
Instead of (cl:quote ,lisp-float)
write ',lisp-float
library/math/conversions.lisp
Outdated
(cl:if (cl:and (cl:> x (cl:expt -2 ,pow)) (cl:< x (cl:expt 2 ,pow))) | ||
(cl:let ((y (cl:coerce x (cl:quote ,lisp-float)))) | ||
(cl:if (cl:null y) | ||
(Err `,(cl:concatenate 'string (cl:symbol-name ,integer) "to " (cl:symbol-name ,float) " conversion out-of-range")) |
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.
Because this coercion should never fail, signal an error with cl:error
instead returning Err
.
Also you need to wrap the macro definition in an |
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.
Looks good
It looks like there's merge conflicts. Resolve them locally with |
@eliaslfox do i update the branch or do you take over from here? |
Don't update with the web ui, it'll create a merge commit. It needs to be done locally with |
do i do this from my current branch |
from |
Also you should squash your commits to a single commit. |
@eliaslfox ok i have successfully rebased -- ie resolved all the conflicts manually. i was having trouble but after eating some chips i was able to to do it |
@eliaslfox hey so i dont think theres merge conflicts now. the other day robert said he could squash the commits on his end. could you squash the commits? im fighting git right now. it seems like an endless cycle |
Yeah I can squash it tomorrow. |
thanks. there shouldnt be merge conflicts. i resolved all the conflicts manually |
@eliaslfox nice it got merged! so cool! |
this PR is about this issue.