number_theory/arithmetic/
mpz_arith.rs1use crate::arithmetic::inlineops::*;
2use crate::arithmetic::muldiv::*;
3use crate::arithmetic::sliceops::*;
4use crate::Mpz;
5use crate::arithmetic::sign::Sign;
6use std::cmp::Ordering;
7use crate::ntrait::NumberTheory;
8
9impl std::cmp::PartialOrd for Mpz{
10 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
11 match (self.sign,other.sign){
12 (Sign::Negative,Sign::Positive) => Some(std::cmp::Ordering::Less),
13 (Sign::Positive,Sign::Negative) => Some(std::cmp::Ordering::Greater),
14 _=> Some(self.u_cmp(other)),
15 }
16 }
17}
18
19impl std::cmp::Eq for Mpz{}
20
21impl std::cmp::Ord for Mpz{
22 fn cmp(&self,other: &Self) -> std::cmp::Ordering{
23 match (self.sign,other.sign){
24 (Sign::Negative,Sign::Positive) => std::cmp::Ordering::Less,
25 (Sign::Positive,Sign::Negative) => std::cmp::Ordering::Greater,
26 _=> self.u_cmp(other),
27 }
28
29 }
30}
31
32impl Mpz {
33 pub fn mut_and(&mut self, other: &Self) {
39 for (i, j) in self.limbs.iter_mut().zip(other.limbs.iter()) {
40 *i &= j
41 }
42 self.limbs.truncate(other.len());
43 self.normalize();
44 }
45
46 pub fn mut_or(&mut self, other: &Self) {
48 for (i, j) in self.limbs.iter_mut().zip(other.limbs.iter()) {
49 *i |= j
50 }
51
52 if self.len() < other.len() {
53 self.limbs.extend_from_slice(&other.limbs[self.len()..])
54 }
55 }
56 pub fn mut_xor(&mut self, other: &Self) {
58 for (i, j) in self.limbs.iter_mut().zip(other.limbs.iter()) {
59 *i ^= j
60 }
61
62 if self.len() < other.len() {
63 self.limbs.extend_from_slice(&other.limbs[self.len()..])
64 }
65 }
66 pub fn mut_not(&mut self) {
68 for i in self.limbs.iter_mut() {
69 *i = !*i
70 }
71 self.normalize();
72 }
73pub fn mut_shl(&mut self, shift: usize) {
75 let mut trail_zeroes = vec![0; shift / 64usize];
77
78 let carry = shl_slice(&mut self.limbs[..], (shift % 64usize) as u32);
79
80 trail_zeroes.extend_from_slice(&self.limbs[..]);
81
82 if carry > 0 {
83 trail_zeroes.push(carry)
84 }
85
86 self.limbs = trail_zeroes;
87 }
88
89pub fn mut_shr(&mut self, shift: usize) {
91 let mut carry = 0u64;
92
93 let mut vector: Vec<u64> = self
94 .limbs
95 .drain((shift / 64usize)..self.limbs.len())
96 .collect();
97 let sub_shift = shift % 64usize;
98
99 for i in vector.iter_mut().rev() {
100 carry = carry_shr(carry, *i, sub_shift as u32, i);
101 }
102
103 self.limbs = vector;
104 }
105
106pub fn shl(&self, shift: usize) -> Mpz {
108 let mut k = self.clone();
109 k.mut_shl(shift);
110 k
111 }
112pub fn shr(&self, shift: usize) -> Mpz {
114 let mut k = self.clone();
115 k.mut_shr(shift);
116 k
117 }
118pub fn and(&self, other: &Self) -> Self {
120 let mut k = self.clone();
121 k.mut_and(other);
122 k
123 }
124pub fn or(&self, other: &Self) -> Self {
126 let mut k = self.clone();
127 k.mut_or(other);
128 k
129 }
130pub fn xor(&self, other: &Self) -> Self {
132 let mut k = self.clone();
133 k.mut_xor(other);
134 k
135 }
136
137 pub fn mut_addition(&mut self, mut other: Self) {
142 let carry: u8;
143
144 if self.sign == other.sign {
145 if self.limbs.len() < other.limbs.len() {
146 let len = self.len();
147 self.limbs.extend_from_slice(&other.limbs[len..]);
148 carry = add_slice(&mut self.limbs[..], &other.limbs[..len]);
149 } else {
150 carry = add_slice(&mut self.limbs[..], &other.limbs[..]);
151 }
152 if carry == 1u8 {
153 self.limbs.push(1u64)
154 }
155 } else {
156 if self.u_cmp(&other) == Ordering::Less {
157 sub_slice(&mut other.limbs[..], &self.limbs[..]);
158 *self = other;
159 self.normalize();
160 } else if self.u_cmp(&other) == Ordering::Equal {
161 self.limbs.truncate(0);
162 self.limbs.push(0);
163 self.sign = Sign::Positive;
164 } else {
165 sub_slice(&mut self.limbs[..], &other.limbs[..]);
166 self.normalize();
167 }
168 }
169 }
170 pub fn ref_addition(&self, other: &Self) -> Self {
172 let mut k = self.clone();
173 k.mut_addition(other.clone());
174 k
175 }
176 pub fn mut_subtraction(&mut self, mut other: Self) {
178 other.neg();
179 self.mut_addition(other)
180 }
181 pub fn ref_subtraction(&self, other: &Self) -> Self {
183 let mut k = self.clone();
184 k.mut_subtraction(other.clone());
185 k
186 }
187 pub fn ref_product(&self, other: &Self) -> Self {
189 if self == &Mpz::zero() {
190 return Mpz::zero();
191 }
192
193 if other == &Mpz::zero() {
194 return Mpz::zero();
195 }
196
197 if self.is_unit() {
198 return Mpz::unchecked_new(self.sign.mul(&other.sign), other.limbs.clone());
199 }
200
201 if other.is_unit() {
202 return Mpz::unchecked_new(self.sign.mul(&other.sign), self.limbs.clone());
203 }
204
205 let mut t = vec![0u64; self.len() + other.len() + 1];
206
207 mul_slice(&self.limbs[..], &other.limbs[..], &mut t[..]);
208 remove_lead_zeros(&mut t);
209 Mpz::unchecked_new(self.sign.mul(&other.sign), t)
210 }
211
212pub fn mut_product(&mut self, other: Self) {
214 if self == &Mpz::zero() {}
215
216 if other == Mpz::zero() {
217 self.limbs.truncate(0);
218 self.limbs.push(0u64);
219 self.sign = Sign::Positive;
220 }
221
222 if self.is_unit() {
223 self.limbs.truncate(0);
224 self.limbs.extend_from_slice(&other.limbs[..]);
225 self.sign = self.sign.mul(&other.sign);
226 }
227
228 if other.is_unit() {
229 self.sign = self.sign.mul(&other.sign);
230 } else {
231 let mut t = vec![0u64; self.len() + other.len() + 1];
232
233 mul_slice(&self.limbs[..], &other.limbs[..], &mut t[..]);
234 remove_lead_zeros(&mut t);
235 self.limbs = t;
236 self.sign = self.sign.mul(&other.sign);
237 }
238 }
239 pub fn mut_scale_add(&mut self, x: u64, y: u64){
241 let mut carry = scale_slice(&mut self.limbs[..],x);
242 carry += add_slice(&mut self.limbs[..],&[y]) as u64;
243 if carry > 0{
244 self.limbs.push(carry);
245 }
246 }
247
248 pub fn scale_add(&self, x: u64, y: u64) -> Self{
250 let mut k = self.clone();
251 k.mut_scale_add(x,y);
252 k
253 }
254
255
256 pub fn sqr(&self) -> Self {
258 self.ref_product(self)
259 }
260
261 pub fn mut_sqr(&mut self){
263 self.mut_product(self.clone());
264 }
265
266 pub fn ref_euclidean(&self, other: &Self) -> (Self, Self) {
268 let mut dividend = Mpz::from_slice(Sign::Positive, &self.limbs[..]);
269
270 if dividend == Mpz::zero() {
271 return (Mpz::zero(), Mpz::zero());
272 }
273
274 if dividend.len() == 0usize {
275 return (Mpz::zero(), Mpz::zero());
276 }
277
278 if other.len() == 0usize || other == &Mpz::zero() {
279 panic!("Division by zero is undefined in Z")
280 }
281
282 if other.len() == 1 {
283 if other.limbs == [1] {
284 return (dividend, Mpz::zero());
285 }
286
287 let rem = div_slice(&mut dividend.limbs, other.limbs[0]);
288
289 remove_lead_zeros(&mut dividend.limbs);
290 return (dividend, Mpz::unchecked_new(Sign::Positive, vec![rem]));
291 }
292
293 if dividend.u_cmp(other) == Ordering::Equal {
294 return (Mpz::one(), Mpz::zero());
295 }
296
297 if dividend.u_cmp(other) == Ordering::Less {
298 return (Mpz::zero(), dividend);
299 }
300
301 let shift = other.limbs.last().unwrap().leading_zeros() as usize;
302
303 if shift == 0 {
304 let (quo, rem) = euclidean_slice(&mut dividend.limbs, &other.limbs[..]);
305 (
306 Mpz::unchecked_new(Sign::Positive, quo),
307 Mpz::unchecked_new(Sign::Positive, rem),
308 )
309 } else {
310 let (q, r) =
311 euclidean_slice(&mut dividend.shl(shift).limbs, &other.shl(shift).limbs[..]);
312
313 (
314 Mpz::unchecked_new(Sign::Positive, q),
315 Mpz::unchecked_new(Sign::Positive, r).shr(shift),
316 )
317 }
318 }
319}