Bug 1856755 - Add faster multiplication and division for fixed-point values. r=jfkthame,layout-reviewers

Even though I ended up not using the division code, it seems useful.

Differential Revision: https://phabricator.services.mozilla.com/D190024
This commit is contained in:
Emilio Cobos Álvarez 2023-10-06 12:20:20 +00:00
parent 953794b454
commit bb6ca40e99

View File

@ -23,6 +23,7 @@ use crate::Atom;
use cssparser::{serialize_identifier, CssStringWriter, Parser};
#[cfg(feature = "gecko")]
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use num_traits::cast::AsPrimitive;
use std::fmt::{self, Write};
use style_traits::{CssWriter, ParseError, ToCss};
@ -73,15 +74,15 @@ pub struct FixedPoint<T, const FRACTION_BITS: u16> {
impl<T, const FRACTION_BITS: u16> FixedPoint<T, FRACTION_BITS>
where
T: num_traits::cast::AsPrimitive<f32>,
f32: num_traits::cast::AsPrimitive<T>,
T: AsPrimitive<f32>,
f32: AsPrimitive<T>,
u16: AsPrimitive<T>,
{
const SCALE: u16 = 1 << FRACTION_BITS;
const INVERSE_SCALE: f32 = 1.0 / Self::SCALE as f32;
/// Returns a fixed-point bit from a floating-point context.
pub fn from_float(v: f32) -> Self {
use num_traits::cast::AsPrimitive;
Self {
value: (v * Self::SCALE as f32).round().as_(),
}
@ -93,6 +94,25 @@ where
}
}
// We implement this and mul below only for u16 types, because u32 types might need more care about
// overflow. But it's not hard to implement in either case.
impl<const FRACTION_BITS: u16> std::ops::Div for FixedPoint<u16, FRACTION_BITS> {
type Output = Self;
fn div(self, rhs: Self) -> Self {
Self {
value: (((self.value as u32) << (FRACTION_BITS as u32)) / (rhs.value as u32)) as u16,
}
}
}
impl<const FRACTION_BITS: u16> std::ops::Mul for FixedPoint<u16, FRACTION_BITS> {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
Self {
value: (((self.value as u32) * (rhs.value as u32)) >> (FRACTION_BITS as u32)) as u16,
}
}
}
/// font-weight: range 1..1000, fractional values permitted; keywords
/// 'normal', 'bold' aliased to 400, 700 respectively.
///