1
use std::{
2
    fmt::Debug,
3
    marker::PhantomData,
4
    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
5
};
6

            
7
use approx::{AbsDiffEq, RelativeEq, UlpsEq};
8
use num_traits::{NumCast, One, ToPrimitive, Zero};
9

            
10
use crate::{
11
    num::{Ceil, Floor},
12
    Approx, DisplayScale, Displayable, Pixels, Points, Round, Scale, Scaled,
13
};
14

            
15
/// A value in a specific unit.
16
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17
pub struct Figure<T, Unit> {
18
    value: T,
19
    _unit: PhantomData<Unit>,
20
}
21

            
22
impl<T: Debug, Unit> Debug for Figure<T, Unit> {
23
1
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24
1
        f.debug_tuple("Figure").field(&self.value).finish()
25
1
    }
26
}
27

            
28
impl<T: Copy, Unit> Copy for Figure<T, Unit> {}
29
impl<T: Clone, Unit> Clone for Figure<T, Unit> {
30
    fn clone(&self) -> Self {
31
        Self::from(self.value.clone())
32
    }
33
}
34

            
35
impl<T, Unit> Figure<T, Unit> {
36
    /// Returns a new figure with `value`.
37
7
    pub const fn new(value: T) -> Self {
38
7
        Self {
39
7
            value,
40
7
            _unit: PhantomData,
41
7
        }
42
7
    }
43
}
44

            
45
impl<T: Copy, Unit> Figure<T, Unit> {
46
    /// Returns the inner value
47
56
    pub fn get(&self) -> T {
48
56
        self.value
49
56
    }
50

            
51
    /// Returns this value with the new unit. Does not affect the underlying
52
    /// value.
53
1
    pub fn cast_unit<NewUnit>(&self) -> Figure<T, NewUnit> {
54
1
        Figure::new(self.value)
55
1
    }
56
}
57

            
58
impl<T, Unit> Figure<T, Unit>
59
where
60
    T: std::cmp::PartialOrd + Copy,
61
{
62
    /// Returns the smaller value of `self` and `rhs`.
63
4
    pub fn min(self, rhs: Self) -> Self {
64
4
        if self.get() <= rhs.get() {
65
3
            self
66
        } else {
67
1
            rhs
68
        }
69
4
    }
70

            
71
    /// Returns the larger value of `self` and `rhs`.
72
4
    pub fn max(self, rhs: Self) -> Self {
73
4
        if self.get() >= rhs.get() {
74
1
            self
75
        } else {
76
3
            rhs
77
        }
78
4
    }
79
}
80

            
81
impl<T, Unit> From<T> for Figure<T, Unit> {
82
62
    fn from(value: T) -> Self {
83
62
        Self {
84
62
            value,
85
62
            _unit: PhantomData::default(),
86
62
        }
87
62
    }
88
}
89

            
90
impl<T, Unit> ToPrimitive for Figure<T, Unit>
91
where
92
    T: ToPrimitive,
93
{
94
1
    fn to_i64(&self) -> Option<i64> {
95
1
        T::to_i64(&self.value)
96
1
    }
97

            
98
1
    fn to_u64(&self) -> Option<u64> {
99
1
        T::to_u64(&self.value)
100
1
    }
101

            
102
1
    fn to_isize(&self) -> Option<isize> {
103
1
        T::to_isize(&self.value)
104
1
    }
105

            
106
1
    fn to_i8(&self) -> Option<i8> {
107
1
        T::to_i8(&self.value)
108
1
    }
109

            
110
1
    fn to_i16(&self) -> Option<i16> {
111
1
        T::to_i16(&self.value)
112
1
    }
113

            
114
1
    fn to_i32(&self) -> Option<i32> {
115
1
        T::to_i32(&self.value)
116
1
    }
117

            
118
1
    fn to_i128(&self) -> Option<i128> {
119
1
        T::to_i128(&self.value)
120
1
    }
121

            
122
1
    fn to_usize(&self) -> Option<usize> {
123
1
        T::to_usize(&self.value)
124
1
    }
125

            
126
1
    fn to_u8(&self) -> Option<u8> {
127
1
        T::to_u8(&self.value)
128
1
    }
129

            
130
1
    fn to_u16(&self) -> Option<u16> {
131
1
        T::to_u16(&self.value)
132
1
    }
133

            
134
1
    fn to_u32(&self) -> Option<u32> {
135
1
        T::to_u32(&self.value)
136
1
    }
137

            
138
1
    fn to_u128(&self) -> Option<u128> {
139
1
        T::to_u128(&self.value)
140
1
    }
141

            
142
1
    fn to_f32(&self) -> Option<f32> {
143
1
        T::to_f32(&self.value)
144
1
    }
145

            
146
1
    fn to_f64(&self) -> Option<f64> {
147
1
        T::to_f64(&self.value)
148
1
    }
149
}
150

            
151
impl<T, Unit> NumCast for Figure<T, Unit>
152
where
153
    T: NumCast,
154
{
155
1
    fn from<N: num_traits::ToPrimitive>(n: N) -> Option<Self> {
156
1
        T::from(n).map(<Self as std::convert::From<T>>::from)
157
1
    }
158
}
159

            
160
impl<T, Unit> Default for Figure<T, Unit>
161
where
162
    T: Default,
163
{
164
1
    fn default() -> Self {
165
1
        Self {
166
1
            value: T::default(),
167
1
            _unit: PhantomData::default(),
168
1
        }
169
1
    }
170
}
171

            
172
impl<T, Unit> Eq for Figure<T, Unit> where T: Eq {}
173

            
174
impl<T, Unit> PartialEq for Figure<T, Unit>
175
where
176
    T: PartialEq,
177
{
178
11
    fn eq(&self, other: &Self) -> bool {
179
11
        self.value.eq(&other.value)
180
11
    }
181
}
182

            
183
impl<T, Unit> Ord for Figure<T, Unit>
184
where
185
    T: Ord,
186
{
187
1
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
188
1
        self.value.cmp(&other.value)
189
1
    }
190
}
191

            
192
impl<T, Unit> PartialOrd for Figure<T, Unit>
193
where
194
    T: PartialOrd,
195
{
196
1
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
197
1
        self.value.partial_cmp(&other.value)
198
1
    }
199
}
200

            
201
impl<T, Unit> Add for Figure<T, Unit>
202
where
203
    T: Add<Output = T>,
204
{
205
    type Output = Self;
206

            
207
1
    fn add(self, rhs: Self) -> Self::Output {
208
1
        Self {
209
1
            value: self.value.add(rhs.value),
210
1
            _unit: PhantomData::default(),
211
1
        }
212
1
    }
213
}
214

            
215
impl<T, Unit> Sub for Figure<T, Unit>
216
where
217
    T: Sub<Output = T>,
218
{
219
    type Output = Self;
220

            
221
3
    fn sub(self, rhs: Self) -> Self::Output {
222
3
        Self {
223
3
            value: self.value.sub(rhs.value),
224
3
            _unit: PhantomData::default(),
225
3
        }
226
3
    }
227
}
228

            
229
impl<T, Unit> Mul for Figure<T, Unit>
230
where
231
    T: Mul<Output = T>,
232
{
233
    type Output = Self;
234

            
235
1
    fn mul(self, rhs: Self) -> Self::Output {
236
1
        Self {
237
1
            value: self.value.mul(rhs.value),
238
1
            _unit: PhantomData::default(),
239
1
        }
240
1
    }
241
}
242

            
243
impl<T, Unit> Div for Figure<T, Unit>
244
where
245
    T: Div<Output = T>,
246
{
247
    type Output = Self;
248

            
249
1
    fn div(self, rhs: Self) -> Self::Output {
250
1
        Self {
251
1
            value: self.value.div(rhs.value),
252
1
            _unit: PhantomData::default(),
253
1
        }
254
1
    }
255
}
256

            
257
impl<T, Unit> Rem for Figure<T, Unit>
258
where
259
    T: Rem<Output = T>,
260
{
261
    type Output = Self;
262

            
263
1
    fn rem(self, rhs: Self) -> Self::Output {
264
1
        Self {
265
1
            value: self.value.rem(rhs.value),
266
1
            _unit: PhantomData::default(),
267
1
        }
268
1
    }
269
}
270

            
271
impl<T, Unit> AddAssign for Figure<T, Unit>
272
where
273
    T: AddAssign,
274
{
275
1
    fn add_assign(&mut self, rhs: Self) {
276
1
        self.value.add_assign(rhs.value);
277
1
    }
278
}
279

            
280
impl<T, Unit> SubAssign for Figure<T, Unit>
281
where
282
    T: SubAssign,
283
{
284
1
    fn sub_assign(&mut self, rhs: Self) {
285
1
        self.value.sub_assign(rhs.value);
286
1
    }
287
}
288

            
289
impl<T, Unit> DivAssign for Figure<T, Unit>
290
where
291
    T: DivAssign,
292
{
293
1
    fn div_assign(&mut self, rhs: Self) {
294
1
        self.value.div_assign(rhs.value);
295
1
    }
296
}
297

            
298
impl<T, Unit> MulAssign for Figure<T, Unit>
299
where
300
    T: MulAssign,
301
{
302
1
    fn mul_assign(&mut self, rhs: Self) {
303
1
        self.value.mul_assign(rhs.value);
304
1
    }
305
}
306

            
307
impl<T, Unit> RemAssign for Figure<T, Unit>
308
where
309
    T: RemAssign,
310
{
311
1
    fn rem_assign(&mut self, rhs: Self) {
312
1
        self.value.rem_assign(rhs.value);
313
1
    }
314
}
315

            
316
impl<T, Unit> Add<T> for Figure<T, Unit>
317
where
318
    T: Add<Output = T>,
319
{
320
    type Output = Self;
321

            
322
1
    fn add(self, rhs: T) -> Self::Output {
323
1
        Self {
324
1
            value: self.value.add(rhs),
325
1
            _unit: PhantomData::default(),
326
1
        }
327
1
    }
328
}
329

            
330
impl<T, Unit> Sub<T> for Figure<T, Unit>
331
where
332
    T: Sub<Output = T>,
333
{
334
    type Output = Self;
335

            
336
1
    fn sub(self, rhs: T) -> Self::Output {
337
1
        Self {
338
1
            value: self.value.sub(rhs),
339
1
            _unit: PhantomData::default(),
340
1
        }
341
1
    }
342
}
343

            
344
impl<T, Unit> Mul<T> for Figure<T, Unit>
345
where
346
    T: Mul<Output = T>,
347
{
348
    type Output = Self;
349

            
350
1
    fn mul(self, rhs: T) -> Self::Output {
351
1
        Self {
352
1
            value: self.value.mul(rhs),
353
1
            _unit: PhantomData::default(),
354
1
        }
355
1
    }
356
}
357

            
358
impl<T, Unit> Div<T> for Figure<T, Unit>
359
where
360
    T: Div<Output = T>,
361
{
362
    type Output = Self;
363

            
364
1
    fn div(self, rhs: T) -> Self::Output {
365
1
        Self {
366
1
            value: self.value.div(rhs),
367
1
            _unit: PhantomData::default(),
368
1
        }
369
1
    }
370
}
371

            
372
impl<T, Unit> Rem<T> for Figure<T, Unit>
373
where
374
    T: Rem<Output = T>,
375
{
376
    type Output = Self;
377

            
378
1
    fn rem(self, rhs: T) -> Self::Output {
379
1
        Self {
380
1
            value: self.value.rem(rhs),
381
1
            _unit: PhantomData::default(),
382
1
        }
383
1
    }
384
}
385

            
386
impl<T, Unit> AddAssign<T> for Figure<T, Unit>
387
where
388
    T: AddAssign,
389
{
390
1
    fn add_assign(&mut self, rhs: T) {
391
1
        self.value.add_assign(rhs);
392
1
    }
393
}
394

            
395
impl<T, Unit> SubAssign<T> for Figure<T, Unit>
396
where
397
    T: SubAssign,
398
{
399
1
    fn sub_assign(&mut self, rhs: T) {
400
1
        self.value.sub_assign(rhs);
401
1
    }
402
}
403

            
404
impl<T, Unit> DivAssign<T> for Figure<T, Unit>
405
where
406
    T: DivAssign,
407
{
408
1
    fn div_assign(&mut self, rhs: T) {
409
1
        self.value.div_assign(rhs);
410
1
    }
411
}
412

            
413
impl<T, Unit> MulAssign<T> for Figure<T, Unit>
414
where
415
    T: MulAssign,
416
{
417
1
    fn mul_assign(&mut self, rhs: T) {
418
1
        self.value.mul_assign(rhs);
419
1
    }
420
}
421

            
422
impl<T, Unit> RemAssign<T> for Figure<T, Unit>
423
where
424
    T: RemAssign,
425
{
426
1
    fn rem_assign(&mut self, rhs: T) {
427
1
        self.value.rem_assign(rhs);
428
1
    }
429
}
430

            
431
impl<T, Unit> Neg for Figure<T, Unit>
432
where
433
    T: Neg<Output = T>,
434
{
435
    type Output = Self;
436

            
437
1
    fn neg(self) -> Self::Output {
438
1
        Self {
439
1
            value: self.value.neg(),
440
1
            _unit: PhantomData::default(),
441
1
        }
442
1
    }
443
}
444

            
445
impl<T, Unit> One for Figure<T, Unit>
446
where
447
    T: One,
448
{
449
5
    fn one() -> Self {
450
5
        Self::from(T::one())
451
5
    }
452
}
453

            
454
impl<T, Unit> Zero for Figure<T, Unit>
455
where
456
    T: Zero,
457
{
458
2
    fn zero() -> Self {
459
2
        Self::from(T::zero())
460
2
    }
461

            
462
1
    fn is_zero(&self) -> bool {
463
1
        self.value.is_zero()
464
1
    }
465
}
466

            
467
impl<T, UnitA, UnitB> Mul<Scale<T, UnitA, UnitB>> for Figure<T, UnitA>
468
where
469
    T: Mul<T, Output = T> + Copy,
470
{
471
    type Output = Figure<T, UnitB>;
472

            
473
3
    fn mul(self, rhs: Scale<T, UnitA, UnitB>) -> Self::Output {
474
3
        Figure {
475
3
            value: self.value.mul(rhs.get()),
476
3
            _unit: PhantomData::default(),
477
3
        }
478
3
    }
479
}
480

            
481
impl<T, UnitA, UnitB> Div<Scale<T, UnitA, UnitB>> for Figure<T, UnitB>
482
where
483
    T: Div<T, Output = T> + Copy,
484
{
485
    type Output = Figure<T, UnitA>;
486

            
487
3
    fn div(self, rhs: Scale<T, UnitA, UnitB>) -> Self::Output {
488
3
        Figure {
489
3
            value: self.value.div(rhs.get()),
490
3
            _unit: PhantomData::default(),
491
3
        }
492
3
    }
493
}
494

            
495
impl<T> Displayable<T> for Figure<T, Scaled>
496
where
497
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
498
{
499
    type Pixels = Figure<T, Pixels>;
500
    type Points = Figure<T, Points>;
501
    type Scaled = Self;
502

            
503
1
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
504
1
        *self * scale.total
505
1
    }
506

            
507
1
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
508
1
        *self * scale.additional
509
1
    }
510

            
511
1
    fn to_scaled(&self, _scale: &DisplayScale<T>) -> Self::Scaled {
512
1
        *self
513
1
    }
514
}
515

            
516
impl<T> Displayable<T> for Figure<T, Points>
517
where
518
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
519
{
520
    type Pixels = Figure<T, Pixels>;
521
    type Points = Self;
522
    type Scaled = Figure<T, Scaled>;
523

            
524
1
    fn to_pixels(&self, scale: &DisplayScale<T>) -> Self::Pixels {
525
1
        *self * scale.dpi
526
1
    }
527

            
528
1
    fn to_points(&self, _scale: &DisplayScale<T>) -> Self::Points {
529
1
        *self
530
1
    }
531

            
532
1
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
533
1
        *self / scale.additional
534
1
    }
535
}
536

            
537
impl<T> Displayable<T> for Figure<T, Pixels>
538
where
539
    T: Div<T, Output = T> + Mul<T, Output = T> + Copy,
540
{
541
    type Pixels = Self;
542
    type Points = Figure<T, Points>;
543
    type Scaled = Figure<T, Scaled>;
544

            
545
1
    fn to_pixels(&self, _scale: &DisplayScale<T>) -> Self::Pixels {
546
1
        *self
547
1
    }
548

            
549
1
    fn to_points(&self, scale: &DisplayScale<T>) -> Self::Points {
550
1
        *self / scale.dpi
551
1
    }
552

            
553
1
    fn to_scaled(&self, scale: &DisplayScale<T>) -> Self::Scaled {
554
1
        *self / scale.total
555
1
    }
556
}
557

            
558
impl<T, Unit> Round for Figure<T, Unit>
559
where
560
    T: Round,
561
{
562
1
    fn round(mut self) -> Self {
563
1
        self.value = self.value.round();
564
1
        self
565
1
    }
566
}
567

            
568
impl<T, Unit> Ceil for Figure<T, Unit>
569
where
570
    T: Ceil,
571
{
572
1
    fn ceil(mut self) -> Self {
573
1
        self.value = self.value.ceil();
574
1
        self
575
1
    }
576
}
577

            
578
impl<T, Unit> Floor for Figure<T, Unit>
579
where
580
    T: Floor,
581
{
582
1
    fn floor(mut self) -> Self {
583
1
        self.value = self.value.floor();
584
1
        self
585
1
    }
586
}
587

            
588
impl<T, Unit> Approx<T> for Figure<T, Unit>
589
where
590
    T: AbsDiffEq,
591
{
592
21
    fn approx_eq(&self, other: &Self) -> bool {
593
21
        self.value.abs_diff_eq(&other.value, T::default_epsilon())
594
21
    }
595
}
596

            
597
impl<T, Unit> AbsDiffEq for Figure<T, Unit>
598
where
599
    T: AbsDiffEq,
600
{
601
    type Epsilon = T::Epsilon;
602

            
603
    fn default_epsilon() -> Self::Epsilon {
604
        T::default_epsilon()
605
    }
606

            
607
    fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
608
        self.value.abs_diff_eq(&other.value, epsilon)
609
    }
610

            
611
    fn abs_diff_ne(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
612
        self.value.abs_diff_ne(&other.value, epsilon)
613
    }
614
}
615

            
616
impl<T, Unit> UlpsEq for Figure<T, Unit>
617
where
618
    T: UlpsEq,
619
{
620
    fn default_max_ulps() -> u32 {
621
        T::default_max_ulps()
622
    }
623

            
624
    fn ulps_eq(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
625
        self.value.ulps_eq(&other.value, epsilon, max_ulps)
626
    }
627

            
628
    fn ulps_ne(&self, other: &Self, epsilon: Self::Epsilon, max_ulps: u32) -> bool {
629
        self.value.ulps_ne(&other.value, epsilon, max_ulps)
630
    }
631
}
632

            
633
impl<T, Unit> RelativeEq for Figure<T, Unit>
634
where
635
    T: RelativeEq,
636
{
637
    fn default_max_relative() -> Self::Epsilon {
638
        T::default_max_relative()
639
    }
640

            
641
    fn relative_eq(
642
        &self,
643
        other: &Self,
644
        epsilon: Self::Epsilon,
645
        max_relative: Self::Epsilon,
646
    ) -> bool {
647
        self.value.relative_eq(&other.value, epsilon, max_relative)
648
    }
649

            
650
    fn relative_ne(
651
        &self,
652
        other: &Self,
653
        epsilon: Self::Epsilon,
654
        max_relative: Self::Epsilon,
655
    ) -> bool {
656
        self.value.relative_ne(&other.value, epsilon, max_relative)
657
    }
658
}
659

            
660
1
#[test]
661
1
fn debug_test() {
662
1
    assert_eq!(&format!("{:?}", Figure::<u32, Pixels>::new(1)), "Figure(1)");
663
1
}
664

            
665
1
#[test]
666
1
fn cast_unit_test() {
667
1
    let pixels = Figure::<u32, Pixels>::new(1);
668
1
    let points: Figure<_, Points> = pixels.cast_unit();
669
1
    assert_eq!(pixels.get(), points.get());
670
1
}
671

            
672
1
#[test]
673
1
fn partial_ord_tests() {
674
1
    let one = Figure::<u32, Pixels>::one();
675
1
    let zero = Figure::<u32, Pixels>::zero();
676
1
    assert!(zero.is_zero());
677

            
678
1
    assert_eq!(one.min(zero), zero);
679
1
    assert_eq!(zero.min(one), zero);
680
1
    assert_eq!(one.max(zero), one);
681
1
    assert_eq!(zero.max(one), one);
682
1
}
683

            
684
1
#[test]
685
1
fn to_primitive_tests() {
686
1
    let zero = Figure::<u32, Pixels>::default();
687
1

            
688
1
    assert_eq!(zero.to_i8(), Some(0));
689
1
    assert_eq!(zero.to_i16(), Some(0));
690
1
    assert_eq!(zero.to_i32(), Some(0));
691
1
    assert_eq!(zero.to_i64(), Some(0));
692
1
    assert_eq!(zero.to_i128(), Some(0));
693
1
    assert_eq!(zero.to_isize(), Some(0));
694
1
    assert_eq!(zero.to_u8(), Some(0));
695
1
    assert_eq!(zero.to_u16(), Some(0));
696
1
    assert_eq!(zero.to_u32(), Some(0));
697
1
    assert_eq!(zero.to_u64(), Some(0));
698
1
    assert_eq!(zero.to_u128(), Some(0));
699
1
    assert_eq!(zero.to_usize(), Some(0));
700
1
    approx::assert_abs_diff_eq!(zero.to_f32().unwrap(), 0.);
701
1
    approx::assert_abs_diff_eq!(zero.to_f64().unwrap(), 0.);
702
1
}
703

            
704
1
#[test]
705
1
fn numcast_test() {
706
1
    let zero = <Figure<u32, Pixels> as NumCast>::from(0.0_f64);
707
1

            
708
1
    assert_eq!(zero.unwrap().get(), 0_u32);
709
1
}
710

            
711
1
#[test]
712
1
fn ords_test() {
713
1
    let zero = Figure::<u32, Pixels>::zero();
714
1
    let one = Figure::<u32, Pixels>::one();
715
1

            
716
1
    assert_eq!(zero.cmp(&one), std::cmp::Ordering::Less);
717
1
    assert_eq!(zero.partial_cmp(&one), Some(std::cmp::Ordering::Less));
718
1
}
719

            
720
1
#[test]
721
1
fn maths_test() {
722
1
    let one = Figure::<u32, Pixels>::one();
723
1
    assert_eq!(one.get(), 1);
724
1
    let two = one + one;
725
1
    assert_eq!(two.get(), 2);
726
1
    let four = two * two;
727
1
    assert_eq!(four.get(), 4);
728
1
    let three = four - one;
729
1
    assert_eq!(three.get(), 3);
730
1
    let one_rem = four % three;
731
1
    assert_eq!(one_rem.get(), 1);
732
1
    let two_div = four / two;
733
1
    assert_eq!(two_div.get(), 2);
734

            
735
1
    let mut value = one;
736
1
    value += one;
737
1
    assert_eq!(value.get(), 2);
738
1
    value -= one;
739
1
    assert_eq!(value.get(), 1);
740
1
    value *= four;
741
1
    assert_eq!(value.get(), 4);
742
1
    value /= two;
743
1
    assert_eq!(value.get(), 2);
744
1
    value %= two;
745
1
    assert_eq!(value.get(), 0);
746
1
}
747

            
748
1
#[test]
749
1
fn scalar_maths_test() {
750
1
    let one = Figure::<i32, Pixels>::one();
751
1
    assert_eq!(one.get(), 1);
752
1
    let two = one + 1;
753
1
    assert_eq!(two.get(), 2);
754
1
    let four = two * 2;
755
1
    assert_eq!(four.get(), 4);
756
1
    let three = four - 1;
757
1
    assert_eq!(three.get(), 3);
758
1
    let one_rem = four % 3;
759
1
    assert_eq!(one_rem.get(), 1);
760
1
    let two_div = four / 2;
761
1
    assert_eq!(two_div.get(), 2);
762
1
    let neg_two = -two_div;
763
1
    assert_eq!(neg_two.get(), -2);
764

            
765
1
    let mut value = one;
766
1
    value += 1;
767
1
    assert_eq!(value.get(), 2);
768
1
    value -= 1;
769
1
    assert_eq!(value.get(), 1);
770
1
    value *= 4;
771
1
    assert_eq!(value.get(), 4);
772
1
    value /= 2;
773
1
    assert_eq!(value.get(), 2);
774
1
    value %= 2;
775
1
    assert_eq!(value.get(), 0);
776
1
}
777

            
778
1
#[test]
779
1
fn display_scale_math() {
780
1
    let scale = DisplayScale::<u32>::new(Scale::new(2), Scale::new(3));
781
1
    let one_scaled = Figure::<u32, Scaled>::one();
782
1
    assert_eq!(one_scaled.to_scaled(&scale), one_scaled);
783
1
    let two_points = one_scaled.to_points(&scale);
784
1
    assert_eq!(two_points.get(), 3);
785
1
    assert_eq!(two_points.to_points(&scale), two_points);
786
1
    let six_pixels = one_scaled.to_pixels(&scale);
787
1
    assert_eq!(six_pixels.get(), 6);
788
1
    assert_eq!(six_pixels.to_pixels(&scale), six_pixels);
789

            
790
1
    assert_eq!(six_pixels.to_points(&scale), two_points);
791
1
    assert_eq!(six_pixels.to_scaled(&scale), one_scaled);
792

            
793
1
    assert_eq!(two_points.to_pixels(&scale), six_pixels);
794
1
    assert_eq!(two_points.to_scaled(&scale), one_scaled);
795
1
}
796

            
797
1
#[test]
798
1
fn float_ops_test() {
799
1
    let one = Figure::<f32, Pixels>::new(1.);
800
1
    assert!(Figure::<f32, Pixels>::new(0.5).round().approx_eq(&one));
801
1
    assert!(Figure::<f32, Pixels>::new(0.1).ceil().approx_eq(&one));
802
1
    assert!(Figure::<f32, Pixels>::new(1.9).floor().approx_eq(&one));
803
1
}