use cas_parser::parser::ast::literal::DIGITS;
use rug::{ops::Pow, Assign, Complex, Float, Integer};
pub const PRECISION: u32 = 1 << 9;
pub fn int<T>(n: T) -> Integer
where
Integer: From<T>,
{
Integer::from(n)
}
pub fn int_from_float(f: Float) -> Integer {
f.trunc().to_integer().unwrap()
}
pub fn int_from_str(s: &str) -> Integer {
Integer::from_str_radix(s, 10).unwrap()
}
pub fn float<T>(n: T) -> Float
where
Float: Assign<T>,
{
Float::with_val(PRECISION, n)
}
pub fn float_from_str(s: &str) -> Float {
Float::with_val(PRECISION, Float::parse(s).unwrap())
}
pub fn from_str_radix(s: &str, radix: u8) -> Integer {
let mut result = int(0);
let allowed_digits = &DIGITS[..radix as usize];
let radix = int(radix);
for (i, c) in s.chars().rev().enumerate() {
let digit = int(allowed_digits.iter().position(|&d| d == c).unwrap());
result += digit * int((&radix).pow(i as u32));
}
result
}
pub fn complex<T>(n: T) -> Complex
where
Complex: Assign<T>,
{
Complex::with_val(PRECISION, n)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn radix_eval() {
let expected = 1072.0;
let numbers = [
(2, "10000110000"),
(8, "2060"),
(25, "1hm"),
(32, "11g"),
(47, "mC"),
];
for (radix, number) in numbers.iter() {
assert_eq!(from_str_radix(number, *radix), expected);
}
}
}