Use KalkValue::has_imaginary()

This commit is contained in:
bakk 2022-01-16 20:12:44 +01:00 committed by PaddiM8
parent 6ab25d573c
commit a36d9849d5
3 changed files with 45 additions and 41 deletions

View File

@ -478,7 +478,7 @@ impl KalkValue {
pub fn has_imaginary(&self) -> bool { pub fn has_imaginary(&self) -> bool {
if let KalkValue::Number(_, imaginary, _) = self { if let KalkValue::Number(_, imaginary, _) = self {
imaginary != &0f64 imaginary != &0f64 && imaginary != &-0f64
} else { } else {
false false
} }
@ -825,11 +825,11 @@ impl KalkValue {
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, _, _),
KalkValue::Number(real_rhs, imaginary_rhs, unit), KalkValue::Number(real_rhs, _, unit),
) => { ) => {
// Avoid unecessary calculations // Avoid unecessary calculations
if imaginary == 0f64 && imaginary_rhs == 0f64 { if !self.has_imaginary() && !rhs.has_imaginary() {
KalkValue::Number(real / real_rhs, float!(0f64), unit) KalkValue::Number(real / real_rhs, float!(0f64), unit)
} else { } else {
// Multiply both the numerator and denominator // Multiply both the numerator and denominator
@ -861,7 +861,7 @@ impl KalkValue {
KalkValue::Number(real, imaginary, _), KalkValue::Number(real, imaginary, _),
KalkValue::Number(real_rhs, imaginary_rhs, unit), KalkValue::Number(real_rhs, imaginary_rhs, unit),
) => { ) => {
if imaginary != 0f64 || imaginary_rhs != &0f64 || (real < 0f64 && real_rhs < &1f64) if self.has_imaginary() || imaginary_rhs != &0f64 || (real < 0f64 && real_rhs < &1f64)
{ {
let a = real.clone(); let a = real.clone();
let b = imaginary.clone(); let b = imaginary.clone();

View File

@ -267,8 +267,9 @@ pub mod funcs {
use crate::{as_number_or_return, as_vector_or_return, float, kalk_value::KalkValue}; use crate::{as_number_or_return, as_vector_or_return, float, kalk_value::KalkValue};
pub fn abs(x: KalkValue) -> KalkValue { pub fn abs(x: KalkValue) -> KalkValue {
let has_imaginary = x.has_imaginary();
let (real, imaginary, unit) = as_number_or_return!(x); let (real, imaginary, unit) = as_number_or_return!(x);
if imaginary != 0f64 { if has_imaginary {
// |z| = sqrt(a² + b²) // |z| = sqrt(a² + b²)
let a = real.clone() * real; let a = real.clone() * real;
let b = imaginary.clone() * imaginary; let b = imaginary.clone() * imaginary;
@ -280,8 +281,8 @@ pub mod funcs {
} }
pub fn acos(x: KalkValue) -> KalkValue { pub fn acos(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real > 1f64 || real < -1f64 { if x.has_imaginary() || real > 1f64 || real < -1f64 {
// -i * ln(i * sqrt(1 - z²) + z) // -i * ln(i * sqrt(1 - z²) + z)
let root = let root =
sqrt(KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&x))); sqrt(KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&x)));
@ -298,7 +299,7 @@ pub mod funcs {
pub fn acosh(x: KalkValue) -> KalkValue { pub fn acosh(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 < 1f64 { if x.has_imaginary() || real < 1f64 {
let sqrt1 = sqrt(KalkValue::Number( let sqrt1 = sqrt(KalkValue::Number(
real.clone() + 1f64, real.clone() + 1f64,
imaginary.clone(), imaginary.clone(),
@ -317,8 +318,8 @@ pub mod funcs {
} }
pub fn acot(x: KalkValue) -> KalkValue { pub fn acot(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 { if x.has_imaginary() {
// atan(1/z) // atan(1/z)
atan(KalkValue::from(1f64).div_without_unit(&x)) atan(KalkValue::from(1f64).div_without_unit(&x))
} else { } else {
@ -327,8 +328,8 @@ pub mod funcs {
} }
pub fn acoth(x: KalkValue) -> KalkValue { pub fn acoth(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real <= 1f64 || real >= -1f64 { if x.has_imaginary() || 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));
@ -347,8 +348,8 @@ pub mod funcs {
} }
pub fn acsc(x: KalkValue) -> KalkValue { pub fn acsc(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 1f64 || real > -1f64 { if x.has_imaginary() || 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 {
@ -357,8 +358,8 @@ pub mod funcs {
} }
pub fn acsch(x: KalkValue) -> KalkValue { pub fn acsch(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real == 0f64 { if x.has_imaginary() || 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)) KalkValue::from(1f64).div_without_unit(&x.clone().mul_without_unit(&x))
); );
@ -376,8 +377,8 @@ pub mod funcs {
} }
pub fn asec(x: KalkValue) -> KalkValue { pub fn asec(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 1f64 || real > -1f64 { if x.has_imaginary() || 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 {
@ -386,8 +387,8 @@ pub mod funcs {
} }
pub fn asech(x: KalkValue) -> KalkValue { pub fn asech(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real <= 0f64 || real > 1f64 { if x.has_imaginary() || real <= 0f64 || real > 1f64 {
// 1/z // 1/z
let inv = KalkValue::from(1f64).div_without_unit(&x); let inv = KalkValue::from(1f64).div_without_unit(&x);
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());
@ -412,8 +413,8 @@ pub mod funcs {
} }
pub fn asin(x: KalkValue) -> KalkValue { pub fn asin(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real > 1f64 || real < -1f64 { if x.has_imaginary() || real > 1f64 || real < -1f64 {
// i * ln(sqrt(1 - z²) - iz) // i * ln(sqrt(1 - z²) - iz)
let root = let root =
sqrt(KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&x))); sqrt(KalkValue::from(1f64).sub_without_unit(&x.clone().mul_without_unit(&x)));
@ -426,8 +427,8 @@ pub mod funcs {
} }
pub fn asinh(x: KalkValue) -> KalkValue { pub fn asinh(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 { if x.has_imaginary() {
let (x2_real, x2_imaginary, x2_unit) = let (x2_real, x2_imaginary, x2_unit) =
as_number_or_return!(x.clone().mul_without_unit(&x)); as_number_or_return!(x.clone().mul_without_unit(&x));
let sqrt = sqrt(KalkValue::Number(x2_real + 1f64, x2_imaginary, x2_unit)); let sqrt = sqrt(KalkValue::Number(x2_real + 1f64, x2_imaginary, x2_unit));
@ -439,8 +440,8 @@ pub mod funcs {
} }
pub fn atan(x: KalkValue) -> KalkValue { pub fn atan(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 { if x.has_imaginary() {
let (iz_real, iz_imaginary, iz_unit) = as_number_or_return!(multiply_with_i(x)); let (iz_real, iz_imaginary, iz_unit) = as_number_or_return!(multiply_with_i(x));
// 1 - iz // 1 - iz
@ -463,8 +464,9 @@ pub mod funcs {
} }
pub fn atanh(x: KalkValue) -> KalkValue { pub fn atanh(x: KalkValue) -> KalkValue {
let has_imaginary = x.has_imaginary();
let (real, imaginary, unit) = as_number_or_return!(x); let (real, imaginary, unit) = as_number_or_return!(x);
if imaginary != 0f64 || real >= 1f64 || real <= -1f64 { if has_imaginary || real >= 1f64 || real <= -1f64 {
// 1/2 * log(z + 1) - 1/2 * log(-z + 1) // 1/2 * log(z + 1) - 1/2 * log(-z + 1)
let log1 = ln(KalkValue::Number( let log1 = ln(KalkValue::Number(
1f64 + real.clone(), 1f64 + real.clone(),
@ -559,9 +561,9 @@ pub mod funcs {
} }
pub fn exp(x: KalkValue) -> KalkValue { pub fn exp(x: KalkValue) -> KalkValue {
let has_imaginary = x.has_imaginary();
let (real, imaginary, unit) = as_number_or_return!(x); let (real, imaginary, unit) = as_number_or_return!(x);
if has_imaginary {
if imaginary != 0f64 {
// e^a*cos(b) + ie^a*sin(b) // e^a*cos(b) + ie^a*sin(b)
let exp_a = real.exp(); let exp_a = real.exp();
let b = imaginary; let b = imaginary;
@ -597,7 +599,7 @@ pub mod funcs {
) )
} }
if imaginary != 0f64 || y.has_imaginary() { if x.has_imaginary() || y.has_imaginary() {
if real.clone().fract() != 0f64 if real.clone().fract() != 0f64
|| real_rhs.clone().fract() != 0f64 || real_rhs.clone().fract() != 0f64
|| imaginary.clone().fract() != 0f64 || imaginary.clone().fract() != 0f64
@ -691,8 +693,8 @@ pub mod funcs {
} }
pub fn log(x: KalkValue) -> KalkValue { pub fn log(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 0f64 { if x.has_imaginary() || 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 {
@ -701,9 +703,9 @@ pub mod funcs {
} }
pub fn logx(x: KalkValue, y: KalkValue) -> KalkValue { pub fn logx(x: KalkValue, y: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
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 x.has_imaginary() || 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 {
@ -712,8 +714,8 @@ pub mod funcs {
} }
pub fn ln(x: KalkValue) -> KalkValue { pub fn ln(x: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, _, unit) = as_number_or_return!(x.clone());
if imaginary != 0f64 || real < 0f64 { if x.has_imaginary() || 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)))
@ -792,7 +794,7 @@ pub mod funcs {
pub fn sqrt(x: KalkValue) -> KalkValue { pub fn sqrt(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 { if x.has_imaginary() {
let (abs_real, _, abs_unit) = as_number_or_return!(abs(x.clone())); let (abs_real, _, abs_unit) = as_number_or_return!(abs(x.clone()));
let r = abs_real; let r = abs_real;
let a = real; let a = real;
@ -812,8 +814,9 @@ pub mod funcs {
} }
pub fn tan(x: KalkValue) -> KalkValue { pub fn tan(x: KalkValue) -> KalkValue {
let has_imaginary = x.has_imaginary();
let (real, imaginary, unit) = as_number_or_return!(x); let (real, imaginary, unit) = as_number_or_return!(x);
if imaginary != 0f64 { if has_imaginary {
let a = real * 2f64; let a = real * 2f64;
let b = imaginary * 2f64; let b = imaginary * 2f64;
KalkValue::Number( KalkValue::Number(
@ -827,8 +830,9 @@ pub mod funcs {
} }
pub fn tanh(x: KalkValue) -> KalkValue { pub fn tanh(x: KalkValue) -> KalkValue {
let has_imaginary = x.has_imaginary();
let (real, imaginary, unit) = as_number_or_return!(x); let (real, imaginary, unit) = as_number_or_return!(x);
if imaginary != 0f64 { if has_imaginary {
let a = real * 2f64; let a = real * 2f64;
let b = imaginary * 2f64; let b = imaginary * 2f64;
KalkValue::Number( KalkValue::Number(

View File

@ -101,7 +101,7 @@ pub(crate) mod funcs {
pub fn hypot(x: KalkValue, y: KalkValue) -> KalkValue { pub fn hypot(x: KalkValue, y: KalkValue) -> KalkValue {
let (real, imaginary, unit) = as_number_or_return!(x.clone()); let (real, imaginary, unit) = as_number_or_return!(x.clone());
let (real_rhs, imaginary_rhs, _) = as_number_or_return!(y.clone()); let (real_rhs, imaginary_rhs, _) = as_number_or_return!(y.clone());
if imaginary != 0f64 || imaginary_rhs != 0f64 { if x.has_imaginary() || y.has_imaginary() {
let abs_x = abs(x); let abs_x = abs(x);
let abs_y = abs(y); let abs_y = abs(y);
crate::prelude::funcs::sqrt( crate::prelude::funcs::sqrt(