zng_unit/
factor.rs

1use std::{fmt, ops, time::Duration};
2
3use crate::{
4    Dip, DipPoint, DipRect, DipSize, DipVector, EQ_EPSILON, EQ_EPSILON_100, Px, PxPoint, PxRect, PxSize, PxVector, about_eq, about_eq_hash,
5    about_eq_ord,
6};
7
8/// Extension methods for initializing factor units.
9///
10/// This trait is implemented for [`f32`] and [`u32`] allowing initialization of factor unit types using the `<number>.<unit>()` syntax.
11///
12/// # Examples
13///
14/// ```
15/// # use zng_unit::*;
16/// let percent = 100.pct();
17/// ```
18pub trait FactorUnits {
19    /// Percent factor.
20    fn pct(self) -> FactorPercent;
21
22    /// Normalized factor.
23    ///
24    /// # Note
25    ///
26    /// [`Factor`] implements `From<f32>`.
27    fn fct(self) -> Factor;
28}
29impl FactorUnits for f32 {
30    fn pct(self) -> FactorPercent {
31        FactorPercent(self)
32    }
33
34    fn fct(self) -> Factor {
35        self.into()
36    }
37}
38impl FactorUnits for i32 {
39    fn pct(self) -> FactorPercent {
40        FactorPercent(self as f32)
41    }
42
43    fn fct(self) -> Factor {
44        Factor(self as f32)
45    }
46}
47
48/// Normalized multiplication factor.
49///
50/// Values of this type are normalized to generally be in between `0.0` and `1.0` to indicate a fraction
51/// of a unit. However, values are not clamped to this range, `Factor(2.0)` is a valid value and so are
52/// negative values.
53///
54/// # Equality
55///
56/// Equality is determined to within `0.00001` epsilon.
57#[derive(Copy, Clone, serde::Serialize, serde::Deserialize, bytemuck::Zeroable, bytemuck::Pod)]
58#[repr(transparent)]
59#[serde(transparent)]
60pub struct Factor(pub f32);
61impl Factor {
62    /// Clamp factor to `[0.0..=1.0]` range.
63    pub fn clamp_range(self) -> Self {
64        Factor(self.0.clamp(0.0, 1.0))
65    }
66
67    /// Returns the maximum of two factors.
68    pub fn max(self, other: impl Into<Factor>) -> Factor {
69        Factor(self.0.max(other.into().0))
70    }
71
72    /// Returns the minimum of two factors.
73    pub fn min(self, other: impl Into<Factor>) -> Factor {
74        Factor(self.0.min(other.into().0))
75    }
76
77    /// Returns `self` if `min <= self <= max`, returns `min` if `self < min` or returns `max` if `self > max`.
78    pub fn clamp(self, min: impl Into<Factor>, max: impl Into<Factor>) -> Factor {
79        self.min(max).max(min)
80    }
81
82    /// Computes the absolute value of self.
83    pub fn abs(self) -> Factor {
84        Factor(self.0.abs())
85    }
86
87    /// Flip factor, around `0.5`,
88    ///
89    /// Returns `1.0 - self`.
90    pub fn flip(self) -> Factor {
91        Self(1.0) - self
92    }
93
94    /// Factor as percentage.
95    pub fn pct(self) -> FactorPercent {
96        self.into()
97    }
98}
99impl fmt::Debug for Factor {
100    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101        if f.alternate() {
102            f.debug_tuple("Factor").field(&self.0).finish()
103        } else {
104            write!(f, "{}.fct()", self.0)
105        }
106    }
107}
108impl fmt::Display for Factor {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        write!(f, "{}", self.0)
111    }
112}
113impl From<f32> for Factor {
114    fn from(value: f32) -> Self {
115        Factor(value)
116    }
117}
118impl ops::Add for Factor {
119    type Output = Self;
120
121    fn add(self, rhs: Self) -> Self::Output {
122        Self(self.0 + rhs.0)
123    }
124}
125impl ops::AddAssign for Factor {
126    fn add_assign(&mut self, rhs: Self) {
127        self.0 += rhs.0;
128    }
129}
130impl ops::Sub for Factor {
131    type Output = Self;
132
133    fn sub(self, rhs: Self) -> Self::Output {
134        Self(self.0 - rhs.0)
135    }
136}
137impl ops::SubAssign for Factor {
138    fn sub_assign(&mut self, rhs: Self) {
139        self.0 -= rhs.0;
140    }
141}
142impl std::hash::Hash for Factor {
143    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
144        about_eq_hash(self.0, EQ_EPSILON, state)
145    }
146}
147impl PartialEq for Factor {
148    fn eq(&self, other: &Self) -> bool {
149        about_eq(self.0, other.0, EQ_EPSILON)
150    }
151}
152impl std::cmp::PartialOrd for Factor {
153    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
154        Some(about_eq_ord(self.0, other.0, EQ_EPSILON))
155    }
156}
157impl ops::Mul for Factor {
158    type Output = Self;
159
160    fn mul(self, rhs: Self) -> Self::Output {
161        Factor(self.0 * rhs.0)
162    }
163}
164impl ops::MulAssign for Factor {
165    fn mul_assign(&mut self, rhs: Self) {
166        *self = *self * rhs;
167    }
168}
169impl ops::Div for Factor {
170    type Output = Self;
171
172    fn div(self, rhs: Self) -> Self::Output {
173        Factor(self.0 / rhs.0)
174    }
175}
176impl ops::DivAssign for Factor {
177    fn div_assign(&mut self, rhs: Self) {
178        *self = *self / rhs;
179    }
180}
181
182impl ops::Mul<Factor> for Px {
183    type Output = Px;
184
185    fn mul(self, rhs: Factor) -> Px {
186        self * rhs.0
187    }
188}
189impl ops::Div<Factor> for Px {
190    type Output = Px;
191
192    fn div(self, rhs: Factor) -> Px {
193        self / rhs.0
194    }
195}
196impl ops::MulAssign<Factor> for Px {
197    fn mul_assign(&mut self, rhs: Factor) {
198        *self = *self * rhs;
199    }
200}
201impl ops::DivAssign<Factor> for Px {
202    fn div_assign(&mut self, rhs: Factor) {
203        *self = *self / rhs;
204    }
205}
206
207impl ops::Mul<Factor> for Dip {
208    type Output = Dip;
209
210    fn mul(self, rhs: Factor) -> Dip {
211        self * rhs.0
212    }
213}
214impl ops::Div<Factor> for Dip {
215    type Output = Dip;
216
217    fn div(self, rhs: Factor) -> Dip {
218        self / rhs.0
219    }
220}
221impl ops::MulAssign<Factor> for Dip {
222    fn mul_assign(&mut self, rhs: Factor) {
223        *self = *self * rhs;
224    }
225}
226impl ops::DivAssign<Factor> for Dip {
227    fn div_assign(&mut self, rhs: Factor) {
228        *self = *self / rhs;
229    }
230}
231
232impl ops::Mul<Factor> for PxPoint {
233    type Output = PxPoint;
234
235    fn mul(mut self, rhs: Factor) -> PxPoint {
236        self.x *= rhs;
237        self.y *= rhs;
238        self
239    }
240}
241impl ops::Div<Factor> for PxPoint {
242    type Output = PxPoint;
243
244    fn div(mut self, rhs: Factor) -> PxPoint {
245        self.x /= rhs;
246        self.y /= rhs;
247        self
248    }
249}
250impl ops::MulAssign<Factor> for PxPoint {
251    fn mul_assign(&mut self, rhs: Factor) {
252        self.x *= rhs;
253        self.y *= rhs;
254    }
255}
256impl ops::DivAssign<Factor> for PxPoint {
257    fn div_assign(&mut self, rhs: Factor) {
258        self.x /= rhs;
259        self.y /= rhs;
260    }
261}
262
263impl ops::Mul<Factor> for euclid::Point2D<f32, Px> {
264    type Output = euclid::Point2D<f32, Px>;
265
266    fn mul(mut self, rhs: Factor) -> euclid::Point2D<f32, Px> {
267        self.x *= rhs.0;
268        self.y *= rhs.0;
269        self
270    }
271}
272impl ops::Div<Factor> for euclid::Point2D<f32, Px> {
273    type Output = euclid::Point2D<f32, Px>;
274
275    fn div(mut self, rhs: Factor) -> euclid::Point2D<f32, Px> {
276        self.x /= rhs.0;
277        self.y /= rhs.0;
278        self
279    }
280}
281impl ops::MulAssign<Factor> for euclid::Point2D<f32, Px> {
282    fn mul_assign(&mut self, rhs: Factor) {
283        self.x *= rhs.0;
284        self.y *= rhs.0;
285    }
286}
287impl ops::DivAssign<Factor> for euclid::Point2D<f32, Px> {
288    fn div_assign(&mut self, rhs: Factor) {
289        self.x /= rhs.0;
290        self.y /= rhs.0;
291    }
292}
293
294impl ops::Mul<Factor> for DipPoint {
295    type Output = DipPoint;
296
297    fn mul(mut self, rhs: Factor) -> DipPoint {
298        self.x *= rhs;
299        self.y *= rhs;
300        self
301    }
302}
303impl ops::Div<Factor> for DipPoint {
304    type Output = DipPoint;
305
306    fn div(mut self, rhs: Factor) -> DipPoint {
307        self.x /= rhs;
308        self.y /= rhs;
309        self
310    }
311}
312impl ops::MulAssign<Factor> for DipPoint {
313    fn mul_assign(&mut self, rhs: Factor) {
314        self.x *= rhs;
315        self.y *= rhs;
316    }
317}
318impl ops::DivAssign<Factor> for DipPoint {
319    fn div_assign(&mut self, rhs: Factor) {
320        self.x /= rhs;
321        self.y /= rhs;
322    }
323}
324
325impl ops::Mul<Factor> for PxVector {
326    type Output = PxVector;
327
328    fn mul(mut self, rhs: Factor) -> PxVector {
329        self.x *= rhs;
330        self.y *= rhs;
331        self
332    }
333}
334impl ops::Div<Factor> for PxVector {
335    type Output = PxVector;
336
337    fn div(mut self, rhs: Factor) -> PxVector {
338        self.x /= rhs;
339        self.y /= rhs;
340        self
341    }
342}
343impl ops::MulAssign<Factor> for PxVector {
344    fn mul_assign(&mut self, rhs: Factor) {
345        self.x *= rhs;
346        self.y *= rhs;
347    }
348}
349impl ops::DivAssign<Factor> for PxVector {
350    fn div_assign(&mut self, rhs: Factor) {
351        self.x /= rhs;
352        self.y /= rhs;
353    }
354}
355
356impl ops::Mul<Factor> for DipVector {
357    type Output = DipVector;
358
359    fn mul(mut self, rhs: Factor) -> DipVector {
360        self.x *= rhs;
361        self.y *= rhs;
362        self
363    }
364}
365impl ops::Div<Factor> for DipVector {
366    type Output = DipVector;
367
368    fn div(mut self, rhs: Factor) -> DipVector {
369        self.x /= rhs;
370        self.y /= rhs;
371        self
372    }
373}
374impl ops::MulAssign<Factor> for DipVector {
375    fn mul_assign(&mut self, rhs: Factor) {
376        self.x *= rhs;
377        self.y *= rhs;
378    }
379}
380impl ops::DivAssign<Factor> for DipVector {
381    fn div_assign(&mut self, rhs: Factor) {
382        self.x /= rhs;
383        self.y /= rhs;
384    }
385}
386
387impl ops::Mul<Factor> for PxSize {
388    type Output = PxSize;
389
390    fn mul(mut self, rhs: Factor) -> PxSize {
391        self.width *= rhs;
392        self.height *= rhs;
393        self
394    }
395}
396impl ops::Div<Factor> for PxSize {
397    type Output = PxSize;
398
399    fn div(mut self, rhs: Factor) -> PxSize {
400        self.width /= rhs;
401        self.height /= rhs;
402        self
403    }
404}
405impl ops::MulAssign<Factor> for PxSize {
406    fn mul_assign(&mut self, rhs: Factor) {
407        self.width *= rhs;
408        self.height *= rhs;
409    }
410}
411impl ops::DivAssign<Factor> for PxSize {
412    fn div_assign(&mut self, rhs: Factor) {
413        self.width /= rhs;
414        self.height /= rhs;
415    }
416}
417
418impl ops::Mul<Factor> for euclid::Size2D<f32, Px> {
419    type Output = euclid::Size2D<f32, Px>;
420
421    fn mul(mut self, rhs: Factor) -> euclid::Size2D<f32, Px> {
422        self.width *= rhs.0;
423        self.height *= rhs.0;
424        self
425    }
426}
427impl ops::Div<Factor> for euclid::Size2D<f32, Px> {
428    type Output = euclid::Size2D<f32, Px>;
429
430    fn div(mut self, rhs: Factor) -> euclid::Size2D<f32, Px> {
431        self.width /= rhs.0;
432        self.height /= rhs.0;
433        self
434    }
435}
436impl ops::MulAssign<Factor> for euclid::Size2D<f32, Px> {
437    fn mul_assign(&mut self, rhs: Factor) {
438        self.width *= rhs.0;
439        self.height *= rhs.0;
440    }
441}
442impl ops::DivAssign<Factor> for euclid::Size2D<f32, Px> {
443    fn div_assign(&mut self, rhs: Factor) {
444        self.width /= rhs.0;
445        self.height /= rhs.0;
446    }
447}
448
449impl ops::Mul<Factor> for DipSize {
450    type Output = DipSize;
451
452    fn mul(mut self, rhs: Factor) -> DipSize {
453        self.width *= rhs;
454        self.height *= rhs;
455        self
456    }
457}
458impl ops::Div<Factor> for DipSize {
459    type Output = DipSize;
460
461    fn div(mut self, rhs: Factor) -> DipSize {
462        self.width /= rhs;
463        self.height /= rhs;
464        self
465    }
466}
467impl ops::MulAssign<Factor> for DipSize {
468    fn mul_assign(&mut self, rhs: Factor) {
469        self.width *= rhs;
470        self.height *= rhs;
471    }
472}
473impl ops::DivAssign<Factor> for DipSize {
474    fn div_assign(&mut self, rhs: Factor) {
475        self.width /= rhs;
476        self.height /= rhs;
477    }
478}
479impl ops::Mul<Factor> for PxRect {
480    type Output = PxRect;
481
482    fn mul(mut self, rhs: Factor) -> PxRect {
483        self.origin *= rhs;
484        self.size *= rhs;
485        self
486    }
487}
488impl ops::Div<Factor> for PxRect {
489    type Output = PxRect;
490
491    fn div(mut self, rhs: Factor) -> PxRect {
492        self.origin /= rhs;
493        self.size /= rhs;
494        self
495    }
496}
497impl ops::MulAssign<Factor> for PxRect {
498    fn mul_assign(&mut self, rhs: Factor) {
499        self.origin *= rhs;
500        self.size *= rhs;
501    }
502}
503impl ops::DivAssign<Factor> for PxRect {
504    fn div_assign(&mut self, rhs: Factor) {
505        self.origin /= rhs;
506        self.size /= rhs;
507    }
508}
509
510impl ops::Mul<Factor> for DipRect {
511    type Output = DipRect;
512
513    fn mul(mut self, rhs: Factor) -> DipRect {
514        self.origin *= rhs;
515        self.size *= rhs;
516        self
517    }
518}
519impl ops::Div<Factor> for DipRect {
520    type Output = DipRect;
521
522    fn div(mut self, rhs: Factor) -> DipRect {
523        self.origin /= rhs;
524        self.size /= rhs;
525        self
526    }
527}
528impl ops::MulAssign<Factor> for DipRect {
529    fn mul_assign(&mut self, rhs: Factor) {
530        self.origin *= rhs;
531        self.size *= rhs;
532    }
533}
534impl ops::DivAssign<Factor> for DipRect {
535    fn div_assign(&mut self, rhs: Factor) {
536        self.origin /= rhs;
537        self.size /= rhs;
538    }
539}
540
541impl ops::Neg for Factor {
542    type Output = Factor;
543
544    fn neg(self) -> Self::Output {
545        Factor(-self.0)
546    }
547}
548impl From<bool> for Factor {
549    fn from(value: bool) -> Self {
550        if value { Factor(1.0) } else { Factor(0.0) }
551    }
552}
553
554macro_rules! impl_for_integer {
555    ($($T:ty,)+) => {$(
556        impl ops::Mul<Factor> for $T {
557            type Output = $T;
558
559            fn mul(self, rhs: Factor) -> $T {
560                (self as f64 * rhs.0 as f64).round() as $T
561            }
562        }
563        impl ops::Div<Factor> for $T {
564            type Output = $T;
565
566            fn div(self, rhs: Factor) -> $T {
567                (self as f64 / rhs.0 as f64).round() as $T
568            }
569        }
570        impl ops::MulAssign<Factor> for $T {
571            fn mul_assign(&mut self, rhs: Factor) {
572                *self = *self * rhs;
573            }
574        }
575        impl ops::DivAssign<Factor> for $T {
576            fn div_assign(&mut self, rhs: Factor) {
577                *self = *self / rhs;
578            }
579        }
580    )+}
581}
582impl_for_integer! {
583    u8, i8, u16, i16, u32, i32, u64, i64, usize, isize, u128, i128,
584}
585
586impl ops::Mul<Factor> for f32 {
587    type Output = f32;
588
589    fn mul(self, rhs: Factor) -> f32 {
590        self * rhs.0
591    }
592}
593impl ops::Div<Factor> for f32 {
594    type Output = f32;
595
596    fn div(self, rhs: Factor) -> f32 {
597        self / rhs.0
598    }
599}
600impl ops::MulAssign<Factor> for f32 {
601    fn mul_assign(&mut self, rhs: Factor) {
602        *self = *self * rhs;
603    }
604}
605impl ops::DivAssign<Factor> for f32 {
606    fn div_assign(&mut self, rhs: Factor) {
607        *self = *self / rhs;
608    }
609}
610
611impl ops::Mul<Factor> for f64 {
612    type Output = f64;
613
614    fn mul(self, rhs: Factor) -> f64 {
615        self * rhs.0 as f64
616    }
617}
618impl ops::Div<Factor> for f64 {
619    type Output = f64;
620
621    fn div(self, rhs: Factor) -> f64 {
622        self / rhs.0 as f64
623    }
624}
625impl ops::MulAssign<Factor> for f64 {
626    fn mul_assign(&mut self, rhs: Factor) {
627        *self = *self * rhs;
628    }
629}
630impl ops::DivAssign<Factor> for f64 {
631    fn div_assign(&mut self, rhs: Factor) {
632        *self = *self / rhs;
633    }
634}
635
636impl ops::Mul<Factor> for Duration {
637    type Output = Duration;
638
639    fn mul(self, rhs: Factor) -> Duration {
640        self.mul_f32(rhs.0)
641    }
642}
643impl ops::Div<Factor> for Duration {
644    type Output = Duration;
645
646    fn div(self, rhs: Factor) -> Duration {
647        self.div_f32(rhs.0)
648    }
649}
650impl ops::MulAssign<Factor> for Duration {
651    fn mul_assign(&mut self, rhs: Factor) {
652        *self = *self * rhs;
653    }
654}
655impl ops::DivAssign<Factor> for Duration {
656    fn div_assign(&mut self, rhs: Factor) {
657        *self = *self / rhs;
658    }
659}
660
661impl From<Factor> for FactorPercent {
662    fn from(value: Factor) -> Self {
663        Self(value.0 * 100.0)
664    }
665}
666impl From<FactorPercent> for Factor {
667    fn from(value: FactorPercent) -> Self {
668        Self(value.0 / 100.0)
669    }
670}
671
672/// Multiplication factor in percentage (0%-100%).
673///
674/// See [`FactorUnits`] for more details.
675///
676/// # Equality
677///
678/// Equality is determined using [`about_eq`] with `0.001` epsilon.
679#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
680#[serde(transparent)]
681pub struct FactorPercent(pub f32);
682impl FactorPercent {
683    /// Clamp factor to [0.0..=100.0] range.
684    pub fn clamp_range(self) -> Self {
685        FactorPercent(self.0.clamp(0.0, 100.0))
686    }
687
688    /// Convert to [`Factor`].
689    pub fn fct(self) -> Factor {
690        self.into()
691    }
692}
693impl ops::Add for FactorPercent {
694    type Output = Self;
695
696    fn add(self, rhs: Self) -> Self::Output {
697        Self(self.0 + rhs.0)
698    }
699}
700impl ops::AddAssign for FactorPercent {
701    fn add_assign(&mut self, rhs: Self) {
702        self.0 += rhs.0;
703    }
704}
705impl ops::Sub for FactorPercent {
706    type Output = Self;
707
708    fn sub(self, rhs: Self) -> Self::Output {
709        Self(self.0 - rhs.0)
710    }
711}
712impl ops::SubAssign for FactorPercent {
713    fn sub_assign(&mut self, rhs: Self) {
714        self.0 -= rhs.0;
715    }
716}
717impl ops::Neg for FactorPercent {
718    type Output = Self;
719
720    fn neg(self) -> Self::Output {
721        FactorPercent(-self.0)
722    }
723}
724impl PartialEq for FactorPercent {
725    fn eq(&self, other: &Self) -> bool {
726        about_eq(self.0, other.0, EQ_EPSILON_100)
727    }
728}
729impl ops::Mul for FactorPercent {
730    type Output = Self;
731
732    fn mul(self, rhs: Self) -> Self::Output {
733        Self(self.0 * rhs.0)
734    }
735}
736impl ops::MulAssign for FactorPercent {
737    fn mul_assign(&mut self, rhs: Self) {
738        *self = *self * rhs;
739    }
740}
741impl ops::Div for FactorPercent {
742    type Output = Self;
743
744    fn div(self, rhs: Self) -> Self::Output {
745        Self(self.0 / rhs.0)
746    }
747}
748impl ops::DivAssign for FactorPercent {
749    fn div_assign(&mut self, rhs: Self) {
750        *self = *self / rhs;
751    }
752}
753impl fmt::Debug for FactorPercent {
754    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
755        if f.alternate() {
756            f.debug_tuple("FactorPercent").field(&self.0).finish()
757        } else {
758            write!(f, "{}.pct()", self.0)
759        }
760    }
761}
762impl fmt::Display for FactorPercent {
763    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764        // round by 2 decimal places, without printing `.00`
765        write!(f, "{}%", (self.0 * 100.0).round() / 100.0)
766    }
767}
768
769impl ops::Mul<Factor> for FactorPercent {
770    type Output = FactorPercent;
771
772    fn mul(self, rhs: Factor) -> Self {
773        Self(self.0 * rhs.0)
774    }
775}
776impl ops::Div<Factor> for FactorPercent {
777    type Output = FactorPercent;
778
779    fn div(self, rhs: Factor) -> Self {
780        Self(self.0 / rhs.0)
781    }
782}
783impl ops::MulAssign<Factor> for FactorPercent {
784    fn mul_assign(&mut self, rhs: Factor) {
785        *self = *self * rhs;
786    }
787}
788impl ops::DivAssign<Factor> for FactorPercent {
789    fn div_assign(&mut self, rhs: Factor) {
790        *self = *self / rhs;
791    }
792}