relp_num/integer/big/ops/
mod.rs1use std::hint::assert_unchecked;
2use std::ops::{Add, AddAssign, Mul};
3
4use num_traits::Zero;
5
6use crate::integer::big::{NonZeroUbig, Ubig};
7use crate::integer::big::ops::building_blocks::add_assign_slice;
8use crate::integer::big::ops::non_zero::{add_assign, mul_non_zero};
9
10pub(crate) mod building_blocks;
11pub mod non_zero;
12pub mod div;
13pub mod normalize;
14
15
16impl<const S: usize> Add for Ubig<S> {
17 type Output = Self;
18
19 #[inline]
20 fn add(self, rhs: Self) -> Self::Output {
21 let (mut left, right) = if rhs.0.len() > self.0.len() {
22 (rhs, self)
23 } else {
24 (self, rhs)
25 };
26
27 if right.is_zero() {
28 return left;
29 }
30
31 unsafe {
32 let overflow = add_assign_slice(left.inner_mut(), &right);
34 if overflow {
35 left.inner_mut().push(1);
36 }
37 }
38
39 left
40 }
41}
42
43
44impl<const S: usize> Add for NonZeroUbig<S> {
45 type Output = Self;
46
47 #[inline]
48 fn add(self, rhs: Self) -> Self::Output {
49 let (mut left, right) = if rhs.0.len() > self.0.len() {
50 (rhs, self)
51 } else {
52 (self, rhs)
53 };
54
55 left += &right;
56
57 left
58 }
59}
60
61
62impl<const S: usize> AddAssign<&Self> for Ubig<S> {
63 #[inline]
64 fn add_assign(&mut self, rhs: &Ubig<S>) {
65 add_assign(&mut self.0, &rhs.0);
66 }
67}
68
69impl<const S: usize> AddAssign<&Self> for NonZeroUbig<S> {
70 #[inline]
71 fn add_assign(&mut self, rhs: &Self) {
72 unsafe {
73 assert_unchecked(!self.0.is_empty());
75 assert_unchecked(!rhs.0.is_empty());
76 }
77 add_assign(&mut self.0, &rhs.0);
78 }
79}
80
81impl<const S: usize> Mul for Ubig<S> {
82 type Output = Self;
83
84 fn mul(mut self, rhs: Self) -> Self::Output {
85 if !self.is_zero() && !rhs.is_zero() {
86 unsafe {
87 Self(mul_non_zero(&self.0, &rhs.0))
89 }
90 } else {
91 self.set_zero();
92 self
93 }
94 }
95}
96
97impl<const S: usize> Mul for NonZeroUbig<S> {
98 type Output = Self;
99
100 fn mul(self, rhs: Self) -> Self::Output {
101 unsafe {
102 Self(mul_non_zero(&self.0, &rhs.0))
104 }
105 }
106}
107
108#[cfg(test)]
109mod test {
110 use std::str::FromStr;
111
112 use num_traits::One;
113 use smallvec::smallvec;
114
115 use crate::{NonZeroUbig, Ubig};
116
117 #[test]
118 fn test_add() {
119 assert_eq!(Ubig::<8>::from(0) + Ubig::<8>::from(0), Ubig::<8>::from(0));
120 assert_eq!(Ubig::<8>::from(0) + Ubig::<8>::from(1), Ubig::<8>::from(1));
121 assert_eq!(Ubig::<8>::from(1) + Ubig::<8>::from(0), Ubig::<8>::from(1));
122 assert_eq!(Ubig::<8>::from(8) + Ubig::<8>::from(9), Ubig::<8>::from(17));
123 assert_eq!(
124 Ubig::<8>::from(usize::MAX) + Ubig::<8>::from(1),
125 unsafe { Ubig::<8>::from_inner_unchecked(smallvec![0, 1]) },
126 );
127 }
128
129 #[test]
130 fn test_add_non_zero() {
131 assert_eq!(
132 NonZeroUbig::<8>::from_str("8").unwrap() + NonZeroUbig::<8>::from_str("9").unwrap(),
133 NonZeroUbig::<8>::from_str("17").unwrap(),
134 );
135 assert_eq!(
136 NonZeroUbig::<8>::from_str("18446744073709551615").unwrap() + NonZeroUbig::<8>::one(),
137 NonZeroUbig::<8>::from_str("18446744073709551616").unwrap(),
138 );
139 }
140
141 #[test]
142 fn test_mul() {
143 assert_eq!(Ubig::<8>::from(0) * Ubig::<8>::from(0), Ubig::<8>::from(0));
144 assert_eq!(Ubig::<8>::from(0) * Ubig::<8>::from(1), Ubig::<8>::from(0));
145 assert_eq!(Ubig::<8>::from(1) * Ubig::<8>::from(0), Ubig::<8>::from(0));
146 assert_eq!(Ubig::<8>::from(8) * Ubig::<8>::from(9), Ubig::<8>::from(72));
147 assert_eq!(
148 Ubig::<8>::from(usize::MAX) * Ubig::<8>::from(1),
149 Ubig::<8>::from(usize::MAX),
150 );
151 }
152
153 #[test]
154 fn test_mul_non_zero() {
155 assert_eq!(
156 NonZeroUbig::<8>::from_str("8").unwrap() * NonZeroUbig::<8>::from_str("9").unwrap(),
157 NonZeroUbig::<8>::from_str("72").unwrap(),
158 );
159 assert_eq!(
160 NonZeroUbig::<8>::from_str("18446744073709551615").unwrap() * NonZeroUbig::<8>::one(),
161 NonZeroUbig::<8>::from_str("18446744073709551615").unwrap(),
162 );
163 }
164}