From 3f916efb6419aefc690ff45398fded1663245432 Mon Sep 17 00:00:00 2001 From: Archan Patkar Date: Mon, 8 Jul 2019 23:11:37 +0530 Subject: [PATCH] math: additional complex operations with tests --- vlib/math/complex.v | 63 ++++++++++++++++++++ vlib/math/complex_test.v | 125 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) diff --git a/vlib/math/complex.v b/vlib/math/complex.v index 87782410b9..d98172dcff 100644 --- a/vlib/math/complex.v +++ b/vlib/math/complex.v @@ -92,6 +92,69 @@ pub fn (c1 Complex) conjugate() Complex{ return Complex{c1.re,-c1.im} } +// Complex Additive Inverse +// Based on +// http://tutorial.math.lamar.edu/Extras/ComplexPrimer/Arithmetic.aspx +pub fn (c1 Complex) addinv() Complex { + return Complex{-c1.re,-c1.im} +} + +// Complex Multiplicative Inverse +// Based on +// http://tutorial.math.lamar.edu/Extras/ComplexPrimer/Arithmetic.aspx +pub fn (c1 Complex) mulinv() Complex { + return Complex { + c1.re / (pow(c1.re,2) + pow(c1.im,2)), + -c1.im / (pow(c1.re,2) + pow(c1.im,2)) + } +} + +// Complex Mod or Absolute +// Based on +// http://tutorial.math.lamar.edu/Extras/ComplexPrimer/ConjugateModulus.aspx +pub fn (c1 Complex) mod() f64 { + return sqrt(pow(c1.re,2)+pow(c1.im,2)) +} + +// Complex Power +// Based on +// https://www.khanacademy.org/math/precalculus/imaginary-and-complex-numbers/multiplying-and-dividing-complex-numbers-in-polar-form/a/complex-number-polar-form-review +pub fn (c1 Complex) pow(n f64) Complex { + r := pow(c1.mod(),n) + angle := atan2(c1.im,c1.re) + return Complex { + r * cos(n*angle), + r * sin(n*angle) + } +} + +// Complex nth root +pub fn (c1 Complex) root(n f64) Complex { + return c1.pow(1.0/n) +} + +// Complex Exponential +// Using Euler's Identity +// Based on +// https://www.math.wisc.edu/~angenent/Free-Lecture-Notes/freecomplexnumbers.pdf +pub fn (c1 Complex) exp() Complex { + a := exp(c1.re) + return Complex { + a * cos(c1.im), + a * sin(c1.im) + } +} + +// Complex Natural Logarithm +// Based on +// http://www.chemistrylearning.com/logarithm-of-complex-number/ +pub fn (c1 Complex) ln() Complex { + return Complex { + log(c1.mod()), + atan2(c1.im,c1.re) + } +} + // Complex Equals pub fn (c1 Complex) equals(c2 Complex) bool { return (c1.re == c2.re) && (c1.im == c2.im) diff --git a/vlib/math/complex_test.v b/vlib/math/complex_test.v index 0f2c637d32..0e9b5dafea 100644 --- a/vlib/math/complex_test.v +++ b/vlib/math/complex_test.v @@ -117,3 +117,128 @@ fn test_complex_angle(){ mut cc := c.conjugate() assert cc.angle() + c.angle() == 0 } + + +fn test_complex_addinv() { + // Tests were also verified on Wolfram Alpha + mut c1 := math.complex(5,7) + mut c2 := math.complex(-5,-7) + mut result := c1.addinv() + assert result.equals(c2) + c1 = math.complex(-3,4) + c2 = math.complex(3,-4) + result = c1.addinv() + assert result.equals(c2) + c1 = math.complex(-1,-2) + c2 = math.complex(1,2) + result = c1.addinv() + assert result.equals(c2) +} + +fn test_complex_mulinv() { + // Tests were also verified on Wolfram Alpha + mut c1 := math.complex(5,7) + mut c2 := math.complex(0.067568,-0.094595) + mut result := c1.mulinv() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-3,4) + c2 = math.complex(-0.12,-0.16) + result = c1.mulinv() + assert result.str().eq(c2.str()) + c1 = math.complex(-1,-2) + c2 = math.complex(-0.2,0.4) + result = c1.mulinv() + assert result.equals(c2) +} + +fn test_complex_mod() { + // Tests were also verified on Wolfram Alpha + mut c1 := math.complex(5,7) + mut result := c1.mod() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq('8.602325') + c1 = math.complex(-3,4) + result = c1.mod() + assert result == 5 + c1 = math.complex(-1,-2) + result = c1.mod() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq('2.236068') +} + +fn test_complex_pow() { + // Tests were also verified on Wolfram Alpha + mut c1 := math.complex(5,7) + mut c2 := math.complex(-24.0,70.0) + mut result := c1.pow(2) + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-3,4) + c2 = math.complex(117,44) + result = c1.pow(3) + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-1,-2) + c2 = math.complex(-7,-24) + result = c1.pow(4) + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) +} + +fn test_complex_root() { + // Tests were also verified on Wolfram Alpha + mut c1 := math.complex(5,7) + mut c2 := math.complex(2.607904,1.342074) + mut result := c1.root(2) + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-3,4) + c2 = math.complex(1.264953,1.150614) + result = c1.root(3) + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-1,-2) + c2 = math.complex(1.068059,-0.595482) + result = c1.root(4) + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) +} + +fn test_complex_exp() { + // Tests were also verified on Wolfram Alpha + mut c1 := math.complex(5,7) + mut c2 := math.complex(111.889015,97.505457) + mut result := c1.exp() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-3,4) + c2 = math.complex(-0.032543,-0.037679) + result = c1.exp() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-1,-2) + c2 = math.complex(-0.153092,-0.334512) + result = c1.exp() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) +} + +fn test_complex_ln() { + // Tests were also verified on Wolfram Alpha + mut c1 := math.complex(5,7) + mut c2 := math.complex(2.152033,0.950547) + mut result := c1.ln() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-3,4) + c2 = math.complex(1.609438,2.214297) + result = c1.ln() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) + c1 = math.complex(-1,-2) + c2 = math.complex(0.804719,-2.034444) + result = c1.ln() + // Some issue with precision comparison in f64 using == operator hence serializing to string + assert result.str().eq(c2.str()) +}