mirror of
https://github.com/PaddiM8/kalker.git
synced 2024-12-12 09:30:40 +01:00
Added vector operations
This commit is contained in:
parent
92521f842b
commit
78efe183c4
@ -21,6 +21,7 @@ pub enum Expr {
|
||||
FnCall(Identifier, Vec<Expr>),
|
||||
Literal(f64),
|
||||
Piecewise(Vec<ConditionalPiece>),
|
||||
Vector(Vec<Expr>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
|
@ -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,
|
||||
|
@ -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::*;
|
||||
|
@ -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)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
match (self.clone(), rhs) {
|
||||
(
|
||||
KalkValue::Number(real, imaginary, _),
|
||||
KalkValue::Number(real_rhs, imaginary_rhs, unit),
|
||||
) => {
|
||||
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.clone() / 2f64 * raised.ln();
|
||||
|
||||
pub(crate) fn pow_without_unit(self, rhs: KalkValue) -> KalkValue {
|
||||
if let (
|
||||
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) {
|
||||
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();
|
||||
|
||||
KalkValue::Number(polar.clone().cos() * exp.clone(), polar.sin() * exp, unit)
|
||||
} else {
|
||||
KalkValue::Number(pow(real, real_rhs), float!(0), unit)
|
||||
KalkValue::Number(
|
||||
polar.clone().cos() * exp.clone(),
|
||||
polar.sin() * exp,
|
||||
unit.to_string(),
|
||||
)
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user