zng_unit/
factor.rs

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