diff --git a/kalk/scripts/generate_funcs_test_cases.py b/kalk/scripts/generate_funcs_test_cases.py new file mode 100755 index 0000000..c05806f --- /dev/null +++ b/kalk/scripts/generate_funcs_test_cases.py @@ -0,0 +1,65 @@ +#!/bin/python + +from random import randint +import mpmath + + +funcs = [ + (mpmath.arg, "arg"), + (mpmath.ceil, "ceil"), + (mpmath.exp, "exp"), + (mpmath.floor, "floor"), + (mpmath.log10, "log"), + (mpmath.ln, "ln"), + (mpmath.sqrt, "sqrt"), + (mpmath.acos, "acos"), + (mpmath.acosh, "acosh"), + (mpmath.acsc, "acsc"), + (mpmath.acsch, "acsch"), + (mpmath.acot, "acot"), + (mpmath.acoth, "acoth"), + (mpmath.asec, "asec"), + (mpmath.asech, "asech"), + (mpmath.asin, "asin"), + (mpmath.asinh, "asinh"), + (mpmath.atan, "atan"), + (mpmath.atanh, "atanh"), + (mpmath.cos, "cos"), + (mpmath.cosh, "cosh"), + (mpmath.csc, "csc"), + (mpmath.csch, "csch"), + (mpmath.cot, "cot"), + (mpmath.coth, "coth"), + (mpmath.sec, "sec"), + (mpmath.sech, "sech"), + (mpmath.sin, "sin"), + (mpmath.sinh, "sinh"), + (mpmath.tan, "tan"), + (mpmath.tanh, "tanh"), +] + +for func in funcs: + args = [ + (randint(-10, 10) / 10, 0), + (0, randint(-10, 10) / 10), + (randint(-10, 10) / 10, randint(-10, 10) / 10), + (randint(-10, 10) / 10, randint(-10, 10) / 10), + (randint(15, 30) / 10, 0), + (randint(-30, -15) / 10, 0), + (0, 0) + ] + + for arg in args: + result = 0 + defined = True + try: + result = func[0](complex(arg[0], arg[1])) + except: + defined = False + + print("({0}, ({1}f64, {2}f64), ({3}, {4})),".format( + func[1], + arg[0], + arg[1], + str(round(result.real, 7)) + "f64" if defined else "f64::NAN", + str(round(result.imag, 7)) + "f64" if defined else "f64::NAN")) diff --git a/kalk/src/calculus.rs b/kalk/src/calculus.rs index c8d05cc..57a3742 100644 --- a/kalk/src/calculus.rs +++ b/kalk/src/calculus.rs @@ -144,10 +144,6 @@ mod tests { ) } - fn cmp(x: f64, y: f64) -> bool { - (x - y).abs() < 0.0001 - } - #[test] fn test_derive_func() { let mut symbol_table = SymbolTable::new(); diff --git a/kalk/src/interpreter.rs b/kalk/src/interpreter.rs index a8f597e..f680d9a 100644 --- a/kalk/src/interpreter.rs +++ b/kalk/src/interpreter.rs @@ -272,25 +272,6 @@ pub(crate) fn eval_fn_call_expr( let prelude_func = match expressions.len() { 1 => { let x = eval_expr(context, &expressions[0], "")?; - - // Turn eg. sqrt(-1) into i - if x.value < 0f64 && (identifier.full_name == "sqrt" || identifier.full_name == "√") { - let abs_value = x.mul(context, KalkNum::from(-1f64)); - let (sqrt, unit) = prelude::call_unary_func( - context, - &identifier.full_name, - abs_value, - &context.angle_unit.clone(), - ) - .unwrap(); - - return Ok(KalkNum::new_with_imaginary( - KalkNum::default().value, - &unit, - sqrt.value, - )); - } - if identifier.prime_count > 0 { return calculus::derive_func(context, &identifier, x); } else { diff --git a/kalk/src/kalk_num/regular.rs b/kalk/src/kalk_num/regular.rs index 3b36edf..0dd5332 100644 --- a/kalk/src/kalk_num/regular.rs +++ b/kalk/src/kalk_num/regular.rs @@ -23,7 +23,11 @@ impl KalkNum { Self { value, unit: unit.to_string(), - imaginary_value, + imaginary_value: if imaginary_value == -0f64 { + 0f64 + } else { + imaginary_value + }, } } diff --git a/kalk/src/kalk_num/with_rug.rs b/kalk/src/kalk_num/with_rug.rs index b7686ee..c34b02c 100644 --- a/kalk/src/kalk_num/with_rug.rs +++ b/kalk/src/kalk_num/with_rug.rs @@ -26,7 +26,11 @@ impl KalkNum { Self { value, unit: unit.to_string(), - imaginary_value, + imaginary_value: if imaginary_value == -0f64 { + imaginary_value.abs() + } else { + imaginary_value + }, } } @@ -48,7 +52,7 @@ impl KalkNum { } pub fn to_i32(&self) -> i32 { - self.value.to_i32_saturating().unwrap() + self.value.to_i32_saturating().unwrap_or(0i32) } pub fn get_unit(&self) -> &str { diff --git a/kalk/src/prelude/mod.rs b/kalk/src/prelude/mod.rs index 2937dc0..493cf3d 100644 --- a/kalk/src/prelude/mod.rs +++ b/kalk/src/prelude/mod.rs @@ -234,7 +234,7 @@ pub mod funcs { } pub fn acos(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value > 1f64 || x.value < -1f64 { // -i * ln(i * sqrt(1 - z²) + z) let root = sqrt(KalkNum::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone()))); @@ -249,7 +249,7 @@ pub mod funcs { } pub fn acosh(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value < 1f64 { let sqrt1 = sqrt(KalkNum::new_with_imaginary( x.value.clone() + 1f64, &x.unit, @@ -277,7 +277,7 @@ pub mod funcs { } pub fn acoth(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value <= 1f64 || x.value >= -1f64 { // 1 / z let inv_x = KalkNum::from(1f64).div_without_unit(x); let ln1 = ln(KalkNum::new_with_imaginary( @@ -299,7 +299,7 @@ pub mod funcs { } pub fn acsc(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value < 1f64 || x.value > -1f64 { // asin(1/z) asin(KalkNum::from(1f64).div_without_unit(x)) } else { @@ -308,7 +308,7 @@ pub mod funcs { } pub fn acsch(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value == 0f64 { let inv_x2 = KalkNum::from(1f64).div_without_unit(x.clone().mul_without_unit(x.clone())); let sqrt = sqrt(KalkNum::new_with_imaginary( @@ -325,7 +325,7 @@ pub mod funcs { } pub fn asec(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value < 1f64 || x.value > -1f64 { // acos(1/z) acos(KalkNum::from(1f64).div_without_unit(x)) } else { @@ -334,7 +334,7 @@ pub mod funcs { } pub fn asech(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value <= 0f64 || x.value > 1f64 { // 1/z let inv_x = KalkNum::from(1f64).div_without_unit(x.clone()); // sqrt(1/z - 1) @@ -358,7 +358,7 @@ pub mod funcs { } pub fn asin(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value > 1f64 || x.value < -1f64 { // i * ln(sqrt(1 - z²) - iz) let root = sqrt(KalkNum::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone()))); @@ -388,26 +388,28 @@ pub mod funcs { pub fn atan(x: KalkNum) -> KalkNum { if x.has_imaginary() { let iz = multiply_with_i(x); - // 1 + iz - let numerator = KalkNum::new_with_imaginary( - 1f64 + iz.value.clone(), - &iz.unit, - iz.imaginary_value.clone(), - ); - // 1 - iz - let denominator = - KalkNum::new_with_imaginary(1f64 - iz.value, &iz.unit, -iz.imaginary_value); - let ln = ln(numerator.div_without_unit(denominator)); - // -0.5iz = -0.5i(a + bi) = b/2 - ai/2 - multiply_with_i(ln).div_without_unit(KalkNum::from(-2f64)) + // 1 - iz + let neg = KalkNum::new_with_imaginary( + 1f64 - iz.value.clone(), + &iz.unit, + -iz.imaginary_value.clone(), + ); + + // 1 + iz + let pos = KalkNum::new_with_imaginary(1f64 + iz.value, &iz.unit, iz.imaginary_value); + + // ln(1 - iz) - ln(1 + iz) + let ln = ln(neg).sub_without_unit(ln(pos)); + + multiply_with_i(ln).div_without_unit(KalkNum::from(2f64)) } else { KalkNum::new(x.value.atan(), &x.unit) } } pub fn atanh(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value >= 1f64 || x.value <= -1f64 { // 1/2 * log(z + 1) - 1/2 * log(-z + 1) let log1 = ln(KalkNum::new_with_imaginary( 1f64 + x.value.clone(), @@ -499,7 +501,7 @@ pub mod funcs { } pub fn log(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value < 0f64 { // ln(z) / ln(10) ln(x).div_without_unit(KalkNum::from(10f64.ln())) } else { @@ -508,7 +510,7 @@ pub mod funcs { } pub fn logx(x: KalkNum, y: KalkNum) -> KalkNum { - if x.has_imaginary() || y.has_imaginary() { + if x.has_imaginary() || y.has_imaginary() || x.value < 0f64 || y.value < 0f64 { // ln(z) / ln(n) ln(x).div_without_unit(ln(y)) } else { @@ -517,7 +519,7 @@ pub mod funcs { } pub fn ln(x: KalkNum) -> KalkNum { - if x.has_imaginary() { + if x.has_imaginary() || x.value < 0f64 { let r = abs(x.clone()); // ln|z| + i * arg z ln(r).add_without_unit(multiply_with_i(arg(x))) @@ -571,6 +573,8 @@ pub mod funcs { &abs.unit, (b.clone() / b.abs()) * ((r - a) / 2f64).sqrt(), ) + } else if x.value < 0f64 { + KalkNum::from_imaginary(x.value.abs().sqrt()) } else { KalkNum::new(x.value.sqrt(), &x.unit) } @@ -613,3 +617,304 @@ pub mod funcs { KalkNum::new_with_imaginary(-z.imaginary_value, &z.unit, z.value) } } + +#[cfg(test)] +mod tests { + use super::funcs::*; + use crate::prelude::KalkNum; + use crate::test_helpers::cmp; + + #[test] + fn test_funcs() { + let in_out = vec![ + (abs as fn(KalkNum) -> KalkNum, (3f64, 4f64), (5f64, 0f64)), + (abs, (-3f64, 4f64), (5f64, 0f64)), + (abs, (3f64, -4f64), (5f64, 0f64)), + (abs, (-3f64, 0f64), (3f64, 0f64)), + ]; + + for (i, (func, input, expected_output)) in in_out.iter().enumerate() { + let actual_output = func(KalkNum::new_with_imaginary( + KalkNum::from(input.0).value, + "", + KalkNum::from(input.1).value, + )); + + println!( + "{} | expected: {}, {}", + i, expected_output.0, expected_output.1 + ); + println!( + "{} | got: {}, {}", + i, + actual_output.to_f64(), + actual_output.imaginary_to_f64() + ); + assert!(cmp(expected_output.0, actual_output.to_f64())); + assert!(cmp(expected_output.1, actual_output.imaginary_to_f64())); + } + } + + #[test] + fn test_trig_funcs() { + // Auto-generated using kalk/scripts/generate_funcs_test_cases.py + let in_out = vec![ + ( + arg as fn(KalkNum) -> KalkNum, + (0.3f64, 0f64), + (0.0f64, 0.0f64), + ), + (arg, (0f64, 0.0f64), (0.0f64, 0.0f64)), + (arg, (-0.1f64, -0.5f64), (-1.7681919f64, 0.0f64)), + (arg, (0.6f64, -0.5f64), (-0.6947383f64, 0.0f64)), + (arg, (2.8f64, 0f64), (0.0f64, 0.0f64)), + (arg, (-2.6f64, 0f64), (3.1415927f64, 0.0f64)), + (arg, (0f64, 0f64), (0.0f64, 0.0f64)), + (ceil, (0.2f64, 0f64), (1.0f64, 0.0f64)), + (ceil, (0f64, -0.7f64), (0.0f64, 0.0f64)), + (ceil, (-0.8f64, -0.3f64), (0.0f64, 0.0f64)), + (ceil, (0.5f64, -0.6f64), (1.0f64, 0.0f64)), + (ceil, (2.2f64, 0f64), (3.0f64, 0.0f64)), + (ceil, (-2.7f64, 0f64), (-2.0f64, 0.0f64)), + (ceil, (0f64, 0f64), (0.0f64, 0.0f64)), + (exp, (-0.3f64, 0f64), (0.7408182f64, 0.0f64)), + (exp, (0f64, -1.0f64), (0.5403023f64, -0.841471f64)), + (exp, (0.5f64, 0.8f64), (1.1486752f64, 1.1827202f64)), + (exp, (-0.8f64, 0.5f64), (0.3943233f64, 0.2154198f64)), + (exp, (2.9f64, 0f64), (18.1741454f64, 0.0f64)), + (exp, (-2.0f64, 0f64), (0.1353353f64, 0.0f64)), + (exp, (0f64, 0f64), (1.0f64, 0.0f64)), + (floor, (-0.8f64, 0f64), (-1.0f64, 0.0f64)), + (floor, (0f64, 0.4f64), (0.0f64, 0.0f64)), + (floor, (0.1f64, 0.8f64), (0.0f64, 0.0f64)), + (floor, (0.6f64, -0.4f64), (0.0f64, -1.0f64)), + (floor, (1.8f64, 0f64), (1.0f64, 0.0f64)), + (floor, (-1.8f64, 0f64), (-2.0f64, 0.0f64)), + (floor, (0f64, 0f64), (0.0f64, 0.0f64)), + (log, (0.4f64, 0f64), (-0.39794f64, 0.0f64)), + (log, (0f64, -0.6f64), (-0.2218487f64, -0.6821882f64)), + (log, (0.6f64, 0.1f64), (-0.2158991f64, 0.0717232f64)), + (log, (-0.7f64, -0.8f64), (0.0265392f64, -0.9943721f64)), + (log, (2.2f64, 0f64), (0.3424227f64, 0.0f64)), + (log, (-2.9f64, 0f64), (0.462398f64, 1.3643764f64)), + (log, (0f64, 0f64), (f64::NEG_INFINITY, 0.0f64)), + (ln, (0.3f64, 0f64), (-1.2039728f64, 0.0f64)), + (ln, (0f64, 0.0f64), (f64::NEG_INFINITY, 0.0f64)), + (ln, (-1.0f64, 0.8f64), (0.2473481f64, 2.4668517f64)), + (ln, (-0.2f64, 1.0f64), (0.0196104f64, 1.7681919f64)), + (ln, (1.5f64, 0f64), (0.4054651f64, 0.0f64)), + (ln, (-2.4f64, 0f64), (0.8754687f64, 3.1415927f64)), + (ln, (0f64, 0f64), (f64::NEG_INFINITY, 0.0f64)), + (sqrt, (-0.9f64, 0f64), (0.0f64, 0.9486833f64)), + (sqrt, (0f64, 0.3f64), (0.3872983f64, 0.3872983f64)), + (sqrt, (0.6f64, -0.2f64), (0.7850018f64, -0.1273882f64)), + (sqrt, (0.0f64, 0.4f64), (0.4472136f64, 0.4472136f64)), + (sqrt, (2.5f64, 0f64), (1.5811388f64, 0.0f64)), + (sqrt, (-2.5f64, 0f64), (0.0f64, 1.5811388f64)), + (sqrt, (0f64, 0f64), (0.0f64, 0.0f64)), + (acos, (-0.8f64, 0f64), (2.4980915f64, 0.0f64)), + (acos, (0f64, 0.4f64), (1.5707963f64, -0.3900353f64)), + (acos, (-0.5f64, 0.9f64), (1.9389155f64, -0.8561366f64)), + (acos, (0.4f64, -1.0f64), (1.2899829f64, 0.9099081f64)), + (acos, (2.2f64, 0f64), (0.0f64, 1.4254169f64)), + (acos, (-1.5f64, 0f64), (3.1415927f64, -0.9624237f64)), + (acos, (0f64, 0f64), (1.5707963f64, 0.0f64)), + (acosh, (0.6f64, 0f64), (0.0f64, 0.9272952f64)), + (acosh, (0f64, 0.5f64), (0.4812118f64, 1.5707963f64)), + (acosh, (1.0f64, -1.0f64), (1.0612751f64, -0.9045569f64)), + (acosh, (0.5f64, 0.6f64), (0.6197743f64, 1.1403656f64)), + (acosh, (2.2f64, 0f64), (1.4254169f64, 0.0f64)), + (acosh, (-2.7f64, 0f64), (1.6501935f64, 3.1415927f64)), + (acosh, (0f64, 0f64), (0.0f64, 1.5707963f64)), + (acsc, (-0.9f64, 0f64), (-1.5707963f64, 0.4671453f64)), + (acsc, (0f64, -0.9f64), (0.0f64, 0.9578004f64)), + (acsc, (0.8f64, -0.6f64), (0.6847192f64, 0.7127085f64)), + (acsc, (0.3f64, -0.5f64), (0.4742891f64, 1.2767722f64)), + (acsc, (2.7f64, 0f64), (0.3794077f64, 0.0f64)), + (acsc, (-1.7f64, 0f64), (-0.6288749f64, 0.0f64)), + (acsc, (0f64, 0f64), (f64::NAN, f64::NAN)), + (acsch, (-0.8f64, 0f64), (-1.047593f64, 0.0f64)), + (acsch, (0f64, 0.4f64), (-1.5667992f64, -1.5707963f64)), + (acsch, (-0.1f64, -0.9f64), (-0.5019389f64, 1.335583f64)), + (acsch, (1.0f64, -0.7f64), (0.6735491f64, 0.3900529f64)), + (acsch, (2.5f64, 0f64), (0.3900353f64, 0.0f64)), + (acsch, (-2.4f64, 0f64), (-0.4054651f64, 0.0f64)), + (acsch, (0f64, 0f64), (f64::NAN, f64::NAN)), + (acot, (-1.0f64, 0f64), (-0.7853982f64, 0.0f64)), + (acot, (0f64, -0.5f64), (1.5707963f64, 0.5493061f64)), + (acot, (-0.4f64, -0.4f64), (-1.1376452f64, 0.3513356f64)), + (acot, (-0.9f64, -0.7f64), (-0.7028238f64, 0.3534233f64)), + (acot, (2.3f64, 0f64), (0.4101273f64, 0.0f64)), + (acot, (-1.7f64, 0f64), (-0.5317241f64, 0.0f64)), + (acot, (0f64, 0f64), (1.5707963f64, 0.0f64)), + (acoth, (0.5f64, 0f64), (0.5493061f64, -1.5707963f64)), + (acoth, (0f64, 0.9f64), (0.0f64, -0.8379812f64)), + (acoth, (-0.4f64, -0.1f64), (-0.4180715f64, 1.4525683f64)), + (acoth, (-0.9f64, -0.5f64), (-0.6744352f64, 0.7554341f64)), + (acoth, (1.7f64, 0f64), (0.6749634f64, 0.0f64)), + (acoth, (-2.1f64, 0f64), (-0.518046f64, 0.0f64)), + (acoth, (0f64, 0f64), (0.0f64, 1.5707963f64)), + (asec, (-0.1f64, 0f64), (3.1415927f64, -2.9932228f64)), + (asec, (0f64, 0.7f64), (1.5707963f64, 1.1544774f64)), + (asec, (0.9f64, -0.4f64), (0.6818568f64, -0.6148366f64)), + (asec, (-0.5f64, 0.9f64), (1.9278638f64, 0.8134796f64)), + (asec, (1.5f64, 0f64), (0.8410687f64, 0.0f64)), + (asec, (-2.7f64, 0f64), (1.950204f64, 0.0f64)), + (asec, (0f64, 0f64), (f64::NAN, f64::NAN)), + (asech, (0.6f64, 0f64), (1.0986123f64, 0.0f64)), + (asech, (0f64, -1.0f64), (0.8813736f64, 1.5707963f64)), + (asech, (0.1f64, -0.7f64), (1.1434743f64, 1.4548078f64)), + (asech, (-0.4f64, -0.3f64), (1.3742673f64, 2.4355905f64)), + (asech, (2.3f64, 0f64), (0.0f64, 1.1209995f64)), + (asech, (-2.2f64, 0f64), (0.0f64, 2.0426582f64)), + (asech, (0f64, 0f64), (f64::NAN, f64::NAN)), + (asin, (-0.8f64, 0f64), (-0.9272952f64, 0.0f64)), + (asin, (0f64, 0.5f64), (0.0f64, 0.4812118f64)), + (asin, (-0.2f64, -1.0f64), (-0.1411811f64, -0.8884618f64)), + (asin, (-0.8f64, 0.3f64), (-0.8214537f64, 0.427304f64)), + (asin, (1.5f64, 0f64), (1.5707963f64, -0.9624237f64)), + (asin, (-3.0f64, 0f64), (-1.5707963f64, 1.7627472f64)), + (asin, (0f64, 0f64), (0.0f64, 0.0f64)), + (asinh, (1.0f64, 0f64), (0.8813736f64, 0.0f64)), + (asinh, (0f64, 0.1f64), (0.0f64, 0.1001674f64)), + (asinh, (0.9f64, 1.0f64), (1.0029766f64, 0.7031f64)), + (asinh, (-0.5f64, 0.8f64), (-0.627368f64, 0.7272513f64)), + (asinh, (1.8f64, 0f64), (1.3504407f64, 0.0f64)), + (asinh, (-2.4f64, 0f64), (-1.6094379f64, 0.0f64)), + (asinh, (0f64, 0f64), (0.0f64, 0.0f64)), + (atan, (0.0f64, 0f64), (0.0f64, 0.0f64)), + (atan, (0f64, 0.8f64), (0.0f64, 1.0986123f64)), + (atan, (0.4f64, 0.2f64), (0.3926991f64, 0.1732868f64)), + (atan, (0.4f64, -0.3f64), (0.4088225f64, -0.2614921f64)), + (atan, (1.5f64, 0f64), (0.9827937f64, 0.0f64)), + (atan, (-1.8f64, 0f64), (-1.0636978f64, 0.0f64)), + (atan, (0f64, 0f64), (0.0f64, 0.0f64)), + (atanh, (0.9f64, 0f64), (1.4722195f64, 0.0f64)), + (atanh, (0f64, -0.1f64), (0.0f64, -0.0996687f64)), + (atanh, (-1.0f64, -0.3f64), (-0.9541226f64, -0.8598431f64)), + (atanh, (0.6f64, -0.4f64), (0.5350165f64, -0.5151884f64)), + (atanh, (1.5f64, 0f64), (0.804719f64, -1.5707963f64)), + (atanh, (-2.3f64, 0f64), (-0.4657791f64, 1.5707963f64)), + (atanh, (0f64, 0f64), (0.0f64, 0.0f64)), + (cos, (0.1f64, 0f64), (0.9950042f64, 0.0f64)), + (cos, (0f64, -0.2f64), (1.0200668f64, 0.0f64)), + (cos, (-0.1f64, -0.1f64), (0.9999833f64, -0.01f64)), + (cos, (0.5f64, -0.4f64), (0.9487303f64, 0.1969252f64)), + (cos, (2.4f64, 0f64), (-0.7373937f64, 0.0f64)), + (cos, (-2.2f64, 0f64), (-0.5885011f64, 0.0f64)), + (cos, (0f64, 0f64), (1.0f64, 0.0f64)), + (cosh, (0.0f64, 0f64), (1.0f64, 0.0f64)), + (cosh, (0f64, 0.9f64), (0.62161f64, 0.0f64)), + (cosh, (0.8f64, -0.4f64), (1.2318592f64, -0.3458448f64)), + (cosh, (-0.2f64, 1.0f64), (0.5511444f64, -0.1694184f64)), + (cosh, (2.9f64, 0f64), (9.1145843f64, 0.0f64)), + (cosh, (-2.7f64, 0f64), (7.4734686f64, 0.0f64)), + (cosh, (0f64, 0f64), (1.0f64, 0.0f64)), + (csc, (0.5f64, 0f64), (2.0858296f64, 0.0f64)), + (csc, (0f64, -0.6f64), (0.0f64, 1.5707129f64)), + (csc, (-0.9f64, -0.7f64), (-0.8268848f64, 0.3965713f64)), + (csc, (0.3f64, -0.5f64), (0.9285645f64, 1.3871816f64)), + (csc, (2.3f64, 0f64), (1.3410125f64, 0.0f64)), + (csc, (-2.5f64, 0f64), (-1.6709215f64, 0.0f64)), + (csc, (0f64, 0f64), (f64::NAN, f64::NAN)), + (csch, (-0.8f64, 0f64), (-1.1259917f64, 0.0f64)), + (csch, (0f64, 0.7f64), (0.0f64, -1.5522703f64)), + (csch, (0.6f64, -0.4f64), (1.0528253f64, 0.8288386f64)), + (csch, (-0.4f64, 0.0f64), (-2.4345571f64, 0.0f64)), + (csch, (2.7f64, 0f64), (0.1350209f64, 0.0f64)), + (csch, (-3.0f64, 0f64), (-0.0998216f64, 0.0f64)), + (csch, (0f64, 0f64), (f64::NAN, f64::NAN)), + (cot, (-0.3f64, 0f64), (-3.2327281f64, 0.0f64)), + (cot, (0f64, 0.4f64), (0.0f64, -2.6319324f64)), + (cot, (-0.9f64, 0.4f64), (-0.6224112f64, -0.5676115f64)), + (cot, (-0.2f64, 0.8f64), (-0.2350987f64, -1.4341723f64)), + (cot, (1.7f64, 0f64), (-0.1299275f64, 0.0f64)), + (cot, (-1.8f64, 0f64), (0.2333035f64, 0.0f64)), + (cot, (0f64, 0f64), (f64::NAN, f64::NAN)), + (coth, (0.3f64, 0f64), (3.4327384f64, 0.0f64)), + (coth, (0f64, 0.9f64), (0.0f64, -0.7935511f64)), + (coth, (-0.7f64, -0.5f64), (-1.1823582f64, 0.5224593f64)), + (coth, (-0.8f64, -0.3f64), (-1.3558181f64, 0.3222608f64)), + (coth, (2.8f64, 0f64), (1.0074232f64, 0.0f64)), + (coth, (-2.3f64, 0f64), (-1.0203078f64, 0.0f64)), + (coth, (0f64, 0f64), (f64::NAN, f64::NAN)), + (sec, (0.4f64, 0f64), (1.0857044f64, 0.0f64)), + (sec, (0f64, -0.7f64), (0.7967055f64, 0.0f64)), + (sec, (0.7f64, -0.2f64), (1.2472669f64, -0.2073543f64)), + (sec, (0.0f64, 0.1f64), (0.9950207f64, 0.0f64)), + (sec, (1.5f64, 0f64), (14.1368329f64, 0.0f64)), + (sec, (-1.6f64, 0f64), (-34.2471356f64, 0.0f64)), + (sec, (0f64, 0f64), (1.0f64, 0.0f64)), + (sech, (-0.6f64, 0f64), (0.8435507f64, 0.0f64)), + (sech, (0f64, 1.0f64), (1.8508157f64, 0.0f64)), + (sech, (0.5f64, -0.9f64), (1.0653621f64, 0.6204037f64)), + (sech, (-0.8f64, 0.9f64), (0.7074639f64, 0.5919997f64)), + (sech, (2.0f64, 0f64), (0.2658022f64, 0.0f64)), + (sech, (-2.0f64, 0f64), (0.2658022f64, 0.0f64)), + (sech, (0f64, 0f64), (1.0f64, 0.0f64)), + (sin, (1.0f64, 0f64), (0.841471f64, 0.0f64)), + (sin, (0f64, -0.3f64), (0.0f64, -0.3045203f64)), + (sin, (-0.1f64, -0.6f64), (-0.118349f64, -0.633473f64)), + (sin, (-0.4f64, 0.4f64), (-0.4209894f64, 0.3783279f64)), + (sin, (2.8f64, 0f64), (0.3349882f64, 0.0f64)), + (sin, (-2.0f64, 0f64), (-0.9092974f64, 0.0f64)), + (sin, (0f64, 0f64), (0.0f64, 0.0f64)), + (sinh, (-0.4f64, 0f64), (-0.4107523f64, 0.0f64)), + (sinh, (0f64, -1.0f64), (0.0f64, -0.841471f64)), + (sinh, (-0.9f64, -0.4f64), (-0.9454845f64, -0.5580701f64)), + (sinh, (0.0f64, 0.9f64), (0.0f64, 0.7833269f64)), + (sinh, (2.7f64, 0f64), (7.4062631f64, 0.0f64)), + (sinh, (-1.9f64, 0f64), (-3.2681629f64, 0.0f64)), + (sinh, (0f64, 0f64), (0.0f64, 0.0f64)), + (tan, (-0.6f64, 0f64), (-0.6841368f64, 0.0f64)), + (tan, (0f64, -0.9f64), (0.0f64, -0.7162979f64)), + (tan, (-0.1f64, 0.1f64), (-0.099328f64, 0.1006613f64)), + (tan, (0.7f64, -0.1f64), (0.8280854f64, -0.1691851f64)), + (tan, (2.8f64, 0f64), (-0.3555298f64, 0.0f64)), + (tan, (-1.6f64, 0f64), (34.2325327f64, 0.0f64)), + (tan, (0f64, 0f64), (0.0f64, 0.0f64)), + (tanh, (-0.4f64, 0f64), (-0.379949f64, 0.0f64)), + (tanh, (0f64, -0.3f64), (0.0f64, -0.3093362f64)), + (tanh, (-0.8f64, 0.5f64), (-0.7619454f64, 0.2698954f64)), + (tanh, (-0.3f64, 0.0f64), (-0.2913126f64, 0.0f64)), + (tanh, (1.5f64, 0f64), (0.9051483f64, 0.0f64)), + (tanh, (-2.3f64, 0f64), (-0.9800964f64, 0.0f64)), + (tanh, (0f64, 0f64), (0.0f64, 0.0f64)), + ]; + + for (i, (func, input, expected_output)) in in_out.iter().enumerate() { + let actual_output = func(KalkNum::new_with_imaginary( + KalkNum::from(input.0).value, + "", + KalkNum::from(input.1).value, + )); + + let expected_has_nan_or_inf = expected_output.0.is_nan() + || expected_output.0.is_infinite() + || expected_output.1.is_nan() + || expected_output.1.is_infinite(); + let actual_has_nan_or_inf = actual_output.to_f64().is_nan() + || actual_output.to_f64().is_infinite() + || actual_output.imaginary_to_f64().is_nan() + || actual_output.imaginary_to_f64().is_infinite(); + + if expected_has_nan_or_inf || actual_has_nan_or_inf { + assert!(true); + continue; + } + + println!( + "{} | expected: {}, {}", + i, expected_output.0, expected_output.1 + ); + println!( + "{} | got: {}, {}", + i, + actual_output.to_f64(), + actual_output.imaginary_to_f64() + ); + assert!(cmp(expected_output.0, actual_output.to_f64())); + assert!(cmp(expected_output.1, actual_output.imaginary_to_f64())); + } + } +} diff --git a/kalk/src/prelude/with_rug.rs b/kalk/src/prelude/with_rug.rs index 1adf48a..4a2f3ab 100644 --- a/kalk/src/prelude/with_rug.rs +++ b/kalk/src/prelude/with_rug.rs @@ -11,7 +11,6 @@ pub(crate) mod funcs { use crate::prelude::funcs::abs; pub fn arg(x: KalkNum) -> KalkNum { - // i(ln|x| - ln(x)) KalkNum::new(x.imaginary_value.atan2(&x.value), &x.unit) } diff --git a/kalk/src/test_helpers.rs b/kalk/src/test_helpers.rs index 48e470e..1111e11 100755 --- a/kalk/src/test_helpers.rs +++ b/kalk/src/test_helpers.rs @@ -13,6 +13,10 @@ pub fn token(kind: TokenKind, value: &str) -> Token { } } +pub fn cmp(x: f64, y: f64) -> bool { + (x - y).abs() < 0.0001 +} + pub fn literal(value: f64) -> Box { Box::new(Expr::Literal(value)) }