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