1use std::char;
37use std::cmp::Ordering;
38use std::fmt;
39use std::iter;
40use std::iter::{DoubleEndedIterator, Iterator};
41use std::ops::{Add, Deref, Index, Mul, Neg, Shl, Sub};
42
43mod ops;
44
45#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub enum Sign {
48 Positive,
49 Negative,
50 NoSign,
51}
52
53impl Sign {
54 pub fn is_positive(self) -> bool {
56 match self {
57 Sign::Positive => true,
58 _ => false,
59 }
60 }
61
62 pub fn is_negative(self) -> bool {
64 match self {
65 Sign::Negative => true,
66 _ => false,
67 }
68 }
69
70 pub fn is_nosign(self) -> bool {
72 match self {
73 Sign::NoSign => true,
74 _ => false,
75 }
76 }
77}
78
79impl fmt::Display for Sign {
80 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
81 match *self {
82 Sign::Positive => write!(formatter, "+"),
83 Sign::Negative => write!(formatter, "-"),
84 Sign::NoSign => Ok(()),
85 }
86 }
87}
88
89#[derive(Clone, Debug, PartialEq)]
102pub struct BigInteger {
103 digits: Vec<u8>,
104 sign: Sign,
105}
106
107impl BigInteger {
108 pub fn new(literal: &str) -> BigInteger {
145 let char_to_digit = |character: char| {
147 character
148 .to_digit(10)
149 .expect("BigInteger literal must use numeric characters") as u8
150 };
151
152 let mut digits: Vec<u8> = Vec::new();
153 let mut chars = literal.chars();
154
155 let sign = match chars.next() {
157 Some(character) if character == '+' => Sign::Positive,
158 Some(character) if character == '-' => Sign::Negative,
159 Some(character) => {
160 digits.push(char_to_digit(character));
161
162 Sign::Positive
164 }
165 None => panic!("BigInteger literal must begin with a sign or a digit"),
166 };
167
168 digits.extend(chars.map(char_to_digit));
170
171 BigInteger::from_digits(&digits[..], sign)
172 }
173
174 pub fn from_digits(digits: &[u8], sign: Sign) -> BigInteger {
176 let digits = Vec::from(digits);
177
178 let mut result = BigInteger { digits, sign };
179
180 result.trim();
181 result
182 }
183
184 pub fn is_positive(&self) -> bool {
186 self.sign.is_positive()
187 }
188
189 pub fn is_negative(&self) -> bool {
191 self.sign.is_negative()
192 }
193
194 pub fn count(&self) -> usize {
196 self.digits.len()
197 }
198
199 pub fn as_slice(&self) -> &[u8] {
201 self
202 }
203
204 pub fn digits(&self) -> impl Iterator<Item = u8> + DoubleEndedIterator + '_ {
223 self.digits.iter().cloned().rev()
226 }
227
228 fn trim(&mut self) {
230 self.digits = self
233 .digits
234 .iter()
235 .cloned()
236 .skip_while(|&digit| digit == 0)
237 .collect();
238
239 if self.digits.is_empty() {
241 self.digits.push(0);
242 self.sign = Sign::NoSign;
243 }
244 }
245}
246
247impl fmt::Display for BigInteger {
248 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
249 let mut display_value = String::new();
250
251 display_value.extend(self.digits.iter().map(|digit| {
252 char::from_digit(u32::from(*digit), 10)
253 .expect("Error occured whilst encoding BigInteger digit")
254 }));
255
256 write!(formatter, "{}{}", self.sign, display_value)
257 }
258}
259
260impl Deref for BigInteger {
261 type Target = Vec<u8>;
262
263 fn deref(&self) -> &Vec<u8> {
264 &self.digits
265 }
266}
267
268impl Index<usize> for BigInteger {
269 type Output = u8;
270
271 fn index(&self, index: usize) -> &u8 {
272 &self.digits[index]
273 }
274}
275
276impl PartialOrd for BigInteger {
277 fn partial_cmp(&self, other: &BigInteger) -> Option<Ordering> {
278 match (self.is_positive(), other.is_positive()) {
281 (true, true) => Some(ops::cmp(self, other)),
282 (false, true) => Some(Ordering::Less),
283 (true, false) => Some(Ordering::Greater),
284 (false, false) => {
285 match ops::cmp(self, other) {
287 Ordering::Less => Some(Ordering::Greater),
288 Ordering::Equal => Some(Ordering::Equal),
289 Ordering::Greater => Some(Ordering::Less),
290 }
291 }
292 }
293 }
294}
295
296impl Neg for BigInteger {
297 type Output = BigInteger;
298
299 fn neg(mut self) -> BigInteger {
300 self.sign = match self.sign {
301 Sign::Positive => Sign::Negative,
302 Sign::NoSign => Sign::NoSign,
303 Sign::Negative => Sign::Negative,
304 };
305 self
306 }
307}
308
309impl Shl<usize> for BigInteger {
310 type Output = Self;
311
312 fn shl(mut self, count: usize) -> BigInteger {
313 self.digits.extend(iter::repeat(0u8).take(count));
314 self
315 }
316}
317
318impl<'a> Add<&'a BigInteger> for BigInteger {
319 type Output = Self;
320
321 fn add(self, other: &BigInteger) -> BigInteger {
322 match (self.sign, other.sign) {
323 (Sign::NoSign, Sign::NoSign) => self,
324 (Sign::NoSign, _) => other.clone(),
325 (_, Sign::NoSign) => self,
326 (Sign::Positive, Sign::Positive) => ops::add(&self, other),
327 (Sign::Negative, Sign::Positive) => ops::sub(other, &self),
328 (Sign::Positive, Sign::Negative) => ops::sub(&self, other),
329 (Sign::Negative, Sign::Negative) => -ops::add(&self, other),
330 }
331 }
332}
333
334impl<'a> Sub<&'a BigInteger> for BigInteger {
335 type Output = Self;
336
337 fn sub(self, other: &BigInteger) -> BigInteger {
338 match (self.sign, other.sign) {
339 (Sign::NoSign, Sign::NoSign) => self,
340 (Sign::NoSign, _) => other.clone(),
341 (_, Sign::NoSign) => self,
342 (Sign::Positive, Sign::Positive) => ops::sub(&self, other),
343 (Sign::Negative, Sign::Positive) => -ops::add(&self, other),
344 (Sign::Positive, Sign::Negative) => ops::add(&self, other),
345 (Sign::Negative, Sign::Negative) => ops::sub(other, &self),
346 }
347 }
348}
349
350impl<'a> Mul<&'a BigInteger> for BigInteger {
351 type Output = Self;
352
353 #[allow(clippy::suspicious_arithmetic_impl)]
354 fn mul(self, other: &BigInteger) -> BigInteger {
355 if self.sign.is_nosign() || other.sign.is_nosign() {
356 return BigInteger::from_digits(&[0], Sign::NoSign);
357 }
358
359 let positive = self.is_positive() == other.is_positive();
360
361 let mut result = ops::mul(&self, other);
362
363 result.sign = if positive {
364 Sign::Positive
365 } else {
366 Sign::Negative
367 };
368 result
369 }
370}
371
372#[cfg(test)]
373mod tests {
374 use super::BigInteger;
375
376 #[test]
379 fn new_from_literal() {
380 assert_eq!(BigInteger::new("123456789").to_string(), "+123456789");
381 }
382
383 #[test]
384 fn new_from_positive_literal() {
385 assert_eq!(BigInteger::new("+123456789").to_string(), "+123456789");
386 }
387
388 #[test]
389 fn new_from_negative_literal() {
390 assert_eq!(BigInteger::new("-123456789").to_string(), "-123456789");
391 }
392
393 #[test]
394 fn new_with_extraneous_zeroes() {
395 assert_eq!(BigInteger::new("000001").to_string(), "+1");
396 }
397
398 #[test]
401 fn add_single_digits() {
402 let result = BigInteger::new("2") + &BigInteger::new("2");
403
404 assert_eq!(result, BigInteger::new("4"));
405 }
406
407 #[test]
408 fn add_zero() {
409 let result = BigInteger::new("2") + &BigInteger::new("0");
410
411 assert_eq!(result, BigInteger::new("2"));
412 }
413
414 #[test]
415 fn add_with_carry() {
416 let result = BigInteger::new("6") + &BigInteger::new("6");
417
418 assert_eq!(result, BigInteger::new("12"));
419 }
420
421 #[test]
422 fn add_multiple_digits() {
423 let result = BigInteger::new("123") + &BigInteger::new("456");
424
425 assert_eq!(result, BigInteger::new("579"));
426 }
427
428 #[test]
429 fn add_large() {
430 let result = BigInteger::new("999999999999") + &BigInteger::new("999999999999");
431
432 assert_eq!(result, BigInteger::new("1999999999998"));
433 }
434
435 #[test]
436 fn add_negative() {
437 let result = BigInteger::new("456") + &BigInteger::new("-123");
438
439 assert_eq!(result, BigInteger::new("333"));
440 }
441
442 #[test]
445 fn subtract_single_digits() {
446 let result = BigInteger::new("4") - &BigInteger::new("2");
447
448 assert_eq!(result, BigInteger::new("2"));
449 }
450
451 #[test]
452 fn subtract_zero() {
453 let result = BigInteger::new("2") - &BigInteger::new("0");
454
455 assert_eq!(result, BigInteger::new("2"));
456 }
457
458 #[test]
459 fn subtract_multiple_digits() {
460 let result = BigInteger::new("456") - &BigInteger::new("123");
461
462 assert_eq!(result, BigInteger::new("333"));
463 }
464
465 #[test]
466 fn subtract_negative() {
467 let result = BigInteger::new("123") - &BigInteger::new("-456");
468
469 assert_eq!(result, BigInteger::new("579"));
470 }
471
472 #[test]
473 fn subtract_below_zero() {
474 let result = BigInteger::new("2") - &BigInteger::new("4");
475
476 assert_eq!(result, BigInteger::new("-2"));
477 }
478
479 #[test]
480 fn subtract_from_negative() {
481 let result = BigInteger::new("-123") - &BigInteger::new("456");
482
483 assert_eq!(result, BigInteger::new("-579"));
484 }
485
486 #[test]
487 fn subtract_large() {
488 let result = BigInteger::new("2") - &BigInteger::new("999999999999");
489
490 assert_eq!(result, BigInteger::new("-999999999997"));
491 }
492
493 #[test]
496 fn multiply_single_digits() {
497 let result = BigInteger::new("2") * &BigInteger::new("2");
498
499 assert_eq!(result, BigInteger::new("4"));
500 }
501
502 #[test]
503 fn multiply_uneven() {
504 let result = BigInteger::new("2") * &BigInteger::new("16384");
505
506 assert_eq!(result, BigInteger::new("32768"));
507 }
508
509 #[test]
510 fn multiply_large() {
511 let result = BigInteger::new("901238123") * &BigInteger::new("238271282");
512
513 assert_eq!(result, BigInteger::new("214739162954483686"));
514 }
515}