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