1use super::UnknownUnit;
11use crate::approxord::{max, min};
12use crate::length::Length;
13use crate::num::*;
14use crate::scale::Scale;
15use crate::vector::{vec2, BoolVector2D, Vector2D};
16use crate::vector::{vec3, BoolVector3D, Vector3D};
17
18use core::cmp::{Eq, PartialEq};
19use core::fmt;
20use core::hash::Hash;
21use core::iter::Sum;
22use core::marker::PhantomData;
23use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
24
25#[cfg(feature = "bytemuck")]
26use bytemuck::{Pod, Zeroable};
27#[cfg(feature = "malloc_size_of")]
28use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
29#[cfg(feature = "mint")]
30use mint;
31use num_traits::{Float, NumCast, Signed};
32#[cfg(feature = "serde")]
33use serde;
34
35#[repr(C)]
37pub struct Size2D<T, U> {
38 pub width: T,
40 pub height: T,
42 #[doc(hidden)]
43 pub _unit: PhantomData<U>,
44}
45
46impl<T: Copy, U> Copy for Size2D<T, U> {}
47
48impl<T: Clone, U> Clone for Size2D<T, U> {
49 fn clone(&self) -> Self {
50 Size2D {
51 width: self.width.clone(),
52 height: self.height.clone(),
53 _unit: PhantomData,
54 }
55 }
56}
57
58#[cfg(feature = "serde")]
59impl<'de, T, U> serde::Deserialize<'de> for Size2D<T, U>
60where
61 T: serde::Deserialize<'de>,
62{
63 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
65 where
66 D: serde::Deserializer<'de>,
67 {
68 let (width, height) = serde::Deserialize::deserialize(deserializer)?;
69 Ok(Size2D {
70 width,
71 height,
72 _unit: PhantomData,
73 })
74 }
75}
76
77#[cfg(feature = "serde")]
78impl<T, U> serde::Serialize for Size2D<T, U>
79where
80 T: serde::Serialize,
81{
82 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
84 where
85 S: serde::Serializer,
86 {
87 (&self.width, &self.height).serialize(serializer)
88 }
89}
90
91#[cfg(feature = "arbitrary")]
92impl<'a, T, U> arbitrary::Arbitrary<'a> for Size2D<T, U>
93where
94 T: arbitrary::Arbitrary<'a>,
95{
96 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
97 let (width, height) = arbitrary::Arbitrary::arbitrary(u)?;
98 Ok(Size2D {
99 width,
100 height,
101 _unit: PhantomData,
102 })
103 }
104}
105
106#[cfg(feature = "bytemuck")]
107unsafe impl<T: Zeroable, U> Zeroable for Size2D<T, U> {}
108
109#[cfg(feature = "bytemuck")]
110unsafe impl<T: Pod, U: 'static> Pod for Size2D<T, U> {}
111
112#[cfg(feature = "malloc_size_of")]
113impl<T: MallocSizeOf, U> MallocSizeOf for Size2D<T, U> {
114 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
115 self.width.size_of(ops) + self.height.size_of(ops)
116 }
117}
118
119impl<T, U> Eq for Size2D<T, U> where T: Eq {}
120
121impl<T, U> PartialEq for Size2D<T, U>
122where
123 T: PartialEq,
124{
125 fn eq(&self, other: &Self) -> bool {
126 self.width == other.width && self.height == other.height
127 }
128}
129
130impl<T, U> Hash for Size2D<T, U>
131where
132 T: Hash,
133{
134 fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
135 self.width.hash(h);
136 self.height.hash(h);
137 }
138}
139
140impl<T: fmt::Debug, U> fmt::Debug for Size2D<T, U> {
141 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142 fmt::Debug::fmt(&self.width, f)?;
143 write!(f, "x")?;
144 fmt::Debug::fmt(&self.height, f)
145 }
146}
147
148impl<T: Default, U> Default for Size2D<T, U> {
149 fn default() -> Self {
150 Size2D::new(Default::default(), Default::default())
151 }
152}
153
154impl<T, U> Size2D<T, U> {
155 #[inline]
159 pub fn zero() -> Self
160 where
161 T: Zero,
162 {
163 Size2D::new(Zero::zero(), Zero::zero())
164 }
165
166 #[inline]
168 pub const fn new(width: T, height: T) -> Self {
169 Size2D {
170 width,
171 height,
172 _unit: PhantomData,
173 }
174 }
175 #[inline]
177 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
178 Size2D::new(width.0, height.0)
179 }
180
181 #[inline]
183 pub fn splat(v: T) -> Self
184 where
185 T: Clone,
186 {
187 Size2D {
188 width: v.clone(),
189 height: v,
190 _unit: PhantomData,
191 }
192 }
193
194 #[inline]
196 pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
197 Size2D::new(p.width, p.height)
198 }
199}
200
201impl<T: Copy, U> Size2D<T, U> {
202 #[inline]
204 pub fn to_array(self) -> [T; 2] {
205 [self.width, self.height]
206 }
207
208 #[inline]
210 pub fn to_tuple(self) -> (T, T) {
211 (self.width, self.height)
212 }
213
214 #[inline]
216 pub fn to_vector(self) -> Vector2D<T, U> {
217 vec2(self.width, self.height)
218 }
219
220 #[inline]
222 pub fn to_untyped(self) -> Size2D<T, UnknownUnit> {
223 self.cast_unit()
224 }
225
226 #[inline]
228 pub fn cast_unit<V>(self) -> Size2D<T, V> {
229 Size2D::new(self.width, self.height)
230 }
231
232 #[inline]
243 #[must_use]
244 pub fn round(self) -> Self
245 where
246 T: Round,
247 {
248 Size2D::new(self.width.round(), self.height.round())
249 }
250
251 #[inline]
262 #[must_use]
263 pub fn ceil(self) -> Self
264 where
265 T: Ceil,
266 {
267 Size2D::new(self.width.ceil(), self.height.ceil())
268 }
269
270 #[inline]
281 #[must_use]
282 pub fn floor(self) -> Self
283 where
284 T: Floor,
285 {
286 Size2D::new(self.width.floor(), self.height.floor())
287 }
288
289 pub fn area(self) -> T::Output
291 where
292 T: Mul,
293 {
294 self.width * self.height
295 }
296
297 #[inline]
315 pub fn lerp(self, other: Self, t: T) -> Self
316 where
317 T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
318 {
319 let one_t = T::one() - t;
320 self * one_t + other * t
321 }
322}
323
324impl<T: NumCast + Copy, U> Size2D<T, U> {
325 #[inline]
331 pub fn cast<NewT: NumCast>(self) -> Size2D<NewT, U> {
332 self.try_cast().unwrap()
333 }
334
335 pub fn try_cast<NewT: NumCast>(self) -> Option<Size2D<NewT, U>> {
341 match (NumCast::from(self.width), NumCast::from(self.height)) {
342 (Some(w), Some(h)) => Some(Size2D::new(w, h)),
343 _ => None,
344 }
345 }
346
347 #[inline]
351 pub fn to_f32(self) -> Size2D<f32, U> {
352 self.cast()
353 }
354
355 #[inline]
357 pub fn to_f64(self) -> Size2D<f64, U> {
358 self.cast()
359 }
360
361 #[inline]
367 pub fn to_usize(self) -> Size2D<usize, U> {
368 self.cast()
369 }
370
371 #[inline]
377 pub fn to_u32(self) -> Size2D<u32, U> {
378 self.cast()
379 }
380
381 #[inline]
387 pub fn to_u64(self) -> Size2D<u64, U> {
388 self.cast()
389 }
390
391 #[inline]
397 pub fn to_i32(self) -> Size2D<i32, U> {
398 self.cast()
399 }
400
401 #[inline]
407 pub fn to_i64(self) -> Size2D<i64, U> {
408 self.cast()
409 }
410}
411
412impl<T: Float, U> Size2D<T, U> {
413 #[inline]
415 pub fn is_finite(self) -> bool {
416 self.width.is_finite() && self.height.is_finite()
417 }
418}
419
420impl<T: Signed, U> Size2D<T, U> {
421 pub fn abs(self) -> Self {
427 size2(self.width.abs(), self.height.abs())
428 }
429
430 pub fn is_positive(self) -> bool {
432 self.width.is_positive() && self.height.is_positive()
433 }
434}
435
436impl<T: PartialOrd, U> Size2D<T, U> {
437 #[inline]
439 pub fn min(self, other: Self) -> Self {
440 size2(min(self.width, other.width), min(self.height, other.height))
441 }
442
443 #[inline]
445 pub fn max(self, other: Self) -> Self {
446 size2(max(self.width, other.width), max(self.height, other.height))
447 }
448
449 #[inline]
454 pub fn clamp(self, start: Self, end: Self) -> Self
455 where
456 T: Copy,
457 {
458 self.max(start).min(end)
459 }
460
461 #[inline]
463 pub fn contains(self, other: Self) -> bool {
464 self.width >= other.width && self.height >= other.height
465 }
466
467 pub fn greater_than(self, other: Self) -> BoolVector2D {
469 BoolVector2D {
470 x: self.width > other.width,
471 y: self.height > other.height,
472 }
473 }
474
475 pub fn lower_than(self, other: Self) -> BoolVector2D {
477 BoolVector2D {
478 x: self.width < other.width,
479 y: self.height < other.height,
480 }
481 }
482
483 pub fn is_empty(self) -> bool
485 where
486 T: Zero,
487 {
488 let zero = T::zero();
489 !(self.width > zero && self.height > zero)
492 }
493}
494
495impl<T: PartialEq, U> Size2D<T, U> {
496 pub fn equal(self, other: Self) -> BoolVector2D {
498 BoolVector2D {
499 x: self.width == other.width,
500 y: self.height == other.height,
501 }
502 }
503
504 pub fn not_equal(self, other: Self) -> BoolVector2D {
506 BoolVector2D {
507 x: self.width != other.width,
508 y: self.height != other.height,
509 }
510 }
511}
512
513impl<T: Round, U> Round for Size2D<T, U> {
514 #[inline]
516 fn round(self) -> Self {
517 self.round()
518 }
519}
520
521impl<T: Ceil, U> Ceil for Size2D<T, U> {
522 #[inline]
524 fn ceil(self) -> Self {
525 self.ceil()
526 }
527}
528
529impl<T: Floor, U> Floor for Size2D<T, U> {
530 #[inline]
532 fn floor(self) -> Self {
533 self.floor()
534 }
535}
536
537impl<T: Zero, U> Zero for Size2D<T, U> {
538 #[inline]
539 fn zero() -> Self {
540 Size2D::new(Zero::zero(), Zero::zero())
541 }
542}
543
544impl<T: Neg, U> Neg for Size2D<T, U> {
545 type Output = Size2D<T::Output, U>;
546
547 #[inline]
548 fn neg(self) -> Self::Output {
549 Size2D::new(-self.width, -self.height)
550 }
551}
552
553impl<T: Add, U> Add for Size2D<T, U> {
554 type Output = Size2D<T::Output, U>;
555
556 #[inline]
557 fn add(self, other: Self) -> Self::Output {
558 Size2D::new(self.width + other.width, self.height + other.height)
559 }
560}
561
562impl<T: Copy + Add<T, Output = T>, U> Add<&Self> for Size2D<T, U> {
563 type Output = Self;
564 fn add(self, other: &Self) -> Self {
565 Size2D::new(self.width + other.width, self.height + other.height)
566 }
567}
568
569impl<T: Add<Output = T> + Zero, U> Sum for Size2D<T, U> {
570 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
571 iter.fold(Self::zero(), Add::add)
572 }
573}
574
575impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Size2D<T, U> {
576 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
577 iter.fold(Self::zero(), Add::add)
578 }
579}
580
581impl<T: AddAssign, U> AddAssign for Size2D<T, U> {
582 #[inline]
583 fn add_assign(&mut self, other: Self) {
584 self.width += other.width;
585 self.height += other.height;
586 }
587}
588
589impl<T: Sub, U> Sub for Size2D<T, U> {
590 type Output = Size2D<T::Output, U>;
591
592 #[inline]
593 fn sub(self, other: Self) -> Self::Output {
594 Size2D::new(self.width - other.width, self.height - other.height)
595 }
596}
597
598impl<T: SubAssign, U> SubAssign for Size2D<T, U> {
599 #[inline]
600 fn sub_assign(&mut self, other: Self) {
601 self.width -= other.width;
602 self.height -= other.height;
603 }
604}
605
606impl<T: Copy + Mul, U> Mul<T> for Size2D<T, U> {
607 type Output = Size2D<T::Output, U>;
608
609 #[inline]
610 fn mul(self, scale: T) -> Self::Output {
611 Size2D::new(self.width * scale, self.height * scale)
612 }
613}
614
615impl<T: Copy + MulAssign, U> MulAssign<T> for Size2D<T, U> {
616 #[inline]
617 fn mul_assign(&mut self, other: T) {
618 self.width *= other;
619 self.height *= other;
620 }
621}
622
623impl<T: Copy + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size2D<T, U1> {
624 type Output = Size2D<T::Output, U2>;
625
626 #[inline]
627 fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
628 Size2D::new(self.width * scale.0, self.height * scale.0)
629 }
630}
631
632impl<T: Copy + MulAssign, U> MulAssign<Scale<T, U, U>> for Size2D<T, U> {
633 #[inline]
634 fn mul_assign(&mut self, other: Scale<T, U, U>) {
635 *self *= other.0;
636 }
637}
638
639impl<T: Copy + Div, U> Div<T> for Size2D<T, U> {
640 type Output = Size2D<T::Output, U>;
641
642 #[inline]
643 fn div(self, scale: T) -> Self::Output {
644 Size2D::new(self.width / scale, self.height / scale)
645 }
646}
647
648impl<T: Copy + DivAssign, U> DivAssign<T> for Size2D<T, U> {
649 #[inline]
650 fn div_assign(&mut self, other: T) {
651 self.width /= other;
652 self.height /= other;
653 }
654}
655
656impl<T: Copy + Div, U1, U2> Div<Scale<T, U1, U2>> for Size2D<T, U2> {
657 type Output = Size2D<T::Output, U1>;
658
659 #[inline]
660 fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
661 Size2D::new(self.width / scale.0, self.height / scale.0)
662 }
663}
664
665impl<T: Copy + DivAssign, U> DivAssign<Scale<T, U, U>> for Size2D<T, U> {
666 #[inline]
667 fn div_assign(&mut self, other: Scale<T, U, U>) {
668 *self /= other.0;
669 }
670}
671
672#[inline]
674pub const fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
675 Size2D::new(w, h)
676}
677
678#[cfg(feature = "mint")]
679impl<T, U> From<mint::Vector2<T>> for Size2D<T, U> {
680 #[inline]
681 fn from(v: mint::Vector2<T>) -> Self {
682 Size2D {
683 width: v.x,
684 height: v.y,
685 _unit: PhantomData,
686 }
687 }
688}
689#[cfg(feature = "mint")]
690impl<T, U> From<Size2D<T, U>> for mint::Vector2<T> {
691 #[inline]
692 fn from(s: Size2D<T, U>) -> Self {
693 mint::Vector2 {
694 x: s.width,
695 y: s.height,
696 }
697 }
698}
699
700impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
701 #[inline]
702 fn from(v: Vector2D<T, U>) -> Self {
703 size2(v.x, v.y)
704 }
705}
706
707impl<T, U> From<Size2D<T, U>> for [T; 2] {
708 #[inline]
709 fn from(s: Size2D<T, U>) -> Self {
710 [s.width, s.height]
711 }
712}
713
714impl<T, U> From<[T; 2]> for Size2D<T, U> {
715 #[inline]
716 fn from([w, h]: [T; 2]) -> Self {
717 size2(w, h)
718 }
719}
720
721impl<T, U> From<Size2D<T, U>> for (T, T) {
722 #[inline]
723 fn from(s: Size2D<T, U>) -> Self {
724 (s.width, s.height)
725 }
726}
727
728impl<T, U> From<(T, T)> for Size2D<T, U> {
729 #[inline]
730 fn from(tuple: (T, T)) -> Self {
731 size2(tuple.0, tuple.1)
732 }
733}
734
735#[cfg(test)]
736mod size2d {
737 use crate::default::Size2D;
738 #[cfg(feature = "mint")]
739 use mint;
740
741 #[test]
742 pub fn test_area() {
743 let p = Size2D::new(1.5, 2.0);
744 assert_eq!(p.area(), 3.0);
745 }
746
747 #[cfg(feature = "mint")]
748 #[test]
749 pub fn test_mint() {
750 let s1 = Size2D::new(1.0, 2.0);
751 let sm: mint::Vector2<_> = s1.into();
752 let s2 = Size2D::from(sm);
753
754 assert_eq!(s1, s2);
755 }
756
757 mod ops {
758 use crate::default::Size2D;
759 use crate::scale::Scale;
760
761 pub enum Mm {}
762 pub enum Cm {}
763
764 pub type Size2DMm<T> = crate::Size2D<T, Mm>;
765 pub type Size2DCm<T> = crate::Size2D<T, Cm>;
766
767 #[test]
768 pub fn test_neg() {
769 assert_eq!(-Size2D::new(1.0, 2.0), Size2D::new(-1.0, -2.0));
770 assert_eq!(-Size2D::new(0.0, 0.0), Size2D::new(-0.0, -0.0));
771 assert_eq!(-Size2D::new(-1.0, -2.0), Size2D::new(1.0, 2.0));
772 }
773
774 #[test]
775 pub fn test_add() {
776 let s1 = Size2D::new(1.0, 2.0);
777 let s2 = Size2D::new(3.0, 4.0);
778 assert_eq!(s1 + s2, Size2D::new(4.0, 6.0));
779 assert_eq!(s1 + &s2, Size2D::new(4.0, 6.0));
780
781 let s1 = Size2D::new(1.0, 2.0);
782 let s2 = Size2D::new(0.0, 0.0);
783 assert_eq!(s1 + s2, Size2D::new(1.0, 2.0));
784 assert_eq!(s1 + &s2, Size2D::new(1.0, 2.0));
785
786 let s1 = Size2D::new(1.0, 2.0);
787 let s2 = Size2D::new(-3.0, -4.0);
788 assert_eq!(s1 + s2, Size2D::new(-2.0, -2.0));
789 assert_eq!(s1 + &s2, Size2D::new(-2.0, -2.0));
790
791 let s1 = Size2D::new(0.0, 0.0);
792 let s2 = Size2D::new(0.0, 0.0);
793 assert_eq!(s1 + s2, Size2D::new(0.0, 0.0));
794 assert_eq!(s1 + &s2, Size2D::new(0.0, 0.0));
795 }
796
797 #[test]
798 pub fn test_add_assign() {
799 let mut s = Size2D::new(1.0, 2.0);
800 s += Size2D::new(3.0, 4.0);
801 assert_eq!(s, Size2D::new(4.0, 6.0));
802
803 let mut s = Size2D::new(1.0, 2.0);
804 s += Size2D::new(0.0, 0.0);
805 assert_eq!(s, Size2D::new(1.0, 2.0));
806
807 let mut s = Size2D::new(1.0, 2.0);
808 s += Size2D::new(-3.0, -4.0);
809 assert_eq!(s, Size2D::new(-2.0, -2.0));
810
811 let mut s = Size2D::new(0.0, 0.0);
812 s += Size2D::new(0.0, 0.0);
813 assert_eq!(s, Size2D::new(0.0, 0.0));
814 }
815
816 #[test]
817 pub fn test_sum() {
818 let sizes = [
819 Size2D::new(0.0, 1.0),
820 Size2D::new(1.0, 2.0),
821 Size2D::new(2.0, 3.0),
822 ];
823 let sum = Size2D::new(3.0, 6.0);
824 assert_eq!(sizes.iter().sum::<Size2D<_>>(), sum);
825 }
826
827 #[test]
828 pub fn test_sub() {
829 let s1 = Size2D::new(1.0, 2.0);
830 let s2 = Size2D::new(3.0, 4.0);
831 assert_eq!(s1 - s2, Size2D::new(-2.0, -2.0));
832
833 let s1 = Size2D::new(1.0, 2.0);
834 let s2 = Size2D::new(0.0, 0.0);
835 assert_eq!(s1 - s2, Size2D::new(1.0, 2.0));
836
837 let s1 = Size2D::new(1.0, 2.0);
838 let s2 = Size2D::new(-3.0, -4.0);
839 assert_eq!(s1 - s2, Size2D::new(4.0, 6.0));
840
841 let s1 = Size2D::new(0.0, 0.0);
842 let s2 = Size2D::new(0.0, 0.0);
843 assert_eq!(s1 - s2, Size2D::new(0.0, 0.0));
844 }
845
846 #[test]
847 pub fn test_sub_assign() {
848 let mut s = Size2D::new(1.0, 2.0);
849 s -= Size2D::new(3.0, 4.0);
850 assert_eq!(s, Size2D::new(-2.0, -2.0));
851
852 let mut s = Size2D::new(1.0, 2.0);
853 s -= Size2D::new(0.0, 0.0);
854 assert_eq!(s, Size2D::new(1.0, 2.0));
855
856 let mut s = Size2D::new(1.0, 2.0);
857 s -= Size2D::new(-3.0, -4.0);
858 assert_eq!(s, Size2D::new(4.0, 6.0));
859
860 let mut s = Size2D::new(0.0, 0.0);
861 s -= Size2D::new(0.0, 0.0);
862 assert_eq!(s, Size2D::new(0.0, 0.0));
863 }
864
865 #[test]
866 pub fn test_mul_scalar() {
867 let s1: Size2D<f32> = Size2D::new(3.0, 5.0);
868
869 let result = s1 * 5.0;
870
871 assert_eq!(result, Size2D::new(15.0, 25.0));
872 }
873
874 #[test]
875 pub fn test_mul_assign_scalar() {
876 let mut s1 = Size2D::new(3.0, 5.0);
877
878 s1 *= 5.0;
879
880 assert_eq!(s1, Size2D::new(15.0, 25.0));
881 }
882
883 #[test]
884 pub fn test_mul_scale() {
885 let s1 = Size2DMm::new(1.0, 2.0);
886 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
887
888 let result = s1 * cm_per_mm;
889
890 assert_eq!(result, Size2DCm::new(0.1, 0.2));
891 }
892
893 #[test]
894 pub fn test_mul_assign_scale() {
895 let mut s1 = Size2DMm::new(1.0, 2.0);
896 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
897
898 s1 *= scale;
899
900 assert_eq!(s1, Size2DMm::new(0.1, 0.2));
901 }
902
903 #[test]
904 pub fn test_div_scalar() {
905 let s1: Size2D<f32> = Size2D::new(15.0, 25.0);
906
907 let result = s1 / 5.0;
908
909 assert_eq!(result, Size2D::new(3.0, 5.0));
910 }
911
912 #[test]
913 pub fn test_div_assign_scalar() {
914 let mut s1: Size2D<f32> = Size2D::new(15.0, 25.0);
915
916 s1 /= 5.0;
917
918 assert_eq!(s1, Size2D::new(3.0, 5.0));
919 }
920
921 #[test]
922 pub fn test_div_scale() {
923 let s1 = Size2DCm::new(0.1, 0.2);
924 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
925
926 let result = s1 / cm_per_mm;
927
928 assert_eq!(result, Size2DMm::new(1.0, 2.0));
929 }
930
931 #[test]
932 pub fn test_div_assign_scale() {
933 let mut s1 = Size2DMm::new(0.1, 0.2);
934 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
935
936 s1 /= scale;
937
938 assert_eq!(s1, Size2DMm::new(1.0, 2.0));
939 }
940
941 #[test]
942 pub fn test_nan_empty() {
943 use std::f32::NAN;
944 assert!(Size2D::new(NAN, 2.0).is_empty());
945 assert!(Size2D::new(0.0, NAN).is_empty());
946 assert!(Size2D::new(NAN, -2.0).is_empty());
947 }
948 }
949}
950
951#[repr(C)]
953pub struct Size3D<T, U> {
954 pub width: T,
956 pub height: T,
958 pub depth: T,
960 #[doc(hidden)]
961 pub _unit: PhantomData<U>,
962}
963
964impl<T: Copy, U> Copy for Size3D<T, U> {}
965
966impl<T: Clone, U> Clone for Size3D<T, U> {
967 fn clone(&self) -> Self {
968 Size3D {
969 width: self.width.clone(),
970 height: self.height.clone(),
971 depth: self.depth.clone(),
972 _unit: PhantomData,
973 }
974 }
975}
976
977#[cfg(feature = "serde")]
978impl<'de, T, U> serde::Deserialize<'de> for Size3D<T, U>
979where
980 T: serde::Deserialize<'de>,
981{
982 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
983 where
984 D: serde::Deserializer<'de>,
985 {
986 let (width, height, depth) = serde::Deserialize::deserialize(deserializer)?;
987 Ok(Size3D {
988 width,
989 height,
990 depth,
991 _unit: PhantomData,
992 })
993 }
994}
995
996#[cfg(feature = "serde")]
997impl<T, U> serde::Serialize for Size3D<T, U>
998where
999 T: serde::Serialize,
1000{
1001 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1002 where
1003 S: serde::Serializer,
1004 {
1005 (&self.width, &self.height, &self.depth).serialize(serializer)
1006 }
1007}
1008
1009#[cfg(feature = "arbitrary")]
1010impl<'a, T, U> arbitrary::Arbitrary<'a> for Size3D<T, U>
1011where
1012 T: arbitrary::Arbitrary<'a>,
1013{
1014 fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1015 let (width, height, depth) = arbitrary::Arbitrary::arbitrary(u)?;
1016 Ok(Size3D {
1017 width,
1018 height,
1019 depth,
1020 _unit: PhantomData,
1021 })
1022 }
1023}
1024
1025#[cfg(feature = "bytemuck")]
1026unsafe impl<T: Zeroable, U> Zeroable for Size3D<T, U> {}
1027
1028#[cfg(feature = "bytemuck")]
1029unsafe impl<T: Pod, U: 'static> Pod for Size3D<T, U> {}
1030
1031#[cfg(feature = "malloc_size_of")]
1032impl<T: MallocSizeOf, U> MallocSizeOf for Size3D<T, U> {
1033 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1034 self.width.size_of(ops) + self.height.size_of(ops) + self.depth.size_of(ops)
1035 }
1036}
1037
1038impl<T, U> Eq for Size3D<T, U> where T: Eq {}
1039
1040impl<T, U> PartialEq for Size3D<T, U>
1041where
1042 T: PartialEq,
1043{
1044 fn eq(&self, other: &Self) -> bool {
1045 self.width == other.width && self.height == other.height && self.depth == other.depth
1046 }
1047}
1048
1049impl<T, U> Hash for Size3D<T, U>
1050where
1051 T: Hash,
1052{
1053 fn hash<H: core::hash::Hasher>(&self, h: &mut H) {
1054 self.width.hash(h);
1055 self.height.hash(h);
1056 self.depth.hash(h);
1057 }
1058}
1059
1060impl<T: fmt::Debug, U> fmt::Debug for Size3D<T, U> {
1061 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1062 fmt::Debug::fmt(&self.width, f)?;
1063 write!(f, "x")?;
1064 fmt::Debug::fmt(&self.height, f)?;
1065 write!(f, "x")?;
1066 fmt::Debug::fmt(&self.depth, f)
1067 }
1068}
1069
1070impl<T: Default, U> Default for Size3D<T, U> {
1071 fn default() -> Self {
1072 Size3D::new(Default::default(), Default::default(), Default::default())
1073 }
1074}
1075
1076impl<T, U> Size3D<T, U> {
1077 pub fn zero() -> Self
1081 where
1082 T: Zero,
1083 {
1084 Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
1085 }
1086
1087 #[inline]
1089 pub const fn new(width: T, height: T, depth: T) -> Self {
1090 Size3D {
1091 width,
1092 height,
1093 depth,
1094 _unit: PhantomData,
1095 }
1096 }
1097 #[inline]
1099 pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
1100 Size3D::new(width.0, height.0, depth.0)
1101 }
1102
1103 #[inline]
1105 pub fn splat(v: T) -> Self
1106 where
1107 T: Clone,
1108 {
1109 Size3D {
1110 width: v.clone(),
1111 height: v.clone(),
1112 depth: v,
1113 _unit: PhantomData,
1114 }
1115 }
1116
1117 #[inline]
1119 pub fn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
1120 Size3D::new(p.width, p.height, p.depth)
1121 }
1122}
1123
1124impl<T: Copy, U> Size3D<T, U> {
1125 #[inline]
1127 pub fn to_array(self) -> [T; 3] {
1128 [self.width, self.height, self.depth]
1129 }
1130
1131 #[inline]
1133 pub fn to_tuple(self) -> (T, T, T) {
1134 (self.width, self.height, self.depth)
1135 }
1136
1137 #[inline]
1139 pub fn to_vector(self) -> Vector3D<T, U> {
1140 vec3(self.width, self.height, self.depth)
1141 }
1142
1143 #[inline]
1145 pub fn to_untyped(self) -> Size3D<T, UnknownUnit> {
1146 self.cast_unit()
1147 }
1148
1149 #[inline]
1151 pub fn cast_unit<V>(self) -> Size3D<T, V> {
1152 Size3D::new(self.width, self.height, self.depth)
1153 }
1154
1155 #[inline]
1166 #[must_use]
1167 pub fn round(self) -> Self
1168 where
1169 T: Round,
1170 {
1171 Size3D::new(self.width.round(), self.height.round(), self.depth.round())
1172 }
1173
1174 #[inline]
1185 #[must_use]
1186 pub fn ceil(self) -> Self
1187 where
1188 T: Ceil,
1189 {
1190 Size3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
1191 }
1192
1193 #[inline]
1204 #[must_use]
1205 pub fn floor(self) -> Self
1206 where
1207 T: Floor,
1208 {
1209 Size3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
1210 }
1211
1212 pub fn volume(self) -> T
1214 where
1215 T: Mul<Output = T>,
1216 {
1217 self.width * self.height * self.depth
1218 }
1219
1220 #[inline]
1238 pub fn lerp(self, other: Self, t: T) -> Self
1239 where
1240 T: One + Sub<Output = T> + Mul<Output = T> + Add<Output = T>,
1241 {
1242 let one_t = T::one() - t;
1243 self * one_t + other * t
1244 }
1245}
1246
1247impl<T: NumCast + Copy, U> Size3D<T, U> {
1248 #[inline]
1254 pub fn cast<NewT: NumCast>(self) -> Size3D<NewT, U> {
1255 self.try_cast().unwrap()
1256 }
1257
1258 pub fn try_cast<NewT: NumCast>(self) -> Option<Size3D<NewT, U>> {
1264 match (
1265 NumCast::from(self.width),
1266 NumCast::from(self.height),
1267 NumCast::from(self.depth),
1268 ) {
1269 (Some(w), Some(h), Some(d)) => Some(Size3D::new(w, h, d)),
1270 _ => None,
1271 }
1272 }
1273
1274 #[inline]
1278 pub fn to_f32(self) -> Size3D<f32, U> {
1279 self.cast()
1280 }
1281
1282 #[inline]
1284 pub fn to_f64(self) -> Size3D<f64, U> {
1285 self.cast()
1286 }
1287
1288 #[inline]
1294 pub fn to_usize(self) -> Size3D<usize, U> {
1295 self.cast()
1296 }
1297
1298 #[inline]
1304 pub fn to_u32(self) -> Size3D<u32, U> {
1305 self.cast()
1306 }
1307
1308 #[inline]
1314 pub fn to_i32(self) -> Size3D<i32, U> {
1315 self.cast()
1316 }
1317
1318 #[inline]
1324 pub fn to_i64(self) -> Size3D<i64, U> {
1325 self.cast()
1326 }
1327}
1328
1329impl<T: Float, U> Size3D<T, U> {
1330 #[inline]
1332 pub fn is_finite(self) -> bool {
1333 self.width.is_finite() && self.height.is_finite() && self.depth.is_finite()
1334 }
1335}
1336
1337impl<T: Signed, U> Size3D<T, U> {
1338 pub fn abs(self) -> Self {
1344 size3(self.width.abs(), self.height.abs(), self.depth.abs())
1345 }
1346
1347 pub fn is_positive(self) -> bool {
1349 self.width.is_positive() && self.height.is_positive() && self.depth.is_positive()
1350 }
1351}
1352
1353impl<T: PartialOrd, U> Size3D<T, U> {
1354 #[inline]
1356 pub fn min(self, other: Self) -> Self {
1357 size3(
1358 min(self.width, other.width),
1359 min(self.height, other.height),
1360 min(self.depth, other.depth),
1361 )
1362 }
1363
1364 #[inline]
1366 pub fn max(self, other: Self) -> Self {
1367 size3(
1368 max(self.width, other.width),
1369 max(self.height, other.height),
1370 max(self.depth, other.depth),
1371 )
1372 }
1373
1374 #[inline]
1379 pub fn clamp(self, start: Self, end: Self) -> Self
1380 where
1381 T: Copy,
1382 {
1383 self.max(start).min(end)
1384 }
1385
1386 #[inline]
1388 pub fn contains(self, other: Self) -> bool {
1389 self.width >= other.width && self.height >= other.height && self.depth >= other.depth
1390 }
1391
1392 pub fn greater_than(self, other: Self) -> BoolVector3D {
1394 BoolVector3D {
1395 x: self.width > other.width,
1396 y: self.height > other.height,
1397 z: self.depth > other.depth,
1398 }
1399 }
1400
1401 pub fn lower_than(self, other: Self) -> BoolVector3D {
1403 BoolVector3D {
1404 x: self.width < other.width,
1405 y: self.height < other.height,
1406 z: self.depth < other.depth,
1407 }
1408 }
1409
1410 pub fn is_empty(self) -> bool
1412 where
1413 T: Zero,
1414 {
1415 let zero = T::zero();
1416 !(self.width > zero && self.height > zero && self.depth > zero)
1417 }
1418}
1419
1420impl<T: PartialEq, U> Size3D<T, U> {
1421 pub fn equal(self, other: Self) -> BoolVector3D {
1423 BoolVector3D {
1424 x: self.width == other.width,
1425 y: self.height == other.height,
1426 z: self.depth == other.depth,
1427 }
1428 }
1429
1430 pub fn not_equal(self, other: Self) -> BoolVector3D {
1432 BoolVector3D {
1433 x: self.width != other.width,
1434 y: self.height != other.height,
1435 z: self.depth != other.depth,
1436 }
1437 }
1438}
1439
1440impl<T: Round, U> Round for Size3D<T, U> {
1441 #[inline]
1443 fn round(self) -> Self {
1444 self.round()
1445 }
1446}
1447
1448impl<T: Ceil, U> Ceil for Size3D<T, U> {
1449 #[inline]
1451 fn ceil(self) -> Self {
1452 self.ceil()
1453 }
1454}
1455
1456impl<T: Floor, U> Floor for Size3D<T, U> {
1457 #[inline]
1459 fn floor(self) -> Self {
1460 self.floor()
1461 }
1462}
1463
1464impl<T: Zero, U> Zero for Size3D<T, U> {
1465 #[inline]
1466 fn zero() -> Self {
1467 Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
1468 }
1469}
1470
1471impl<T: Neg, U> Neg for Size3D<T, U> {
1472 type Output = Size3D<T::Output, U>;
1473
1474 #[inline]
1475 fn neg(self) -> Self::Output {
1476 Size3D::new(-self.width, -self.height, -self.depth)
1477 }
1478}
1479
1480impl<T: Add, U> Add for Size3D<T, U> {
1481 type Output = Size3D<T::Output, U>;
1482
1483 #[inline]
1484 fn add(self, other: Self) -> Self::Output {
1485 Size3D::new(
1486 self.width + other.width,
1487 self.height + other.height,
1488 self.depth + other.depth,
1489 )
1490 }
1491}
1492
1493impl<T: Copy + Add<T, Output = T>, U> Add<&Self> for Size3D<T, U> {
1494 type Output = Self;
1495 fn add(self, other: &Self) -> Self {
1496 Size3D::new(
1497 self.width + other.width,
1498 self.height + other.height,
1499 self.depth + other.depth,
1500 )
1501 }
1502}
1503
1504impl<T: Add<Output = T> + Zero, U> Sum for Size3D<T, U> {
1505 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1506 iter.fold(Self::zero(), Add::add)
1507 }
1508}
1509
1510impl<'a, T: 'a + Add<Output = T> + Copy + Zero, U: 'a> Sum<&'a Self> for Size3D<T, U> {
1511 fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
1512 iter.fold(Self::zero(), Add::add)
1513 }
1514}
1515
1516impl<T: AddAssign, U> AddAssign for Size3D<T, U> {
1517 #[inline]
1518 fn add_assign(&mut self, other: Self) {
1519 self.width += other.width;
1520 self.height += other.height;
1521 self.depth += other.depth;
1522 }
1523}
1524
1525impl<T: Sub, U> Sub for Size3D<T, U> {
1526 type Output = Size3D<T::Output, U>;
1527
1528 #[inline]
1529 fn sub(self, other: Self) -> Self::Output {
1530 Size3D::new(
1531 self.width - other.width,
1532 self.height - other.height,
1533 self.depth - other.depth,
1534 )
1535 }
1536}
1537
1538impl<T: SubAssign, U> SubAssign for Size3D<T, U> {
1539 #[inline]
1540 fn sub_assign(&mut self, other: Self) {
1541 self.width -= other.width;
1542 self.height -= other.height;
1543 self.depth -= other.depth;
1544 }
1545}
1546
1547impl<T: Copy + Mul, U> Mul<T> for Size3D<T, U> {
1548 type Output = Size3D<T::Output, U>;
1549
1550 #[inline]
1551 #[rustfmt::skip]
1552 fn mul(self, scale: T) -> Self::Output {
1553 Size3D::new(
1554 self.width * scale,
1555 self.height * scale,
1556 self.depth * scale,
1557 )
1558 }
1559}
1560
1561impl<T: Copy + MulAssign, U> MulAssign<T> for Size3D<T, U> {
1562 #[inline]
1563 fn mul_assign(&mut self, other: T) {
1564 self.width *= other;
1565 self.height *= other;
1566 self.depth *= other;
1567 }
1568}
1569
1570impl<T: Copy + Mul, U1, U2> Mul<Scale<T, U1, U2>> for Size3D<T, U1> {
1571 type Output = Size3D<T::Output, U2>;
1572
1573 #[inline]
1574 fn mul(self, scale: Scale<T, U1, U2>) -> Self::Output {
1575 Size3D::new(
1576 self.width * scale.0,
1577 self.height * scale.0,
1578 self.depth * scale.0,
1579 )
1580 }
1581}
1582
1583impl<T: Copy + MulAssign, U> MulAssign<Scale<T, U, U>> for Size3D<T, U> {
1584 #[inline]
1585 fn mul_assign(&mut self, other: Scale<T, U, U>) {
1586 *self *= other.0;
1587 }
1588}
1589
1590impl<T: Copy + Div, U> Div<T> for Size3D<T, U> {
1591 type Output = Size3D<T::Output, U>;
1592
1593 #[inline]
1594 #[rustfmt::skip]
1595 fn div(self, scale: T) -> Self::Output {
1596 Size3D::new(
1597 self.width / scale,
1598 self.height / scale,
1599 self.depth / scale,
1600 )
1601 }
1602}
1603
1604impl<T: Copy + DivAssign, U> DivAssign<T> for Size3D<T, U> {
1605 #[inline]
1606 fn div_assign(&mut self, other: T) {
1607 self.width /= other;
1608 self.height /= other;
1609 self.depth /= other;
1610 }
1611}
1612
1613impl<T: Copy + Div, U1, U2> Div<Scale<T, U1, U2>> for Size3D<T, U2> {
1614 type Output = Size3D<T::Output, U1>;
1615
1616 #[inline]
1617 fn div(self, scale: Scale<T, U1, U2>) -> Self::Output {
1618 Size3D::new(
1619 self.width / scale.0,
1620 self.height / scale.0,
1621 self.depth / scale.0,
1622 )
1623 }
1624}
1625
1626impl<T: Copy + DivAssign, U> DivAssign<Scale<T, U, U>> for Size3D<T, U> {
1627 #[inline]
1628 fn div_assign(&mut self, other: Scale<T, U, U>) {
1629 *self /= other.0;
1630 }
1631}
1632
1633#[cfg(feature = "mint")]
1634impl<T, U> From<mint::Vector3<T>> for Size3D<T, U> {
1635 #[inline]
1636 fn from(v: mint::Vector3<T>) -> Self {
1637 size3(v.x, v.y, v.z)
1638 }
1639}
1640#[cfg(feature = "mint")]
1641impl<T, U> From<Size3D<T, U>> for mint::Vector3<T> {
1642 #[inline]
1643 fn from(s: Size3D<T, U>) -> Self {
1644 mint::Vector3 {
1645 x: s.width,
1646 y: s.height,
1647 z: s.depth,
1648 }
1649 }
1650}
1651
1652impl<T, U> From<Vector3D<T, U>> for Size3D<T, U> {
1653 #[inline]
1654 fn from(v: Vector3D<T, U>) -> Self {
1655 size3(v.x, v.y, v.z)
1656 }
1657}
1658
1659impl<T, U> From<Size3D<T, U>> for [T; 3] {
1660 #[inline]
1661 fn from(s: Size3D<T, U>) -> Self {
1662 [s.width, s.height, s.depth]
1663 }
1664}
1665
1666impl<T, U> From<[T; 3]> for Size3D<T, U> {
1667 #[inline]
1668 fn from([w, h, d]: [T; 3]) -> Self {
1669 size3(w, h, d)
1670 }
1671}
1672
1673impl<T, U> From<Size3D<T, U>> for (T, T, T) {
1674 #[inline]
1675 fn from(s: Size3D<T, U>) -> Self {
1676 (s.width, s.height, s.depth)
1677 }
1678}
1679
1680impl<T, U> From<(T, T, T)> for Size3D<T, U> {
1681 #[inline]
1682 fn from(tuple: (T, T, T)) -> Self {
1683 size3(tuple.0, tuple.1, tuple.2)
1684 }
1685}
1686
1687#[inline]
1689pub const fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
1690 Size3D::new(w, h, d)
1691}
1692
1693#[cfg(test)]
1694mod size3d {
1695 mod ops {
1696 use crate::default::{Size2D, Size3D};
1697 use crate::scale::Scale;
1698
1699 pub enum Mm {}
1700 pub enum Cm {}
1701
1702 pub type Size3DMm<T> = crate::Size3D<T, Mm>;
1703 pub type Size3DCm<T> = crate::Size3D<T, Cm>;
1704
1705 #[test]
1706 pub fn test_neg() {
1707 assert_eq!(-Size3D::new(1.0, 2.0, 3.0), Size3D::new(-1.0, -2.0, -3.0));
1708 assert_eq!(-Size3D::new(0.0, 0.0, 0.0), Size3D::new(-0.0, -0.0, -0.0));
1709 assert_eq!(-Size3D::new(-1.0, -2.0, -3.0), Size3D::new(1.0, 2.0, 3.0));
1710 }
1711
1712 #[test]
1713 pub fn test_add() {
1714 let s1 = Size3D::new(1.0, 2.0, 3.0);
1715 let s2 = Size3D::new(4.0, 5.0, 6.0);
1716 assert_eq!(s1 + s2, Size3D::new(5.0, 7.0, 9.0));
1717 assert_eq!(s1 + &s2, Size3D::new(5.0, 7.0, 9.0));
1718
1719 let s1 = Size3D::new(1.0, 2.0, 3.0);
1720 let s2 = Size3D::new(0.0, 0.0, 0.0);
1721 assert_eq!(s1 + s2, Size3D::new(1.0, 2.0, 3.0));
1722 assert_eq!(s1 + &s2, Size3D::new(1.0, 2.0, 3.0));
1723
1724 let s1 = Size3D::new(1.0, 2.0, 3.0);
1725 let s2 = Size3D::new(-4.0, -5.0, -6.0);
1726 assert_eq!(s1 + s2, Size3D::new(-3.0, -3.0, -3.0));
1727 assert_eq!(s1 + &s2, Size3D::new(-3.0, -3.0, -3.0));
1728
1729 let s1 = Size3D::new(0.0, 0.0, 0.0);
1730 let s2 = Size3D::new(0.0, 0.0, 0.0);
1731 assert_eq!(s1 + s2, Size3D::new(0.0, 0.0, 0.0));
1732 assert_eq!(s1 + &s2, Size3D::new(0.0, 0.0, 0.0));
1733 }
1734
1735 #[test]
1736 pub fn test_sum() {
1737 let sizes = [
1738 Size3D::new(0.0, 1.0, 2.0),
1739 Size3D::new(1.0, 2.0, 3.0),
1740 Size3D::new(2.0, 3.0, 4.0),
1741 ];
1742 let sum = Size3D::new(3.0, 6.0, 9.0);
1743 assert_eq!(sizes.iter().sum::<Size3D<_>>(), sum);
1744 }
1745
1746 #[test]
1747 pub fn test_add_assign() {
1748 let mut s = Size3D::new(1.0, 2.0, 3.0);
1749 s += Size3D::new(4.0, 5.0, 6.0);
1750 assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1751
1752 let mut s = Size3D::new(1.0, 2.0, 3.0);
1753 s += Size3D::new(0.0, 0.0, 0.0);
1754 assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1755
1756 let mut s = Size3D::new(1.0, 2.0, 3.0);
1757 s += Size3D::new(-4.0, -5.0, -6.0);
1758 assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1759
1760 let mut s = Size3D::new(0.0, 0.0, 0.0);
1761 s += Size3D::new(0.0, 0.0, 0.0);
1762 assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1763 }
1764
1765 #[test]
1766 pub fn test_sub() {
1767 let s1 = Size3D::new(1.0, 2.0, 3.0);
1768 let s2 = Size3D::new(4.0, 5.0, 6.0);
1769 assert_eq!(s1 - s2, Size3D::new(-3.0, -3.0, -3.0));
1770
1771 let s1 = Size3D::new(1.0, 2.0, 3.0);
1772 let s2 = Size3D::new(0.0, 0.0, 0.0);
1773 assert_eq!(s1 - s2, Size3D::new(1.0, 2.0, 3.0));
1774
1775 let s1 = Size3D::new(1.0, 2.0, 3.0);
1776 let s2 = Size3D::new(-4.0, -5.0, -6.0);
1777 assert_eq!(s1 - s2, Size3D::new(5.0, 7.0, 9.0));
1778
1779 let s1 = Size3D::new(0.0, 0.0, 0.0);
1780 let s2 = Size3D::new(0.0, 0.0, 0.0);
1781 assert_eq!(s1 - s2, Size3D::new(0.0, 0.0, 0.0));
1782 }
1783
1784 #[test]
1785 pub fn test_sub_assign() {
1786 let mut s = Size3D::new(1.0, 2.0, 3.0);
1787 s -= Size3D::new(4.0, 5.0, 6.0);
1788 assert_eq!(s, Size3D::new(-3.0, -3.0, -3.0));
1789
1790 let mut s = Size3D::new(1.0, 2.0, 3.0);
1791 s -= Size3D::new(0.0, 0.0, 0.0);
1792 assert_eq!(s, Size3D::new(1.0, 2.0, 3.0));
1793
1794 let mut s = Size3D::new(1.0, 2.0, 3.0);
1795 s -= Size3D::new(-4.0, -5.0, -6.0);
1796 assert_eq!(s, Size3D::new(5.0, 7.0, 9.0));
1797
1798 let mut s = Size3D::new(0.0, 0.0, 0.0);
1799 s -= Size3D::new(0.0, 0.0, 0.0);
1800 assert_eq!(s, Size3D::new(0.0, 0.0, 0.0));
1801 }
1802
1803 #[test]
1804 pub fn test_mul_scalar() {
1805 let s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1806
1807 let result = s1 * 5.0;
1808
1809 assert_eq!(result, Size3D::new(15.0, 25.0, 35.0));
1810 }
1811
1812 #[test]
1813 pub fn test_mul_assign_scalar() {
1814 let mut s1: Size3D<f32> = Size3D::new(3.0, 5.0, 7.0);
1815
1816 s1 *= 5.0;
1817
1818 assert_eq!(s1, Size3D::new(15.0, 25.0, 35.0));
1819 }
1820
1821 #[test]
1822 pub fn test_mul_scale() {
1823 let s1 = Size3DMm::new(1.0, 2.0, 3.0);
1824 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1825
1826 let result = s1 * cm_per_mm;
1827
1828 assert_eq!(result, Size3DCm::new(0.1, 0.2, 0.3));
1829 }
1830
1831 #[test]
1832 pub fn test_mul_assign_scale() {
1833 let mut s1 = Size3DMm::new(1.0, 2.0, 3.0);
1834 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1835
1836 s1 *= scale;
1837
1838 assert_eq!(s1, Size3DMm::new(0.1, 0.2, 0.3));
1839 }
1840
1841 #[test]
1842 pub fn test_div_scalar() {
1843 let s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1844
1845 let result = s1 / 5.0;
1846
1847 assert_eq!(result, Size3D::new(3.0, 5.0, 7.0));
1848 }
1849
1850 #[test]
1851 pub fn test_div_assign_scalar() {
1852 let mut s1: Size3D<f32> = Size3D::new(15.0, 25.0, 35.0);
1853
1854 s1 /= 5.0;
1855
1856 assert_eq!(s1, Size3D::new(3.0, 5.0, 7.0));
1857 }
1858
1859 #[test]
1860 pub fn test_div_scale() {
1861 let s1 = Size3DCm::new(0.1, 0.2, 0.3);
1862 let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
1863
1864 let result = s1 / cm_per_mm;
1865
1866 assert_eq!(result, Size3DMm::new(1.0, 2.0, 3.0));
1867 }
1868
1869 #[test]
1870 pub fn test_div_assign_scale() {
1871 let mut s1 = Size3DMm::new(0.1, 0.2, 0.3);
1872 let scale: Scale<f32, Mm, Mm> = Scale::new(0.1);
1873
1874 s1 /= scale;
1875
1876 assert_eq!(s1, Size3DMm::new(1.0, 2.0, 3.0));
1877 }
1878
1879 #[test]
1880 fn test_nonempty() {
1881 assert!(!Size2D::new(1.0, 1.0).is_empty());
1882 assert!(!Size3D::new(1.0, 1.0, 1.0).is_empty());
1883 }
1884
1885 #[test]
1886 pub fn test_nan_empty() {
1887 use std::f32::NAN;
1888 assert!(Size3D::new(NAN, 2.0, 3.0).is_empty());
1889 assert!(Size3D::new(0.0, NAN, 0.0).is_empty());
1890 assert!(Size3D::new(1.0, 2.0, NAN).is_empty());
1891 }
1892 }
1893}