Made unit field Optional in KalkValue

This commit is contained in:
bakk 2022-01-23 01:16:34 +01:00
parent 8f7726eab5
commit e10f129706
5 changed files with 147 additions and 119 deletions

View File

@ -15,15 +15,24 @@ pub fn derive_func(
argument: KalkValue,
) -> Result<KalkValue, CalcError> {
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_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 f_x_h = interpreter::eval_fn_call_expr(context, &new_identifier, &[argument_with_h], unit)?;
let f_x =
interpreter::eval_fn_call_expr(context, &new_identifier, &[argument_without_h], unit)?;
let f_x_h = interpreter::eval_fn_call_expr(
context,
&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
.sub_without_unit(&f_x)
@ -87,8 +96,8 @@ fn simpsons_rule(
.get_and_remove_var(integration_variable);
const N: i32 = 900;
let a = interpreter::eval_expr(context, a_expr, "")?;
let b = interpreter::eval_expr(context, b_expr, "")?;
let a = interpreter::eval_expr(context, a_expr, None)?;
let b = interpreter::eval_expr(context, b_expr, None)?;
let h = (b.sub_without_unit(&a)).div_without_unit(&KalkValue::from(N));
for i in 0..=N {
let variable_value = a
@ -103,11 +112,11 @@ fn simpsons_rule(
0 | N => 1,
_ if i % 3 == 0 => 2,
_ => 3,
});
} as f64);
// factor * f(x_n)
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_imaginary += mul_imaginary;
@ -121,7 +130,7 @@ fn simpsons_rule(
.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);
Ok(result.mul_without_unit(&KalkValue::Number(
@ -219,7 +228,7 @@ mod tests {
let result = super::derive_func(
&mut context,
&Identifier::from_full_name("f'"),
KalkValue::Number(float!(2f64), float!(3f64), String::new()),
KalkValue::Number(float!(2f64), float!(3f64), None),
)
.unwrap();
assert!(cmp(result.to_f64(), -4.5f64) || cmp(result.to_f64(), -4.499999f64));
@ -264,11 +273,7 @@ mod tests {
let result = super::integrate(
&mut context,
&*literal(2f64),
&ast::build_literal_ast(&KalkValue::Number(
float!(3f64),
float!(4f64),
String::new(),
)),
&ast::build_literal_ast(&KalkValue::Number(float!(3f64), float!(4f64), None)),
&*binary(var("x"), Star, var("i")),
"x",
)

View File

@ -53,7 +53,7 @@ impl<'a> Context<'a> {
Stmt::VarDecl(
Identifier::from_full_name("ans"),
Box::new(Expr::Unit(
num.get_unit().clone(),
num.get_unit().unwrap().to_string(),
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> {
eval_expr(context, expr, "")
eval_expr(context, expr, None)
}
pub(crate) fn eval_expr(
context: &mut Context,
expr: &Expr,
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
#[cfg(not(target_arch = "wasm32"))]
if let (Ok(elapsed), Some(timeout)) = (context.start_time.elapsed(), context.timeout) {
@ -143,20 +143,25 @@ fn eval_binary_expr(
left_expr: &Expr,
op: &TokenKind,
right_expr: &Expr,
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
if let TokenKind::ToKeyword = op {
// TODO: When the unit conversion function takes a Float instead of Expr,
// move this to the match statement further down.
if let Expr::Var(right_unit) = right_expr {
let left_unit = eval_expr(context, left_expr, "")?.get_unit();
return convert_unit(context, left_expr, &left_unit, &right_unit.full_name);
let left_unit = eval_expr(context, left_expr, None)?.get_unit().cloned();
return convert_unit(
context,
left_expr,
left_unit.as_ref(),
Some(&right_unit.full_name),
);
// TODO: Avoid evaluating this twice.
}
}
let left = eval_expr(context, left_expr, "")?;
let mut right = eval_expr(context, right_expr, "")?;
let left = eval_expr(context, left_expr, None)?;
let mut right = eval_expr(context, right_expr, None)?;
if let Expr::Unary(TokenKind::Percent, _) = right_expr {
right = right.mul(context, left.clone());
if let TokenKind::Star = op {
@ -179,12 +184,12 @@ fn eval_binary_expr(
TokenKind::LessOrEquals => left.less_or_equals(context, right),
TokenKind::And => left.and(&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 {
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,
op: &TokenKind,
expr: &Expr,
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
let num = eval_expr(context, expr, unit)?;
@ -214,18 +219,29 @@ fn eval_unit_expr(
) -> Result<KalkValue, CalcError> {
let angle_unit = &context.angle_unit.clone();
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(
context: &mut Context,
expr: &Expr,
from_unit: &str,
to_unit: &str,
from_unit: Option<&String>,
to_unit: Option<&String>,
) -> 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)) =
context.symbol_table.get_unit(to_unit, from_unit).cloned()
{
@ -234,8 +250,8 @@ pub fn convert_unit(
Box::new(expr.clone()),
));
let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, "")?);
Ok(KalkValue::Number(real, imaginary, to_unit.into()))
let (real, imaginary, _) = as_number_or_zero!(eval_expr(context, &unit_def, None)?);
Ok(KalkValue::Number(real, imaginary, Some(to_unit.clone())))
} else {
Err(CalcError::InvalidUnit)
}
@ -244,7 +260,7 @@ pub fn convert_unit(
fn eval_var_expr(
context: &mut Context,
identifier: &Identifier,
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
// 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) {
@ -277,12 +293,12 @@ fn eval_var_expr(
fn eval_literal_expr(
context: &mut Context,
value: f64,
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
let mut float = float!(value);
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)]
@ -290,7 +306,7 @@ fn eval_literal_expr(
fn eval_literal_expr(
context: &mut Context,
value: f64,
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
Ok(KalkValue::Number(
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)
}
@ -307,13 +327,13 @@ pub(crate) fn eval_fn_call_expr(
context: &mut Context,
identifier: &Identifier,
expressions: &[Expr],
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
// Prelude vector function
if prelude::is_vector_func(&identifier.full_name) {
let mut values = Vec::new();
for expression in expressions {
let value = eval_expr(context, expression, "")?;
let value = eval_expr(context, expression, None)?;
if expressions.len() == 1 {
if let KalkValue::Vector(internal_values) = value {
values = internal_values;
@ -333,7 +353,7 @@ pub(crate) fn eval_fn_call_expr(
// Prelude
let prelude_func = match expressions.len() {
1 => {
let x = eval_expr(context, &expressions[0], "")?;
let x = eval_expr(context, &expressions[0], None)?;
if identifier.prime_count > 0 {
return calculus::derive_func(context, identifier, x);
} else {
@ -346,8 +366,8 @@ pub(crate) fn eval_fn_call_expr(
}
}
2 => {
let x = eval_expr(context, &expressions[0], "")?;
let y = eval_expr(context, &expressions[1], "")?;
let x = eval_expr(context, &expressions[0], None)?;
let y = eval_expr(context, &expressions[1], None)?;
prelude::call_binary_func(
context,
&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,
// it may be due to incompatible types.
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
// 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 end = eval_expr(context, &expressions[1], "")?.to_f64() as i128;
let start = eval_expr(context, start_expr, None)?.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() {
"sum" => true,
"prod" => false,
@ -470,7 +490,7 @@ pub(crate) fn eval_fn_call_expr(
let sum_variables = context.sum_variables.as_mut().unwrap();
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 {
sum = sum.add(context, eval);
} else {
@ -484,7 +504,7 @@ pub(crate) fn eval_fn_call_expr(
let (sum_real, sum_imaginary, _) = as_number_or_zero!(sum);
// 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" => {
return match expressions.len() {
@ -542,7 +562,7 @@ pub(crate) fn eval_fn_call_expr(
Box::new(crate::ast::build_literal_ast(&eval_expr(
context,
&expressions[i],
"",
None,
)?)),
);
@ -581,7 +601,7 @@ pub(crate) fn eval_fn_call_expr(
fn eval_piecewise(
context: &mut Context,
pieces: &[crate::ast::ConditionalPiece],
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
for piece in pieces {
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> {
let mut eval_values = Vec::new();
for value in values {
eval_values.push(eval_expr(context, value, "")?);
eval_values.push(eval_expr(context, value, None)?);
}
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 {
let mut eval_row = Vec::new();
for value in row {
eval_row.push(eval_expr(context, value, "")?)
eval_row.push(eval_expr(context, value, None)?)
}
eval_rows.push(eval_row);
@ -621,7 +641,7 @@ fn eval_indexer(
context: &mut Context,
var: &Expr,
index_expressions: &[Expr],
unit: &str,
unit: Option<&String>,
) -> Result<KalkValue, CalcError> {
let var_value = eval_expr(context, var, unit)?;
match var_value {
@ -682,7 +702,7 @@ fn eval_indexer(
fn as_indices(context: &mut Context, expressions: &[Expr]) -> Result<Vec<usize>, CalcError> {
let mut indices = Vec::new();
for expr in expressions {
let value = eval_expr(context, expr, "")?;
let value = eval_expr(context, expr, None)?;
if value.has_imaginary() {
return Err(CalcError::CannotIndexByImaginary);
}
@ -715,8 +735,8 @@ fn eval_comprehension(
Box::new(Expr::Literal(0f64)),
));
let min = eval_expr(context, &var.min, "")?.to_f64() as i32;
let max = eval_expr(context, &var.max, "")?.to_f64() as i32;
let min = eval_expr(context, &var.min, None)?.to_f64() as i32;
let max = eval_expr(context, &var.max, None)?.to_f64() as i32;
let mut values = Vec::new();
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 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"))]
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)
}

View File

@ -93,7 +93,7 @@ macro_rules! as_number_or_zero {
if let KalkValue::Number(real, imaginary, unit) = $x {
(real, imaginary, unit)
} 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)]
pub enum KalkValue {
#[cfg(not(feature = "rug"))]
Number(f64, f64, String),
Number(f64, f64, Option<String>),
#[cfg(feature = "rug")]
Number(Float, Float, String),
Number(Float, Float, Option<String>),
Boolean(bool),
Vector(Vec<KalkValue>),
Matrix(Vec<Vec<KalkValue>>),
@ -227,7 +227,7 @@ impl std::fmt::Display for KalkValue {
impl KalkValue {
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 {
@ -325,7 +325,7 @@ impl KalkValue {
}
}
if !unit.is_empty() {
if let Some(unit) = unit {
output.push_str(&format!(" {}", unit));
}
@ -346,7 +346,9 @@ impl KalkValue {
pub fn to_string_with_unit(&self) -> String {
match self {
KalkValue::Number(_, _, unit) => format!("{} {}", self, unit),
KalkValue::Number(_, _, unit) => {
format!("{} {}", self, unit.as_ref().unwrap_or(&String::new()))
}
_ => self.to_string(),
}
}
@ -432,7 +434,7 @@ impl KalkValue {
} else {
original_imaginary.clone()
},
unit.to_string(),
unit.clone(),
))
}
@ -489,17 +491,17 @@ impl KalkValue {
pub fn has_unit(&self) -> bool {
if let KalkValue::Number(_, _, unit) = self {
!unit.is_empty()
unit.is_some()
} else {
false
}
}
pub fn get_unit(&self) -> String {
pub fn get_unit(&self) -> Option<&String> {
if let KalkValue::Number(_, _, unit) = self {
unit.to_string()
unit.as_ref()
} else {
String::new()
None
}
}
@ -512,8 +514,8 @@ impl KalkValue {
let result = crate::interpreter::convert_unit(
context,
&Expr::Literal(primitive!(real)),
unit,
to_unit,
unit.as_ref(),
Some(&to_unit.to_string()),
);
if let Ok(num) = result {
@ -675,7 +677,7 @@ impl KalkValue {
(
KalkValue::Number(real, imaginary, _),
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(_)) => {
calculate_matrix(self, rhs, &KalkValue::add_without_unit)
}
@ -691,7 +693,7 @@ impl KalkValue {
(
KalkValue::Number(real, imaginary, _),
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(_)) => {
calculate_matrix(self, rhs, &KalkValue::sub_without_unit)
}
@ -719,7 +721,7 @@ impl KalkValue {
// (a + bi)(c + di) = ac + adi + bci + bdi²
real.clone() * real_rhs - imaginary.clone() * imaginary_rhs,
real.clone() * imaginary_rhs + imaginary * real_rhs,
unit.to_string(),
unit.clone(),
),
(KalkValue::Matrix(rows), KalkValue::Number(_, _, _)) => KalkValue::Matrix(
rows.iter()
@ -849,10 +851,10 @@ impl KalkValue {
KalkValue::Number(
polar.clone().cos() * exp.clone(),
polar.sin() * exp,
unit.to_string(),
unit.clone(),
)
} 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, _)) => {
@ -1107,12 +1109,12 @@ fn calculate_unit(
(left, &right)
{
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 {
Some(KalkValue::Number(
real_right.clone(),
imaginary_right.clone(),
unit_left.to_string(),
unit_left.clone(),
))
}
} else {
@ -1165,31 +1167,31 @@ impl From<KalkValue> for f64 {
impl From<f64> for KalkValue {
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 {
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 {
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 {
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 {
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 {
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
.add_without_unit(&KalkValue::Number(float!(b.0), float!(b.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), None));
assert_eq!(actual_result.to_f64(), expected_result.0);
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
}
@ -1225,8 +1227,8 @@ mod tests {
];
for (a, b, expected_result) in in_out {
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
.sub_without_unit(&KalkValue::Number(float!(b.0), float!(b.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), None));
assert_eq!(actual_result.to_f64(), expected_result.0);
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
}
@ -1242,8 +1244,8 @@ mod tests {
];
for (a, b, expected_result) in in_out {
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
.mul_without_unit(&KalkValue::Number(float!(b.0), float!(b.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), None));
assert_eq!(actual_result.to_f64(), expected_result.0);
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
}
@ -1258,8 +1260,8 @@ mod tests {
];
for (a, b, expected_result) in in_out {
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
.div_without_unit(&KalkValue::Number(float!(b.0), float!(b.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), None));
assert_eq!(actual_result.to_f64(), expected_result.0);
assert_eq!(actual_result.imaginary_to_f64(), expected_result.1);
}
@ -1286,8 +1288,8 @@ mod tests {
];
for (a, b, expected_result) in in_out {
let actual_result = KalkValue::Number(float!(a.0), float!(a.1), String::new())
.pow_without_unit(&KalkValue::Number(float!(b.0), float!(b.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), None));
assert!(cmp(actual_result.to_f64(), expected_result.0));
assert!(cmp(actual_result.imaginary_to_f64(), expected_result.1));
}
@ -1320,8 +1322,8 @@ mod tests {
(3.00000000004, 0.0, "3"),
];
for (real, imaginary, output) in in_out {
let result = KalkValue::Number(float!(real), float!(imaginary), String::new())
.to_string_pretty();
let result =
KalkValue::Number(float!(real), float!(imaginary), None).to_string_pretty();
assert_eq!(output, result);
}
}

View File

@ -240,7 +240,7 @@ fn equivalent_root(value: f64) -> Option<String> {
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()
.values()
.0;
@ -282,10 +282,10 @@ pub(super) fn round(
let new_value = integer * sign;
let new_num = match complex_number_type {
ComplexNumberType::Real => {
KalkValue::Number(new_value, imaginary.clone(), input.get_unit())
KalkValue::Number(new_value, imaginary.clone(), input.get_unit().cloned())
}
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_num = match complex_number_type {
ComplexNumberType::Real => {
KalkValue::Number(new_value, imaginary.clone(), input.get_unit())
KalkValue::Number(new_value, imaginary.clone(), input.get_unit().cloned())
}
ComplexNumberType::Imaginary => {
KalkValue::Number(real.clone(), new_value, input.get_unit())
KalkValue::Number(real.clone(), new_value, input.get_unit().cloned())
}
};

View File

@ -232,8 +232,13 @@ 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 {
match angle_unit {
"rad" => x,
_ => interpreter::convert_unit(context, &Expr::Literal(x.to_f64()), "rad", angle_unit)
.unwrap(),
_ => interpreter::convert_unit(
context,
&Expr::Literal(x.to_f64()),
Some(&String::from("rad")),
Some(&angle_unit.to_string()),
)
.unwrap(),
}
}
@ -244,8 +249,13 @@ fn from_angle_unit(
) -> KalkValue {
match angle_unit {
"rad" => x,
_ => interpreter::convert_unit(context, &Expr::Literal(x.to_f64()), angle_unit, "rad")
.unwrap(),
_ => interpreter::convert_unit(
context,
&Expr::Literal(x.to_f64()),
Some(&angle_unit.to_string()),
Some(&String::from("rad")),
)
.unwrap(),
}
}
@ -478,8 +488,7 @@ pub mod funcs {
sum_imaginary += imaginary;
}
KalkValue::Number(sum_real, sum_imaginary, String::new())
.div_without_unit(&KalkValue::from(count))
KalkValue::Number(sum_real, sum_imaginary, None).div_without_unit(&KalkValue::from(count))
}
pub fn cbrt(x: KalkValue) -> KalkValue {
@ -1011,11 +1020,7 @@ mod tests {
];
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
let actual_output = func(KalkValue::Number(
float!(input.0),
float!(input.1),
String::new(),
));
let actual_output = func(KalkValue::Number(float!(input.0), float!(input.1), None));
println!(
"{} | expected: {}, {}",
@ -1051,8 +1056,8 @@ mod tests {
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
let actual_output = func(
KalkValue::Number(float!(input.0 .0), float!(input.0 .1), String::new()),
KalkValue::Number(float!(input.1 .0), float!(input.1 .1), String::new()),
KalkValue::Number(float!(input.0 .0), float!(input.0 .1), None),
KalkValue::Number(float!(input.1 .0), float!(input.1 .1), None),
);
println!(
@ -1360,11 +1365,7 @@ mod tests {
];
for (i, (func, input, expected_output)) in in_out.iter().enumerate() {
let actual_output = func(KalkValue::Number(
float!(input.0),
float!(input.1),
String::new(),
));
let actual_output = func(KalkValue::Number(float!(input.0), float!(input.1), None));
let expected_has_nan_or_inf = expected_output.0.is_nan()
|| expected_output.0.is_infinite()