Skip to content
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

Fix ToPrimitive for f64 -> f32 conversion. #180

Merged
merged 1 commit into from
Apr 15, 2016

Conversation

bluss
Copy link
Contributor

@bluss bluss commented Mar 7, 2016

Fix ToPrimitive for f64 -> f32 conversion.

It should use the destination type and not the source type to check if
the conversion would be to a value that's in range.

NOTE: A finite f64 value that is larger than the f32 value range now produces
None when converted to f32 with ToPrimitive.

Previously, too large f64 values would produce inf f32 values. This as
cast has an undefined result and was not specified to always produce for
example inf.

The conversion preserves nan/+-inf specifically.

@bluss
Copy link
Contributor Author

bluss commented Mar 16, 2016

I guess this is stopping because of the ongoing trait refactoring? That's ok, I think splitting is a good idea.

@cuviper
Copy link
Member

cuviper commented Mar 16, 2016 via email

@homu
Copy link
Contributor

homu commented Apr 13, 2016

☔ The latest upstream changes (presumably #164) made this pull request unmergeable. Please resolve the merge conflicts.

@bluss
Copy link
Contributor Author

bluss commented Apr 14, 2016

Updated. This is a breaking (behavior, not compile) change but also a bug fix.

@bluss
Copy link
Contributor Author

bluss commented Apr 14, 2016

The effect of the bug was that it always return Some for floats. Maybe that's a bad thing to change without a new version? The current code is just nonsensical and we could change it into just the cast without the if.

@bluss
Copy link
Contributor Author

bluss commented Apr 14, 2016

Hm ok it's alwaysnot always. inf is always converted to None.

@cuviper
Copy link
Member

cuviper commented Apr 14, 2016

I think it's safe to classify this as a pure bugfix, not a breaking change, as the intent was clearly there to have a range check. Otherwise, we'll never be able to change anything! (ref https://xkcd.com/1172/)

However, there are some strange edge cases here. If I'm reading correctly, f32->f64 inf will succeed, but either f32->f32 or f64->f64 will be None. I think it's reasonable to expect inf and NaN to convert all around, but then shouldn't large f64 just be f32 inf anyway?

@cuviper
Copy link
Member

cuviper commented Apr 14, 2016

(nevermind, comparing sizes <= makes self-conversion stable. I read it as just <)

@bluss
Copy link
Contributor Author

bluss commented Apr 14, 2016

I had to do research. Now we have even better backing for changing the behavior. Casting a too large f64 to f32 is UBhas undefined result according to langref. This is indeed the instruction rust uses playground link (Nightly/Release/LLVM IR to see).

Now this isn't fully num's concern to solve, core Rust will have to solve this and I think it's pretty well known (the trouble with as and floating point casts). But it means that the range check in the method is well intentioned.

@cuviper
Copy link
Member

cuviper commented Apr 15, 2016

Can you make it so +/-inf and NaN carry over from f64 to f32?

The range check could decide to manually create inf for out of range values, dodging the undefined result. But maybe None is better so there's a signal that it didn't really convert.

(And then float->int is completely unchecked... #135 was working on that.)

@bluss
Copy link
Contributor Author

bluss commented Apr 15, 2016

Yes, I will come back to it tomorrow.

It should use the destination type and not the source type to check if
the conversion would be to a value that's in range.

NOTE: A finite f64 value that is larger than the f32 value range now produces
None when converted to f32 with ToPrimitive.

Previously, too large f64 values would produce inf f32 values. This `as`
cast has an undefined result and was not specified to always produce for
example `inf`.

The conversion preserves nan/+-inf specifically.
@bluss
Copy link
Contributor Author

bluss commented Apr 15, 2016

Updated commit & PR message. It now preserves nan/inf (using !f32::is_finite())

@cuviper
Copy link
Member

cuviper commented Apr 15, 2016

Thanks!

@homu r+ acde249

@homu
Copy link
Contributor

homu commented Apr 15, 2016

⚡ Test exempted - status

@homu homu merged commit acde249 into rust-num:master Apr 15, 2016
homu added a commit that referenced this pull request Apr 15, 2016
Fix ToPrimitive for f64 -> f32 conversion.

Fix ToPrimitive for f64 -> f32 conversion.

It should use the destination type and not the source type to check if
the conversion would be to a value that's in range.

NOTE: A finite f64 value that is larger than the f32 value range now produces
None when converted to f32 with ToPrimitive.

Previously, too large f64 values would produce inf f32 values. This `as`
cast has an undefined result and was not specified to always produce for
example `inf`.

The conversion preserves nan/+-inf specifically.
@bluss bluss deleted the fix-toprimitive-float branch April 15, 2016 16:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants