1use crate::constants::EPSILON;
10use crate::error::PositiveError;
11use approx::{AbsDiffEq, RelativeEq};
12use num_traits::{FromPrimitive, Pow, ToPrimitive};
13use rust_decimal::{Decimal, MathematicalOps};
14use rust_decimal_macros::dec;
15use serde::de::Visitor;
16use serde::{Deserialize, Deserializer, Serialize, Serializer};
17use std::cmp::{Ordering, PartialEq};
18use std::fmt;
19use std::fmt::Display;
20use std::iter::Sum;
21use std::ops::{Add, AddAssign, Div, Mul, MulAssign, Neg, Sub};
22use std::str::FromStr;
23
24#[derive(PartialEq, Clone, Copy, Hash)]
29#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
30pub struct Positive(pub Decimal);
31
32#[must_use]
34pub fn is_positive<T: 'static>() -> bool {
35 std::any::TypeId::of::<T>() == std::any::TypeId::of::<Positive>()
36}
37
38impl Positive {
39 pub const ZERO: Positive = crate::constants::ZERO;
42 pub const ONE: Positive = crate::constants::ONE;
44 pub const TWO: Positive = crate::constants::TWO;
46 pub const THREE: Positive = crate::constants::THREE;
48 pub const FOUR: Positive = crate::constants::FOUR;
50 pub const FIVE: Positive = crate::constants::FIVE;
52 pub const SIX: Positive = crate::constants::SIX;
54 pub const SEVEN: Positive = crate::constants::SEVEN;
56 pub const EIGHT: Positive = crate::constants::EIGHT;
58 pub const NINE: Positive = crate::constants::NINE;
60 pub const TEN: Positive = crate::constants::TEN;
62 pub const FIFTEEN: Positive = crate::constants::FIFTEEN;
64 pub const TWENTY: Positive = crate::constants::TWENTY;
66 pub const TWENTY_FIVE: Positive = crate::constants::TWENTY_FIVE;
68 pub const THIRTY: Positive = crate::constants::THIRTY;
70 pub const THIRTY_FIVE: Positive = crate::constants::THIRTY_FIVE;
72 pub const FORTY: Positive = crate::constants::FORTY;
74 pub const FORTY_FIVE: Positive = crate::constants::FORTY_FIVE;
76 pub const FIFTY: Positive = crate::constants::FIFTY;
78 pub const FIFTY_FIVE: Positive = crate::constants::FIFTY_FIVE;
80 pub const SIXTY: Positive = crate::constants::SIXTY;
82 pub const SIXTY_FIVE: Positive = crate::constants::SIXTY_FIVE;
84 pub const SEVENTY: Positive = crate::constants::SEVENTY;
86 pub const SEVENTY_FIVE: Positive = crate::constants::SEVENTY_FIVE;
88 pub const EIGHTY: Positive = crate::constants::EIGHTY;
90 pub const EIGHTY_FIVE: Positive = crate::constants::EIGHTY_FIVE;
92 pub const NINETY: Positive = crate::constants::NINETY;
94 pub const NINETY_FIVE: Positive = crate::constants::NINETY_FIVE;
96 pub const HUNDRED: Positive = crate::constants::HUNDRED;
98 pub const TWO_HUNDRED: Positive = crate::constants::TWO_HUNDRED;
100 pub const THREE_HUNDRED: Positive = crate::constants::THREE_HUNDRED;
102 pub const FOUR_HUNDRED: Positive = crate::constants::FOUR_HUNDRED;
104 pub const FIVE_HUNDRED: Positive = crate::constants::FIVE_HUNDRED;
106 pub const SIX_HUNDRED: Positive = crate::constants::SIX_HUNDRED;
108 pub const SEVEN_HUNDRED: Positive = crate::constants::SEVEN_HUNDRED;
110 pub const EIGHT_HUNDRED: Positive = crate::constants::EIGHT_HUNDRED;
112 pub const NINE_HUNDRED: Positive = crate::constants::NINE_HUNDRED;
114 pub const THOUSAND: Positive = crate::constants::THOUSAND;
116 pub const TWO_THOUSAND: Positive = crate::constants::TWO_THOUSAND;
118 pub const THREE_THOUSAND: Positive = crate::constants::THREE_THOUSAND;
120 pub const FOUR_THOUSAND: Positive = crate::constants::FOUR_THOUSAND;
122 pub const FIVE_THOUSAND: Positive = crate::constants::FIVE_THOUSAND;
124 pub const SIX_THOUSAND: Positive = crate::constants::SIX_THOUSAND;
126 pub const SEVEN_THOUSAND: Positive = crate::constants::SEVEN_THOUSAND;
128 pub const EIGHT_THOUSAND: Positive = crate::constants::EIGHT_THOUSAND;
130 pub const NINE_THOUSAND: Positive = crate::constants::NINE_THOUSAND;
132 pub const TEN_THOUSAND: Positive = crate::constants::TEN_THOUSAND;
134 pub const PI: Positive = crate::constants::PI;
136 pub const E: Positive = crate::constants::E;
138 pub const INFINITY: Positive = crate::constants::INFINITY;
140
141 pub fn new(value: f64) -> Result<Self, PositiveError> {
143 let dec = Decimal::from_f64(value);
144 match dec {
145 Some(value) if value >= Decimal::ZERO => Ok(Positive(value)),
146 Some(value) => Err(PositiveError::OutOfBounds {
147 value: value.to_f64().unwrap_or(0.0),
148 min: 0.0,
149 max: f64::MAX,
150 }),
151 None => Err(PositiveError::ConversionError {
152 from_type: "f64".to_string(),
153 to_type: "Positive".to_string(),
154 reason: "failed to parse Decimal".to_string(),
155 }),
156 }
157 }
158
159 pub fn new_decimal(value: Decimal) -> Result<Self, PositiveError> {
161 if value >= Decimal::ZERO {
162 Ok(Positive(value))
163 } else {
164 Err(PositiveError::OutOfBounds {
165 value: value.to_f64().unwrap_or(0.0),
166 min: 0.0,
167 max: f64::INFINITY,
168 })
169 }
170 }
171
172 #[must_use]
174 pub fn value(&self) -> Decimal {
175 self.0
176 }
177
178 #[must_use]
180 pub fn to_dec(&self) -> Decimal {
181 self.0
182 }
183
184 #[must_use]
186 pub fn to_dec_ref(&self) -> &Decimal {
187 &self.0
188 }
189
190 #[must_use]
197 pub fn to_f64(&self) -> f64 {
198 self.0
199 .to_f64()
200 .expect("Decimal to f64 conversion failed - value out of range")
201 }
202
203 #[must_use]
205 pub fn to_f64_checked(&self) -> Option<f64> {
206 self.0.to_f64()
207 }
208
209 #[must_use]
211 pub fn to_f64_lossy(&self) -> f64 {
212 self.0.to_f64().unwrap_or(0.0)
213 }
214
215 #[must_use]
222 pub fn to_i64(&self) -> i64 {
223 self.0
224 .to_i64()
225 .expect("Decimal to i64 conversion failed - value out of range")
226 }
227
228 #[must_use]
230 pub fn to_i64_checked(&self) -> Option<i64> {
231 self.0.to_i64()
232 }
233
234 #[must_use]
241 pub fn to_u64(&self) -> u64 {
242 self.0
243 .to_u64()
244 .expect("Decimal to u64 conversion failed - value out of range")
245 }
246
247 #[must_use]
249 pub fn to_u64_checked(&self) -> Option<u64> {
250 self.0.to_u64()
251 }
252
253 #[must_use]
260 pub fn to_usize(&self) -> usize {
261 self.0
262 .to_usize()
263 .expect("Decimal to usize conversion failed - value out of range")
264 }
265
266 #[must_use]
268 pub fn to_usize_checked(&self) -> Option<usize> {
269 self.0.to_usize()
270 }
271
272 #[must_use]
274 pub fn max(self, other: Positive) -> Positive {
275 if self.0 > other.0 { self } else { other }
276 }
277
278 #[must_use]
280 pub fn min(self, other: Positive) -> Positive {
281 if self.0 < other.0 { self } else { other }
282 }
283
284 #[must_use]
286 pub fn floor(&self) -> Positive {
287 Positive(self.0.floor())
288 }
289
290 #[must_use]
292 pub fn powi(&self, n: i64) -> Positive {
293 Positive(self.0.powi(n))
294 }
295
296 #[must_use]
298 pub fn pow(&self, n: Positive) -> Positive {
299 Positive(self.0.pow(n.to_dec()))
300 }
301
302 #[must_use]
304 pub fn powu(&self, n: u64) -> Positive {
305 Positive(self.0.powu(n))
306 }
307
308 #[must_use]
310 pub fn powd(&self, p0: Decimal) -> Positive {
311 Positive(self.0.powd(p0))
312 }
313
314 #[must_use]
316 pub fn round(&self) -> Positive {
317 Positive(self.0.round())
318 }
319
320 #[must_use]
322 pub fn round_to_nice_number(&self) -> Positive {
323 let magnitude = self.log10().floor();
324 let ten_pow = Positive::TEN.pow(magnitude);
325 let normalized = self / &ten_pow;
326 let nice_number = if normalized < dec!(1.5) {
327 Positive::ONE
328 } else if normalized < pos_or_panic!(3.0) {
329 Positive::TWO
330 } else if normalized < pos_or_panic!(7.0) {
331 pos_or_panic!(5.0)
332 } else {
333 Positive::TEN
334 };
335 nice_number * pos_or_panic!(10.0).powu(magnitude.to_u64())
336 }
337
338 #[must_use]
345 pub fn sqrt(&self) -> Positive {
346 Positive(self.0.sqrt().expect("Square root calculation failed"))
347 }
348
349 pub fn sqrt_checked(&self) -> Result<Positive, PositiveError> {
351 self.0.sqrt().map(Positive).ok_or_else(|| {
352 PositiveError::arithmetic_error("sqrt", "square root calculation failed")
353 })
354 }
355
356 #[must_use]
358 pub fn ln(&self) -> Positive {
359 Positive(self.0.ln())
360 }
361
362 #[must_use]
364 pub fn round_to(&self, decimal_places: u32) -> Positive {
365 Positive(self.0.round_dp(decimal_places))
366 }
367
368 #[must_use]
370 pub fn format_fixed_places(&self, decimal_places: u32) -> String {
371 let rounded = self.round_to(decimal_places).to_f64();
372 format!("{:.1$}", rounded, decimal_places as usize)
373 }
374
375 #[must_use]
377 pub fn exp(&self) -> Positive {
378 Positive(self.0.exp())
379 }
380
381 #[must_use]
383 pub fn clamp(&self, min: Positive, max: Positive) -> Positive {
384 if self < &min {
385 min
386 } else if self > &max {
387 max
388 } else {
389 *self
390 }
391 }
392
393 #[must_use]
395 pub fn is_zero(&self) -> bool {
396 self.0.is_zero()
397 }
398
399 #[must_use]
401 pub fn ceiling(&self) -> Positive {
402 Positive(self.to_dec().ceil())
403 }
404
405 #[must_use]
407 pub fn log10(&self) -> Positive {
408 Positive(self.0.log10())
409 }
410
411 #[must_use]
413 pub fn sub_or_zero(&self, other: &Decimal) -> Positive {
414 if &self.0 > other {
415 Positive(self.0 - other)
416 } else {
417 Positive(Decimal::ZERO)
418 }
419 }
420
421 #[must_use]
423 pub fn sub_or_none(&self, other: &Decimal) -> Option<Positive> {
424 if &self.0 >= other {
425 Some(Positive(self.0 - other))
426 } else {
427 None
428 }
429 }
430
431 pub fn checked_sub(&self, rhs: &Self) -> Result<Self, PositiveError> {
433 Positive::new_decimal(self.0 - rhs.0)
434 }
435
436 #[must_use]
438 pub fn saturating_sub(&self, rhs: &Self) -> Self {
439 if self.0 > rhs.0 {
440 Positive(self.0 - rhs.0)
441 } else {
442 Positive::ZERO
443 }
444 }
445
446 pub fn checked_div(&self, rhs: &Self) -> Result<Self, PositiveError> {
448 if rhs.is_zero() {
449 Err(PositiveError::arithmetic_error(
450 "division",
451 "division by zero",
452 ))
453 } else {
454 Ok(Positive(self.0 / rhs.0))
455 }
456 }
457
458 #[must_use]
460 pub fn is_multiple(&self, other: f64) -> bool {
461 let value = self.to_f64();
462 if !value.is_finite() {
463 return false;
464 }
465 let remainder = value % other;
466 remainder.abs() < f64::EPSILON || (other - remainder.abs()).abs() < f64::EPSILON
467 }
468
469 #[must_use]
471 pub fn is_multiple_of(&self, other: &Positive) -> bool {
472 if other.is_zero() {
473 return false;
474 }
475 let remainder = self.0 % other.0;
476 remainder.abs() < EPSILON
477 }
478
479 #[must_use]
498 pub const unsafe fn new_unchecked(value: Decimal) -> Self {
499 Positive(value)
500 }
501}
502
503impl From<Positive> for Decimal {
504 fn from(value: Positive) -> Self {
505 value.0
506 }
507}
508
509impl PartialEq<&Positive> for Positive {
510 fn eq(&self, other: &&Positive) -> bool {
511 self == *other
512 }
513}
514
515impl From<Positive> for u64 {
516 fn from(pos_u64: Positive) -> Self {
517 pos_u64.0.to_u64().unwrap_or(0)
518 }
519}
520
521impl From<&Positive> for f64 {
522 fn from(value: &Positive) -> Self {
523 value.0.to_f64().unwrap_or(0.0)
524 }
525}
526
527impl From<Positive> for f64 {
528 fn from(value: Positive) -> Self {
529 value.0.to_f64().unwrap_or(0.0)
530 }
531}
532
533impl From<Positive> for usize {
534 fn from(value: Positive) -> Self {
535 value.0.to_f64().unwrap_or(0.0) as usize
536 }
537}
538
539impl PartialEq<&Positive> for f64 {
540 fn eq(&self, other: &&Positive) -> bool {
541 self == &other.0.to_f64().unwrap_or(0.0)
542 }
543}
544
545impl PartialOrd<&Positive> for f64 {
546 fn partial_cmp(&self, other: &&Positive) -> Option<Ordering> {
547 self.partial_cmp(&other.0.to_f64().unwrap_or(0.0))
548 }
549}
550
551impl PartialEq<Positive> for f64 {
552 fn eq(&self, other: &Positive) -> bool {
553 self == &other.0.to_f64().unwrap_or(0.0)
554 }
555}
556
557impl PartialOrd<Positive> for f64 {
558 fn partial_cmp(&self, other: &Positive) -> Option<Ordering> {
559 self.partial_cmp(&other.0.to_f64().unwrap_or(0.0))
560 }
561}
562
563impl Mul<Positive> for f64 {
564 type Output = f64;
565 fn mul(self, rhs: Positive) -> Self::Output {
566 self * rhs.to_f64()
567 }
568}
569
570impl Div<Positive> for f64 {
571 type Output = f64;
572 fn div(self, rhs: Positive) -> Self::Output {
573 self / rhs.to_f64()
574 }
575}
576
577impl Sub<Positive> for f64 {
578 type Output = f64;
579 fn sub(self, rhs: Positive) -> Self::Output {
580 self - rhs.to_f64()
581 }
582}
583
584impl Add<Positive> for f64 {
585 type Output = f64;
586 fn add(self, rhs: Positive) -> Self::Output {
587 self + rhs.to_f64()
588 }
589}
590
591impl FromStr for Positive {
592 type Err = String;
593 fn from_str(s: &str) -> Result<Self, Self::Err> {
594 match s.parse::<Decimal>() {
595 Ok(value) if value >= Decimal::ZERO => Ok(Positive(value)),
596 Ok(value) => Err(format!("Value must be positive, got {value}")),
597 Err(e) => Err(format!("Failed to parse as Decimal: {e}")),
598 }
599 }
600}
601
602impl TryFrom<f64> for Positive {
603 type Error = PositiveError;
604
605 fn try_from(value: f64) -> Result<Self, Self::Error> {
611 Positive::new(value)
612 }
613}
614
615impl TryFrom<usize> for Positive {
616 type Error = PositiveError;
617
618 fn try_from(value: usize) -> Result<Self, Self::Error> {
624 Positive::new(value as f64)
625 }
626}
627
628impl TryFrom<Decimal> for Positive {
629 type Error = PositiveError;
630
631 fn try_from(value: Decimal) -> Result<Self, Self::Error> {
637 Positive::new_decimal(value)
638 }
639}
640
641impl TryFrom<&Decimal> for Positive {
642 type Error = PositiveError;
643
644 fn try_from(value: &Decimal) -> Result<Self, Self::Error> {
650 Positive::new_decimal(*value)
651 }
652}
653
654impl TryFrom<i64> for Positive {
655 type Error = PositiveError;
656
657 fn try_from(value: i64) -> Result<Self, Self::Error> {
663 Positive::new_decimal(Decimal::from(value))
664 }
665}
666
667impl TryFrom<u64> for Positive {
668 type Error = PositiveError;
669
670 fn try_from(value: u64) -> Result<Self, Self::Error> {
676 Positive::new_decimal(Decimal::from(value))
677 }
678}
679
680impl From<&Positive> for Positive {
681 fn from(value: &Positive) -> Self {
682 Positive(value.0)
683 }
684}
685
686impl Mul<f64> for Positive {
687 type Output = Positive;
688 fn mul(self, rhs: f64) -> Positive {
689 Positive::new(self.to_f64() * rhs).expect("Multiplication result must be positive")
690 }
691}
692
693impl Div<f64> for Positive {
694 type Output = Positive;
695 fn div(self, rhs: f64) -> Positive {
696 Positive::new(self.to_f64() / rhs).expect("Division result must be positive")
697 }
698}
699
700impl Div<f64> for &Positive {
701 type Output = Positive;
702 fn div(self, rhs: f64) -> Positive {
703 Positive::new(self.to_f64() / rhs).expect("Division result must be positive")
704 }
705}
706
707impl Sub<f64> for Positive {
708 type Output = Positive;
709 fn sub(self, rhs: f64) -> Self::Output {
710 Positive::new(self.to_f64() - rhs).expect("Subtraction result must be positive")
711 }
712}
713
714impl Add<f64> for Positive {
715 type Output = Positive;
716 fn add(self, rhs: f64) -> Self::Output {
717 Positive::new(self.to_f64() + rhs).expect("Addition result must be positive")
718 }
719}
720
721impl PartialOrd<f64> for Positive {
722 fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
723 self.0.to_f64().unwrap_or(0.0).partial_cmp(other)
724 }
725}
726
727impl PartialEq<f64> for &Positive {
728 fn eq(&self, other: &f64) -> bool {
729 self.0.to_f64().unwrap_or(0.0) == *other
730 }
731}
732
733impl PartialOrd<f64> for &Positive {
734 fn partial_cmp(&self, other: &f64) -> Option<Ordering> {
735 self.0.to_f64().unwrap_or(0.0).partial_cmp(other)
736 }
737}
738
739impl PartialEq<f64> for Positive {
740 fn eq(&self, other: &f64) -> bool {
741 self.to_f64() == *other
742 }
743}
744
745impl Display for Positive {
746 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
747 if *self == Positive::INFINITY {
748 write!(f, "{}", f64::MAX)
749 } else if self.0.scale() == 0 {
750 match self.0.to_i64() {
751 Some(val) => write!(f, "{val}"),
752 None => write!(f, "{}", self.0),
753 }
754 } else if let Some(precision) = f.precision() {
755 write!(f, "{:.1$}", self.0, precision)
756 } else {
757 let s = self.0.to_string();
758 let trimmed = s.trim_end_matches('0').trim_end_matches('.');
759 write!(f, "{trimmed}")
760 }
761 }
762}
763
764impl fmt::Debug for Positive {
765 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
766 if *self == Positive::INFINITY {
767 write!(f, "{}", f64::MAX)
768 } else if self.0.scale() == 0 {
769 match self.0.to_i64() {
770 Some(val) => write!(f, "{val}"),
771 None => write!(f, "{}", self.0),
772 }
773 } else {
774 write!(f, "{}", self.0)
775 }
776 }
777}
778
779impl PartialEq<Decimal> for Positive {
780 fn eq(&self, other: &Decimal) -> bool {
781 (self.0 - *other).abs() <= EPSILON * Decimal::from(100)
782 }
783}
784
785impl Serialize for Positive {
786 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
787 where
788 S: Serializer,
789 {
790 if *self == Positive::INFINITY {
791 return serializer.serialize_f64(f64::MAX);
792 }
793 if self.0.scale() == 0 {
794 serializer.serialize_i64(
795 self.0
796 .to_i64()
797 .ok_or_else(|| serde::ser::Error::custom("Failed to convert to i64"))?,
798 )
799 } else {
800 serializer.serialize_f64(
801 self.0
802 .to_f64()
803 .ok_or_else(|| serde::ser::Error::custom("Failed to convert to f64"))?,
804 )
805 }
806 }
807}
808
809impl<'de> Deserialize<'de> for Positive {
810 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
811 where
812 D: Deserializer<'de>,
813 {
814 struct PositiveVisitor;
815
816 impl Visitor<'_> for PositiveVisitor {
817 type Value = Positive;
818
819 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
820 formatter.write_str("a positive number")
821 }
822
823 fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
824 where
825 E: serde::de::Error,
826 {
827 Err(serde::de::Error::custom(format!(
828 "Invalid string: '{value}'. Expected a positive number."
829 )))
830 }
831
832 fn visit_i64<E>(self, value: i64) -> Result<Self::Value, E>
833 where
834 E: serde::de::Error,
835 {
836 if value < 0 {
837 Err(serde::de::Error::custom("Expected a non-negative integer"))
838 } else {
839 Positive::new_decimal(Decimal::from(value)).map_err(serde::de::Error::custom)
840 }
841 }
842
843 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
844 where
845 E: serde::de::Error,
846 {
847 Positive::new_decimal(Decimal::from(value)).map_err(serde::de::Error::custom)
848 }
849
850 fn visit_f64<E>(self, value: f64) -> Result<Self::Value, E>
851 where
852 E: serde::de::Error,
853 {
854 if value.is_infinite() && value.is_sign_positive() {
855 return Ok(Positive::INFINITY);
856 }
857 if value == f64::MAX {
858 return Ok(Positive::INFINITY);
859 }
860 let decimal = Decimal::from_f64(value)
861 .ok_or_else(|| serde::de::Error::custom("Failed to convert f64 to Decimal"))?;
862 if value < 0.0 {
863 Err(serde::de::Error::custom("Expected a non-negative float"))
864 } else {
865 Positive::new_decimal(decimal).map_err(serde::de::Error::custom)
866 }
867 }
868 }
869
870 deserializer.deserialize_any(PositiveVisitor)
871 }
872}
873
874impl Add for Positive {
875 type Output = Positive;
876 fn add(self, other: Positive) -> Positive {
877 Positive(self.0 + other.0)
878 }
879}
880
881impl Sub for Positive {
882 type Output = Positive;
883 fn sub(self, rhs: Self) -> Self::Output {
884 let result = self.0 - rhs.0;
885 if result < Decimal::ZERO {
886 panic!("Resulting value must be positive");
887 } else {
888 Positive(result)
889 }
890 }
891}
892
893impl Div for Positive {
894 type Output = Positive;
895 fn div(self, other: Positive) -> Self::Output {
896 Positive(self.0 / other.0)
897 }
898}
899
900impl Div for &Positive {
901 type Output = Positive;
902 fn div(self, other: &Positive) -> Self::Output {
903 Positive(self.0 / other.0)
904 }
905}
906
907impl Add<Decimal> for Positive {
908 type Output = Positive;
909 fn add(self, rhs: Decimal) -> Positive {
910 Positive(self.0 + rhs)
911 }
912}
913
914impl Add<&Decimal> for Positive {
915 type Output = Positive;
916 fn add(self, rhs: &Decimal) -> Self::Output {
917 Positive::new_decimal(self.0 + rhs).expect("Addition result must be positive")
918 }
919}
920
921impl Sub<Decimal> for Positive {
922 type Output = Positive;
923 fn sub(self, rhs: Decimal) -> Positive {
924 Positive::new_decimal(self.0 - rhs).expect("Resulting value must be positive")
925 }
926}
927
928impl Sub<&Decimal> for Positive {
929 type Output = Positive;
930 fn sub(self, rhs: &Decimal) -> Self::Output {
931 Positive::new_decimal(self.0 - rhs).expect("Resulting value must be positive")
932 }
933}
934
935impl AddAssign for Positive {
936 fn add_assign(&mut self, other: Positive) {
937 self.0 += other.0;
938 }
939}
940
941impl AddAssign<Decimal> for Positive {
942 fn add_assign(&mut self, rhs: Decimal) {
943 self.0 += rhs;
944 }
945}
946
947impl MulAssign<Decimal> for Positive {
948 fn mul_assign(&mut self, rhs: Decimal) {
949 self.0 *= rhs;
950 }
951}
952
953impl Div<Decimal> for Positive {
954 type Output = Positive;
955 fn div(self, rhs: Decimal) -> Positive {
956 Positive(self.0 / rhs)
957 }
958}
959
960impl Div<&Decimal> for Positive {
961 type Output = Positive;
962 fn div(self, rhs: &Decimal) -> Self::Output {
963 Positive::new_decimal(self.0 / rhs).expect("Division result must be positive")
964 }
965}
966
967impl PartialOrd<Decimal> for Positive {
968 fn partial_cmp(&self, other: &Decimal) -> Option<Ordering> {
969 self.0.partial_cmp(other)
970 }
971}
972
973impl PartialOrd for Positive {
974 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
975 Some(self.cmp(other))
976 }
977
978 fn le(&self, other: &Self) -> bool {
979 self.0 <= other.0
980 }
981
982 fn ge(&self, other: &Self) -> bool {
983 self.0 >= other.0
984 }
985}
986
987impl Eq for Positive {}
988
989impl Ord for Positive {
990 fn cmp(&self, other: &Self) -> Ordering {
991 self.0.partial_cmp(&other.0).unwrap_or(Ordering::Equal)
992 }
993}
994
995impl Neg for Positive {
996 type Output = Self;
997 fn neg(self) -> Self::Output {
998 panic!("Cannot negate a Positive value!");
999 }
1000}
1001
1002impl Mul for Positive {
1003 type Output = Positive;
1004 fn mul(self, other: Positive) -> Positive {
1005 Positive(self.0 * other.0)
1006 }
1007}
1008
1009impl Mul<Decimal> for Positive {
1010 type Output = Positive;
1011 fn mul(self, rhs: Decimal) -> Positive {
1012 Positive(self.0 * rhs)
1013 }
1014}
1015
1016impl Mul<Positive> for Decimal {
1017 type Output = Decimal;
1018 fn mul(self, rhs: Positive) -> Decimal {
1019 self * rhs.0
1020 }
1021}
1022
1023impl Div<Positive> for Decimal {
1024 type Output = Decimal;
1025 fn div(self, rhs: Positive) -> Decimal {
1026 self / rhs.0
1027 }
1028}
1029
1030impl Sub<Positive> for Decimal {
1031 type Output = Decimal;
1032 fn sub(self, rhs: Positive) -> Decimal {
1033 self - rhs.0
1034 }
1035}
1036
1037impl Sub<&Positive> for Decimal {
1038 type Output = Decimal;
1039 fn sub(self, rhs: &Positive) -> Decimal {
1040 self - rhs.0
1041 }
1042}
1043
1044impl Add<Positive> for Decimal {
1045 type Output = Decimal;
1046 fn add(self, rhs: Positive) -> Decimal {
1047 self + rhs.0
1048 }
1049}
1050
1051impl Add<&Positive> for Decimal {
1052 type Output = Decimal;
1053 fn add(self, rhs: &Positive) -> Decimal {
1054 self + rhs.0
1055 }
1056}
1057
1058impl std::ops::AddAssign<Positive> for Decimal {
1059 fn add_assign(&mut self, rhs: Positive) {
1060 *self += rhs.0;
1061 }
1062}
1063
1064impl std::ops::AddAssign<&Positive> for Decimal {
1065 fn add_assign(&mut self, rhs: &Positive) {
1066 *self += rhs.0;
1067 }
1068}
1069
1070impl std::ops::MulAssign<Positive> for Decimal {
1071 fn mul_assign(&mut self, rhs: Positive) {
1072 *self *= rhs.0;
1073 }
1074}
1075
1076impl std::ops::MulAssign<&Positive> for Decimal {
1077 fn mul_assign(&mut self, rhs: &Positive) {
1078 *self *= rhs.0;
1079 }
1080}
1081
1082impl PartialEq<Positive> for Decimal {
1083 fn eq(&self, other: &Positive) -> bool {
1084 *self == other.0
1085 }
1086}
1087
1088impl From<&Positive> for Decimal {
1089 fn from(pos: &Positive) -> Self {
1090 pos.0
1091 }
1092}
1093
1094impl Default for Positive {
1095 fn default() -> Self {
1096 Positive::ZERO
1097 }
1098}
1099
1100impl AbsDiffEq for Positive {
1101 type Epsilon = Decimal;
1102
1103 fn default_epsilon() -> Self::Epsilon {
1104 EPSILON
1105 }
1106
1107 fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
1108 (self.0 - other.0).abs() <= epsilon
1109 }
1110}
1111
1112impl RelativeEq for Positive {
1113 fn default_max_relative() -> Self::Epsilon {
1114 EPSILON * Decimal::from(100)
1115 }
1116
1117 fn relative_eq(
1118 &self,
1119 other: &Self,
1120 epsilon: Self::Epsilon,
1121 max_relative: Self::Epsilon,
1122 ) -> bool {
1123 let abs_diff = (self.0 - other.0).abs();
1124 let largest = self.0.abs().max(other.0.abs());
1125 abs_diff <= epsilon || abs_diff <= max_relative * largest
1126 }
1127}
1128
1129impl Sum for Positive {
1130 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
1131 let sum = iter.fold(Decimal::ZERO, |acc, x| acc + x.value());
1132 Positive::new_decimal(sum).unwrap_or(Positive::ZERO)
1133 }
1134}
1135
1136impl<'a> Sum<&'a Positive> for Positive {
1137 fn sum<I: Iterator<Item = &'a Positive>>(iter: I) -> Self {
1138 let sum = iter.fold(Decimal::ZERO, |acc, x| acc + x.value());
1139 Positive::new_decimal(sum).unwrap_or(Positive::ZERO)
1140 }
1141}