Compare commits
No commits in common. "main" and "refactor" have entirely different histories.
5 changed files with 3 additions and 89 deletions
|
@ -36,7 +36,5 @@ Install the package using Cargo with the command <code>cargo install quickmath</
|
||||||
## Libraries
|
## Libraries
|
||||||
|
|
||||||
- [evalexpr](https://crates.io/crates/evalexpr) — expression evaluator
|
- [evalexpr](https://crates.io/crates/evalexpr) — expression evaluator
|
||||||
- [pico-args](https://crates.io/crates/pico_args) — argument parsing
|
|
||||||
- [rustyline](https://crates.io/crates/rustyline) — input handler
|
|
||||||
- [termion](https://crates.io/crates/termion) — ANSI formatting
|
- [termion](https://crates.io/crates/termion) — ANSI formatting
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
use evalexpr::{
|
use evalexpr::{
|
||||||
Value,
|
Value,
|
||||||
|
|
||||||
|
@ -39,51 +38,6 @@ pub fn fix(arg: &Value) -> EvalResult {
|
||||||
} else { Err(EvalexprError::wrong_function_argument_amount(1, 2)) }
|
} else { Err(EvalexprError::wrong_function_argument_amount(1, 2)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fraction(arg: &Value) -> EvalResult {
|
|
||||||
if let Value::Float(arg) = arg {
|
|
||||||
let mut intermediate = arg.clone();
|
|
||||||
let mut pow = 0;
|
|
||||||
while intermediate.fract() != 0_f64 {
|
|
||||||
intermediate *= 10_f64;
|
|
||||||
pow += 1;
|
|
||||||
}
|
|
||||||
let value = intermediate as i64;
|
|
||||||
let tens: i64 = 10_i64.pow(pow);
|
|
||||||
let gcd = util::gcd(value, tens);
|
|
||||||
|
|
||||||
let numerator = value / gcd;
|
|
||||||
let denominator = tens / gcd;
|
|
||||||
|
|
||||||
Ok(Value::String(format!("{numerator}/{denominator}")))
|
|
||||||
} else { Err(EvalexprError::expected_float(arg.clone())) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn greatest_common_divisor(arg: &Value) -> EvalResult {
|
|
||||||
if let Value::Tuple(args) = arg {
|
|
||||||
let len = args.len();
|
|
||||||
if len != 2 { return Err(EvalexprError::wrong_function_argument_amount(len, 2)); }
|
|
||||||
|
|
||||||
let a = args[0].clone();
|
|
||||||
let b = args[1].clone();
|
|
||||||
|
|
||||||
if let (Value::Int(a), Value::Int(b)) = (a, b) { Ok( Value::Int( util::gcd(i64::max(a, b), i64::min(a, b)) ) ) }
|
|
||||||
else { Err(EvalexprError::expected_int( if !args[0].is_int() { args[0].clone() } else { args[1].clone() } )) }
|
|
||||||
} else { Err(EvalexprError::expected_tuple(arg.clone())) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn least_common_multiple(arg: &Value) -> EvalResult {
|
|
||||||
if let Value::Tuple(args) = arg {
|
|
||||||
let len = args.len();
|
|
||||||
if len != 2 { return Err(EvalexprError::wrong_function_argument_amount(len, 2)); }
|
|
||||||
|
|
||||||
let a = args[0].clone();
|
|
||||||
let b = args[1].clone();
|
|
||||||
|
|
||||||
if let (Value::Int(a), Value::Int(b)) = (a, b) { Ok( Value::Int( util::lcm(i64::max(a, b), i64::min(a, b)) ) ) }
|
|
||||||
else { Err(EvalexprError::expected_int( if !args[0].is_int() { args[0].clone() } else { args[1].clone() } )) }
|
|
||||||
} else { Err(EvalexprError::expected_tuple(arg.clone())) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn logarithm(arg: &Value) -> EvalResult {
|
pub fn logarithm(arg: &Value) -> EvalResult {
|
||||||
let value: f64;
|
let value: f64;
|
||||||
let base: Option<f64>;
|
let base: Option<f64>;
|
||||||
|
@ -91,7 +45,7 @@ pub fn logarithm(arg: &Value) -> EvalResult {
|
||||||
Value::Tuple(tuple)
|
Value::Tuple(tuple)
|
||||||
=> {
|
=> {
|
||||||
let len = tuple.len();
|
let len = tuple.len();
|
||||||
if len != 2 { return Err(EvalexprError::wrong_function_argument_amount_range(len, 1..=2)); }
|
if len != 2 { return Err(EvalexprError::WrongOperatorArgumentAmount { expected: 2, actual: len }) }
|
||||||
|
|
||||||
let i_value = tuple.get(0).unwrap();
|
let i_value = tuple.get(0).unwrap();
|
||||||
if let Value::Float(float) = i_value { value = float.clone(); }
|
if let Value::Float(float) = i_value { value = float.clone(); }
|
||||||
|
@ -158,33 +112,11 @@ pub fn average(arg: &Value) -> EvalResult {
|
||||||
total +=
|
total +=
|
||||||
if let Value::Float(float) = arg { float.clone() }
|
if let Value::Float(float) = arg { float.clone() }
|
||||||
else if let Value::Int(int) = arg { int.clone() as f64 }
|
else if let Value::Int(int) = arg { int.clone() as f64 }
|
||||||
else { return Err(EvalexprError::expected_number(arg.clone())) };
|
else { todo!() };
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok( (total / len).into() )
|
Ok( (total / len).into() )
|
||||||
} else { Err(EvalexprError::expected_tuple(arg.clone())) }
|
} else { todo!() }
|
||||||
}
|
|
||||||
|
|
||||||
pub fn median(arg: &Value) -> EvalResult {
|
|
||||||
if arg.is_tuple() {
|
|
||||||
let args = sort(arg).unwrap().as_tuple().unwrap();
|
|
||||||
let len = args.len();
|
|
||||||
let middle = len / 2;
|
|
||||||
if len % 2 != 0 { Ok(args[middle].as_number().unwrap().into()) }
|
|
||||||
else {
|
|
||||||
let left = args[middle - 1].as_number().unwrap();
|
|
||||||
let right = args[middle].as_number().unwrap();
|
|
||||||
Ok( ((left + right) / 2f64 ).into() )
|
|
||||||
}
|
|
||||||
} else { Err(EvalexprError::expected_tuple(arg.clone())) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn sort(arg: &Value) -> EvalResult {
|
|
||||||
if let Value::Tuple(args) = arg {
|
|
||||||
let mut args = args.clone();
|
|
||||||
args.sort_by(|a, b| a.as_number().unwrap().total_cmp(&b.as_number().unwrap()));
|
|
||||||
Ok(args.into())
|
|
||||||
} else { Err(EvalexprError::expected_tuple(arg.clone())) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Radix conversion
|
// Radix conversion
|
||||||
|
|
|
@ -27,10 +27,7 @@ pub fn build(args: &mut Arguments) -> HashMapContext {
|
||||||
|
|
||||||
// math functions
|
// math functions
|
||||||
"cos" => Function::new(|arg| helper::cosine(arg)),
|
"cos" => Function::new(|arg| helper::cosine(arg)),
|
||||||
"fract" => Function::new(|arg| helper::fraction(arg)),
|
|
||||||
"fix" => Function::new(|arg| helper::fix(arg)),
|
"fix" => Function::new(|arg| helper::fix(arg)),
|
||||||
"gcd" => Function::new(|arg| helper::greatest_common_divisor(arg)),
|
|
||||||
"lcm" => Function::new(|arg| helper::least_common_multiple(arg)),
|
|
||||||
"log" => Function::new(|arg| helper::logarithm(arg)),
|
"log" => Function::new(|arg| helper::logarithm(arg)),
|
||||||
"sin" => Function::new(|arg| helper::sine(arg)),
|
"sin" => Function::new(|arg| helper::sine(arg)),
|
||||||
"sqrt" => Function::new(|arg| helper::square_root(arg)),
|
"sqrt" => Function::new(|arg| helper::square_root(arg)),
|
||||||
|
@ -38,8 +35,6 @@ pub fn build(args: &mut Arguments) -> HashMapContext {
|
||||||
|
|
||||||
// data science functions
|
// data science functions
|
||||||
"avg" => Function::new(|arg| helper::average(arg)),
|
"avg" => Function::new(|arg| helper::average(arg)),
|
||||||
"med" => Function::new(|arg| helper::median(arg)),
|
|
||||||
"sort" => Function::new(|arg| helper::sort(arg)),
|
|
||||||
|
|
||||||
// radix functions
|
// radix functions
|
||||||
"bin" => Function::new(|arg| helper::binary(arg)),
|
"bin" => Function::new(|arg| helper::binary(arg)),
|
||||||
|
|
|
@ -83,7 +83,6 @@ fn main() {
|
||||||
|
|
||||||
fn eval(expression: &str, context: &mut HashMapContext, quiet: bool) {
|
fn eval(expression: &str, context: &mut HashMapContext, quiet: bool) {
|
||||||
let result = eval_with_context_mut(expression, context);
|
let result = eval_with_context_mut(expression, context);
|
||||||
|
|
||||||
if quiet {
|
if quiet {
|
||||||
if let Ok(result) = result { println!("{result}") }
|
if let Ok(result) = result { println!("{result}") }
|
||||||
else { exit(1) }
|
else { exit(1) }
|
||||||
|
|
10
src/util.rs
10
src/util.rs
|
@ -1,16 +1,6 @@
|
||||||
|
|
||||||
use evalexpr::{ EvalexprError, Value };
|
use evalexpr::{ EvalexprError, Value };
|
||||||
|
|
||||||
pub fn gcd(big: i64, small: i64) -> i64 {
|
|
||||||
if small == 0 { big }
|
|
||||||
else { gcd(small, big % small) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lcm(big: i64, small: i64) -> i64 {
|
|
||||||
let product = (big * small).abs();
|
|
||||||
product / gcd(big, small)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn parse_radix(prefix: &str, base: u32, arg: &str) -> Result<Value, EvalexprError> {
|
pub fn parse_radix(prefix: &str, base: u32, arg: &str) -> Result<Value, EvalexprError> {
|
||||||
let parse = arg.strip_prefix(prefix).unwrap_or(arg);
|
let parse = arg.strip_prefix(prefix).unwrap_or(arg);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue