Added vector operations

This commit is contained in:
PaddiM8 2022-01-05 02:49:12 +01:00
parent 92521f842b
commit 78efe183c4
8 changed files with 205 additions and 102 deletions

View File

@ -21,6 +21,7 @@ pub enum Expr {
FnCall(Identifier, Vec<Expr>), FnCall(Identifier, Vec<Expr>),
Literal(f64), Literal(f64),
Piecewise(Vec<ConditionalPiece>), Piecewise(Vec<ConditionalPiece>),
Vector(Vec<Expr>),
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]

View File

@ -17,8 +17,8 @@ pub fn derive_func(
const H: f64 = 0.000001; const H: f64 = 0.000001;
let unit = &argument.get_unit(); let unit = &argument.get_unit();
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(context, &new_identifier, &[argument_with_h], unit)?;
@ -26,8 +26,8 @@ pub fn derive_func(
interpreter::eval_fn_call_expr(context, &new_identifier, &[argument_without_h], unit)?; interpreter::eval_fn_call_expr(context, &new_identifier, &[argument_without_h], unit)?;
Ok(f_x_h Ok(f_x_h
.sub_without_unit(f_x) .sub_without_unit(&f_x)
.div_without_unit((2f64 * H).into()) .div_without_unit(&(2f64 * H).into())
.round_if_needed()) .round_if_needed())
} }
@ -89,11 +89,11 @@ fn simpsons_rule(
const N: i32 = 900; const N: i32 = 900;
let a = interpreter::eval_expr(context, a_expr, "")?; let a = interpreter::eval_expr(context, a_expr, "")?;
let b = interpreter::eval_expr(context, b_expr, "")?; let b = interpreter::eval_expr(context, b_expr, "")?;
let h = (b.sub_without_unit(a.clone())).div_without_unit(KalkValue::from(N)); let h = (b.sub_without_unit(&a.clone())).div_without_unit(&KalkValue::from(N));
for i in 0..=N { for i in 0..=N {
let variable_value = a let variable_value = a
.clone() .clone()
.add_without_unit(KalkValue::from(i).mul_without_unit(h.clone())); .add_without_unit(&KalkValue::from(i).mul_without_unit(&h.clone()));
context.symbol_table.set(Stmt::VarDecl( context.symbol_table.set(Stmt::VarDecl(
Identifier::from_full_name(integration_variable), Identifier::from_full_name(integration_variable),
Box::new(crate::ast::build_literal_ast(&variable_value)), Box::new(crate::ast::build_literal_ast(&variable_value)),
@ -106,8 +106,9 @@ fn simpsons_rule(
}); });
// factor * f(x_n) // factor * f(x_n)
let (mul_real, mul_imaginary, _) = let (mul_real, mul_imaginary, _) = as_number_or_zero!(
as_number_or_zero!(factor.mul_without_unit(interpreter::eval_expr(context, expr, "")?)); factor.mul_without_unit(&interpreter::eval_expr(context, expr, "")?)
);
result_real += mul_real; result_real += mul_real;
result_imaginary += mul_imaginary; result_imaginary += mul_imaginary;
} }
@ -123,7 +124,7 @@ fn simpsons_rule(
let result = KalkValue::Number(result_real, result_imaginary, String::new()); let result = KalkValue::Number(result_real, result_imaginary, String::new());
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(
3f64 / 8f64 * h_real, 3f64 / 8f64 * h_real,
3f64 / 8f64 * h_imaginary, 3f64 / 8f64 * h_imaginary,
h_unit, h_unit,

View File

@ -124,6 +124,7 @@ pub(crate) fn eval_expr(
eval_fn_call_expr(context, identifier, expressions, unit) eval_fn_call_expr(context, identifier, expressions, unit)
} }
Expr::Piecewise(pieces) => eval_piecewise(context, pieces, unit), Expr::Piecewise(pieces) => eval_piecewise(context, pieces, unit),
Expr::Vector(values) => eval_vector(context, values),
} }
} }
@ -476,6 +477,15 @@ fn eval_piecewise(
Err(CalcError::PiecewiseConditionsAreFalse) Err(CalcError::PiecewiseConditionsAreFalse)
} }
fn eval_vector(context: &mut Context, values: &Vec<Expr>) -> Result<KalkValue, CalcError> {
let mut eval_values = Vec::new();
for value in values {
eval_values.push(eval_expr(context, value, "")?);
}
Ok(KalkValue::Vector(eval_values))
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View File

@ -87,6 +87,7 @@ fn invert(
), ),
Expr::Literal(_) => Ok((target_expr, expr.clone())), Expr::Literal(_) => Ok((target_expr, expr.clone())),
Expr::Piecewise(_) => Err(CalcError::UnableToInvert(String::from("Piecewise"))), Expr::Piecewise(_) => Err(CalcError::UnableToInvert(String::from("Piecewise"))),
Expr::Vector(_) => Err(CalcError::UnableToInvert(String::from("Vector"))),
} }
} }
@ -386,6 +387,9 @@ pub fn contains_var(symbol_table: &SymbolTable, expr: &Expr, var_name: &str) ->
} }
Expr::Literal(_) => false, Expr::Literal(_) => false,
Expr::Piecewise(_) => true, // Let it try to invert this. It will just display the error message. Expr::Piecewise(_) => true, // Let it try to invert this. It will just display the error message.
Expr::Vector(items) => items
.iter()
.any(|x| contains_var(symbol_table, x, var_name)),
} }
} }

View File

@ -439,6 +439,14 @@ impl KalkValue {
} }
} }
pub fn is_nan(&self) -> bool {
if let KalkValue::Number(real, imaginary, _) = self {
real.is_nan() || imaginary.is_nan()
} else {
false
}
}
pub fn to_scientific_notation( pub fn to_scientific_notation(
&self, &self,
complex_number_type: ComplexNumberType, complex_number_type: ComplexNumberType,
@ -503,7 +511,7 @@ impl KalkValue {
rhs: KalkValue, rhs: KalkValue,
) -> KalkValue { ) -> KalkValue {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs); let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
self.add_without_unit(right) self.add_without_unit(&right)
} }
pub(crate) fn sub( pub(crate) fn sub(
@ -512,7 +520,7 @@ impl KalkValue {
rhs: KalkValue, rhs: KalkValue,
) -> KalkValue { ) -> KalkValue {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs); let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
self.sub_without_unit(right) self.sub_without_unit(&right)
} }
pub(crate) fn mul( pub(crate) fn mul(
@ -521,7 +529,7 @@ impl KalkValue {
rhs: KalkValue, rhs: KalkValue,
) -> KalkValue { ) -> KalkValue {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs); let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
self.mul_without_unit(right) self.mul_without_unit(&right)
} }
pub(crate) fn div( pub(crate) fn div(
@ -530,7 +538,16 @@ impl KalkValue {
rhs: KalkValue, rhs: KalkValue,
) -> KalkValue { ) -> KalkValue {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs.clone()); let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs.clone());
self.div_without_unit(right) self.div_without_unit(&right)
}
pub(crate) fn pow(
self,
context: &mut crate::interpreter::Context,
rhs: KalkValue,
) -> KalkValue {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
self.pow_without_unit(&right)
} }
pub(crate) fn rem( pub(crate) fn rem(
@ -614,42 +631,51 @@ impl KalkValue {
} }
} }
pub(crate) fn add_without_unit(self, rhs: KalkValue) -> KalkValue { pub(crate) fn add_without_unit(self, rhs: &KalkValue) -> KalkValue {
match (self, rhs) { match (self.clone(), rhs) {
( (
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), ) => KalkValue::Number(real + real_rhs, imaginary + imaginary_rhs, unit.to_string()),
(KalkValue::Vector(_), _) | (_, KalkValue::Vector(_)) => {
calculate_vector(self, rhs, &KalkValue::add_without_unit)
}
_ => KalkValue::nan(), _ => KalkValue::nan(),
} }
} }
pub(crate) fn sub_without_unit(self, rhs: KalkValue) -> KalkValue { pub(crate) fn sub_without_unit(self, rhs: &KalkValue) -> KalkValue {
match (self, rhs) { match (self.clone(), rhs) {
( (
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), ) => KalkValue::Number(real - real_rhs, imaginary - imaginary_rhs, unit.to_string()),
(KalkValue::Vector(_), _) | (_, KalkValue::Vector(_)) => {
calculate_vector(self, rhs, &KalkValue::sub_without_unit)
}
_ => KalkValue::nan(), _ => KalkValue::nan(),
} }
} }
pub(crate) fn mul_without_unit(self, rhs: KalkValue) -> KalkValue { pub(crate) fn mul_without_unit(self, rhs: &KalkValue) -> KalkValue {
// (a + bi)(c + di) = ac + adi + bci + bdi² // (a + bi)(c + di) = ac + adi + bci + bdi²
match (self, rhs) { match (self.clone(), rhs) {
( (
KalkValue::Number(real, imaginary, _), KalkValue::Number(real, imaginary, _),
KalkValue::Number(real_rhs, imaginary_rhs, unit), KalkValue::Number(real_rhs, imaginary_rhs, unit),
) => KalkValue::Number( ) => KalkValue::Number(
real.clone() * real_rhs.clone() - imaginary.clone() * imaginary_rhs.clone(), real.clone() * real_rhs.clone() - imaginary.clone() * imaginary_rhs.clone(),
real * imaginary_rhs + imaginary * real_rhs, real * imaginary_rhs + imaginary * real_rhs,
unit, unit.to_string(),
), ),
(KalkValue::Vector(_), _) | (_, KalkValue::Vector(_)) => {
calculate_vector(self, rhs, &KalkValue::mul_without_unit)
}
_ => KalkValue::nan(), _ => KalkValue::nan(),
} }
} }
pub(crate) fn div_without_unit(self, rhs: KalkValue) -> KalkValue { pub(crate) fn div_without_unit(self, rhs: &KalkValue) -> KalkValue {
match (self.clone(), rhs.clone()) { match (self.clone(), rhs.clone()) {
( (
KalkValue::Number(real, imaginary, _), KalkValue::Number(real, imaginary, _),
@ -663,8 +689,8 @@ impl KalkValue {
// with the conjugate of the denominator, and divide. // with the conjugate of the denominator, and divide.
let conjugate = rhs.get_conjugate(); let conjugate = rhs.get_conjugate();
let (numerator, numerator_imaginary) = let (numerator, numerator_imaginary) =
self.clone().mul_without_unit(conjugate.clone()).values(); self.clone().mul_without_unit(&conjugate.clone()).values();
let (denominator, _) = rhs.clone().mul_without_unit(conjugate).values(); let (denominator, _) = rhs.clone().mul_without_unit(&conjugate).values();
KalkValue::Number( KalkValue::Number(
numerator / denominator.clone(), numerator / denominator.clone(),
numerator_imaginary / denominator, numerator_imaginary / denominator,
@ -672,41 +698,44 @@ impl KalkValue {
) )
} }
} }
(KalkValue::Vector(_), _) | (_, KalkValue::Vector(_)) => {
calculate_vector(self, rhs, &KalkValue::div_without_unit)
}
_ => KalkValue::nan(), _ => KalkValue::nan(),
} }
} }
pub(crate) fn pow( pub(crate) fn pow_without_unit(self, rhs: &KalkValue) -> KalkValue {
self, match (self.clone(), rhs) {
context: &mut crate::interpreter::Context, (
rhs: KalkValue,
) -> KalkValue {
let right = calculate_unit(context, &self, rhs.clone()).unwrap_or(rhs);
self.pow_without_unit(right)
}
pub(crate) fn pow_without_unit(self, rhs: KalkValue) -> KalkValue {
if let (
KalkValue::Number(real, imaginary, _), KalkValue::Number(real, imaginary, _),
KalkValue::Number(real_rhs, imaginary_rhs, unit), KalkValue::Number(real_rhs, imaginary_rhs, unit),
) = (self.clone(), rhs) ) => {
if imaginary != 0f64 || imaginary_rhs != &0f64 || (real < 0f64 && real_rhs < &1f64)
{ {
if imaginary != 0f64 || imaginary_rhs != 0f64 || (real < 0f64 && real_rhs < 1f64) {
let a = real.clone(); let a = real.clone();
let b = imaginary.clone(); let b = imaginary.clone();
let c = real_rhs; let c = real_rhs;
let d = imaginary_rhs; let d = imaginary_rhs;
let arg = crate::prelude::funcs::arg(self).values().0; let arg = crate::prelude::funcs::arg(self).values().0;
let raised = a.clone() * a + b.clone() * b; let raised = a.clone() * a + b.clone() * b;
let exp = pow(raised.clone(), c.clone() / 2f64) * (-d.clone() * arg.clone()).exp(); let exp =
let polar = c * arg + d / 2f64 * raised.ln(); pow(raised.clone(), c.clone() / 2f64) * (-d.clone() * arg.clone()).exp();
let polar = c * arg + d.clone() / 2f64 * raised.ln();
KalkValue::Number(polar.clone().cos() * exp.clone(), polar.sin() * exp, unit) KalkValue::Number(
polar.clone().cos() * exp.clone(),
polar.sin() * exp,
unit.to_string(),
)
} else { } else {
KalkValue::Number(pow(real, real_rhs), float!(0), unit) KalkValue::Number(pow(real, real_rhs.clone()), float!(0), unit.to_string())
} }
} else { }
KalkValue::nan() (KalkValue::Vector(_), _) | (_, KalkValue::Vector(_)) => {
calculate_vector(self, rhs, &KalkValue::pow_without_unit)
}
_ => KalkValue::nan(),
} }
} }
@ -721,6 +750,18 @@ impl KalkValue {
(real.clone() - real_rhs.clone()).abs() < ACCEPTABLE_COMPARISON_MARGIN, (real.clone() - real_rhs.clone()).abs() < ACCEPTABLE_COMPARISON_MARGIN,
) )
} }
(KalkValue::Vector(values), KalkValue::Vector(values_rhs)) => {
let mut vecs_are_equal = true;
for (value, value_rhs) in values.iter().zip(values_rhs) {
if let KalkValue::Boolean(are_equal) = value.eq_without_unit(&value_rhs) {
if !are_equal {
vecs_are_equal = false;
}
}
}
KalkValue::Boolean(vecs_are_equal)
}
_ => KalkValue::nan(), _ => KalkValue::nan(),
} }
} }
@ -788,6 +829,35 @@ pub fn format_number(input: f64) -> String {
} }
} }
fn calculate_vector(
x: KalkValue,
y: &KalkValue,
action: &dyn Fn(KalkValue, &KalkValue) -> KalkValue,
) -> KalkValue {
match (x, y) {
(KalkValue::Vector(values), KalkValue::Number(_, _, _)) => {
KalkValue::Vector(values.iter().map(|x| action(x.clone(), y)).collect())
}
(KalkValue::Number(_, _, _), KalkValue::Vector(values_rhs)) => {
KalkValue::Vector(values_rhs.iter().map(|x| action(x.clone(), x)).collect())
}
(KalkValue::Vector(values), KalkValue::Vector(values_rhs)) => {
if values.len() == values_rhs.len() {
KalkValue::Vector(
values
.iter()
.zip(values_rhs)
.map(|(x, y)| x.clone().add_without_unit(&y))
.collect(),
)
} else {
KalkValue::nan()
}
}
_ => KalkValue::nan(),
}
}
fn calculate_unit( fn calculate_unit(
context: &mut crate::interpreter::Context, context: &mut crate::interpreter::Context,
left: &KalkValue, left: &KalkValue,
@ -885,7 +955,7 @@ 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), String::new())
.add_without_unit(KalkValue::Number(float!(b.0), float!(b.1), String::new())); .add_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
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);
} }
@ -902,7 +972,7 @@ 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), String::new())
.sub_without_unit(KalkValue::Number(float!(b.0), float!(b.1), String::new())); .sub_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
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);
} }
@ -919,7 +989,7 @@ 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), String::new())
.mul_without_unit(KalkValue::Number(float!(b.0), float!(b.1), String::new())); .mul_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
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);
} }
@ -935,7 +1005,7 @@ 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), String::new())
.div_without_unit(KalkValue::Number(float!(b.0), float!(b.1), String::new())); .div_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
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);
} }
@ -963,7 +1033,7 @@ 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), String::new())
.pow_without_unit(KalkValue::Number(float!(b.0), float!(b.1), String::new())); .pow_without_unit(&KalkValue::Number(float!(b.0), float!(b.1), String::new()));
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));
} }

View File

@ -569,9 +569,8 @@ fn parse_factorial(context: &mut Context) -> Result<Expr, CalcError> {
fn parse_primary(context: &mut Context) -> Result<Expr, CalcError> { fn parse_primary(context: &mut Context) -> Result<Expr, CalcError> {
let expr = match peek(context).kind { let expr = match peek(context).kind {
TokenKind::OpenParenthesis => parse_group(context)?, TokenKind::OpenParenthesis => parse_group(context)?,
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor | TokenKind::OpenBracket => { TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
parse_group_fn(context)? TokenKind::OpenBracket => parse_vector(context)?,
}
TokenKind::Identifier => parse_identifier(context)?, TokenKind::Identifier => parse_identifier(context)?,
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?), TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
_ => return Err(CalcError::UnableToParseExpression), _ => return Err(CalcError::UnableToParseExpression),
@ -593,7 +592,6 @@ fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
TokenKind::Pipe => "abs", TokenKind::Pipe => "abs",
TokenKind::OpenCeil => "ceil", TokenKind::OpenCeil => "ceil",
TokenKind::OpenFloor => "floor", TokenKind::OpenFloor => "floor",
TokenKind::OpenBracket => "iverson",
_ => unreachable!(), _ => unreachable!(),
}; };
@ -610,6 +608,20 @@ fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
Ok(Expr::FnCall(Identifier::from_full_name(name), vec![expr])) Ok(Expr::FnCall(Identifier::from_full_name(name), vec![expr]))
} }
fn parse_vector(context: &mut Context) -> Result<Expr, CalcError> {
advance(context);
let mut values = vec![parse_expr(context)?];
while match_token(context, TokenKind::Comma) {
advance(context);
values.push(parse_expr(context)?);
}
advance(context);
Ok(Expr::Vector(values))
}
fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> { fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
let identifier = Identifier::from_full_name(&advance(context).value); let identifier = Identifier::from_full_name(&advance(context).value);

View File

@ -256,11 +256,12 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real > 1f64 || real < -1f64 { if imaginary != 0f64 || real > 1f64 || real < -1f64 {
// -i * ln(i * sqrt(1 - z²) + z) // -i * ln(i * sqrt(1 - z²) + z)
let root = let root = sqrt(
sqrt(KalkValue::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone()))); KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&x.clone())),
);
let iroot = multiply_with_i(root.clone()); let iroot = multiply_with_i(root.clone());
let (ln_real, ln_imaginary, ln_unit) = let (ln_real, ln_imaginary, ln_unit) =
as_number_or_return!(ln(iroot.add_without_unit(x))); as_number_or_return!(ln(iroot.add_without_unit(&x)));
// -iz = -i(a + bi) = b - ai // -iz = -i(a + bi) = b - ai
KalkValue::Number(ln_imaginary, -ln_real, ln_unit) KalkValue::Number(ln_imaginary, -ln_real, ln_unit)
@ -283,7 +284,7 @@ pub mod funcs {
unit, unit,
)); ));
ln(x.add_without_unit(sqrt1.mul_without_unit(sqrt2))) ln(x.add_without_unit(&sqrt1.mul_without_unit(&sqrt2)))
} else { } else {
KalkValue::Number(real.acosh(), float!(0), unit) KalkValue::Number(real.acosh(), float!(0), unit)
} }
@ -293,7 +294,7 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 { if imaginary != 0f64 {
// atan(1/z) // atan(1/z)
atan(KalkValue::from(1f64).div_without_unit(x)) atan(KalkValue::from(1f64).div_without_unit(&x))
} else { } else {
KalkValue::Number((1f64 / real).atan(), float!(0), unit) KalkValue::Number((1f64 / real).atan(), float!(0), unit)
} }
@ -304,7 +305,7 @@ pub mod funcs {
if imaginary != 0f64 || real <= 1f64 || real >= -1f64 { if imaginary != 0f64 || real <= 1f64 || real >= -1f64 {
// 1 / z // 1 / z
let (inv_real, inv_imaginary, inv_unit) = let (inv_real, inv_imaginary, inv_unit) =
as_number_or_return!(KalkValue::from(1f64).div_without_unit(x)); as_number_or_return!(KalkValue::from(1f64).div_without_unit(&x));
let ln1 = ln(KalkValue::Number( let ln1 = ln(KalkValue::Number(
1f64 + inv_real.clone(), 1f64 + inv_real.clone(),
inv_imaginary.clone(), inv_imaginary.clone(),
@ -312,8 +313,8 @@ pub mod funcs {
)); ));
let ln2 = ln(KalkValue::Number(1f64 - inv_real, -inv_imaginary, inv_unit)); let ln2 = ln(KalkValue::Number(1f64 - inv_real, -inv_imaginary, inv_unit));
ln1.sub_without_unit(ln2) ln1.sub_without_unit(&ln2)
.div_without_unit(KalkValue::from(2f64)) .div_without_unit(&KalkValue::from(2f64))
} else { } else {
KalkValue::Number((1f64 / real).atanh(), float!(0), unit) KalkValue::Number((1f64 / real).atanh(), float!(0), unit)
} }
@ -323,7 +324,7 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 1f64 || real > -1f64 { if imaginary != 0f64 || real < 1f64 || real > -1f64 {
// asin(1/z) // asin(1/z)
asin(KalkValue::from(1f64).div_without_unit(x)) asin(KalkValue::from(1f64).div_without_unit(&x))
} else { } else {
KalkValue::Number((1f64 / real).asin(), float!(0), unit) KalkValue::Number((1f64 / real).asin(), float!(0), unit)
} }
@ -333,16 +334,16 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real == 0f64 { if imaginary != 0f64 || real == 0f64 {
let (inv_x2_real, inv_x2_imaginary, inv_x2_unit) = as_number_or_return!( let (inv_x2_real, inv_x2_imaginary, inv_x2_unit) = as_number_or_return!(
KalkValue::from(1f64).div_without_unit(x.clone().mul_without_unit(x.clone())) KalkValue::from(1f64).div_without_unit(&x.clone().mul_without_unit(&x.clone()))
); );
let sqrt = sqrt(KalkValue::Number( let sqrt = sqrt(KalkValue::Number(
1f64 + inv_x2_real, 1f64 + inv_x2_real,
inv_x2_imaginary, inv_x2_imaginary,
inv_x2_unit, inv_x2_unit,
)); ));
let inv_x = KalkValue::from(1f64).div_without_unit(x.clone()); let inv_x = KalkValue::from(1f64).div_without_unit(&x.clone());
ln(sqrt.add_without_unit(inv_x)) ln(sqrt.add_without_unit(&inv_x))
} else { } else {
KalkValue::Number((1f64 / real).asinh(), float!(0), unit) KalkValue::Number((1f64 / real).asinh(), float!(0), unit)
} }
@ -352,7 +353,7 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 1f64 || real > -1f64 { if imaginary != 0f64 || real < 1f64 || real > -1f64 {
// acos(1/z) // acos(1/z)
acos(KalkValue::from(1f64).div_without_unit(x)) acos(KalkValue::from(1f64).div_without_unit(&x))
} else { } else {
KalkValue::Number((1f64 / real).acos(), float!(0), unit) KalkValue::Number((1f64 / real).acos(), float!(0), unit)
} }
@ -362,7 +363,7 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real <= 0f64 || real > 1f64 { if imaginary != 0f64 || real <= 0f64 || real > 1f64 {
// 1/z // 1/z
let inv = KalkValue::from(1f64).div_without_unit(x.clone()); let inv = KalkValue::from(1f64).div_without_unit(&x.clone());
let (inv_real, inv_imaginary, inv_unit) = as_number_or_return!(inv.clone()); let (inv_real, inv_imaginary, inv_unit) = as_number_or_return!(inv.clone());
// sqrt(1/z - 1) // sqrt(1/z - 1)
let sqrt1 = sqrt(KalkValue::Number( let sqrt1 = sqrt(KalkValue::Number(
@ -378,7 +379,7 @@ pub mod funcs {
)); ));
// ln(1/z + sqrt(1/z - 1) * sqrt(1/z + 1)) // ln(1/z + sqrt(1/z - 1) * sqrt(1/z + 1))
ln(sqrt1.mul_without_unit(sqrt2).add_without_unit(inv)) ln(sqrt1.mul_without_unit(&sqrt2).add_without_unit(&inv))
} else { } else {
KalkValue::Number((1f64 / real).acosh(), float!(0), unit) KalkValue::Number((1f64 / real).acosh(), float!(0), unit)
} }
@ -388,10 +389,11 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real > 1f64 || real < -1f64 { if imaginary != 0f64 || real > 1f64 || real < -1f64 {
// i * ln(sqrt(1 - z²) - iz) // i * ln(sqrt(1 - z²) - iz)
let root = let root = sqrt(
sqrt(KalkValue::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone()))); KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&x.clone())),
);
let iz = multiply_with_i(x.clone()); let iz = multiply_with_i(x.clone());
let ln = ln(root.sub_without_unit(iz)); let ln = ln(root.sub_without_unit(&iz));
multiply_with_i(ln) multiply_with_i(ln)
} else { } else {
KalkValue::Number(real.asin(), float!(0), unit) KalkValue::Number(real.asin(), float!(0), unit)
@ -402,10 +404,10 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 { if imaginary != 0f64 {
let (x2_real, x2_imaginary, x2_unit) = let (x2_real, x2_imaginary, x2_unit) =
as_number_or_return!(x.clone().mul_without_unit(x.clone())); as_number_or_return!(x.clone().mul_without_unit(&x.clone()));
let sqrt = sqrt(KalkValue::Number(x2_real + 1f64, x2_imaginary, x2_unit)); let sqrt = sqrt(KalkValue::Number(x2_real + 1f64, x2_imaginary, x2_unit));
ln(x.add_without_unit(sqrt)) ln(x.add_without_unit(&sqrt))
} else { } else {
KalkValue::Number(real.asinh(), float!(0), unit) KalkValue::Number(real.asinh(), float!(0), unit)
} }
@ -427,9 +429,9 @@ pub mod funcs {
let pos = KalkValue::Number(1f64 + iz_real, iz_imaginary, iz_unit); let pos = KalkValue::Number(1f64 + iz_real, iz_imaginary, iz_unit);
// ln(1 - iz) - ln(1 + iz) // ln(1 - iz) - ln(1 + iz)
let ln = ln(neg).sub_without_unit(ln(pos)); let ln = ln(neg).sub_without_unit(&ln(pos));
multiply_with_i(ln).div_without_unit(KalkValue::from(2f64)) multiply_with_i(ln).div_without_unit(&KalkValue::from(2f64))
} else { } else {
KalkValue::Number(real.atan(), float!(0), unit) KalkValue::Number(real.atan(), float!(0), unit)
} }
@ -446,8 +448,8 @@ pub mod funcs {
)); ));
let log2 = ln(KalkValue::Number(1f64 - real, -imaginary, unit)); let log2 = ln(KalkValue::Number(1f64 - real, -imaginary, unit));
log1.sub_without_unit(log2) log1.sub_without_unit(&log2)
.div_without_unit(KalkValue::from(2f64)) .div_without_unit(&KalkValue::from(2f64))
} else { } else {
KalkValue::Number(real.atanh(), float!(0), unit) KalkValue::Number(real.atanh(), float!(0), unit)
} }
@ -486,11 +488,11 @@ pub mod funcs {
} }
pub fn csc(x: KalkValue) -> KalkValue { pub fn csc(x: KalkValue) -> KalkValue {
KalkValue::from(1f64).div_without_unit(sin(x)) KalkValue::from(1f64).div_without_unit(&sin(x))
} }
pub fn csch(x: KalkValue) -> KalkValue { pub fn csch(x: KalkValue) -> KalkValue {
KalkValue::from(1f64).div_without_unit(sinh(x)) KalkValue::from(1f64).div_without_unit(&sinh(x))
} }
pub fn cot(x: KalkValue) -> KalkValue { pub fn cot(x: KalkValue) -> KalkValue {
@ -583,12 +585,15 @@ pub mod funcs {
let (b_real, b_imaginary, b_unit) = as_number_or_return!(b.clone()); let (b_real, b_imaginary, b_unit) = as_number_or_return!(b.clone());
let (c_real, c_imaginary, c_unit) = let (c_real, c_imaginary, c_unit) =
as_number_or_return!(a.clone().div_without_unit(b.clone())); as_number_or_return!(a.clone().div_without_unit(&b.clone()));
if c_imaginary.clone().fract() == 0f64 { if c_imaginary.clone().fract() == 0f64 {
KalkValue::Number(b_real.abs(), b_imaginary, b_unit) KalkValue::Number(b_real.abs(), b_imaginary, b_unit)
} else { } else {
let rounded_c = KalkValue::Number(c_real.round(), c_imaginary.round(), c_unit); let rounded_c = KalkValue::Number(c_real.round(), c_imaginary.round(), c_unit);
gcd(a.sub_without_unit(b.clone().mul_without_unit(rounded_c)), b) gcd(
a.sub_without_unit(&b.clone().mul_without_unit(&rounded_c)),
b,
)
} }
} else { } else {
if real < 0f64 || real_rhs < 0f64 { if real < 0f64 || real_rhs < 0f64 {
@ -642,14 +647,14 @@ pub mod funcs {
let gcd = gcd(x.clone(), y.clone()); let gcd = gcd(x.clone(), y.clone());
let absx = KalkValue::Number(real.abs(), imaginary, unit); let absx = KalkValue::Number(real.abs(), imaginary, unit);
let absy = KalkValue::Number(real_rhs.abs(), imaginary_rhs, unit_rhs); let absy = KalkValue::Number(real_rhs.abs(), imaginary_rhs, unit_rhs);
return absx.div_without_unit(gcd).mul_without_unit(absy); return absx.div_without_unit(&gcd).mul_without_unit(&absy);
} }
pub fn log(x: KalkValue) -> KalkValue { pub fn log(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 0f64 { if imaginary != 0f64 || real < 0f64 {
// ln(z) / ln(10) // ln(z) / ln(10)
ln(x).div_without_unit(KalkValue::from(10f64.ln())) ln(x).div_without_unit(&KalkValue::from(10f64.ln()))
} else { } else {
KalkValue::Number(real.log10(), float!(0), unit) KalkValue::Number(real.log10(), float!(0), unit)
} }
@ -660,7 +665,7 @@ pub mod funcs {
let (real_rhs, _, _) = as_number_or_return!(y.clone()); let (real_rhs, _, _) = as_number_or_return!(y.clone());
if imaginary != 0f64 || y.has_imaginary() || real < 0f64 || real_rhs < 0f64 { if imaginary != 0f64 || y.has_imaginary() || real < 0f64 || real_rhs < 0f64 {
// ln(z) / ln(n) // ln(z) / ln(n)
ln(x).div_without_unit(ln(y)) ln(x).div_without_unit(&ln(y))
} else { } else {
KalkValue::Number(real.log10() / real_rhs.log10(), float!(0), unit) KalkValue::Number(real.log10() / real_rhs.log10(), float!(0), unit)
} }
@ -671,14 +676,14 @@ pub mod funcs {
if imaginary != 0f64 || real < 0f64 { if imaginary != 0f64 || real < 0f64 {
let r = abs(x.clone()); let r = abs(x.clone());
// ln|z| + i * arg z // ln|z| + i * arg z
ln(r).add_without_unit(multiply_with_i(arg(x))) ln(r).add_without_unit(&multiply_with_i(arg(x)))
} else { } else {
KalkValue::Number(real.ln(), float!(0), unit) KalkValue::Number(real.ln(), float!(0), unit)
} }
} }
pub fn nth_root(x: KalkValue, n: KalkValue) -> KalkValue { pub fn nth_root(x: KalkValue, n: KalkValue) -> KalkValue {
x.pow_without_unit(KalkValue::from(1f64).div_without_unit(n)) x.pow_without_unit(&KalkValue::from(1f64).div_without_unit(&n))
} }
pub fn re(x: KalkValue) -> KalkValue { pub fn re(x: KalkValue) -> KalkValue {
@ -692,11 +697,11 @@ pub mod funcs {
} }
pub fn sec(x: KalkValue) -> KalkValue { pub fn sec(x: KalkValue) -> KalkValue {
KalkValue::from(1f64).div_without_unit(cos(x)) KalkValue::from(1f64).div_without_unit(&cos(x))
} }
pub fn sech(x: KalkValue) -> KalkValue { pub fn sech(x: KalkValue) -> KalkValue {
KalkValue::from(1f64).div_without_unit(cosh(x)) KalkValue::from(1f64).div_without_unit(&cosh(x))
} }
pub fn sin(x: KalkValue) -> KalkValue { pub fn sin(x: KalkValue) -> KalkValue {
@ -775,12 +780,12 @@ pub mod funcs {
pub fn ncr(x: KalkValue, y: KalkValue) -> KalkValue { pub fn ncr(x: KalkValue, y: KalkValue) -> KalkValue {
factorial(x.clone()).div_without_unit( factorial(x.clone()).div_without_unit(
factorial(y.clone()).mul_without_unit(factorial(x.sub_without_unit(y))), &factorial(y.clone()).mul_without_unit(&factorial(x.sub_without_unit(&y))),
) )
} }
pub fn npr(x: KalkValue, y: KalkValue) -> KalkValue { pub fn npr(x: KalkValue, y: KalkValue) -> KalkValue {
factorial(x.clone()).div_without_unit(factorial(x.sub_without_unit(y))) factorial(x.clone()).div_without_unit(&factorial(x.sub_without_unit(&y)))
} }
fn multiply_with_i(z: KalkValue) -> KalkValue { fn multiply_with_i(z: KalkValue) -> KalkValue {

View File

@ -83,8 +83,8 @@ pub(crate) mod funcs {
crate::prelude::funcs::sqrt( crate::prelude::funcs::sqrt(
abs_x abs_x
.clone() .clone()
.mul_without_unit(abs_x) .mul_without_unit(&abs_x)
.add_without_unit(abs_y.clone().mul_without_unit(abs_y)), .add_without_unit(&abs_y.clone().mul_without_unit(&abs_y)),
) )
} else { } else {
KalkValue::Number(real.hypot(&real_rhs), float!(0), unit) KalkValue::Number(real.hypot(&real_rhs), float!(0), unit)