mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-13 10:00:51 +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,
|
||||
) -> 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",
|
||||
)
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user