mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-07 14:09:02 +01:00
Made unit field Optional in KalkValue
This commit is contained in:
parent
8f7726eab5
commit
e10f129706
@ -15,15 +15,24 @@ pub fn derive_func(
|
|||||||
argument: KalkValue,
|
argument: KalkValue,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
const H: f64 = 0.000001;
|
const H: f64 = 0.000001;
|
||||||
let unit = &argument.get_unit();
|
|
||||||
|
|
||||||
|
let unit = argument.get_unit().cloned();
|
||||||
let argument_with_h = ast::build_literal_ast(&argument.clone().add_without_unit(&H.into()));
|
let argument_with_h = ast::build_literal_ast(&argument.clone().add_without_unit(&H.into()));
|
||||||
let argument_without_h = ast::build_literal_ast(&argument.sub_without_unit(&H.into()));
|
let argument_without_h = ast::build_literal_ast(&argument.sub_without_unit(&H.into()));
|
||||||
let new_identifier = Identifier::from_name_and_primes(&name.pure_name, name.prime_count - 1);
|
let new_identifier = Identifier::from_name_and_primes(&name.pure_name, name.prime_count - 1);
|
||||||
|
|
||||||
let f_x_h = interpreter::eval_fn_call_expr(context, &new_identifier, &[argument_with_h], unit)?;
|
let f_x_h = interpreter::eval_fn_call_expr(
|
||||||
let f_x =
|
context,
|
||||||
interpreter::eval_fn_call_expr(context, &new_identifier, &[argument_without_h], unit)?;
|
&new_identifier,
|
||||||
|
&[argument_with_h],
|
||||||
|
unit.as_ref(),
|
||||||
|
)?;
|
||||||
|
let f_x = interpreter::eval_fn_call_expr(
|
||||||
|
context,
|
||||||
|
&new_identifier,
|
||||||
|
&[argument_without_h],
|
||||||
|
unit.as_ref(),
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(f_x_h
|
Ok(f_x_h
|
||||||
.sub_without_unit(&f_x)
|
.sub_without_unit(&f_x)
|
||||||
@ -87,8 +96,8 @@ fn simpsons_rule(
|
|||||||
.get_and_remove_var(integration_variable);
|
.get_and_remove_var(integration_variable);
|
||||||
|
|
||||||
const N: i32 = 900;
|
const N: i32 = 900;
|
||||||
let a = interpreter::eval_expr(context, a_expr, "")?;
|
let a = interpreter::eval_expr(context, a_expr, None)?;
|
||||||
let b = interpreter::eval_expr(context, b_expr, "")?;
|
let b = interpreter::eval_expr(context, b_expr, None)?;
|
||||||
let h = (b.sub_without_unit(&a)).div_without_unit(&KalkValue::from(N));
|
let h = (b.sub_without_unit(&a)).div_without_unit(&KalkValue::from(N));
|
||||||
for i in 0..=N {
|
for i in 0..=N {
|
||||||
let variable_value = a
|
let variable_value = a
|
||||||
@ -103,11 +112,11 @@ fn simpsons_rule(
|
|||||||
0 | N => 1,
|
0 | N => 1,
|
||||||
_ if i % 3 == 0 => 2,
|
_ if i % 3 == 0 => 2,
|
||||||
_ => 3,
|
_ => 3,
|
||||||
});
|
} as f64);
|
||||||
|
|
||||||
// factor * f(x_n)
|
// factor * f(x_n)
|
||||||
let (mul_real, mul_imaginary, _) = as_number_or_zero!(
|
let (mul_real, mul_imaginary, _) = as_number_or_zero!(
|
||||||
factor.mul_without_unit(&interpreter::eval_expr(context, expr, "")?)
|
factor.mul_without_unit(&interpreter::eval_expr(context, expr, None)?)
|
||||||
);
|
);
|
||||||
result_real += mul_real;
|
result_real += mul_real;
|
||||||
result_imaginary += mul_imaginary;
|
result_imaginary += mul_imaginary;
|
||||||
@ -121,7 +130,7 @@ fn simpsons_rule(
|
|||||||
.get_and_remove_var(integration_variable);
|
.get_and_remove_var(integration_variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = KalkValue::Number(result_real, result_imaginary, String::new());
|
let result = KalkValue::Number(result_real, result_imaginary, None);
|
||||||
let (h_real, h_imaginary, h_unit) = as_number_or_zero!(h);
|
let (h_real, h_imaginary, h_unit) = as_number_or_zero!(h);
|
||||||
|
|
||||||
Ok(result.mul_without_unit(&KalkValue::Number(
|
Ok(result.mul_without_unit(&KalkValue::Number(
|
||||||
@ -219,7 +228,7 @@ mod tests {
|
|||||||
let result = super::derive_func(
|
let result = super::derive_func(
|
||||||
&mut context,
|
&mut context,
|
||||||
&Identifier::from_full_name("f'"),
|
&Identifier::from_full_name("f'"),
|
||||||
KalkValue::Number(float!(2f64), float!(3f64), String::new()),
|
KalkValue::Number(float!(2f64), float!(3f64), None),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(cmp(result.to_f64(), -4.5f64) || cmp(result.to_f64(), -4.499999f64));
|
assert!(cmp(result.to_f64(), -4.5f64) || cmp(result.to_f64(), -4.499999f64));
|
||||||
@ -264,11 +273,7 @@ mod tests {
|
|||||||
let result = super::integrate(
|
let result = super::integrate(
|
||||||
&mut context,
|
&mut context,
|
||||||
&*literal(2f64),
|
&*literal(2f64),
|
||||||
&ast::build_literal_ast(&KalkValue::Number(
|
&ast::build_literal_ast(&KalkValue::Number(float!(3f64), float!(4f64), None)),
|
||||||
float!(3f64),
|
|
||||||
float!(4f64),
|
|
||||||
String::new(),
|
|
||||||
)),
|
|
||||||
&*binary(var("x"), Star, var("i")),
|
&*binary(var("x"), Star, var("i")),
|
||||||
"x",
|
"x",
|
||||||
)
|
)
|
||||||
|
@ -53,7 +53,7 @@ impl<'a> Context<'a> {
|
|||||||
Stmt::VarDecl(
|
Stmt::VarDecl(
|
||||||
Identifier::from_full_name("ans"),
|
Identifier::from_full_name("ans"),
|
||||||
Box::new(Expr::Unit(
|
Box::new(Expr::Unit(
|
||||||
num.get_unit().clone(),
|
num.get_unit().unwrap().to_string(),
|
||||||
Box::new(crate::ast::build_literal_ast(&num)),
|
Box::new(crate::ast::build_literal_ast(&num)),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
@ -103,13 +103,13 @@ fn eval_unit_decl_stmt() -> Result<KalkValue, CalcError> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<KalkValue, CalcError> {
|
fn eval_expr_stmt(context: &mut Context, expr: &Expr) -> Result<KalkValue, CalcError> {
|
||||||
eval_expr(context, expr, "")
|
eval_expr(context, expr, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn eval_expr(
|
pub(crate) fn eval_expr(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
|
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
|
||||||
@ -143,20 +143,25 @@ fn eval_binary_expr(
|
|||||||
left_expr: &Expr,
|
left_expr: &Expr,
|
||||||
op: &TokenKind,
|
op: &TokenKind,
|
||||||
right_expr: &Expr,
|
right_expr: &Expr,
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
if let TokenKind::ToKeyword = op {
|
if let TokenKind::ToKeyword = op {
|
||||||
// TODO: When the unit conversion function takes a Float instead of Expr,
|
// TODO: When the unit conversion function takes a Float instead of Expr,
|
||||||
// move this to the match statement further down.
|
// move this to the match statement further down.
|
||||||
if let Expr::Var(right_unit) = right_expr {
|
if let Expr::Var(right_unit) = right_expr {
|
||||||
let left_unit = eval_expr(context, left_expr, "")?.get_unit();
|
let left_unit = eval_expr(context, left_expr, None)?.get_unit().cloned();
|
||||||
return convert_unit(context, left_expr, &left_unit, &right_unit.full_name);
|
return convert_unit(
|
||||||
|
context,
|
||||||
|
left_expr,
|
||||||
|
left_unit.as_ref(),
|
||||||
|
Some(&right_unit.full_name),
|
||||||
|
);
|
||||||
// TODO: Avoid evaluating this twice.
|
// TODO: Avoid evaluating this twice.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let left = eval_expr(context, left_expr, "")?;
|
let left = eval_expr(context, left_expr, None)?;
|
||||||
let mut right = eval_expr(context, right_expr, "")?;
|
let mut right = eval_expr(context, right_expr, None)?;
|
||||||
if let Expr::Unary(TokenKind::Percent, _) = right_expr {
|
if let Expr::Unary(TokenKind::Percent, _) = right_expr {
|
||||||
right = right.mul(context, left.clone());
|
right = right.mul(context, left.clone());
|
||||||
if let TokenKind::Star = op {
|
if let TokenKind::Star = op {
|
||||||
@ -179,12 +184,12 @@ fn eval_binary_expr(
|
|||||||
TokenKind::LessOrEquals => left.less_or_equals(context, right),
|
TokenKind::LessOrEquals => left.less_or_equals(context, right),
|
||||||
TokenKind::And => left.and(&right),
|
TokenKind::And => left.and(&right),
|
||||||
TokenKind::Or => left.or(&right),
|
TokenKind::Or => left.or(&right),
|
||||||
_ => KalkValue::from(1),
|
_ => KalkValue::from(1f64),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !unit.is_empty() {
|
if unit.is_some() {
|
||||||
if let KalkValue::Number(real, imaginary, _) = result {
|
if let KalkValue::Number(real, imaginary, _) = result {
|
||||||
return Ok(KalkValue::Number(real, imaginary, unit.to_string()));
|
return Ok(KalkValue::Number(real, imaginary, unit.cloned()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -195,7 +200,7 @@ fn eval_unary_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
op: &TokenKind,
|
op: &TokenKind,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
let num = eval_expr(context, expr, unit)?;
|
let num = eval_expr(context, expr, unit)?;
|
||||||
|
|
||||||
@ -214,18 +219,29 @@ fn eval_unit_expr(
|
|||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
let angle_unit = &context.angle_unit.clone();
|
let angle_unit = &context.angle_unit.clone();
|
||||||
if (identifier == "rad" || identifier == "deg") && angle_unit != identifier {
|
if (identifier == "rad" || identifier == "deg") && angle_unit != identifier {
|
||||||
return convert_unit(context, expr, identifier, angle_unit);
|
return convert_unit(
|
||||||
|
context,
|
||||||
|
expr,
|
||||||
|
Some(&identifier.to_string()),
|
||||||
|
Some(angle_unit),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_expr(context, expr, identifier)
|
eval_expr(context, expr, Some(&identifier.to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert_unit(
|
pub fn convert_unit(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
from_unit: &str,
|
from_unit: Option<&String>,
|
||||||
to_unit: &str,
|
to_unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
|
let (from_unit, to_unit) = if let (Some(from_unit), Some(to_unit)) = (from_unit, to_unit) {
|
||||||
|
(from_unit, to_unit)
|
||||||
|
} else {
|
||||||
|
return Err(CalcError::InvalidUnit);
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(Stmt::UnitDecl(_, _, unit_def)) =
|
if let Some(Stmt::UnitDecl(_, _, unit_def)) =
|
||||||
context.symbol_table.get_unit(to_unit, from_unit).cloned()
|
context.symbol_table.get_unit(to_unit, from_unit).cloned()
|
||||||
{
|
{
|
||||||
@ -234,8 +250,8 @@ pub fn convert_unit(
|
|||||||
Box::new(expr.clone()),
|
Box::new(expr.clone()),
|
||||||
));
|
));
|
||||||
|
|
||||||
let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, "")?);
|
let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, None)?);
|
||||||
Ok(KalkValue::Number(real, imaginary, to_unit.into()))
|
Ok(KalkValue::Number(real, imaginary, Some(to_unit.clone())))
|
||||||
} else {
|
} else {
|
||||||
Err(CalcError::InvalidUnit)
|
Err(CalcError::InvalidUnit)
|
||||||
}
|
}
|
||||||
@ -244,7 +260,7 @@ pub fn convert_unit(
|
|||||||
fn eval_var_expr(
|
fn eval_var_expr(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
// If there is a constant with this name, return a literal expression with its value
|
// If there is a constant with this name, return a literal expression with its value
|
||||||
if let Some(value) = prelude::CONSTANTS.get(identifier.full_name.as_ref() as &str) {
|
if let Some(value) = prelude::CONSTANTS.get(identifier.full_name.as_ref() as &str) {
|
||||||
@ -277,12 +293,12 @@ fn eval_var_expr(
|
|||||||
fn eval_literal_expr(
|
fn eval_literal_expr(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
value: f64,
|
value: f64,
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
let mut float = float!(value);
|
let mut float = float!(value);
|
||||||
float.set_prec(context.precision);
|
float.set_prec(context.precision);
|
||||||
|
|
||||||
Ok(KalkValue::Number(float, float!(0), unit.to_string()))
|
Ok(KalkValue::Number(float, float!(0), unit.cloned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@ -290,7 +306,7 @@ fn eval_literal_expr(
|
|||||||
fn eval_literal_expr(
|
fn eval_literal_expr(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
value: f64,
|
value: f64,
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
Ok(KalkValue::Number(
|
Ok(KalkValue::Number(
|
||||||
float!(value),
|
float!(value),
|
||||||
@ -299,7 +315,11 @@ fn eval_literal_expr(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_group_expr(context: &mut Context, expr: &Expr, unit: &str) -> Result<KalkValue, CalcError> {
|
fn eval_group_expr(
|
||||||
|
context: &mut Context,
|
||||||
|
expr: &Expr,
|
||||||
|
unit: Option<&String>,
|
||||||
|
) -> Result<KalkValue, CalcError> {
|
||||||
eval_expr(context, expr, unit)
|
eval_expr(context, expr, unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,13 +327,13 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
identifier: &Identifier,
|
identifier: &Identifier,
|
||||||
expressions: &[Expr],
|
expressions: &[Expr],
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
// Prelude vector function
|
// Prelude vector function
|
||||||
if prelude::is_vector_func(&identifier.full_name) {
|
if prelude::is_vector_func(&identifier.full_name) {
|
||||||
let mut values = Vec::new();
|
let mut values = Vec::new();
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
let value = eval_expr(context, expression, "")?;
|
let value = eval_expr(context, expression, None)?;
|
||||||
if expressions.len() == 1 {
|
if expressions.len() == 1 {
|
||||||
if let KalkValue::Vector(internal_values) = value {
|
if let KalkValue::Vector(internal_values) = value {
|
||||||
values = internal_values;
|
values = internal_values;
|
||||||
@ -333,7 +353,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
// Prelude
|
// Prelude
|
||||||
let prelude_func = match expressions.len() {
|
let prelude_func = match expressions.len() {
|
||||||
1 => {
|
1 => {
|
||||||
let x = eval_expr(context, &expressions[0], "")?;
|
let x = eval_expr(context, &expressions[0], None)?;
|
||||||
if identifier.prime_count > 0 {
|
if identifier.prime_count > 0 {
|
||||||
return calculus::derive_func(context, identifier, x);
|
return calculus::derive_func(context, identifier, x);
|
||||||
} else {
|
} else {
|
||||||
@ -346,8 +366,8 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
2 => {
|
2 => {
|
||||||
let x = eval_expr(context, &expressions[0], "")?;
|
let x = eval_expr(context, &expressions[0], None)?;
|
||||||
let y = eval_expr(context, &expressions[1], "")?;
|
let y = eval_expr(context, &expressions[1], None)?;
|
||||||
prelude::call_binary_func(
|
prelude::call_binary_func(
|
||||||
context,
|
context,
|
||||||
&identifier.full_name,
|
&identifier.full_name,
|
||||||
@ -363,7 +383,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
// If the result is nan and only one argument was given,
|
// If the result is nan and only one argument was given,
|
||||||
// it may be due to incompatible types.
|
// it may be due to incompatible types.
|
||||||
if result.is_nan() && expressions.len() == 1 {
|
if result.is_nan() && expressions.len() == 1 {
|
||||||
let x = eval_expr(context, &expressions[0], "")?;
|
let x = eval_expr(context, &expressions[0], None)?;
|
||||||
|
|
||||||
// If a vector/matrix was given, call the function on every item
|
// If a vector/matrix was given, call the function on every item
|
||||||
// in the vector/matrix.
|
// in the vector/matrix.
|
||||||
@ -453,8 +473,8 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = eval_expr(context, start_expr, "")?.to_f64() as i128;
|
let start = eval_expr(context, start_expr, None)?.to_f64() as i128;
|
||||||
let end = eval_expr(context, &expressions[1], "")?.to_f64() as i128;
|
let end = eval_expr(context, &expressions[1], None)?.to_f64() as i128;
|
||||||
let sum_else_prod = match identifier.full_name.as_ref() {
|
let sum_else_prod = match identifier.full_name.as_ref() {
|
||||||
"sum" => true,
|
"sum" => true,
|
||||||
"prod" => false,
|
"prod" => false,
|
||||||
@ -470,7 +490,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
let sum_variables = context.sum_variables.as_mut().unwrap();
|
let sum_variables = context.sum_variables.as_mut().unwrap();
|
||||||
sum_variables.last_mut().unwrap().value = n;
|
sum_variables.last_mut().unwrap().value = n;
|
||||||
|
|
||||||
let eval = eval_expr(context, &expressions[2], "")?;
|
let eval = eval_expr(context, &expressions[2], None)?;
|
||||||
if sum_else_prod {
|
if sum_else_prod {
|
||||||
sum = sum.add(context, eval);
|
sum = sum.add(context, eval);
|
||||||
} else {
|
} else {
|
||||||
@ -484,7 +504,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
let (sum_real, sum_imaginary, _) = as_number_or_zero!(sum);
|
let (sum_real, sum_imaginary, _) = as_number_or_zero!(sum);
|
||||||
|
|
||||||
// Set the unit as well
|
// Set the unit as well
|
||||||
return Ok(KalkValue::Number(sum_real, sum_imaginary, unit.to_string()));
|
return Ok(KalkValue::Number(sum_real, sum_imaginary, unit.cloned()));
|
||||||
}
|
}
|
||||||
"integrate" => {
|
"integrate" => {
|
||||||
return match expressions.len() {
|
return match expressions.len() {
|
||||||
@ -542,7 +562,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
Box::new(crate::ast::build_literal_ast(&eval_expr(
|
Box::new(crate::ast::build_literal_ast(&eval_expr(
|
||||||
context,
|
context,
|
||||||
&expressions[i],
|
&expressions[i],
|
||||||
"",
|
None,
|
||||||
)?)),
|
)?)),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -581,7 +601,7 @@ pub(crate) fn eval_fn_call_expr(
|
|||||||
fn eval_piecewise(
|
fn eval_piecewise(
|
||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
pieces: &[crate::ast::ConditionalPiece],
|
pieces: &[crate::ast::ConditionalPiece],
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
for piece in pieces {
|
for piece in pieces {
|
||||||
if let KalkValue::Boolean(condition_is_true) = eval_expr(context, &piece.condition, unit)? {
|
if let KalkValue::Boolean(condition_is_true) = eval_expr(context, &piece.condition, unit)? {
|
||||||
@ -597,7 +617,7 @@ fn eval_piecewise(
|
|||||||
fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, CalcError> {
|
fn eval_vector(context: &mut Context, values: &[Expr]) -> Result<KalkValue, CalcError> {
|
||||||
let mut eval_values = Vec::new();
|
let mut eval_values = Vec::new();
|
||||||
for value in values {
|
for value in values {
|
||||||
eval_values.push(eval_expr(context, value, "")?);
|
eval_values.push(eval_expr(context, value, None)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(KalkValue::Vector(eval_values))
|
Ok(KalkValue::Vector(eval_values))
|
||||||
@ -608,7 +628,7 @@ fn eval_matrix(context: &mut Context, rows: &[Vec<Expr>]) -> Result<KalkValue, C
|
|||||||
for row in rows {
|
for row in rows {
|
||||||
let mut eval_row = Vec::new();
|
let mut eval_row = Vec::new();
|
||||||
for value in row {
|
for value in row {
|
||||||
eval_row.push(eval_expr(context, value, "")?)
|
eval_row.push(eval_expr(context, value, None)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
eval_rows.push(eval_row);
|
eval_rows.push(eval_row);
|
||||||
@ -621,7 +641,7 @@ fn eval_indexer(
|
|||||||
context: &mut Context,
|
context: &mut Context,
|
||||||
var: &Expr,
|
var: &Expr,
|
||||||
index_expressions: &[Expr],
|
index_expressions: &[Expr],
|
||||||
unit: &str,
|
unit: Option<&String>,
|
||||||
) -> Result<KalkValue, CalcError> {
|
) -> Result<KalkValue, CalcError> {
|
||||||
let var_value = eval_expr(context, var, unit)?;
|
let var_value = eval_expr(context, var, unit)?;
|
||||||
match var_value {
|
match var_value {
|
||||||
@ -682,7 +702,7 @@ fn eval_indexer(
|
|||||||
fn as_indices(context: &mut Context, expressions: &[Expr]) -> Result<Vec<usize>, CalcError> {
|
fn as_indices(context: &mut Context, expressions: &[Expr]) -> Result<Vec<usize>, CalcError> {
|
||||||
let mut indices = Vec::new();
|
let mut indices = Vec::new();
|
||||||
for expr in expressions {
|
for expr in expressions {
|
||||||
let value = eval_expr(context, expr, "")?;
|
let value = eval_expr(context, expr, None)?;
|
||||||
if value.has_imaginary() {
|
if value.has_imaginary() {
|
||||||
return Err(CalcError::CannotIndexByImaginary);
|
return Err(CalcError::CannotIndexByImaginary);
|
||||||
}
|
}
|
||||||
@ -715,8 +735,8 @@ fn eval_comprehension(
|
|||||||
Box::new(Expr::Literal(0f64)),
|
Box::new(Expr::Literal(0f64)),
|
||||||
));
|
));
|
||||||
|
|
||||||
let min = eval_expr(context, &var.min, "")?.to_f64() as i32;
|
let min = eval_expr(context, &var.min, None)?.to_f64() as i32;
|
||||||
let max = eval_expr(context, &var.max, "")?.to_f64() as i32;
|
let max = eval_expr(context, &var.max, None)?.to_f64() as i32;
|
||||||
|
|
||||||
let mut values = Vec::new();
|
let mut values = Vec::new();
|
||||||
for i in min..max {
|
for i in min..max {
|
||||||
@ -732,10 +752,10 @@ fn eval_comprehension(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let condition = eval_expr(context, condition, "")?;
|
let condition = eval_expr(context, condition, None)?;
|
||||||
if let KalkValue::Boolean(boolean) = condition {
|
if let KalkValue::Boolean(boolean) = condition {
|
||||||
if boolean && vars.len() == 1 {
|
if boolean && vars.len() == 1 {
|
||||||
values.push(eval_expr(context, left, "")?);
|
values.push(eval_expr(context, left, None)?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -800,7 +820,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "rug"))]
|
#[cfg(not(feature = "rug"))]
|
||||||
fn context<'a>(symbol_table: &'a mut SymbolTable, angle_unit: &str) -> Context<'a> {
|
fn context<'a>(symbol_table: &'a mut SymbolTable, angle_unit: Option<&String>) -> Context<'a> {
|
||||||
Context::new(symbol_table, angle_unit, None)
|
Context::new(symbol_table, angle_unit, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ macro_rules! as_number_or_zero {
|
|||||||
if let KalkValue::Number(real, imaginary, unit) = $x {
|
if let KalkValue::Number(real, imaginary, unit) = $x {
|
||||||
(real, imaginary, unit)
|
(real, imaginary, unit)
|
||||||
} else {
|
} else {
|
||||||
(float!(0), float!(0), String::new())
|
(float!(0), float!(0), None)
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@ -145,9 +145,9 @@ impl std::fmt::Display for ScientificNotation {
|
|||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
pub enum KalkValue {
|
pub enum KalkValue {
|
||||||
#[cfg(not(feature = "rug"))]
|
#[cfg(not(feature = "rug"))]
|
||||||
Number(f64, f64, String),
|
Number(f64, f64, Option<String>),
|
||||||
#[cfg(feature = "rug")]
|
#[cfg(feature = "rug")]
|
||||||
Number(Float, Float, String),
|
Number(Float, Float, Option<String>),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Vector(Vec<KalkValue>),
|
Vector(Vec<KalkValue>),
|
||||||
Matrix(Vec<Vec<KalkValue>>),
|
Matrix(Vec<Vec<KalkValue>>),
|
||||||
@ -227,7 +227,7 @@ impl std::fmt::Display for KalkValue {
|
|||||||
|
|
||||||
impl KalkValue {
|
impl KalkValue {
|
||||||
pub fn nan() -> Self {
|
pub fn nan() -> Self {
|
||||||
KalkValue::Number(float!(f64::NAN), float!(0f64), String::new())
|
KalkValue::Number(float!(f64::NAN), float!(0f64), None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string_big(&self) -> String {
|
pub fn to_string_big(&self) -> String {
|
||||||
@ -325,7 +325,7 @@ impl KalkValue {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !unit.is_empty() {
|
if let Some(unit) = unit {
|
||||||
output.push_str(&format!(" {}", unit));
|
output.push_str(&format!(" {}", unit));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,7 +346,9 @@ impl KalkValue {
|
|||||||
|
|
||||||
pub fn to_string_with_unit(&self) -> String {
|
pub fn to_string_with_unit(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
KalkValue::Number(_, _, unit) => format!("{} {}", self, unit),
|
KalkValue::Number(_, _, unit) => {
|
||||||
|
format!("{} {}", self, unit.as_ref().unwrap_or(&String::new()))
|
||||||
|
}
|
||||||
_ => self.to_string(),
|
_ => self.to_string(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -432,7 +434,7 @@ impl KalkValue {
|
|||||||
} else {
|
} else {
|
||||||
original_imaginary.clone()
|
original_imaginary.clone()
|
||||||
},
|
},
|
||||||
unit.to_string(),
|
unit.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,17 +491,17 @@ impl KalkValue {
|
|||||||
|
|
||||||
pub fn has_unit(&self) -> bool {
|
pub fn has_unit(&self) -> bool {
|
||||||
if let KalkValue::Number(_, _, unit) = self {
|
if let KalkValue::Number(_, _, unit) = self {
|
||||||
!unit.is_empty()
|
unit.is_some()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_unit(&self) -> String {
|
pub fn get_unit(&self) -> Option<&String> {
|
||||||
if let KalkValue::Number(_, _, unit) = self {
|
if let KalkValue::Number(_, _, unit) = self {
|
||||||
unit.to_string()
|
unit.as_ref()
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,8 +514,8 @@ impl KalkValue {
|
|||||||
let result = crate::interpreter::convert_unit(
|
let result = crate::interpreter::convert_unit(
|
||||||
context,
|
context,
|
||||||
&Expr::Literal(primitive!(real)),
|
&Expr::Literal(primitive!(real)),
|
||||||
unit,
|
unit.as_ref(),
|
||||||
to_unit,
|
Some(&to_unit.to_string()),
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Ok(num) = result {
|
if let Ok(num) = result {
|
||||||
@ -675,7 +677,7 @@ impl KalkValue {
|
|||||||
(
|
(
|
||||||
KalkValue::Number(real, imaginary, _),
|
KalkValue::Number(real, imaginary, _),
|
||||||
KalkValue::Number(real_rhs, imaginary_rhs, unit),
|
KalkValue::Number(real_rhs, imaginary_rhs, unit),
|
||||||
) => KalkValue::Number(real + real_rhs, imaginary + imaginary_rhs, unit.to_string()),
|
) => KalkValue::Number(real + real_rhs, imaginary + imaginary_rhs, unit.clone()),
|
||||||
(KalkValue::Matrix(_), _) | (_, KalkValue::Matrix(_)) => {
|
(KalkValue::Matrix(_), _) | (_, KalkValue::Matrix(_)) => {
|
||||||
calculate_matrix(self, rhs, &KalkValue::add_without_unit)
|
calculate_matrix(self, rhs, &KalkValue::add_without_unit)
|
||||||
}
|
}
|
||||||
@ -691,7 +693,7 @@ impl KalkValue {
|
|||||||
(
|
(
|
||||||
KalkValue::Number(real, imaginary, _),
|
KalkValue::Number(real, imaginary, _),
|
||||||
KalkValue::Number(real_rhs, imaginary_rhs, unit),
|
KalkValue::Number(real_rhs, imaginary_rhs, unit),
|
||||||
) => KalkValue::Number(real - real_rhs, imaginary - imaginary_rhs, unit.to_string()),
|
) => KalkValue::Number(real - real_rhs, imaginary - imaginary_rhs, unit.clone()),
|
||||||
(KalkValue::Matrix(_), _) | (_, KalkValue::Matrix(_)) => {
|
(KalkValue::Matrix(_), _) | (_, KalkValue::Matrix(_)) => {
|
||||||
calculate_matrix(self, rhs, &KalkValue::sub_without_unit)
|
calculate_matrix(self, rhs, &KalkValue::sub_without_unit)
|
||||||
}
|
}
|
||||||
@ -719,7 +721,7 @@ impl KalkValue {
|
|||||||
// (a + bi)(c + di) = ac + adi + bci + bdi²
|
// (a + bi)(c + di) = ac + adi + bci + bdi²
|
||||||
real.clone() * real_rhs - imaginary.clone() * imaginary_rhs,
|
real.clone() * real_rhs - imaginary.clone() * imaginary_rhs,
|
||||||
real.clone() * imaginary_rhs + imaginary * real_rhs,
|
real.clone() * imaginary_rhs + imaginary * real_rhs,
|
||||||
unit.to_string(),
|
unit.clone(),
|
||||||
),
|
),
|
||||||
(KalkValue::Matrix(rows), KalkValue::Number(_, _, _)) => KalkValue::Matrix(
|
(KalkValue::Matrix(rows), KalkValue::Number(_, _, _)) => KalkValue::Matrix(
|
||||||
rows.iter()
|
rows.iter()
|
||||||
@ -849,10 +851,10 @@ impl KalkValue {
|
|||||||
KalkValue::Number(
|
KalkValue::Number(
|
||||||
polar.clone().cos() * exp.clone(),
|
polar.clone().cos() * exp.clone(),
|
||||||
polar.sin() * exp,
|
polar.sin() * exp,
|
||||||
unit.to_string(),
|
unit.clone(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
KalkValue::Number(pow(real, real_rhs.clone()), float!(0), unit.to_string())
|
KalkValue::Number(pow(real, real_rhs.clone()), float!(0), unit.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(KalkValue::Matrix(rows), KalkValue::Number(real, imaginary, _)) => {
|
(KalkValue::Matrix(rows), KalkValue::Number(real, imaginary, _)) => {
|
||||||
@ -1107,12 +1109,12 @@ fn calculate_unit(
|
|||||||
(left, &right)
|
(left, &right)
|
||||||
{
|
{
|
||||||
if left.has_unit() && right.has_unit() {
|
if left.has_unit() && right.has_unit() {
|
||||||
right.convert_to_unit(context, unit_left)
|
right.convert_to_unit(context, unit_left.as_ref().unwrap())
|
||||||
} else {
|
} else {
|
||||||
Some(KalkValue::Number(
|
Some(KalkValue::Number(
|
||||||
real_right.clone(),
|
real_right.clone(),
|
||||||
imaginary_right.clone(),
|
imaginary_right.clone(),
|
||||||
unit_left.to_string(),
|
unit_left.clone(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1165,31 +1167,31 @@ impl From<KalkValue> for f64 {
|
|||||||
|
|
||||||
impl From<f64> for KalkValue {
|
impl From<f64> for KalkValue {
|
||||||
fn from(x: f64) -> Self {
|
fn from(x: f64) -> Self {
|
||||||
KalkValue::Number(float!(x), float!(0), String::new())
|
KalkValue::Number(float!(x), float!(0), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<f32> for KalkValue {
|
impl From<f32> for KalkValue {
|
||||||
fn from(x: f32) -> Self {
|
fn from(x: f32) -> Self {
|
||||||
KalkValue::Number(float!(x), float!(0), String::new())
|
KalkValue::Number(float!(x), float!(0), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i128> for KalkValue {
|
impl From<i128> for KalkValue {
|
||||||
fn from(x: i128) -> Self {
|
fn from(x: i128) -> Self {
|
||||||
KalkValue::Number(float!(x), float!(0), String::new())
|
KalkValue::Number(float!(x), float!(0), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i64> for KalkValue {
|
impl From<i64> for KalkValue {
|
||||||
fn from(x: i64) -> Self {
|
fn from(x: i64) -> Self {
|
||||||
KalkValue::Number(float!(x), float!(0), String::new())
|
KalkValue::Number(float!(x), float!(0), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<i32> for KalkValue {
|
impl From<i32> for KalkValue {
|
||||||
fn from(x: i32) -> Self {
|
fn from(x: i32) -> Self {
|
||||||
KalkValue::Number(float!(x), float!(0), String::new())
|
KalkValue::Number(float!(x), float!(0), None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1208,8 +1210,8 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (a, b, expected_result) in in_out {
|
for (a, b, expected_result) in in_out {
|
||||||
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
|
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), None)
|
||||||
.add_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
|
.add_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), None));
|
||||||
assert_eq!(actual_result.to_f64(), expected_result.0);
|
assert_eq!(actual_result.to_f64(), expected_result.0);
|
||||||
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
||||||
}
|
}
|
||||||
@ -1225,8 +1227,8 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (a, b, expected_result) in in_out {
|
for (a, b, expected_result) in in_out {
|
||||||
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
|
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), None)
|
||||||
.sub_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
|
.sub_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), None));
|
||||||
assert_eq!(actual_result.to_f64(), expected_result.0);
|
assert_eq!(actual_result.to_f64(), expected_result.0);
|
||||||
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
||||||
}
|
}
|
||||||
@ -1242,8 +1244,8 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (a, b, expected_result) in in_out {
|
for (a, b, expected_result) in in_out {
|
||||||
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
|
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), None)
|
||||||
.mul_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
|
.mul_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), None));
|
||||||
assert_eq!(actual_result.to_f64(), expected_result.0);
|
assert_eq!(actual_result.to_f64(), expected_result.0);
|
||||||
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
||||||
}
|
}
|
||||||
@ -1258,8 +1260,8 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (a, b, expected_result) in in_out {
|
for (a, b, expected_result) in in_out {
|
||||||
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
|
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), None)
|
||||||
.div_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
|
.div_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), None));
|
||||||
assert_eq!(actual_result.to_f64(), expected_result.0);
|
assert_eq!(actual_result.to_f64(), expected_result.0);
|
||||||
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
|
||||||
}
|
}
|
||||||
@ -1286,8 +1288,8 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (a, b, expected_result) in in_out {
|
for (a, b, expected_result) in in_out {
|
||||||
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
|
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), None)
|
||||||
.pow_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
|
.pow_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), None));
|
||||||
assert!(cmp(actual_result.to_f64(), expected_result.0));
|
assert!(cmp(actual_result.to_f64(), expected_result.0));
|
||||||
assert!(cmp(actual_result.imaginary_to_f64(), expected_result.1));
|
assert!(cmp(actual_result.imaginary_to_f64(), expected_result.1));
|
||||||
}
|
}
|
||||||
@ -1320,8 +1322,8 @@ mod tests {
|
|||||||
(3.00000000004, 0.0, "3"),
|
(3.00000000004, 0.0, "3"),
|
||||||
];
|
];
|
||||||
for (real, imaginary, output) in in_out {
|
for (real, imaginary, output) in in_out {
|
||||||
let result = KalkValue::Number(float!(real), float!(imaginary), String::new())
|
let result =
|
||||||
.to_string_pretty();
|
KalkValue::Number(float!(real), float!(imaginary), None).to_string_pretty();
|
||||||
assert_eq!(output, result);
|
assert_eq!(output, result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,7 +240,7 @@ fn equivalent_root(value: f64) -> Option<String> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let squared = KalkValue::Number(float!(value * value), float!(0), String::new())
|
let squared = KalkValue::Number(float!(value * value), float!(0), None)
|
||||||
.round_if_needed()
|
.round_if_needed()
|
||||||
.values()
|
.values()
|
||||||
.0;
|
.0;
|
||||||
@ -282,10 +282,10 @@ pub(super) fn round(
|
|||||||
let new_value = integer * sign;
|
let new_value = integer * sign;
|
||||||
let new_num = match complex_number_type {
|
let new_num = match complex_number_type {
|
||||||
ComplexNumberType::Real => {
|
ComplexNumberType::Real => {
|
||||||
KalkValue::Number(new_value, imaginary.clone(), input.get_unit())
|
KalkValue::Number(new_value, imaginary.clone(), input.get_unit().cloned())
|
||||||
}
|
}
|
||||||
ComplexNumberType::Imaginary => {
|
ComplexNumberType::Imaginary => {
|
||||||
KalkValue::Number(real.clone(), new_value, input.get_unit())
|
KalkValue::Number(real.clone(), new_value, input.get_unit().cloned())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -296,10 +296,10 @@ pub(super) fn round(
|
|||||||
let new_value = value.clone().abs().ceil() * sign;
|
let new_value = value.clone().abs().ceil() * sign;
|
||||||
let new_num = match complex_number_type {
|
let new_num = match complex_number_type {
|
||||||
ComplexNumberType::Real => {
|
ComplexNumberType::Real => {
|
||||||
KalkValue::Number(new_value, imaginary.clone(), input.get_unit())
|
KalkValue::Number(new_value, imaginary.clone(), input.get_unit().cloned())
|
||||||
}
|
}
|
||||||
ComplexNumberType::Imaginary => {
|
ComplexNumberType::Imaginary => {
|
||||||
KalkValue::Number(real.clone(), new_value, input.get_unit())
|
KalkValue::Number(real.clone(), new_value, input.get_unit().cloned())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -232,7 +232,12 @@ pub fn call_vector_func(name: &str, x: KalkValue) -> Option<KalkValue> {
|
|||||||
fn to_angle_unit(context: &mut interpreter::Context, x: KalkValue, angle_unit: &str) -> KalkValue {
|
fn to_angle_unit(context: &mut interpreter::Context, x: KalkValue, angle_unit: &str) -> KalkValue {
|
||||||
match angle_unit {
|
match angle_unit {
|
||||||
"rad" => x,
|
"rad" => x,
|
||||||
_ => interpreter::convert_unit(context, &Expr::Literal(x.to_f64()), "rad", angle_unit)
|
_ => interpreter::convert_unit(
|
||||||
|
context,
|
||||||
|
&Expr::Literal(x.to_f64()),
|
||||||
|
Some(&String::from("rad")),
|
||||||
|
Some(&angle_unit.to_string()),
|
||||||
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,7 +249,12 @@ fn from_angle_unit(
|
|||||||
) -> KalkValue {
|
) -> KalkValue {
|
||||||
match angle_unit {
|
match angle_unit {
|
||||||
"rad" => x,
|
"rad" => x,
|
||||||
_ => interpreter::convert_unit(context, &Expr::Literal(x.to_f64()), angle_unit, "rad")
|
_ => interpreter::convert_unit(
|
||||||
|
context,
|
||||||
|
&Expr::Literal(x.to_f64()),
|
||||||
|
Some(&angle_unit.to_string()),
|
||||||
|
Some(&String::from("rad")),
|
||||||
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -478,8 +488,7 @@ pub mod funcs {
|
|||||||
sum_imaginary += imaginary;
|
sum_imaginary += imaginary;
|
||||||
}
|
}
|
||||||
|
|
||||||
KalkValue::Number(sum_real, sum_imaginary, String::new())
|
KalkValue::Number(sum_real, sum_imaginary, None).div_without_unit(&KalkValue::from(count))
|
||||||
.div_without_unit(&KalkValue::from(count))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cbrt(x: KalkValue) -> KalkValue {
|
pub fn cbrt(x: KalkValue) -> KalkValue {
|
||||||
@ -1011,11 +1020,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
|
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
|
||||||
let actual_output = func(KalkValue::Number(
|
let actual_output = func(KalkValue::Number(float!(input.0), float!(input.1), None));
|
||||||
float!(input.0),
|
|
||||||
float!(input.1),
|
|
||||||
String::new(),
|
|
||||||
));
|
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{} | expected: {}, {}",
|
"{} | expected: {}, {}",
|
||||||
@ -1051,8 +1056,8 @@ mod tests {
|
|||||||
|
|
||||||
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
|
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
|
||||||
let actual_output = func(
|
let actual_output = func(
|
||||||
KalkValue::Number(float!(input.0 .0), float!(input.0 .1), String::new()),
|
KalkValue::Number(float!(input.0 .0), float!(input.0 .1), None),
|
||||||
KalkValue::Number(float!(input.1 .0), float!(input.1 .1), String::new()),
|
KalkValue::Number(float!(input.1 .0), float!(input.1 .1), None),
|
||||||
);
|
);
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
@ -1360,11 +1365,7 @@ mod tests {
|
|||||||
];
|
];
|
||||||
|
|
||||||
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
|
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
|
||||||
let actual_output = func(KalkValue::Number(
|
let actual_output = func(KalkValue::Number(float!(input.0), float!(input.1), None));
|
||||||
float!(input.0),
|
|
||||||
float!(input.1),
|
|
||||||
String::new(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let expected_has_nan_or_inf = expected_output.0.is_nan()
|
let expected_has_nan_or_inf = expected_output.0.is_nan()
|
||||||
|| expected_output.0.is_infinite()
|
|| expected_output.0.is_infinite()
|
||||||
|
Loading…
Reference in New Issue
Block a user