Added tests for prelude functions

This commit is contained in:
bakk 2021-05-25 21:29:59 +02:00
parent 2a7c403c56
commit 16655680e1
8 changed files with 409 additions and 51 deletions

View File

@ -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"))

View File

@ -144,10 +144,6 @@ mod tests {
) )
} }
fn cmp(x: f64, y: f64) -> bool {
(x - y).abs() < 0.0001
}
#[test] #[test]
fn test_derive_func() { fn test_derive_func() {
let mut symbol_table = SymbolTable::new(); let mut symbol_table = SymbolTable::new();

View File

@ -272,25 +272,6 @@ pub(crate) fn eval_fn_call_expr(
let prelude_func = match expressions.len() { let prelude_func = match expressions.len() {
1 => { 1 => {
let x = eval_expr(context, &expressions[0], "")?; 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 { if identifier.prime_count > 0 {
return calculus::derive_func(context, &identifier, x); return calculus::derive_func(context, &identifier, x);
} else { } else {

View File

@ -23,7 +23,11 @@ impl KalkNum {
Self { Self {
value, value,
unit: unit.to_string(), unit: unit.to_string(),
imaginary_value, imaginary_value: if imaginary_value == -0f64 {
0f64
} else {
imaginary_value
},
} }
} }

View File

@ -26,7 +26,11 @@ impl KalkNum {
Self { Self {
value, value,
unit: unit.to_string(), 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 { 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 { pub fn get_unit(&self) -> &str {

View File

@ -234,7 +234,7 @@ pub mod funcs {
} }
pub fn acos(x: KalkNum) -> KalkNum { 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) // -i * ln(i * sqrt(1 - z²) + z)
let root = let root =
sqrt(KalkNum::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone()))); 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 { pub fn acosh(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value < 1f64 {
let sqrt1 = sqrt(KalkNum::new_with_imaginary( let sqrt1 = sqrt(KalkNum::new_with_imaginary(
x.value.clone() + 1f64, x.value.clone() + 1f64,
&x.unit, &x.unit,
@ -277,7 +277,7 @@ pub mod funcs {
} }
pub fn acoth(x: KalkNum) -> KalkNum { pub fn acoth(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value <= 1f64 || x.value >= -1f64 {
// 1 / z // 1 / z
let inv_x = KalkNum::from(1f64).div_without_unit(x); let inv_x = KalkNum::from(1f64).div_without_unit(x);
let ln1 = ln(KalkNum::new_with_imaginary( let ln1 = ln(KalkNum::new_with_imaginary(
@ -299,7 +299,7 @@ pub mod funcs {
} }
pub fn acsc(x: KalkNum) -> KalkNum { pub fn acsc(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value < 1f64 || x.value > -1f64 {
// asin(1/z) // asin(1/z)
asin(KalkNum::from(1f64).div_without_unit(x)) asin(KalkNum::from(1f64).div_without_unit(x))
} else { } else {
@ -308,7 +308,7 @@ pub mod funcs {
} }
pub fn acsch(x: KalkNum) -> KalkNum { pub fn acsch(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value == 0f64 {
let inv_x2 = let inv_x2 =
KalkNum::from(1f64).div_without_unit(x.clone().mul_without_unit(x.clone())); KalkNum::from(1f64).div_without_unit(x.clone().mul_without_unit(x.clone()));
let sqrt = sqrt(KalkNum::new_with_imaginary( let sqrt = sqrt(KalkNum::new_with_imaginary(
@ -325,7 +325,7 @@ pub mod funcs {
} }
pub fn asec(x: KalkNum) -> KalkNum { pub fn asec(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value < 1f64 || x.value > -1f64 {
// acos(1/z) // acos(1/z)
acos(KalkNum::from(1f64).div_without_unit(x)) acos(KalkNum::from(1f64).div_without_unit(x))
} else { } else {
@ -334,7 +334,7 @@ pub mod funcs {
} }
pub fn asech(x: KalkNum) -> KalkNum { pub fn asech(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value <= 0f64 || x.value > 1f64 {
// 1/z // 1/z
let inv_x = KalkNum::from(1f64).div_without_unit(x.clone()); let inv_x = KalkNum::from(1f64).div_without_unit(x.clone());
// sqrt(1/z - 1) // sqrt(1/z - 1)
@ -358,7 +358,7 @@ pub mod funcs {
} }
pub fn asin(x: KalkNum) -> KalkNum { 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) // i * ln(sqrt(1 - z²) - iz)
let root = let root =
sqrt(KalkNum::from(1f64).sub_without_unit(x.clone().mul_without_unit(x.clone()))); 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 { pub fn atan(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() {
let iz = multiply_with_i(x); 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 // 1 - iz
multiply_with_i(ln).div_without_unit(KalkNum::from(-2f64)) 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 { } else {
KalkNum::new(x.value.atan(), &x.unit) KalkNum::new(x.value.atan(), &x.unit)
} }
} }
pub fn atanh(x: KalkNum) -> KalkNum { 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) // 1/2 * log(z + 1) - 1/2 * log(-z + 1)
let log1 = ln(KalkNum::new_with_imaginary( let log1 = ln(KalkNum::new_with_imaginary(
1f64 + x.value.clone(), 1f64 + x.value.clone(),
@ -499,7 +501,7 @@ pub mod funcs {
} }
pub fn log(x: KalkNum) -> KalkNum { pub fn log(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value < 0f64 {
// ln(z) / ln(10) // ln(z) / ln(10)
ln(x).div_without_unit(KalkNum::from(10f64.ln())) ln(x).div_without_unit(KalkNum::from(10f64.ln()))
} else { } else {
@ -508,7 +510,7 @@ pub mod funcs {
} }
pub fn logx(x: KalkNum, y: KalkNum) -> KalkNum { 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(z) / ln(n)
ln(x).div_without_unit(ln(y)) ln(x).div_without_unit(ln(y))
} else { } else {
@ -517,7 +519,7 @@ pub mod funcs {
} }
pub fn ln(x: KalkNum) -> KalkNum { pub fn ln(x: KalkNum) -> KalkNum {
if x.has_imaginary() { if x.has_imaginary() || x.value < 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)))
@ -571,6 +573,8 @@ pub mod funcs {
&abs.unit, &abs.unit,
(b.clone() / b.abs()) * ((r - a) / 2f64).sqrt(), (b.clone() / b.abs()) * ((r - a) / 2f64).sqrt(),
) )
} else if x.value < 0f64 {
KalkNum::from_imaginary(x.value.abs().sqrt())
} else { } else {
KalkNum::new(x.value.sqrt(), &x.unit) 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) 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()));
}
}
}

View File

@ -11,7 +11,6 @@ pub(crate) mod funcs {
use crate::prelude::funcs::abs; use crate::prelude::funcs::abs;
pub fn arg(x: KalkNum) -> KalkNum { pub fn arg(x: KalkNum) -> KalkNum {
// i(ln|x| - ln(x))
KalkNum::new(x.imaginary_value.atan2(&x.value), &x.unit) KalkNum::new(x.imaginary_value.atan2(&x.value), &x.unit)
} }

View File

@ -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<Expr> { pub fn literal(value: f64) -> Box<Expr> {
Box::new(Expr::Literal(value)) Box::new(Expr::Literal(value))
} }