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