largeint/
lib.rs

1//! A library that implements the `LargeInt` struct, used for working with arbitrarily large integers in Rust.
2//! The purpose of this library is to provide an easy-to-use large integer implementation in Rust.
3//! The ideal user is one that is looking to write small scale projects for personal use and does
4//! not want to spend time a lot of time learning a complex crate such as num-bigint. For example,
5//! this library would be ideal for one looking to solve [Project Euler Problem 13](https://projecteuler.net/problem=13).
6//! However, the largeint library is not particularly efficient and therefore it is recommended to use
7//! a crate like num-bigint for more serious projects.
8
9 mod addition;
10 mod difference;
11 mod multiplication;
12 mod division;
13
14/// Implements the LargeInt struct. Supported methods include addition, subtraction,
15/// multiplication, division (floor division), and remainder from floor division. Also includes getters and a compare
16/// method.
17
18pub mod largeint {
19    use difference::*;
20    use addition::*;
21    use multiplication::*;
22    use division::*;
23
24    /// Arithmetic is carried out on instances of LargeInt. The scalar value is stored
25    /// in a String and its sign in the enum Sign.
26
27    #[derive(PartialEq, Debug, Clone)]
28    pub struct LargeInt {
29        /// Stores the scalar value of the LargeInt as a String.
30        pub digits: String,
31        /// Stores the sign of the value as a Sign.
32        pub sign: Sign,
33    }
34
35    /// Represents the sign of a LargeInt.
36    #[derive(PartialEq, Debug, Copy, Clone)]
37    pub enum Sign {
38        Positive,
39        Negative,
40        Unsigned,
41    }
42
43    /// Used in the output of the compare method to distinguish between comparisons of LargeInts.
44    #[derive(PartialEq, Debug)]
45    pub enum Compare {
46        Larger,
47        Equal,
48        Smaller,
49    }
50
51    impl LargeInt {
52
53        /// Returns a copy of the scalar LargeInt value as a String.
54        pub fn get_int(&self) -> String {
55            let mut int =  String::new();
56            int.push_str(&self.digits);
57            int
58        }
59
60        /// Returns the Sign of the LargeInt value as a String.
61        pub fn get_sign(&self) -> String {
62            let sign: String;
63            if &self.sign == &Sign::Positive {
64                sign = String::from("Positive");
65            } else if &self.sign == &Sign::Negative {
66                sign = String::from("Negative");
67            } else {
68                sign = String::from("Unsigned");
69            }
70            sign
71        }
72
73        /// Compares the scalar value of two LargeInts.
74        ///
75        /// # Examples
76        ///
77        /// ```
78        /// extern crate largeint;
79        /// use largeint::largeint::*;
80        ///
81        /// let largeint1 = new(String::from("150"), Sign::Positive);
82        /// let largeint2 = new(String::from("100"), Sign::Positive);
83        ///
84        /// assert_eq!(largeint1.compare(&largeint2), Compare::Larger);
85        /// ```
86
87        pub fn compare(&self, large2: &LargeInt) -> Compare {
88            let mut flag = Compare::Larger;
89            let large1 = to_vec(&self.digits);
90            let large2 = to_vec(&large2.digits);
91
92            if large1.len() > large2.len() {
93                flag = Compare::Larger;
94            } else if large1.len() < large2.len() {
95                flag = Compare::Smaller;
96            } else if large1 == large2 {
97                flag = Compare::Equal;
98            } else if large1.len() == large2.len() {
99                for i in 0..large2.len() {
100                    if &large2[i] > &large1[i] {
101                        flag = Compare::Smaller;
102                        break
103                    }
104                    else if &large2[i] < &large1[i] {
105                        break
106                    }
107                    else {
108                        continue
109                    }
110                }
111            }
112            flag
113        }
114
115        /// Adds two LargeInts together.
116        ///
117        /// # Examples
118        ///
119        /// ```
120        /// extern crate largeint;
121        /// use largeint::largeint::*;
122        ///
123        /// let largeint1 = new(String::from("80000000000000000000000000000"), Sign::Positive);
124        /// let largeint2 = new(String::from("10000000000000000000000000000"), Sign::Positive);
125        /// let sum = largeint1.add(&largeint2);
126        /// let check = new(String::from("90000000000000000000000000000"), Sign::Positive);
127        /// assert_eq!(sum, check);
128        /// ```
129
130        pub fn add(&self, large2: &LargeInt) -> LargeInt {
131            let digits: String;
132            let sign: Sign;
133            if &self.sign == &Sign::Positive && large2.sign == Sign::Positive {
134                digits = addition(&self.digits, &large2.digits);
135                sign = Sign::Positive;
136            } else if &self.sign == &Sign::Positive && large2.sign == Sign::Negative {
137                if &self.digits.len() > &large2.digits.len() {
138                    digits = difference(&self.digits, &large2.digits);
139                    sign = Sign::Positive;
140                } else if &self.digits.len() < &large2.digits.len(){
141                    digits = difference(&large2.digits, &self.digits);
142                    sign = Sign::Negative;
143                } else if &self.compare(&large2) == &Compare::Larger {
144                    digits = difference(&self.digits, &large2.digits);
145                    sign = Sign::Positive;
146                } else if &self.compare(&large2) == &Compare::Smaller {
147                    digits = difference(&large2.digits, &self.digits);
148                    sign = Sign::Negative;
149                } else {
150                    digits = String::from("0");
151                    sign = Sign::Unsigned;
152                    }
153            } else if &self.sign == &Sign::Negative && large2.sign == Sign::Positive {
154                if &self.digits.len() > &large2.digits.len() {
155                    digits = difference(&self.digits, &large2.digits);
156                    sign = Sign::Negative;
157                } else if &self.digits.len() < &large2.digits.len(){
158                    digits = difference(&large2.digits, &self.digits);
159                    sign = Sign::Positive;
160                } else if &self.compare(&large2) == &Compare::Larger {
161                    digits = difference(&self.digits, &large2.digits);
162                    sign = Sign::Negative;
163                } else if &self.compare(&large2) == &Compare::Smaller {
164                    digits = difference(&large2.digits, &self.digits);
165                    sign = Sign::Positive;
166                } else {
167                    digits = String::from("0");
168                    sign = Sign::Unsigned;
169                }
170            } else if &self.sign == &Sign::Unsigned || large2.sign == Sign::Unsigned {
171                match &self.sign {
172                    &Sign::Unsigned => {
173                        if large2.sign == Sign::Positive {
174                            digits = large2.get_int();
175                            sign = Sign::Positive;
176                        } else if large2.sign == Sign::Negative {
177                            digits = large2.get_int();
178                            sign = Sign::Negative;
179                        } else {
180                            digits = String::from("0");
181                            sign = Sign::Unsigned;
182                        }
183                    }
184                    &Sign::Positive => {
185                        digits = self.get_int();
186                        sign = Sign::Positive;
187                    }
188                    &Sign::Negative => {
189                        digits = self.get_int();
190                        sign = Sign::Negative;
191                    }
192                }
193            } else {
194                digits = addition(&self.digits, &large2.digits);
195                sign = Sign::Negative;
196            }
197
198            LargeInt {
199                digits,
200                sign,
201            }
202        }
203
204        /// Subtracts a LargeInt from another.
205        ///
206        /// # Examples
207        ///
208        /// ```
209        /// extern crate largeint;
210        /// use largeint::largeint::*;
211        ///
212        /// let largeint1 = new(String::from("80000000000000000000000000000"), Sign::Positive);
213        /// let largeint2 = new(String::from("10000000000000000000000000000"), Sign::Positive);
214        /// let sum = largeint1.sub(&largeint2);
215        /// let check = new(String::from("70000000000000000000000000000"), Sign::Positive);
216        /// assert_eq!(sum, check);
217        /// ```
218        pub fn sub(&self, large2: &LargeInt) -> LargeInt{
219            let digits: String;
220            let sign: Sign;
221            if &self.sign == &Sign::Positive && large2.sign == Sign::Positive {
222                if &self.digits.len() > &large2.digits.len() {
223                    digits = difference(&self.digits, &large2.digits);
224                    sign = Sign::Positive;
225                } else if &self.digits.len() < &large2.digits.len(){
226                    digits = difference(&large2.digits, &self.digits);
227                    sign = Sign::Negative;
228                } else if &self.compare(&large2) == &Compare::Larger {
229                    digits = difference(&self.digits, &large2.digits);
230                    sign = Sign::Positive;
231                } else if &self.compare(&large2) == &Compare::Smaller {
232                    digits = difference(&large2.digits, &self.digits);
233                    sign = Sign::Negative;
234                } else {
235                    digits = String::from("0");
236                    sign = Sign::Unsigned;
237                }
238            } else if &self.sign == &Sign::Positive && large2.sign == Sign::Negative {
239                digits = addition(&self.digits, &large2.digits);
240                sign = Sign::Positive;
241            } else if &self.sign == &Sign::Negative && large2.sign == Sign::Positive {
242                digits = addition(&self.digits, &large2.digits);
243                sign = Sign::Negative;
244            } else if &self.sign == &Sign::Negative && large2.sign == Sign::Negative {
245                if &self.digits.len() > &large2.digits.len() {
246                    digits = difference(&self.digits, &large2.digits);
247                    sign = Sign::Negative;
248                } else if &self.digits.len() < &large2.digits.len() {
249                    digits = difference(&large2.digits, &self.digits);
250                    sign = Sign::Positive;
251                } else if &self.compare(&large2) == &Compare::Larger {
252                    digits = difference(&self.digits, &large2.digits);
253                    sign = Sign::Negative;
254                } else if &self.compare(&large2) == &Compare::Smaller {
255                    digits = difference(&large2.digits, &self.digits);
256                    sign = Sign::Positive;
257                } else {
258                    digits = String::from("0");
259                    sign = Sign::Unsigned;
260                    }
261            } else {
262                match &self.sign {
263                    &Sign::Unsigned => {
264                        if large2.sign == Sign::Positive {
265                            digits = large2.get_int();
266                            sign = Sign::Negative;
267                        } else if large2.sign == Sign::Negative {
268                            digits = large2.get_int();
269                            sign = Sign::Positive;
270                        } else {
271                            digits = String::from("0");
272                            sign = Sign::Unsigned;
273                        }
274                    }
275                    &Sign::Positive => {
276                        digits = self.get_int();
277                        sign = Sign::Positive;
278                    }
279                    &Sign::Negative => {
280                        digits = self.get_int();
281                        sign = Sign::Negative;
282                    }
283                }
284            }
285            LargeInt {
286                digits,
287                sign,
288            }
289        }
290
291        /// Multiplies two LargeInts together.
292        ///
293        /// # Examples
294        ///
295        /// ```
296        /// extern crate largeint;
297        /// use largeint::largeint::*;
298        ///
299        /// let largeint1 = new(String::from("1110987654321"), Sign::Positive);
300        /// let largeint2 = new(String::from("1234567891011"), Sign::Negative);
301        /// let sum = largeint1.mul(&largeint2);
302        /// let check = new(String::from("1371589685334334871208531"), Sign::Negative);
303        /// assert_eq!(sum, check);
304        /// ```
305
306        pub fn mul(&self, large2: &LargeInt) -> LargeInt{
307            let digits: String;
308            let sign: Sign;
309            if &self.sign == &Sign::Positive && large2.sign == Sign::Positive {
310                digits = multiplication_2(&self.digits, &large2.digits);
311                sign = Sign::Positive;
312            } else if &self.sign == &Sign::Negative && large2.sign == Sign::Negative {
313                digits = multiplication_2(&self.digits, &large2.digits);
314                sign = Sign::Positive;
315            } else if &self.sign == &Sign::Unsigned || large2.sign == Sign::Unsigned {
316                digits = String::from("0");
317                sign = Sign::Unsigned;
318            } else if &self.sign == &Sign::Negative || large2.sign == Sign::Negative {
319                digits = multiplication_2(&self.digits, &large2.digits);
320                sign = Sign::Negative;
321            } else {
322                panic!("Something went wrong while multiplying!")
323            }
324            LargeInt {
325                digits,
326                sign,
327            }
328        }
329
330        /// Divides one LargeInt by another LargeInt.
331        ///
332        /// # Examples
333        ///
334        /// ```
335        /// extern crate largeint;
336        /// use largeint::largeint::*;
337        ///
338        /// let largeint1 = new(String::from("3987382479238749823798759823745983748927"), Sign::Negative);
339        /// let largeint2 = new(String::from("98394783947982377583783759928"), Sign::Negative);
340        /// let sum = largeint1.div(&largeint2);
341        /// let check = new(String::from("40524327807"), Sign::Positive);
342        /// assert_eq!(sum, check);
343        /// ```
344
345        pub fn div(&self, large2: &LargeInt) -> LargeInt {
346            let digits_vec: Vec<String>;
347            let sign: Sign;
348            if large2.sign == Sign::Unsigned {
349                panic!("Cannot divide by 0!")
350            }
351            else if &self.sign == &Sign::Positive && large2.sign == Sign::Positive {
352                sign = Sign::Positive;
353            } else if &self.sign == &Sign::Unsigned {
354
355                sign = Sign::Unsigned;
356            } else if &self.sign == &Sign::Negative && large2.sign == Sign::Negative {
357                sign = Sign::Positive;
358            } else if  &self.sign == &Sign::Negative || large2.sign == Sign::Negative {
359                sign = Sign::Negative;
360            }  else {
361                panic!("This should never run! Please report this issue at:
362                 https://github.com/Starfunk/largeint/issues");
363            }
364            if &self.compare(large2) == &Compare::Larger {
365                digits_vec = division(&self.digits, &large2.digits);
366            } else if &self.compare(large2) == &Compare::Smaller {
367                digits_vec = vec![String::from("0")];
368            } else if &self.sign == &Sign::Unsigned {
369                println!("THIS IS RUNNING MAX");
370                digits_vec = vec![String::from("0")];
371            } else {
372                digits_vec = vec![String::from("1")];
373            }
374            let digits_vec0 = &digits_vec[0];
375            let digits = digits_vec0.to_string();
376            LargeInt {
377                digits,
378                sign,
379            }
380        }
381
382        /// Returns the remainder of a floor division operation.
383        ///
384        /// # Examples
385        ///
386        /// ```
387        /// extern crate largeint;
388        /// use largeint::largeint::*;
389        ///
390        /// let largeint1 = new(String::from("3987382479238749823798759823745983748927"), Sign::Negative);
391        /// let largeint2 = new(String::from("98394783947982377583783759928"), Sign::Negative);
392        /// let sum = largeint1.rem(&largeint2);
393        /// let check = new(String::from("31770318334258129020721031031"), Sign::Positive);
394        /// assert_eq!(sum, check);
395        /// ```
396
397        pub fn rem(&self, large2: &LargeInt) -> LargeInt {
398            let digits_vec: Vec<String>;
399            let digits_vec1: &str;
400            let mut sign: Sign;
401            if large2.sign == Sign::Unsigned {
402                panic!("Cannot divide by 0!")
403            } else if &self.sign == &Sign::Positive && large2.sign == Sign::Positive {
404                sign = Sign::Positive;
405            } else if &self.sign == &Sign::Unsigned {
406                sign = Sign::Unsigned;
407            } else if &self.sign == &Sign::Negative && large2.sign == Sign::Negative {
408                sign = Sign::Positive;
409            } else if  &self.sign == &Sign::Negative || large2.sign == Sign::Negative {
410                sign = Sign::Negative;
411            }  else {
412                panic!("This should never run! Please report this issue at:
413                 https://github.com/Starfunk/largeint/issues");
414            }
415            if &self.digits == "0" {
416                digits_vec1 = "0";
417            }
418            else if &self.compare(large2) == &Compare::Larger {
419                digits_vec = division(&self.digits, &large2.digits);
420                digits_vec1 = &digits_vec[1];
421                if digits_vec1 == "0" {
422                    sign = Sign::Unsigned;
423                }
424            } else if &self.compare(large2) == &Compare::Smaller {
425                digits_vec1 = &large2.digits;
426            } else {
427                digits_vec1 = "0";
428            }
429            let digits = digits_vec1.to_string();
430            LargeInt {
431                digits,
432                sign,
433            }
434        }
435    }
436
437    /// Creates a new instance of LargeInt. It is strongly recommended that
438    /// LargeInt creation is done through the new() function which will instantiate an instance of
439    /// LargeInt safely, making the necessary corrections to the fields if necessary, or panicking
440    /// if an invalid input was submitted. See above for examples of LargeInt creation.
441
442    pub fn new(digits: String, mut sign: Sign) -> LargeInt {
443        let mut digits_clone = digits.clone();
444        let digit_0 = &digits[0..1];
445        if digits == String::from("") {
446            panic!("The large integer value is undefined!")
447        } else if digit_0 == "0" && digits.len() > 1 {
448            panic!("Invalid LargeInt creation. Please remove the leading 0")
449        } else if digit_0 == "0" && digits.len() == 1 {
450            digits_clone = String::from("0");
451            sign = Sign::Unsigned;
452        } else if digit_0 != "0" && sign == Sign::Unsigned {
453            panic!("Invalid LargeInt creation. Nonzero integers must be assigned
454            either Sign::Positive or Sign::Negative")
455        }
456        let new_int = LargeInt {
457            digits: digits_clone,
458            sign: sign,
459        };
460        new_int
461    }
462
463    #[doc(hidden)]
464    pub fn to_vec(input_str: &str) -> Vec<u8> {
465        let mut vec: Vec<u8> = Vec::new();
466        for i in input_str.chars() {
467            let vec_input = i.to_digit(10).unwrap() as u8;
468            vec.push(vec_input);
469        }
470        vec
471    }
472
473    #[doc(hidden)]
474    pub fn vec_to_str(vec: &Vec<u8>) -> String {
475        let mut output = String::from("");
476        for i in vec {
477            output.push_str(&i.to_string());
478        }
479        output
480    }
481}