Closed
Description
Sometimes you need both the quotient and the remainder.
With the current state of the trait you would have to call both div_euclid
and rem_euclid
.
But part of the computation done by each one of those methods can be shared.
See:
impl Euclid for f32 {
#[inline]
fn div_euclid(&self, v: &f32) -> f32 {
let q = <f32 as crate::float::FloatCore>::trunc(self / v);
if self % v < 0.0 {
return if *v > 0.0 { q - 1.0 } else { q + 1.0 };
}
q
}
#[inline]
fn rem_euclid(&self, v: &f32) -> f32 {
let r = self % v;
if r < 0.0 {
r + <f32 as crate::float::FloatCore>::abs(*v)
} else {
r
}
}
}
can become
#[inline]
fn div_and_rem_euclid(&self, v: &f32) -> (f32, f32) {
let q = <f32 as crate::float::FloatCore>::trunc(self / v);
let r = self % v;
if r < 0.0 {
(if *v > 0.0 { q - 1.0 } else { q + 1.0 }, r + <f32 as crate::float::FloatCore>::abs(*v))
} else {
(q, r)
}
}
And you spare one computation of self % v
.
This is a really small optimization for f32, but with the kind of big field elements I'm working with, it actually a pretty significant hit.
The method can be defined with a default impl:
fn div_and_rem_euclid(&self, v: &f32) -> (f32, f32) {
(self.div_euclid(), self.rem_euclid())
}
Which has not optimization nor drawback for people using it, but can be overwritten in order to achieve better performances.
Wdyt?
Metadata
Metadata
Assignees
Labels
No labels