From 02f114d072ffba72c5b18953f2959eac4dee1612 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Mon, 22 Nov 2021 15:50:35 +0100 Subject: [PATCH] Remove decorum --- Cargo.toml | 1 - src/geom/align.rs | 4 +- src/geom/angle.rs | 16 ++-- src/geom/dir.rs | 12 +-- src/geom/em.rs | 20 ++--- src/geom/fr.rs | 18 ++--- src/geom/gen.rs | 2 +- src/geom/length.rs | 36 ++++----- src/geom/linear.rs | 6 +- src/geom/mod.rs | 5 +- src/geom/path.rs | 2 +- src/geom/point.rs | 8 +- src/geom/relative.rs | 18 ++--- src/geom/scalar.rs | 152 ++++++++++++++++++++++++++++++++++++++ src/geom/sides.rs | 2 +- src/geom/size.rs | 12 +-- src/geom/spec.rs | 2 +- src/layout/incremental.rs | 26 +++---- 18 files changed, 248 insertions(+), 94 deletions(-) create mode 100644 src/geom/scalar.rs diff --git a/Cargo.toml b/Cargo.toml index c31d1d89f..bec1306fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ debug = 0 opt-level = 2 [dependencies] -decorum = { version = "0.3.1", default-features = false, features = ["serialize-serde"] } fxhash = "0.2.1" image = { version = "0.23", default-features = false, features = ["png", "jpeg"] } itertools = "0.10" diff --git a/src/geom/align.rs b/src/geom/align.rs index b0cf69db8..e99bebea1 100644 --- a/src/geom/align.rs +++ b/src/geom/align.rs @@ -17,7 +17,7 @@ pub enum Align { impl Align { /// The axis this alignment belongs to if it is specific. - pub fn axis(self) -> Option { + pub const fn axis(self) -> Option { match self { Self::Left => Some(SpecAxis::Horizontal), Self::Top => Some(SpecAxis::Vertical), @@ -28,7 +28,7 @@ impl Align { } /// The inverse alignment. - pub fn inv(self) -> Self { + pub const fn inv(self) -> Self { match self { Self::Left => Self::Right, Self::Top => Self::Bottom, diff --git a/src/geom/angle.rs b/src/geom/angle.rs index 929a96fe6..af47e51df 100644 --- a/src/geom/angle.rs +++ b/src/geom/angle.rs @@ -3,12 +3,12 @@ use super::*; /// An angle. #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Serialize, Deserialize)] -pub struct Angle(N64); +pub struct Angle(Scalar); impl Angle { /// The zero angle. - pub fn zero() -> Self { - Self(N64::from(0.0)) + pub const fn zero() -> Self { + Self(Scalar(0.0)) } /// Create an angle from a number of radians. @@ -22,8 +22,8 @@ impl Angle { } /// Create an angle from a number of raw units. - pub fn raw(raw: f64) -> Self { - Self(N64::from(raw)) + pub const fn raw(raw: f64) -> Self { + Self(Scalar(raw)) } /// Convert this to a number of radians. @@ -37,13 +37,13 @@ impl Angle { } /// Get the value of this angle in raw units. - pub fn to_raw(self) -> f64 { - self.0.into() + pub const fn to_raw(self) -> f64 { + (self.0).0 } /// Create an angle from a value in a unit. pub fn with_unit(val: f64, unit: AngularUnit) -> Self { - Self(N64::from(val * unit.raw_scale())) + Self(Scalar(val * unit.raw_scale())) } /// Get the value of this length in unit. diff --git a/src/geom/dir.rs b/src/geom/dir.rs index d95c7eb9b..8c1d6b9ee 100644 --- a/src/geom/dir.rs +++ b/src/geom/dir.rs @@ -15,7 +15,7 @@ pub enum Dir { impl Dir { /// The side this direction starts at. - pub fn start(self) -> Side { + pub const fn start(self) -> Side { match self { Self::LTR => Side::Left, Self::RTL => Side::Right, @@ -25,7 +25,7 @@ impl Dir { } /// The side this direction ends at. - pub fn end(self) -> Side { + pub const fn end(self) -> Side { match self { Self::LTR => Side::Right, Self::RTL => Side::Left, @@ -35,7 +35,7 @@ impl Dir { } /// The specific axis this direction belongs to. - pub fn axis(self) -> SpecAxis { + pub const fn axis(self) -> SpecAxis { match self { Self::LTR | Self::RTL => SpecAxis::Horizontal, Self::TTB | Self::BTT => SpecAxis::Vertical, @@ -45,7 +45,7 @@ impl Dir { /// Whether this direction points into the positive coordinate direction. /// /// The positive directions are left-to-right and top-to-bottom. - pub fn is_positive(self) -> bool { + pub const fn is_positive(self) -> bool { match self { Self::LTR | Self::TTB => true, Self::RTL | Self::BTT => false, @@ -56,12 +56,12 @@ impl Dir { /// /// - `1.0` if the direction is positive. /// - `-1.0` if the direction is negative. - pub fn factor(self) -> f64 { + pub const fn factor(self) -> f64 { if self.is_positive() { 1.0 } else { -1.0 } } /// The inverse direction. - pub fn inv(self) -> Self { + pub const fn inv(self) -> Self { match self { Self::LTR => Self::RTL, Self::RTL => Self::LTR, diff --git a/src/geom/em.rs b/src/geom/em.rs index caddbcddf..05d1d7d54 100644 --- a/src/geom/em.rs +++ b/src/geom/em.rs @@ -5,27 +5,27 @@ use super::*; /// `1em` is the same as the font size. #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Serialize, Deserialize)] -pub struct Em(N64); +pub struct Em(Scalar); impl Em { /// The zero length. - pub fn zero() -> Self { - Self(N64::from(0.0)) + pub const fn zero() -> Self { + Self(Scalar(0.0)) } /// The font size. - pub fn one() -> Self { - Self(N64::from(1.0)) + pub const fn one() -> Self { + Self(Scalar(1.0)) } /// Create an font-relative length. - pub fn new(em: f64) -> Self { - Self(N64::from(em)) + pub const fn new(em: f64) -> Self { + Self(Scalar(em)) } /// Create font units at the given units per em. pub fn from_units(units: impl Into, units_per_em: f64) -> Self { - Self(N64::from(units.into() / units_per_em)) + Self(Scalar(units.into() / units_per_em)) } /// Convert to a length at the given font size. @@ -34,8 +34,8 @@ impl Em { } /// The number of em units. - pub fn get(self) -> f64 { - self.0.into() + pub const fn get(self) -> f64 { + (self.0).0 } /// Whether the length is zero. diff --git a/src/geom/fr.rs b/src/geom/fr.rs index 28d53d8fd..e7cd276d8 100644 --- a/src/geom/fr.rs +++ b/src/geom/fr.rs @@ -2,27 +2,27 @@ use super::*; /// A fractional length. #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct Fractional(N64); +pub struct Fractional(Scalar); impl Fractional { /// Takes up zero space: `0fr`. - pub fn zero() -> Self { - Self(N64::from(0.0)) + pub const fn zero() -> Self { + Self(Scalar(0.0)) } /// Takes up as much space as all other items with this fractional size: `1fr`. - pub fn one() -> Self { - Self(N64::from(1.0)) + pub const fn one() -> Self { + Self(Scalar(1.0)) } /// Create a new fractional value. - pub fn new(ratio: f64) -> Self { - Self(N64::from(ratio)) + pub const fn new(ratio: f64) -> Self { + Self(Scalar(ratio)) } /// Get the underlying ratio. - pub fn get(self) -> f64 { - self.0.into() + pub const fn get(self) -> f64 { + (self.0).0 } /// Whether the ratio is zero. diff --git a/src/geom/gen.rs b/src/geom/gen.rs index ff8c881aa..e770f80de 100644 --- a/src/geom/gen.rs +++ b/src/geom/gen.rs @@ -11,7 +11,7 @@ pub struct Gen { impl Gen { /// Create a new instance from the two components. - pub fn new(inline: T, block: T) -> Self { + pub const fn new(inline: T, block: T) -> Self { Self { inline, block } } diff --git a/src/geom/length.rs b/src/geom/length.rs index 68261d5f3..210dcce77 100644 --- a/src/geom/length.rs +++ b/src/geom/length.rs @@ -4,17 +4,17 @@ use super::*; #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Serialize, Deserialize)] #[serde(transparent)] -pub struct Length(N64); +pub struct Length(Scalar); impl Length { /// The zero length. - pub fn zero() -> Self { - Self(N64::from(0.0)) + pub const fn zero() -> Self { + Self(Scalar(0.0)) } /// The inifinite length. - pub fn inf() -> Self { - Self(N64::from(f64::INFINITY)) + pub const fn inf() -> Self { + Self(Scalar(f64::INFINITY)) } /// Create a length from a number of points. @@ -38,8 +38,8 @@ impl Length { } /// Create a length from a number of raw units. - pub fn raw(raw: f64) -> Self { - Self(N64::from(raw)) + pub const fn raw(raw: f64) -> Self { + Self(Scalar(raw)) } /// Convert this to a number of points. @@ -63,13 +63,13 @@ impl Length { } /// Get the value of this length in raw units. - pub fn to_raw(self) -> f64 { - self.0.into() + pub const fn to_raw(self) -> f64 { + (self.0).0 } /// Create a length from a value in a unit. pub fn with_unit(val: f64, unit: LengthUnit) -> Self { - Self(N64::from(val * unit.raw_scale())) + Self(Scalar(val * unit.raw_scale())) } /// Get the value of this length in unit. @@ -79,17 +79,17 @@ impl Length { /// Whether the length is zero. pub fn is_zero(self) -> bool { - self.0 == 0.0 + self.to_raw() == 0.0 } /// Whether the length is finite. pub fn is_finite(self) -> bool { - self.0.into_inner().is_finite() + self.to_raw().is_finite() } /// Whether the length is infinite. pub fn is_infinite(self) -> bool { - self.0.into_inner().is_infinite() + self.to_raw().is_infinite() } /// The absolute value of the this length. @@ -211,14 +211,14 @@ assign_impl!(Length *= f64); assign_impl!(Length /= f64); impl Sum for Length { - fn sum>(iter: I) -> Self { - iter.fold(Length::zero(), Add::add) + fn sum>(iter: I) -> Self { + Self(iter.map(|s| s.0).sum()) } } -impl<'a> Sum<&'a Length> for Length { - fn sum>(iter: I) -> Self { - iter.copied().fold(Length::zero(), Add::add) +impl<'a> Sum<&'a Self> for Length { + fn sum>(iter: I) -> Self { + Self(iter.map(|s| s.0).sum()) } } diff --git a/src/geom/linear.rs b/src/geom/linear.rs index 059528e90..4a0def2fe 100644 --- a/src/geom/linear.rs +++ b/src/geom/linear.rs @@ -11,7 +11,7 @@ pub struct Linear { impl Linear { /// The zero linear. - pub fn zero() -> Self { + pub const fn zero() -> Self { Self { rel: Relative::zero(), abs: Length::zero(), @@ -19,7 +19,7 @@ impl Linear { } /// The linear with a relative part of `100%` and no absolute part. - pub fn one() -> Self { + pub const fn one() -> Self { Self { rel: Relative::one(), abs: Length::zero(), @@ -27,7 +27,7 @@ impl Linear { } /// Create a new linear. - pub fn new(rel: Relative, abs: Length) -> Self { + pub const fn new(rel: Relative, abs: Length) -> Self { Self { rel, abs } } diff --git a/src/geom/mod.rs b/src/geom/mod.rs index ad92813eb..c763e8fa8 100644 --- a/src/geom/mod.rs +++ b/src/geom/mod.rs @@ -14,6 +14,7 @@ mod paint; mod path; mod point; mod relative; +mod scalar; mod sides; mod size; mod spec; @@ -30,16 +31,18 @@ pub use paint::*; pub use path::*; pub use point::*; pub use relative::*; +pub use scalar::*; pub use sides::*; pub use size::*; pub use spec::*; +use std::cmp::Ordering; use std::f64::consts::PI; use std::fmt::{self, Debug, Formatter}; +use std::hash::{Hash, Hasher}; use std::iter::Sum; use std::ops::*; -use decorum::N64; use serde::{Deserialize, Serialize}; /// Generic access to a structure's components. diff --git a/src/geom/path.rs b/src/geom/path.rs index 39e753122..20519cb3a 100644 --- a/src/geom/path.rs +++ b/src/geom/path.rs @@ -16,7 +16,7 @@ pub enum PathElement { impl Path { /// Create an empty path. - pub fn new() -> Self { + pub const fn new() -> Self { Self(vec![]) } diff --git a/src/geom/point.rs b/src/geom/point.rs index 8ab043c3b..7c11e81bd 100644 --- a/src/geom/point.rs +++ b/src/geom/point.rs @@ -11,22 +11,22 @@ pub struct Point { impl Point { /// The origin point. - pub fn zero() -> Self { + pub const fn zero() -> Self { Self { x: Length::zero(), y: Length::zero() } } /// Create a new point from x and y coordinate. - pub fn new(x: Length, y: Length) -> Self { + pub const fn new(x: Length, y: Length) -> Self { Self { x, y } } /// Create an instance with two equal components. - pub fn splat(value: Length) -> Self { + pub const fn splat(value: Length) -> Self { Self { x: value, y: value } } /// Convert to the generic representation. - pub fn to_gen(self, block: SpecAxis) -> Gen { + pub const fn to_gen(self, block: SpecAxis) -> Gen { match block { SpecAxis::Horizontal => Gen::new(self.y, self.x), SpecAxis::Vertical => Gen::new(self.x, self.y), diff --git a/src/geom/relative.rs b/src/geom/relative.rs index e46c51de1..463c5d46e 100644 --- a/src/geom/relative.rs +++ b/src/geom/relative.rs @@ -5,27 +5,27 @@ use super::*; /// _Note_: `50%` is represented as `0.5` here, but stored as `50.0` in the /// corresponding [literal](crate::syntax::ast::LitKind::Percent). #[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct Relative(N64); +pub struct Relative(Scalar); impl Relative { /// A ratio of `0%` represented as `0.0`. - pub fn zero() -> Self { - Self(N64::from(0.0)) + pub const fn zero() -> Self { + Self(Scalar(0.0)) } /// A ratio of `100%` represented as `1.0`. - pub fn one() -> Self { - Self(N64::from(1.0)) + pub const fn one() -> Self { + Self(Scalar(1.0)) } /// Create a new relative value. - pub fn new(ratio: f64) -> Self { - Self(N64::from(ratio)) + pub const fn new(ratio: f64) -> Self { + Self(Scalar(ratio)) } /// Get the underlying ratio. - pub fn get(self) -> f64 { - self.0.into() + pub const fn get(self) -> f64 { + (self.0).0 } /// Resolve this relative to the given `length`. diff --git a/src/geom/scalar.rs b/src/geom/scalar.rs new file mode 100644 index 000000000..6536e23ac --- /dev/null +++ b/src/geom/scalar.rs @@ -0,0 +1,152 @@ +use super::*; + +/// A 64-bit float that implements `Eq`, `Ord` and `Hash`. +/// +/// Panics if its `NaN` during any of those operations. +#[derive(Default, Copy, Clone, Serialize, Deserialize)] +#[serde(transparent)] +pub struct Scalar(pub f64); + +impl From for Scalar { + fn from(float: f64) -> Self { + Self(float) + } +} + +impl From for f64 { + fn from(scalar: Scalar) -> Self { + scalar.0 + } +} + +impl Debug for Scalar { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + self.0.fmt(f) + } +} + +impl Ord for Scalar { + fn cmp(&self, other: &Self) -> Ordering { + self.partial_cmp(&other).expect("float is NaN") + } +} + +impl PartialOrd for Scalar { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } + + fn lt(&self, other: &Self) -> bool { + self.0 < other.0 + } + + fn le(&self, other: &Self) -> bool { + self.0 <= other.0 + } + + fn gt(&self, other: &Self) -> bool { + self.0 > other.0 + } + + fn ge(&self, other: &Self) -> bool { + self.0 >= other.0 + } +} + +impl Eq for Scalar {} + +impl PartialEq for Scalar { + fn eq(&self, other: &Self) -> bool { + assert!(!self.0.is_nan() && !other.0.is_nan(), "float is NaN"); + self.0 == other.0 + } +} + +impl PartialEq for Scalar { + fn eq(&self, other: &f64) -> bool { + self == &Self(*other) + } +} + +impl Hash for Scalar { + fn hash(&self, state: &mut H) { + debug_assert!(!self.0.is_nan(), "float is NaN"); + self.0.to_bits().hash(state); + } +} + +impl Neg for Scalar { + type Output = Self; + + fn neg(self) -> Self::Output { + Self(-self.0) + } +} + +impl> Add for Scalar { + type Output = Self; + + fn add(self, rhs: T) -> Self::Output { + Self(self.0 + rhs.into().0) + } +} + +impl> AddAssign for Scalar { + fn add_assign(&mut self, rhs: T) { + self.0 += rhs.into().0; + } +} + +impl> Sub for Scalar { + type Output = Self; + + fn sub(self, rhs: T) -> Self::Output { + Self(self.0 - rhs.into().0) + } +} + +impl> SubAssign for Scalar { + fn sub_assign(&mut self, rhs: T) { + self.0 -= rhs.into().0; + } +} + +impl> Mul for Scalar { + type Output = Self; + + fn mul(self, rhs: T) -> Self::Output { + Self(self.0 * rhs.into().0) + } +} + +impl> MulAssign for Scalar { + fn mul_assign(&mut self, rhs: T) { + self.0 *= rhs.into().0; + } +} + +impl> Div for Scalar { + type Output = Self; + + fn div(self, rhs: T) -> Self::Output { + Self(self.0 / rhs.into().0) + } +} + +impl> DivAssign for Scalar { + fn div_assign(&mut self, rhs: T) { + self.0 /= rhs.into().0; + } +} + +impl Sum for Scalar { + fn sum>(iter: I) -> Self { + Self(iter.map(|s| s.0).sum()) + } +} + +impl<'a> Sum<&'a Self> for Scalar { + fn sum>(iter: I) -> Self { + Self(iter.map(|s| s.0).sum()) + } +} diff --git a/src/geom/sides.rs b/src/geom/sides.rs index d1fcf9b78..83407ad66 100644 --- a/src/geom/sides.rs +++ b/src/geom/sides.rs @@ -15,7 +15,7 @@ pub struct Sides { impl Sides { /// Create a new instance from the four components. - pub fn new(left: T, top: T, right: T, bottom: T) -> Self { + pub const fn new(left: T, top: T, right: T, bottom: T) -> Self { Self { left, top, right, bottom } } diff --git a/src/geom/size.rs b/src/geom/size.rs index 2143c46bb..12cb0ad21 100644 --- a/src/geom/size.rs +++ b/src/geom/size.rs @@ -11,17 +11,17 @@ pub struct Size { impl Size { /// The zero size. - pub fn zero() -> Self { + pub const fn zero() -> Self { Self { w: Length::zero(), h: Length::zero() } } /// Create a new size from width and height. - pub fn new(w: Length, h: Length) -> Self { + pub const fn new(w: Length, h: Length) -> Self { Self { w, h } } /// Create an instance with two equal components. - pub fn splat(v: Length) -> Self { + pub const fn splat(v: Length) -> Self { Self { w: v, h: v } } @@ -41,17 +41,17 @@ impl Size { } /// Convert to a point. - pub fn to_point(self) -> Point { + pub const fn to_point(self) -> Point { Point::new(self.w, self.h) } /// Convert to a Spec. - pub fn to_spec(self) -> Spec { + pub const fn to_spec(self) -> Spec { Spec::new(self.w, self.h) } /// Convert to the generic representation. - pub fn to_gen(self, block: SpecAxis) -> Gen { + pub const fn to_gen(self, block: SpecAxis) -> Gen { match block { SpecAxis::Horizontal => Gen::new(self.h, self.w), SpecAxis::Vertical => Gen::new(self.w, self.h), diff --git a/src/geom/spec.rs b/src/geom/spec.rs index 82bedf9e3..576c1c89b 100644 --- a/src/geom/spec.rs +++ b/src/geom/spec.rs @@ -11,7 +11,7 @@ pub struct Spec { impl Spec { /// Create a new instance from the two components. - pub fn new(x: T, y: T) -> Self { + pub const fn new(x: T, y: T) -> Self { Self { x, y } } diff --git a/src/layout/incremental.rs b/src/layout/incremental.rs index a90bac1d2..f9eec71bd 100644 --- a/src/layout/incremental.rs +++ b/src/layout/incremental.rs @@ -2,11 +2,11 @@ use std::cmp::Reverse; use std::collections::HashMap; use std::rc::Rc; -use decorum::N32; use itertools::Itertools; use super::{Constrained, Regions}; use crate::frame::Frame; +use crate::geom::Scalar; const TEMP_LEN: usize = 5; const TEMP_LAST: usize = TEMP_LEN - 1; @@ -135,28 +135,27 @@ impl LayoutCache { .0; for entries in self.frames.values_mut() { - entries.retain(|e| e.cooldown() < threshold); + entries.retain(|f| f.cooldown() < threshold); } } EvictionPolicy::LeastFrequentlyUsed => { let threshold = self .entries() - .map(|f| N32::from(f.hits() as f32 / f.age() as f32)) + .map(|f| Scalar(f.hits() as f64 / f.age() as f64)) .k_smallest(len - self.max_size) .last() - .unwrap(); + .unwrap() + .0; for entries in self.frames.values_mut() { - entries.retain(|f| { - f.hits() as f32 / f.age() as f32 > threshold.into_inner() - }); + entries.retain(|f| f.hits() as f64 / f.age() as f64 > threshold); } } EvictionPolicy::Random => { // Fraction of items that should be kept. - let threshold = self.max_size as f32 / len as f32; + let threshold = self.max_size as f64 / len as f64; for entries in self.frames.values_mut() { - entries.retain(|_| rand::random::() > threshold); + entries.retain(|_| rand::random::() > threshold); } } EvictionPolicy::Patterns => { @@ -170,15 +169,16 @@ impl LayoutCache { let threshold = self .entries() .filter(|f| !f.properties().must_keep()) - .map(|f| N32::from(f.hits() as f32 / f.age() as f32)) + .map(|f| Scalar(f.hits() as f64 / f.age() as f64)) .k_smallest((len - kept) - remaining_capacity) .last() - .unwrap(); + .unwrap() + .0; - for (_, entries) in self.frames.iter_mut() { + for entries in self.frames.values_mut() { entries.retain(|f| { f.properties().must_keep() - || f.hits() as f32 / f.age() as f32 > threshold.into_inner() + || f.hits() as f64 / f.age() as f64 > threshold }); } }