2013-09-29 08:16:03 -04:00
|
|
|
//
|
2013-09-29 08:13:36 -04:00
|
|
|
// FILE: Complex.cpp
|
|
|
|
// AUTHOR: Rob Tillaart
|
2018-04-02 14:48:12 -04:00
|
|
|
// VERSION: 0.1.12
|
2013-09-29 08:13:36 -04:00
|
|
|
// PURPOSE: library for Complex math for Arduino
|
2013-09-29 08:22:21 -04:00
|
|
|
// URL: http://arduino.cc/playground/Main/ComplexMath
|
2013-09-29 08:16:03 -04:00
|
|
|
//
|
2013-09-29 08:13:36 -04:00
|
|
|
// Released to the public domain
|
|
|
|
//
|
2018-04-02 14:48:12 -04:00
|
|
|
// 0.1.12 - 2018-04-02 - fix issue #33 double -> float
|
|
|
|
// 0.1.11 - 2018-01-29 - fix sin and cos formula - issue #91
|
2018-01-29 03:28:23 -05:00
|
|
|
// 0.1.10 - 2018-01-15 - uppercase #define COMPLEX_H
|
|
|
|
// 0.1.09 - 2016-10-15 - added (0,0) constructor
|
|
|
|
// 0.1.08 - 2015-06-03 - refactor
|
|
|
|
// 0.1.07 - 2015-06-03 - refactor interfaces
|
2013-09-29 08:16:03 -04:00
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
#include "complex.h"
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
// PRINTING
|
|
|
|
size_t Complex::printTo(Print& p) const
|
2013-09-29 08:16:03 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
size_t n = 0;
|
|
|
|
n += p.print(re, 3);
|
|
|
|
n += p.print(' ');
|
|
|
|
n += p.print(im, 3);
|
|
|
|
n += p.print('i');
|
|
|
|
return n;
|
2015-03-06 04:41:34 -05:00
|
|
|
};
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2018-04-02 14:48:12 -04:00
|
|
|
void Complex::polar(const float modulus, const float phase)
|
2013-09-29 08:16:03 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
re = modulus * cos(phase);
|
|
|
|
im = modulus * sin(phase);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::reciprocal()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float f = 1.0/(re*re + im*im);
|
|
|
|
float r = re*f;
|
|
|
|
float i = -im*f;
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(r,i);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:31:13 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
// EQUALITIES
|
2015-03-06 04:41:34 -05:00
|
|
|
bool Complex::operator == (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (re == c.re) && (im == c.im);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
bool Complex::operator != (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (re != c.re) || (im != c.im);
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
// NEGATE
|
|
|
|
Complex Complex::operator - ()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(-re, -im);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
// BASIC MATH
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex Complex::operator + (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(re + c.re, im + c.im);
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex Complex::operator - (const Complex &c)
|
2013-09-29 08:16:03 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(re - c.re, im - c.im);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex Complex::operator * (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float r = re * c.re - im * c.im;
|
|
|
|
float i = re * c.im + im * c.re;
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(r, i);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex Complex::operator / (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float f = 1.0/(c.re*c.re + c.im*c.im);
|
|
|
|
float r = (re * c.re + im * c.im) * f;
|
|
|
|
float i = (im * c.re - re * c.im) * f;
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(r, i);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex& Complex::operator += (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
re += c.re;
|
|
|
|
im += c.im;
|
|
|
|
return *this;
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex& Complex::operator -= (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
re -= c.re;
|
|
|
|
im -= c.im;
|
|
|
|
return *this;
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex& Complex::operator *= (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float r = re * c.re - im * c.im;
|
|
|
|
float i = re * c.im + im * c.re;
|
2018-01-29 03:28:23 -05:00
|
|
|
re = r;
|
|
|
|
im = i;
|
|
|
|
return *this;
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex& Complex::operator /= (const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float f = 1.0/(c.re*c.re + c.im*c.im);
|
|
|
|
float r = (re * c.re + im * c.im) * f;
|
|
|
|
float i = (im * c.re - re * c.im) * f;
|
2018-01-29 03:28:23 -05:00
|
|
|
re = r;
|
|
|
|
im = i;
|
|
|
|
return *this;
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
//
|
|
|
|
// POWER FUNCTIONS
|
|
|
|
//
|
2013-09-29 08:22:21 -04:00
|
|
|
Complex Complex::c_sqr()
|
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float r = re * re - im * im;
|
|
|
|
float i = 2 * re * im;
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(r, i);
|
2013-09-29 08:22:21 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_sqrt()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float m = modulus();
|
|
|
|
float r = sqrt(0.5 * (m+re));
|
|
|
|
float i = sqrt(0.5 * (m-re));
|
2018-01-29 03:28:23 -05:00
|
|
|
if (im < 0) i = -i;
|
|
|
|
return Complex(r, i);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_exp()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float e = exp(re);
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(e * cos(im), e * sin(im));
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_log()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-04-02 14:48:12 -04:00
|
|
|
float m = modulus();
|
|
|
|
float p = phase();
|
2018-01-29 03:28:23 -05:00
|
|
|
if (p > PI) p -= 2*PI;
|
|
|
|
return Complex(log(m), p);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 08:02:38 -05:00
|
|
|
Complex Complex::c_pow(const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
Complex t = c_log();
|
|
|
|
t = t * c;
|
|
|
|
return t.c_exp();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 08:02:38 -05:00
|
|
|
Complex Complex::c_logn(const Complex &c)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
Complex t = c;
|
|
|
|
return c_log()/t.c_log();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_log10()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return c_logn(10);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
//
|
2015-10-18 06:22:28 -04:00
|
|
|
// GONIO I - SIN COS TAN
|
2013-09-29 08:16:03 -04:00
|
|
|
//
|
|
|
|
Complex Complex::c_sin()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(sin(re) * cosh(im), cos(re) * sinh(im));
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_cos()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(cos(re) * cosh(im), -sin(re) * sinh(im));
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_tan()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
/* faster but 350 bytes longer!!
|
2018-04-02 14:48:12 -04:00
|
|
|
float s = sin(re);
|
|
|
|
float c = cos(re);
|
|
|
|
float sh = sinh(im);
|
|
|
|
float ch = cosh(im);
|
2013-09-29 08:31:13 -04:00
|
|
|
// return Complex(s*ch, c*sh) / Complex(c*ch, -s*sh);
|
2018-04-02 14:48:12 -04:00
|
|
|
float r0 = s*ch;
|
|
|
|
float i0 = c*sh;
|
|
|
|
float cre = c*ch;
|
|
|
|
float cim = -s*sh;
|
|
|
|
float f = 1.0/(cre*cre + cim*cim);
|
|
|
|
float r = r0 * cre + i0 * cim;
|
|
|
|
float i = r0 * cim - i0 * cre;
|
2013-09-29 08:31:13 -04:00
|
|
|
return Complex(r * f, -i * f);
|
|
|
|
*/
|
2018-01-29 03:28:23 -05:00
|
|
|
return c_sin() / c_cos();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex Complex::gonioHelper1(const byte mode)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
Complex c = (one - this->c_sqr()).c_sqrt();
|
|
|
|
if (mode == 0)
|
|
|
|
{
|
|
|
|
c = c + *this * Complex(0,-1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = *this + c * Complex(0,-1);
|
|
|
|
}
|
|
|
|
c = c.c_log() * Complex(0,1);
|
|
|
|
return c;
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_asin()
|
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return gonioHelper1(0);
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_acos()
|
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return gonioHelper1(1);
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_atan()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (Complex(0,-1) * (Complex(re, im - 1)/Complex(-re, -im - 1)).c_log()) * 0.5;
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
//
|
|
|
|
// GONIO II - CSC SEC COT
|
|
|
|
//
|
|
|
|
Complex Complex::c_csc()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return one / c_sin();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_sec()
|
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return one / c_cos();
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_cot()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return one / c_tan();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_acsc()
|
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (one / *this).c_asin();
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_asec()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (one / *this).c_acos();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_acot()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (one / *this).c_atan();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
//
|
|
|
|
// GONIO HYPERBOLICUS I
|
|
|
|
//
|
|
|
|
Complex Complex::c_sinh()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(cos(im) * sinh(re), sin(im) * cosh(re));
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_cosh()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return Complex(cos(im) * cosh(re), sin(im) * sinh(re));
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_tanh()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return c_sinh() / c_cosh();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2015-03-06 04:41:34 -05:00
|
|
|
Complex Complex::gonioHelper2(const byte mode)
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
Complex c = c_sqr();
|
|
|
|
if (mode == 0)
|
|
|
|
{
|
|
|
|
c += 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c -= 1;
|
|
|
|
}
|
|
|
|
c = (*this + c.c_sqrt()).c_log();
|
|
|
|
return c;
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_asinh()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return gonioHelper2(0);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_acosh()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return gonioHelper2(1);
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_atanh()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
Complex c = (*this + one).c_log();
|
|
|
|
c = c - (-(*this - one)).c_log();
|
|
|
|
return c * 0.5;
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
2013-09-29 08:13:36 -04:00
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
//
|
|
|
|
// GONIO HYPERBOLICUS II
|
|
|
|
//
|
|
|
|
Complex Complex::c_csch()
|
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return one / c_sinh();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_sech()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return one / c_cosh();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_coth()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return one / c_tanh();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_acsch()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (one / *this).c_asinh();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_asech()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (one / *this).c_acosh();
|
2013-09-29 08:13:36 -04:00
|
|
|
}
|
|
|
|
|
2013-09-29 08:16:03 -04:00
|
|
|
Complex Complex::c_acoth()
|
2013-09-29 08:13:36 -04:00
|
|
|
{
|
2018-01-29 03:28:23 -05:00
|
|
|
return (one / *this).c_atanh();
|
2013-09-29 08:16:03 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// --- END OF FILE ---
|