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}
385impl<U> ops::Mul<Factor> for euclid::Vector2D<f32, U> {
386    type Output = Self;
387
388    fn mul(mut self, rhs: Factor) -> Self {
389        self.x *= rhs;
390        self.y *= rhs;
391        self
392    }
393}
394impl<U> ops::Div<Factor> for euclid::Vector2D<f32, U> {
395    type Output = Self;
396
397    fn div(mut self, rhs: Factor) -> Self {
398        self.x /= rhs;
399        self.y /= rhs;
400        self
401    }
402}
403
404impl ops::Mul<Factor> for PxSize {
405    type Output = PxSize;
406
407    fn mul(mut self, rhs: Factor) -> PxSize {
408        self.width *= rhs;
409        self.height *= rhs;
410        self
411    }
412}
413impl ops::Div<Factor> for PxSize {
414    type Output = PxSize;
415
416    fn div(mut self, rhs: Factor) -> PxSize {
417        self.width /= rhs;
418        self.height /= rhs;
419        self
420    }
421}
422impl ops::MulAssign<Factor> for PxSize {
423    fn mul_assign(&mut self, rhs: Factor) {
424        self.width *= rhs;
425        self.height *= rhs;
426    }
427}
428impl ops::DivAssign<Factor> for PxSize {
429    fn div_assign(&mut self, rhs: Factor) {
430        self.width /= rhs;
431        self.height /= rhs;
432    }
433}
434
435impl ops::Mul<Factor> for euclid::Size2D<f32, Px> {
436    type Output = euclid::Size2D<f32, Px>;
437
438    fn mul(mut self, rhs: Factor) -> euclid::Size2D<f32, Px> {
439        self.width *= rhs.0;
440        self.height *= rhs.0;
441        self
442    }
443}
444impl ops::Div<Factor> for euclid::Size2D<f32, Px> {
445    type Output = euclid::Size2D<f32, Px>;
446
447    fn div(mut self, rhs: Factor) -> euclid::Size2D<f32, Px> {
448        self.width /= rhs.0;
449        self.height /= rhs.0;
450        self
451    }
452}
453impl ops::MulAssign<Factor> for euclid::Size2D<f32, Px> {
454    fn mul_assign(&mut self, rhs: Factor) {
455        self.width *= rhs.0;
456        self.height *= rhs.0;
457    }
458}
459impl ops::DivAssign<Factor> for euclid::Size2D<f32, Px> {
460    fn div_assign(&mut self, rhs: Factor) {
461        self.width /= rhs.0;
462        self.height /= rhs.0;
463    }
464}
465
466impl ops::Mul<Factor> for DipSize {
467    type Output = DipSize;
468
469    fn mul(mut self, rhs: Factor) -> DipSize {
470        self.width *= rhs;
471        self.height *= rhs;
472        self
473    }
474}
475impl ops::Div<Factor> for DipSize {
476    type Output = DipSize;
477
478    fn div(mut self, rhs: Factor) -> DipSize {
479        self.width /= rhs;
480        self.height /= rhs;
481        self
482    }
483}
484impl ops::MulAssign<Factor> for DipSize {
485    fn mul_assign(&mut self, rhs: Factor) {
486        self.width *= rhs;
487        self.height *= rhs;
488    }
489}
490impl ops::DivAssign<Factor> for DipSize {
491    fn div_assign(&mut self, rhs: Factor) {
492        self.width /= rhs;
493        self.height /= rhs;
494    }
495}
496impl ops::Mul<Factor> for PxRect {
497    type Output = PxRect;
498
499    fn mul(mut self, rhs: Factor) -> PxRect {
500        self.origin *= rhs;
501        self.size *= rhs;
502        self
503    }
504}
505impl ops::Div<Factor> for PxRect {
506    type Output = PxRect;
507
508    fn div(mut self, rhs: Factor) -> PxRect {
509        self.origin /= rhs;
510        self.size /= rhs;
511        self
512    }
513}
514impl ops::MulAssign<Factor> for PxRect {
515    fn mul_assign(&mut self, rhs: Factor) {
516        self.origin *= rhs;
517        self.size *= rhs;
518    }
519}
520impl ops::DivAssign<Factor> for PxRect {
521    fn div_assign(&mut self, rhs: Factor) {
522        self.origin /= rhs;
523        self.size /= rhs;
524    }
525}
526
527impl ops::Mul<Factor> for DipRect {
528    type Output = DipRect;
529
530    fn mul(mut self, rhs: Factor) -> DipRect {
531        self.origin *= rhs;
532        self.size *= rhs;
533        self
534    }
535}
536impl ops::Div<Factor> for DipRect {
537    type Output = DipRect;
538
539    fn div(mut self, rhs: Factor) -> DipRect {
540        self.origin /= rhs;
541        self.size /= rhs;
542        self
543    }
544}
545impl ops::MulAssign<Factor> for DipRect {
546    fn mul_assign(&mut self, rhs: Factor) {
547        self.origin *= rhs;
548        self.size *= rhs;
549    }
550}
551impl ops::DivAssign<Factor> for DipRect {
552    fn div_assign(&mut self, rhs: Factor) {
553        self.origin /= rhs;
554        self.size /= rhs;
555    }
556}
557
558impl ops::Neg for Factor {
559    type Output = Factor;
560
561    fn neg(self) -> Self::Output {
562        Factor(-self.0)
563    }
564}
565impl From<bool> for Factor {
566    fn from(value: bool) -> Self {
567        if value { Factor(1.0) } else { Factor(0.0) }
568    }
569}
570
571macro_rules! impl_for_integer {
572    ($($T:ty),+ $(,)?) => {$(
573        impl ops::Mul<Factor> for $T {
574            type Output = $T;
575
576            fn mul(self, rhs: Factor) -> $T {
577                (self as f64 * rhs.0 as f64).round() as $T
578            }
579        }
580        impl ops::Div<Factor> for $T {
581            type Output = $T;
582
583            fn div(self, rhs: Factor) -> $T {
584                (self as f64 / rhs.0 as f64).round() as $T
585            }
586        }
587        impl ops::MulAssign<Factor> for $T {
588            fn mul_assign(&mut self, rhs: Factor) {
589                *self = *self * rhs;
590            }
591        }
592        impl ops::DivAssign<Factor> for $T {
593            fn div_assign(&mut self, rhs: Factor) {
594                *self = *self / rhs;
595            }
596        }
597    )+}
598}
599impl_for_integer! { u8, i8, u16, i16, u32, i32, u64, i64, usize, isize, u128, i128 }
600
601impl ops::Mul<Factor> for f32 {
602    type Output = f32;
603
604    fn mul(self, rhs: Factor) -> f32 {
605        self * rhs.0
606    }
607}
608impl ops::Div<Factor> for f32 {
609    type Output = f32;
610
611    fn div(self, rhs: Factor) -> f32 {
612        self / rhs.0
613    }
614}
615impl ops::MulAssign<Factor> for f32 {
616    fn mul_assign(&mut self, rhs: Factor) {
617        *self = *self * rhs;
618    }
619}
620impl ops::DivAssign<Factor> for f32 {
621    fn div_assign(&mut self, rhs: Factor) {
622        *self = *self / rhs;
623    }
624}
625
626impl ops::Mul<Factor> for f64 {
627    type Output = f64;
628
629    fn mul(self, rhs: Factor) -> f64 {
630        self * rhs.0 as f64
631    }
632}
633impl ops::Div<Factor> for f64 {
634    type Output = f64;
635
636    fn div(self, rhs: Factor) -> f64 {
637        self / rhs.0 as f64
638    }
639}
640impl ops::MulAssign<Factor> for f64 {
641    fn mul_assign(&mut self, rhs: Factor) {
642        *self = *self * rhs;
643    }
644}
645impl ops::DivAssign<Factor> for f64 {
646    fn div_assign(&mut self, rhs: Factor) {
647        *self = *self / rhs;
648    }
649}
650
651impl ops::Mul<Factor> for Duration {
652    type Output = Duration;
653
654    fn mul(self, rhs: Factor) -> Duration {
655        self.mul_f32(rhs.0)
656    }
657}
658impl ops::Div<Factor> for Duration {
659    type Output = Duration;
660
661    fn div(self, rhs: Factor) -> Duration {
662        self.div_f32(rhs.0)
663    }
664}
665impl ops::MulAssign<Factor> for Duration {
666    fn mul_assign(&mut self, rhs: Factor) {
667        *self = *self * rhs;
668    }
669}
670impl ops::DivAssign<Factor> for Duration {
671    fn div_assign(&mut self, rhs: Factor) {
672        *self = *self / rhs;
673    }
674}
675
676impl From<Factor> for FactorPercent {
677    fn from(value: Factor) -> Self {
678        Self(value.0 * 100.0)
679    }
680}
681impl From<FactorPercent> for Factor {
682    fn from(value: FactorPercent) -> Self {
683        Self(value.0 / 100.0)
684    }
685}
686
687/// Multiplication factor in percentage (0%-100%).
688///
689/// See [`FactorUnits`] for more details.
690///
691/// # Equality
692///
693/// Equality is determined using [`about_eq`] with `0.001` granularity.
694#[derive(Copy, Clone, serde::Serialize, serde::Deserialize)]
695#[serde(transparent)]
696pub struct FactorPercent(pub f32);
697impl FactorPercent {
698    /// Clamp factor to [0.0..=100.0] range.
699    pub fn clamp_range(self) -> Self {
700        FactorPercent(self.0.clamp(0.0, 100.0))
701    }
702
703    /// Convert to [`Factor`].
704    pub fn fct(self) -> Factor {
705        self.into()
706    }
707}
708impl ops::Add for FactorPercent {
709    type Output = Self;
710
711    fn add(self, rhs: Self) -> Self::Output {
712        Self(self.0 + rhs.0)
713    }
714}
715impl ops::AddAssign for FactorPercent {
716    fn add_assign(&mut self, rhs: Self) {
717        self.0 += rhs.0;
718    }
719}
720impl ops::Sub for FactorPercent {
721    type Output = Self;
722
723    fn sub(self, rhs: Self) -> Self::Output {
724        Self(self.0 - rhs.0)
725    }
726}
727impl ops::SubAssign for FactorPercent {
728    fn sub_assign(&mut self, rhs: Self) {
729        self.0 -= rhs.0;
730    }
731}
732impl ops::Neg for FactorPercent {
733    type Output = Self;
734
735    fn neg(self) -> Self::Output {
736        FactorPercent(-self.0)
737    }
738}
739impl PartialEq for FactorPercent {
740    fn eq(&self, other: &Self) -> bool {
741        about_eq(self.0, other.0, EQ_GRANULARITY_100)
742    }
743}
744impl Eq for FactorPercent {}
745impl ops::Mul for FactorPercent {
746    type Output = Self;
747
748    fn mul(self, rhs: Self) -> Self::Output {
749        Self(self.0 * rhs.0)
750    }
751}
752impl ops::MulAssign for FactorPercent {
753    fn mul_assign(&mut self, rhs: Self) {
754        *self = *self * rhs;
755    }
756}
757impl ops::Div for FactorPercent {
758    type Output = Self;
759
760    fn div(self, rhs: Self) -> Self::Output {
761        Self(self.0 / rhs.0)
762    }
763}
764impl ops::DivAssign for FactorPercent {
765    fn div_assign(&mut self, rhs: Self) {
766        *self = *self / rhs;
767    }
768}
769impl fmt::Debug for FactorPercent {
770    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
771        if f.alternate() {
772            f.debug_tuple("FactorPercent").field(&self.0).finish()
773        } else {
774            write!(f, "{}.pct()", self.0)
775        }
776    }
777}
778impl fmt::Display for FactorPercent {
779    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
780        // round by 2 decimal places, without printing `.00`
781        write!(f, "{}%", (self.0 * 100.0).round() / 100.0)
782    }
783}
784
785impl ops::Mul<Factor> for FactorPercent {
786    type Output = FactorPercent;
787
788    fn mul(self, rhs: Factor) -> Self {
789        Self(self.0 * rhs.0)
790    }
791}
792impl ops::Div<Factor> for FactorPercent {
793    type Output = FactorPercent;
794
795    fn div(self, rhs: Factor) -> Self {
796        Self(self.0 / rhs.0)
797    }
798}
799impl ops::MulAssign<Factor> for FactorPercent {
800    fn mul_assign(&mut self, rhs: Factor) {
801        *self = *self * rhs;
802    }
803}
804impl ops::DivAssign<Factor> for FactorPercent {
805    fn div_assign(&mut self, rhs: Factor) {
806        *self = *self / rhs;
807    }
808}
809
810/// Parses `"##"`, `"##%"` and `"##.fct()"` where `##` is a `f32`.
811impl std::str::FromStr for FactorPercent {
812    type Err = std::num::ParseFloatError;
813
814    fn from_str(s: &str) -> Result<Self, Self::Err> {
815        crate::parse_suffix(s, &["%", ".pct()"]).map(FactorPercent)
816    }
817}