diff options
| author | Melody Horn <melody@boringcactus.com> | 2021-03-07 10:17:40 -0700 | 
|---|---|---|
| committer | Melody Horn <melody@boringcactus.com> | 2021-03-07 10:17:40 -0700 | 
| commit | d5083f4cce47567644fd1b2c5923e5d0dcd98d44 (patch) | |
| tree | ca625bf36a221bef5fd66cec7fb793a36ebad56b /src | |
| parent | c8cfeabc011bfabb6303023a969155ded926d95c (diff) | |
| download | hope-d5083f4cce47567644fd1b2c5923e5d0dcd98d44.tar.gz hope-d5083f4cce47567644fd1b2c5923e5d0dcd98d44.zip  | |
don't round-trip everything through strings!!!
Diffstat (limited to 'src')
| -rw-r--r-- | src/basic_actors.rs | 3 | ||||
| -rw-r--r-- | src/main.rs | 3 | ||||
| -rw-r--r-- | src/number.rs | 54 | 
3 files changed, 34 insertions, 26 deletions
diff --git a/src/basic_actors.rs b/src/basic_actors.rs index da391cf..130c1e2 100644 --- a/src/basic_actors.rs +++ b/src/basic_actors.rs @@ -1,4 +1,5 @@  use std::collections::HashMap; +use std::convert::TryInto;  use std::sync::mpsc::{SyncSender, Receiver};  use crate::actor::{Value, Type, Actorful, Slot}; @@ -98,7 +99,7 @@ impl Actorful for RepeatValue {                  if let Value::Number(count) = count {                      // TODO figure out what a smart thing to do would be here instead                      // this API design is deliberately suboptimal because i'd like to not do it -                    let count: usize = format!("{}", count).parse().unwrap(); +                    let count: usize = count.try_into().unwrap();                      let vec = vec![value; count];                      output_channels["List"].send(Value::List(vec)).unwrap();                  } diff --git a/src/main.rs b/src/main.rs index 6bf920b..8617d6a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use std::convert::TryInto;  use std::time::Duration;  use minifb::{Key, Window, WindowOptions, MouseMode}; @@ -119,7 +120,7 @@ fn main() {                  let u32_data: Vec<u32> = data.into_iter()                      .map(|x| {                          if let actor::Value::Number(x) = x { -                            format!("{}", x).parse().unwrap() +                            x.try_into().unwrap()                          } else {                              panic!("bruh")                          } diff --git a/src/number.rs b/src/number.rs index 94a67f1..5ea7949 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,10 +1,12 @@  use std::cmp::max; -use std::fmt::{Display, Formatter, Result as FormatResult}; +use std::convert::TryFrom; +use std::num::TryFromIntError;  use std::ops::Add;  #[derive(Clone)]  pub struct Number { -    pub integer_part: String, +    // least significant first +    pub integer_part: Vec<usize>,  }  macro_rules! int_conv { @@ -12,7 +14,19 @@ macro_rules! int_conv {          impl From<$t> for Number {              fn from(x: $t) -> Number {                  Number { -                    integer_part: x.to_string(), +                    integer_part: vec![x as usize], +                } +            } +        } + +        impl TryFrom<Number> for $t { +            type Error = TryFromIntError; + +            fn try_from(x: Number) -> Result<$t, TryFromIntError> { +                if x.integer_part.len() > 1 { +                    <u8>::try_from(-1).map(|_| 0) +                } else { +                    <$t>::try_from(x.integer_part[0]).map_err(|_| <u8>::try_from(-1).unwrap_err())                  }              }          } @@ -21,33 +35,25 @@ macro_rules! int_conv {  int_conv!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); -impl Display for Number { -    fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult { -        f.write_str(&self.integer_part) -    } -} -  impl Add for Number {      type Output = Number;      fn add(self, rhs: Self) -> Self::Output {          let longest_ipart_len = max(self.integer_part.len(), rhs.integer_part.len()); -        let self_padded = format!("{:0>len$}", self.integer_part, len=longest_ipart_len); -        let rhs_padded = format!("{:0>len$}", rhs.integer_part, len=longest_ipart_len); -        let mut result_ipart_reverse = "".to_string(); -        let mut carry: u8 = 0; -        for (self_char, rhs_char) in self_padded.chars().rev().zip(rhs_padded.chars().rev()) { -            let self_char_val = self_char.to_digit(10).unwrap() as u8; -            let rhs_char_val = rhs_char.to_digit(10).unwrap() as u8; -            let sum = self_char_val + rhs_char_val + carry; -            let sum_last_digit = (sum % 10).to_string().chars().next().unwrap(); -            carry = sum / 10; -            result_ipart_reverse.push(sum_last_digit); -        } -        if carry > 0 { -            result_ipart_reverse.push_str(&carry.to_string()); +        let mut result_ipart = vec![]; +        let mut carry: usize = 0; +        for i in 0..longest_ipart_len { +            let self_part = self.integer_part.get(i).copied().unwrap_or(0); +            let rhs_part = rhs.integer_part.get(i).copied().unwrap_or(0); +            let (half_sum, early_carry) = self_part.overflowing_add(rhs_part); +            let (full_sum, late_carry) = half_sum.overflowing_add(carry); +            carry = if early_carry || late_carry { +                1 +            } else { +                0 +            }; +            result_ipart.push(full_sum);          } -        let result_ipart = result_ipart_reverse.chars().rev().collect();          Number {              integer_part: result_ipart,          }  |