-
Notifications
You must be signed in to change notification settings - Fork 174
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 crate that enables the full float APIs in #[no_std]
#4002
Conversation
core_float
crate that enables the full float APIs in #[no_std]
core_float
crate that enables the full float APIs in #[no_std]
utils/core_maths/src/lib.rs
Outdated
let r = self % rhs; | ||
if r < 0.0 { | ||
r + rhs.abs() | ||
} else { | ||
r | ||
} |
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.
General issue: We should minimize the amount of math code in this crate. If we must add any, it should be well tested. One way to test it is to run it against the standard library implementation on a suitably diverse set of inputs.
Specific issue: Pretty sure the div/rem euclid impls here aren't right. The standard library impl Rem says:
The remainder has the same sign as the dividend and is computed as:
x - (x / y).trunc() * y
But rem_euclid is a different thing. It is the remainder relative to the floor, not the trunc. You can't derive that by taking .abs()
.
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.
All code here is copied from std
, with calls to intrinsics replaced by libm. You're linking to Rem
, which is a different operation to rem_euclid
.
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 r + rhs.abs()
I think is correct. We care a lot about rem_euclid for calendrical calculations.
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.
rhs.abs()
is the more general form, we use rhs
in our version because we require rhs > 0
utils/core_maths/src/lib.rs
Outdated
} | ||
|
||
#[inline] | ||
fn powi(self, mut exp: i32) -> Self { |
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.
this is the only code not copied from std::f64
, libm doesn't have a powi
so this is from u64::pow
.
core_float
crate that enables the full float APIs in #[no_std]
core_maths
crate that enables the full float APIs in #[no_std]
utils/core_maths/Cargo.toml
Outdated
include.workspace = true | ||
|
||
[dependencies] | ||
libm = "0.2" |
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 this dep be cfg(target_os = none)
?
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.
Sure
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.
actually this doesn't work, it's possible to build no_std
on a target with an OS.
core_maths
crate that enables the full float APIs in #[no_std]
core_float
crate that enables the full float APIs in #[no_std]
I'm not convinced that this PR is a positive change for these reasons:
Footnotes
|
We don't have to keep it in sync, Rust We have other utility crates that are not used by every component, like crlify, deduplicating_array, even litemap is only used by two components. This trait is not object safe because it takes |
core_float
crate that enables the full float APIs in #[no_std]
#[no_std]
|
The most likely situation I'm thinking of is Rust std adding new mathematical operations. Not super common but it does seem to happen from time to time (f64::clamp, f64::total_cmp, f64::from_ne_bytes and friends, f64::to_int_unchecked, f64::EPSILON, f64::copysign, f64::div_euclid, and f64::rem_euclid are all examples of APIs added after 1.0), and I don't want the ICU4X team to take on the responsibility to check for that. |
I think you might be overestimating the maintenance burden. I'm happy to own this crate. |
I would be happy with any of the following options (not in any particular order):
(however, there are other 1.3 blocking issues that are all higher priority than landing this PR, in my opinion) |
I will not write tests for std against std, that just does not make sense. It's also not possible to exhaustively test This is very simple code, which can easily reviewed by looking at the mathematical definition that each method represents. It is not comparable to the complicated business logic in #3644.
I'm happy to do that but what exactly does that achieve? I'll still want to depend on this from ICU4X. |
It provides an extension trait for
f32
andf64
that replicates the whole std API, backed bylibm
. This allows us to remove explicitlibm
calls from our business logic, and use the std implementations on std targets via shadowing.This PR uses
core_float
inicu_segmenter
, I will also apply it incalendrical_calculations
after #3985 is merged.