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>),
Literal(f64),
Piecewise(Vec<ConditionalPiece>),
Vector(Vec<Expr>),
}
#[derive(Debug, Clone, PartialEq)]

View File

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

View File

@ -124,6 +124,7 @@ pub(crate) fn eval_expr(
eval_fn_call_expr(context, identifier, expressions, 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)
}
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)]
mod tests {
use super::*;

View File

@ -87,6 +87,7 @@ fn invert(
),
Expr::Literal(_) => Ok((target_expr, expr.clone())),
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::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(
&self,
complex_number_type: ComplexNumberType,
@ -503,7 +511,7 @@ impl KalkValue {
rhs: KalkValue,
) -> KalkValue {
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(
@ -512,7 +520,7 @@ impl KalkValue {
rhs: KalkValue,
) -> KalkValue {
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(
@ -521,7 +529,7 @@ impl KalkValue {
rhs: KalkValue,
) -> KalkValue {
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(
@ -530,7 +538,16 @@ impl KalkValue {
rhs: KalkValue,
) -> KalkValue {
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(
@ -614,42 +631,51 @@ impl KalkValue {
}
}
pub(crate) fn add_without_unit(self, rhs: KalkValue) -> KalkValue {
match (self, rhs) {
pub(crate) fn add_without_unit(self, rhs: &KalkValue) -> KalkValue {
match (self.clone(), rhs) {
(
KalkValue::Number(real, imaginary, _),
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(),
}
}
pub(crate) fn sub_without_unit(self, rhs: KalkValue) -> KalkValue {
match (self, rhs) {
pub(crate) fn sub_without_unit(self, rhs: &KalkValue) -> KalkValue {
match (self.clone(), rhs) {
(
KalkValue::Number(real, imaginary, _),
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(),
}
}
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²
match (self, rhs) {
match (self.clone(), rhs) {
(
KalkValue::Number(real, imaginary, _),
KalkValue::Number(real_rhs, imaginary_rhs, unit),
) => KalkValue::Number(
real.clone() * real_rhs.clone() - imaginary.clone() * imaginary_rhs.clone(),
real * imaginary_rhs + imaginary * real_rhs,
unit,
unit.to_string(),
),
(KalkValue::Vector(_), _) | (_, KalkValue::Vector(_)) => {
calculate_vector(self, rhs, &KalkValue::mul_without_unit)
}
_ => 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()) {
(
KalkValue::Number(real, imaginary, _),
@ -663,8 +689,8 @@ impl KalkValue {
// with the conjugate of the denominator, and divide.
let conjugate = rhs.get_conjugate();
let (numerator, numerator_imaginary) =
self.clone().mul_without_unit(conjugate.clone()).values();
let (denominator, _) = rhs.clone().mul_without_unit(conjugate).values();
self.clone().mul_without_unit(&conjugate.clone()).values();
let (denominator, _) = rhs.clone().mul_without_unit(&conjugate).values();
KalkValue::Number(
numerator / denominator.clone(),
numerator_imaginary / denominator,
@ -672,41 +698,44 @@ impl KalkValue {
)
}
}
(KalkValue::Vector(_), _) | (_, KalkValue::Vector(_)) => {
calculate_vector(self, rhs, &KalkValue::div_without_unit)
}
_ => KalkValue::nan(),
}
}
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 pow_without_unit(self, rhs: KalkValue) -> KalkValue {
if let (
pub(crate) fn pow_without_unit(self, rhs: &KalkValue) -> KalkValue {
match (self.clone(), rhs) {
(
KalkValue::Number(real, imaginary, _),
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 b = imaginary.clone();
let c = real_rhs;
let d = imaginary_rhs;
let arg = crate::prelude::funcs::arg(self).values().0;
let raised = a.clone() * a + b.clone() * b;
let exp = pow(raised.clone(), c.clone() / 2f64) * (-d.clone() * arg.clone()).exp();
let polar = c * arg + d / 2f64 * raised.ln();
let exp =
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 {
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,
)
}
(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(),
}
}
@ -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(
context: &mut crate::interpreter::Context,
left: &KalkValue,
@ -885,7 +955,7 @@ 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()));
.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.imaginary_to_f64(), expected_result.1);
}
@ -902,7 +972,7 @@ 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()));
.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.imaginary_to_f64(), expected_result.1);
}
@ -919,7 +989,7 @@ 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()));
.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.imaginary_to_f64(), expected_result.1);
}
@ -935,7 +1005,7 @@ 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()));
.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.imaginary_to_f64(), expected_result.1);
}
@ -963,7 +1033,7 @@ 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()));
.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.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> {
let expr = match peek(context).kind {
TokenKind::OpenParenthesis => parse_group(context)?,
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor | TokenKind::OpenBracket => {
parse_group_fn(context)?
}
TokenKind::Pipe | TokenKind::OpenCeil | TokenKind::OpenFloor => parse_group_fn(context)?,
TokenKind::OpenBracket => parse_vector(context)?,
TokenKind::Identifier => parse_identifier(context)?,
TokenKind::Literal => Expr::Literal(string_to_num(&advance(context).value)?),
_ => return Err(CalcError::UnableToParseExpression),
@ -593,7 +592,6 @@ fn parse_group_fn(context: &mut Context) -> Result<Expr, CalcError> {
TokenKind::Pipe => "abs",
TokenKind::OpenCeil => "ceil",
TokenKind::OpenFloor => "floor",
TokenKind::OpenBracket => "iverson",
_ => 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]))
}
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> {
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());
if imaginary != 0f64 || real > 1f64 || real < -1f64 {
// -i * ln(i * sqrt(1 - z²) + z)
let root =
sqrt(KalkValue::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone())));
let root = sqrt(
KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&x.clone())),
);
let iroot = multiply_with_i(root.clone());
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
KalkValue::Number(ln_imaginary, -ln_real, ln_unit)
@ -283,7 +284,7 @@ pub mod funcs {
unit,
));
ln(x.add_without_unit(sqrt1.mul_without_unit(sqrt2)))
ln(x.add_without_unit(&sqrt1.mul_without_unit(&sqrt2)))
} else {
KalkValue::Number(real.acosh(), float!(0), unit)
}
@ -293,7 +294,7 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 {
// atan(1/z)
atan(KalkValue::from(1f64).div_without_unit(x))
atan(KalkValue::from(1f64).div_without_unit(&x))
} else {
KalkValue::Number((1f64 / real).atan(), float!(0), unit)
}
@ -304,7 +305,7 @@ pub mod funcs {
if imaginary != 0f64 || real <= 1f64 || real >= -1f64 {
// 1 / z
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(
1f64 + inv_real.clone(),
inv_imaginary.clone(),
@ -312,8 +313,8 @@ pub mod funcs {
));
let ln2 = ln(KalkValue::Number(1f64 - inv_real, -inv_imaginary, inv_unit));
ln1.sub_without_unit(ln2)
.div_without_unit(KalkValue::from(2f64))
ln1.sub_without_unit(&ln2)
.div_without_unit(&KalkValue::from(2f64))
} else {
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());
if imaginary != 0f64 || real < 1f64 || real > -1f64 {
// asin(1/z)
asin(KalkValue::from(1f64).div_without_unit(x))
asin(KalkValue::from(1f64).div_without_unit(&x))
} else {
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());
if imaginary != 0f64 || real == 0f64 {
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(
1f64 + inv_x2_real,
inv_x2_imaginary,
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 {
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());
if imaginary != 0f64 || real < 1f64 || real > -1f64 {
// acos(1/z)
acos(KalkValue::from(1f64).div_without_unit(x))
acos(KalkValue::from(1f64).div_without_unit(&x))
} else {
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());
if imaginary != 0f64 || real <= 0f64 || real > 1f64 {
// 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());
// sqrt(1/z - 1)
let sqrt1 = sqrt(KalkValue::Number(
@ -378,7 +379,7 @@ pub mod funcs {
));
// 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 {
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());
if imaginary != 0f64 || real > 1f64 || real < -1f64 {
// i * ln(sqrt(1 - z²) - iz)
let root =
sqrt(KalkValue::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone())));
let root = sqrt(
KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&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)
} else {
KalkValue::Number(real.asin(), float!(0), unit)
@ -402,10 +404,10 @@ pub mod funcs {
let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 {
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));
ln(x.add_without_unit(sqrt))
ln(x.add_without_unit(&sqrt))
} else {
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);
// 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 {
KalkValue::Number(real.atan(), float!(0), unit)
}
@ -446,8 +448,8 @@ pub mod funcs {
));
let log2 = ln(KalkValue::Number(1f64 - real, -imaginary, unit));
log1.sub_without_unit(log2)
.div_without_unit(KalkValue::from(2f64))
log1.sub_without_unit(&log2)
.div_without_unit(&KalkValue::from(2f64))
} else {
KalkValue::Number(real.atanh(), float!(0), unit)
}
@ -486,11 +488,11 @@ pub mod funcs {
}
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 {
KalkValue::from(1f64).div_without_unit(sinh(x))
KalkValue::from(1f64).div_without_unit(&sinh(x))
}
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 (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 {
KalkValue::Number(b_real.abs(), b_imaginary, b_unit)
} else {
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 {
if real < 0f64 || real_rhs < 0f64 {
@ -642,14 +647,14 @@ pub mod funcs {
let gcd = gcd(x.clone(), y.clone());
let absx = KalkValue::Number(real.abs(), imaginary, unit);
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 {
let (real, imaginary, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 0f64 {
// ln(z) / ln(10)
ln(x).div_without_unit(KalkValue::from(10f64.ln()))
ln(x).div_without_unit(&KalkValue::from(10f64.ln()))
} else {
KalkValue::Number(real.log10(), float!(0), unit)
}
@ -660,7 +665,7 @@ pub mod funcs {
let (real_rhs, _, _) = as_number_or_return!(y.clone());
if imaginary != 0f64 || y.has_imaginary() || real < 0f64 || real_rhs < 0f64 {
// ln(z) / ln(n)
ln(x).div_without_unit(ln(y))
ln(x).div_without_unit(&ln(y))
} else {
KalkValue::Number(real.log10() / real_rhs.log10(), float!(0), unit)
}
@ -671,14 +676,14 @@ pub mod funcs {
if imaginary != 0f64 || real < 0f64 {
let r = abs(x.clone());
// 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 {
KalkValue::Number(real.ln(), float!(0), unit)
}
}
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 {
@ -692,11 +697,11 @@ pub mod funcs {
}
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 {
KalkValue::from(1f64).div_without_unit(cosh(x))
KalkValue::from(1f64).div_without_unit(&cosh(x))
}
pub fn sin(x: KalkValue) -> KalkValue {
@ -775,12 +780,12 @@ pub mod funcs {
pub fn ncr(x: KalkValue, y: KalkValue) -> KalkValue {
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 {
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 {

View File

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