aboutsummaryrefslogtreecommitdiff
path: root/src/format.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/format.rs')
-rw-r--r--src/format.rs97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/format.rs b/src/format.rs
new file mode 100644
index 0000000..45673d7
--- /dev/null
+++ b/src/format.rs
@@ -0,0 +1,97 @@
1extern crate num;
2use num::{BigInt, FromPrimitive, ToPrimitive};
3
4use crate::error::{CalcError, Math};
5use crate::CONFIGURATION;
6
7pub fn autobalance_parens(input: &str) -> Result<String, CalcError> {
8 let mut balanced = String::from(input);
9 let mut left_parens = 0;
10 let mut right_parens = 0;
11 for letter in input.chars() {
12 if letter == '(' {
13 left_parens += 1;
14 } else if letter == ')' {
15 right_parens += 1;
16 }
17 }
18
19 if left_parens > right_parens {
20 let extras = ")".repeat(left_parens - right_parens);
21 balanced.push_str(&extras[..]);
22 Ok(balanced)
23 } else if left_parens < right_parens {
24 Err(CalcError::Syntax("Mismatched parentheses!".into()))
25 } else {
26 Ok(balanced)
27 }
28}
29
30fn radix_fmt(number: f64, obase: usize) -> Result<String, CalcError> {
31 if obase > 36 {
32 return Err(CalcError::Math(Math::UnknownBase));
33 }
34
35 match (number.is_infinite(), number.is_sign_positive()) {
36 (true, true) => return Ok("inf".to_string()),
37 (true, false) => return Ok("-inf".to_string()),
38 _ => (),
39 }
40
41 if number.is_nan() {
42 return Ok("nan".to_string());
43 }
44
45 let table: Vec<char> = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars().collect();
46
47 // format integral part of float
48 let mut integral = BigInt::from_f64(number.abs().trunc()).unwrap();
49 let mut obase_int = String::new();
50 let obaseb = BigInt::from_usize(obase).unwrap();
51
52 while integral >= obaseb {
53 obase_int.push(table[(&integral % &obaseb).to_usize().unwrap()]);
54 integral /= &obaseb;
55 }
56 obase_int.push(table[integral.to_usize().unwrap()]);
57 if number.is_sign_negative() {
58 obase_int.push('-');
59 }
60 let obase_int = obase_int.chars().rev().collect::<String>();
61
62 // format fractional part of float
63 let mut fract = number.abs().fract();
64 let mut obase_fract = String::new();
65 let mut i = 0;
66 loop {
67 fract *= obase as f64;
68 obase_fract.push(table[fract.trunc() as usize]);
69 i += 1;
70 if fract.fract() == 0. || i >= CONFIGURATION.fix {
71 break;
72 }
73 fract = fract.fract();
74 }
75 Ok(format!("{}.{}", obase_int, obase_fract))
76}
77
78fn thousand_sep(inp: &str) -> String {
79 let mut result_string = String::new();
80 for (i, c) in inp.to_string().chars().rev().enumerate() {
81 if i % 3 == 0 && i != 0 && c.to_string() != "-" {
82 result_string.push(',');
83 }
84 result_string.push(c)
85 }
86 result_string.chars().rev().collect::<String>()
87}
88
89pub fn pprint(ans: f64) {
90 let ans_string = radix_fmt(ans, CONFIGURATION.base).unwrap();
91 let ans_vector: Vec<&str> = ans_string.split('.').collect();
92 match ans_vector.len() {
93 1 => println!("{:>10}", thousand_sep(ans_vector[0])),
94 2 => println!("{:>10}.{}", thousand_sep(ans_vector[0]), ans_vector[1]),
95 _ => unreachable!("N-nani?!"),
96 }
97}