fix issue #91 - sin, cos, sinh, cosh

This commit is contained in:
RobTillaart 2018-01-29 09:28:23 +01:00
parent 3405ddd093
commit c5d02f3c95
9 changed files with 315 additions and 128 deletions

View File

@ -1,7 +1,15 @@
ReleaseNote.txt - Complex Library
===================================================================================
2018/01/29
===========
Fixed c_sin, c_cos, c_sinh, c_cosh
They contained an invalid optimization.
===================================================================================
2018/01/25
=============
Issue found in version 0.1.9 - https://github.com/RobTillaart/Arduino/issues/90
Class does not compile for DUE and TEENSY

View File

@ -1,119 +1,120 @@
//
// FILE: Complex.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.10
// VERSION: 0.1.11
// PURPOSE: library for Complex math for Arduino
// URL: http://arduino.cc/playground/Main/ComplexMath
//
// Released to the public domain
//
// 0.1.10 - uppercase #define COMPLEX_H
// 0.1.09 - added (0,0) constructor
// 0.1.08 - refactor
// 0.1.07 - refactor interfaces
// 0.1.11 - 2018-01-29 - fix sin and cos formula - issue #91
// 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
#include "complex.h"
// PRINTING
size_t Complex::printTo(Print& p) const
{
size_t n = 0;
n += p.print(re, 3);
n += p.print(' ');
n += p.print(im, 3);
n += p.print('i');
return n;
size_t n = 0;
n += p.print(re, 3);
n += p.print(' ');
n += p.print(im, 3);
n += p.print('i');
return n;
};
void Complex::polar(const double modulus, const double phase)
{
re = modulus * cos(phase);
im = modulus * sin(phase);
re = modulus * cos(phase);
im = modulus * sin(phase);
}
Complex Complex::reciprocal()
{
double f = 1.0/(re*re + im*im);
double r = re*f;
double i = -im*f;
return Complex(r,i);
double f = 1.0/(re*re + im*im);
double r = re*f;
double i = -im*f;
return Complex(r,i);
}
// EQUALITIES
bool Complex::operator == (const Complex &c)
{
return (re == c.re) && (im == c.im);
return (re == c.re) && (im == c.im);
}
bool Complex::operator != (const Complex &c)
{
return (re != c.re) || (im != c.im);
return (re != c.re) || (im != c.im);
}
// NEGATE
Complex Complex::operator - ()
{
return Complex(-re, -im);
return Complex(-re, -im);
}
// BASIC MATH
Complex Complex::operator + (const Complex &c)
{
return Complex(re + c.re, im + c.im);
return Complex(re + c.re, im + c.im);
}
Complex Complex::operator - (const Complex &c)
{
return Complex(re - c.re, im - c.im);
return Complex(re - c.re, im - c.im);
}
Complex Complex::operator * (const Complex &c)
{
double r = re * c.re - im * c.im;
double i = re * c.im + im * c.re;
return Complex(r, i);
double r = re * c.re - im * c.im;
double i = re * c.im + im * c.re;
return Complex(r, i);
}
Complex Complex::operator / (const Complex &c)
{
double f = 1.0/(c.re*c.re + c.im*c.im);
double r = (re * c.re + im * c.im) * f;
double i = (im * c.re - re * c.im) * f;
return Complex(r, i);
double f = 1.0/(c.re*c.re + c.im*c.im);
double r = (re * c.re + im * c.im) * f;
double i = (im * c.re - re * c.im) * f;
return Complex(r, i);
}
Complex& Complex::operator += (const Complex &c)
{
re += c.re;
im += c.im;
return *this;
re += c.re;
im += c.im;
return *this;
}
Complex& Complex::operator -= (const Complex &c)
{
re -= c.re;
im -= c.im;
return *this;
re -= c.re;
im -= c.im;
return *this;
}
Complex& Complex::operator *= (const Complex &c)
{
double r = re * c.re - im * c.im;
double i = re * c.im + im * c.re;
re = r;
im = i;
return *this;
double r = re * c.re - im * c.im;
double i = re * c.im + im * c.re;
re = r;
im = i;
return *this;
}
Complex& Complex::operator /= (const Complex &c)
{
double f = 1.0/(c.re*c.re + c.im*c.im);
double r = (re * c.re + im * c.im) * f;
double i = (im * c.re - re * c.im) * f;
re = r;
im = i;
return *this;
double f = 1.0/(c.re*c.re + c.im*c.im);
double r = (re * c.re + im * c.im) * f;
double i = (im * c.re - re * c.im) * f;
re = r;
im = i;
return *this;
}
//
@ -121,50 +122,50 @@ Complex& Complex::operator /= (const Complex &c)
//
Complex Complex::c_sqr()
{
double r = re * re - im * im;
double i = 2 * re * im;
return Complex(r, i);
double r = re * re - im * im;
double i = 2 * re * im;
return Complex(r, i);
}
Complex Complex::c_sqrt()
{
double m = modulus();
double r = sqrt(0.5 * (m+re));
double i = sqrt(0.5 * (m-re));
if (im < 0) i = -i;
return Complex(r, i);
double m = modulus();
double r = sqrt(0.5 * (m+re));
double i = sqrt(0.5 * (m-re));
if (im < 0) i = -i;
return Complex(r, i);
}
Complex Complex::c_exp()
{
double e = exp(re);
return Complex(e * cos(im), e * sin(im));
double e = exp(re);
return Complex(e * cos(im), e * sin(im));
}
Complex Complex::c_log()
{
double m = modulus();
double p = phase();
if (p > PI) p -= 2*PI;
return Complex(log(m), p);
double m = modulus();
double p = phase();
if (p > PI) p -= 2*PI;
return Complex(log(m), p);
}
Complex Complex::c_pow(const Complex &c)
{
Complex t = c_log();
t = t * c;
return t.c_exp();
Complex t = c_log();
t = t * c;
return t.c_exp();
}
Complex Complex::c_logn(const Complex &c)
{
Complex t = c;
return c_log()/t.c_log();
Complex t = c;
return c_log()/t.c_log();
}
Complex Complex::c_log10()
{
return c_logn(10);
return c_logn(10);
}
//
@ -172,21 +173,17 @@ Complex Complex::c_log10()
//
Complex Complex::c_sin()
{
double s = sin(re);
double c = sqrt(1.0-s*s);
return Complex(s * cosh(im), c * sinh(im));
return Complex(sin(re) * cosh(im), cos(re) * sinh(im));
}
Complex Complex::c_cos()
{
double s = sin(re);
double c = sqrt(1.0-s*s);
return Complex(c * cosh(im), -s * sinh(im));
return Complex(cos(re) * cosh(im), -sin(re) * sinh(im));
}
Complex Complex::c_tan()
{
/* faster but 350 bytes longer!!
/* faster but 350 bytes longer!!
double s = sin(re);
double c = cos(re);
double sh = sinh(im);
@ -201,37 +198,37 @@ Complex Complex::c_tan()
double i = r0 * cim - i0 * cre;
return Complex(r * f, -i * f);
*/
return c_sin() / c_cos();
return c_sin() / c_cos();
}
Complex Complex::gonioHelper1(const byte mode)
{
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;
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;
}
Complex Complex::c_asin()
{
return gonioHelper1(0);
return gonioHelper1(0);
}
Complex Complex::c_acos()
{
return gonioHelper1(1);
return gonioHelper1(1);
}
Complex Complex::c_atan()
{
return (Complex(0,-1) * (Complex(re, im - 1)/Complex(-re, -im - 1)).c_log()) * 0.5;
return (Complex(0,-1) * (Complex(re, im - 1)/Complex(-re, -im - 1)).c_log()) * 0.5;
}
//
@ -239,32 +236,32 @@ Complex Complex::c_atan()
//
Complex Complex::c_csc()
{
return one / c_sin();
return one / c_sin();
}
Complex Complex::c_sec()
{
return one / c_cos();
return one / c_cos();
}
Complex Complex::c_cot()
{
return one / c_tan();
return one / c_tan();
}
Complex Complex::c_acsc()
{
return (one / *this).c_asin();
return (one / *this).c_asin();
}
Complex Complex::c_asec()
{
return (one / *this).c_acos();
return (one / *this).c_acos();
}
Complex Complex::c_acot()
{
return (one / *this).c_atan();
return (one / *this).c_atan();
}
//
@ -272,53 +269,49 @@ Complex Complex::c_acot()
//
Complex Complex::c_sinh()
{
double s = sin(im);
double c = sqrt(1.0 - s*s);
return Complex(sinh(re) * c, cosh(re)* s);
return Complex(cos(im) * sinh(re), sin(im) * cosh(re));
}
Complex Complex::c_cosh()
{
double s = sin(im);
double c = sqrt(1.0-s*s);
return Complex(cosh(re) * c, sinh(re)* s);
return Complex(cos(im) * cosh(re), sin(im) * sinh(re));
}
Complex Complex::c_tanh()
{
return c_sinh() / c_cosh();
return c_sinh() / c_cosh();
}
Complex Complex::gonioHelper2(const byte mode)
{
Complex c = c_sqr();
if (mode == 0)
{
c += 1;
}
else
{
c -= 1;
}
c = (*this + c.c_sqrt()).c_log();
return c;
Complex c = c_sqr();
if (mode == 0)
{
c += 1;
}
else
{
c -= 1;
}
c = (*this + c.c_sqrt()).c_log();
return c;
}
Complex Complex::c_asinh()
{
return gonioHelper2(0);
return gonioHelper2(0);
}
Complex Complex::c_acosh()
{
return gonioHelper2(1);
return gonioHelper2(1);
}
Complex Complex::c_atanh()
{
Complex c = (*this + one).c_log();
c = c - (-(*this - one)).c_log();
return c * 0.5;
Complex c = (*this + one).c_log();
c = c - (-(*this - one)).c_log();
return c * 0.5;
}
//
@ -326,32 +319,32 @@ Complex Complex::c_atanh()
//
Complex Complex::c_csch()
{
return one / c_sinh();
return one / c_sinh();
}
Complex Complex::c_sech()
{
return one / c_cosh();
return one / c_cosh();
}
Complex Complex::c_coth()
{
return one / c_tanh();
return one / c_tanh();
}
Complex Complex::c_acsch()
{
return (one / *this).c_asinh();
return (one / *this).c_asinh();
}
Complex Complex::c_asech()
{
return (one / *this).c_acosh();
return (one / *this).c_acosh();
}
Complex Complex::c_acoth()
{
return (one / *this).c_atanh();
return (one / *this).c_atanh();
}
// --- END OF FILE ---

View File

@ -1,7 +1,7 @@
//
// FILE: Complex.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.10
// VERSION: 0.1.11
// PURPOSE: library for Complex math for Arduino
// URL: http://arduino.cc/playground/Main/ComplexMath
//
@ -15,7 +15,7 @@
#include "Printable.h"
#define COMPLEX_LIB_VERSION "0.1.10"
#define COMPLEX_LIB_VERSION "0.1.11"
class Complex: public Printable
{

View File

@ -204,10 +204,19 @@ void setup()
c5 = c5.c_acoth();
Serial.println(c5);
Serial.println("\n14. gonio bug fix (minimal) test");
c1.set(3, 4);
Serial.println(c1);
c2 = c1.c_sin();
c2 = c2 * c2;
c3 = c1.c_cos();
c3 = c3 * c3;
Serial.println(c2 + c3); // should print 1, 0i
Serial.println("\n.. Complex done");
uint32_t start = micros();
for (int i=0; i<1000; i++)
for (int i = 0; i < 1000; i++)
{
c5 = c5.c_csc();
}

View File

@ -0,0 +1,110 @@
Complex numbers test for Arduino: 0.1.11
1. Print Complex, set, real, imag
1.000 0.000i
10.000 -2.000i
3.000 0.000i
-10.000 4.000i
-5.000 -5.000i
0.000 0.000i
0.00
0.00
2. == !=
ok :)
ok :)
ok :)
3. negation -
-10.000 2.000i
10.000 -2.000i
ok :)
4. + -
13.000 -2.000i
13.000 -2.000i
7.000 -2.000i
7.000 -2.000i
5. * /
30.000 -6.000i
90.000 -18.000i
30.000 -6.000i
10.000 -2.000i
10.000 -2.000i
10.000 -2.000i
6. assign += -= *= /=
20.000 -4.000i
23.000 -4.000i
13.000 -2.000i
10.000 -2.000i
96.000 -40.000i
288.000 -120.000i
30.000 -6.000i
10.000 -2.000i
7. phase modulus polar
10.000 -2.000i
10.20
-0.20
10.000 -2.000i
8. conjugate reciprocal
10.000 2.000i
10.000 -2.000i
0.096 0.019i
10.000 -2.000i
9. power: exp log pow sqrt sqr logn log10
96.000 -40.000i
-9166.239 -20028.597i
10.000 -2.000i
96.000 -40.000i
10.000 -2.000i
96.000 -40.000i
880.000 -592.000i
10.000 -2.000i
0.534 0.542i
10.000 -2.000i
1.009 -0.086i
10. gonio: sin cos tan asin acos atan
0.541 0.457i
0.500 0.500i
0.990 -0.250i
0.500 0.500i
0.404 0.564i
0.500 0.500i
11. gonio csc sec cot acsc asec acot
1.078 -0.912i
0.500 0.500i
0.950 0.240i
0.500 0.500i
0.839 -1.172i
0.500 0.500i
12. gonio hyperbolicus I
0.457 0.541i
0.500 0.500i
0.990 0.250i
0.500 0.500i
0.564 0.404i
0.500 0.500i
13. gonio hyperbolicus II
0.912 -1.078i
0.500 0.500i
0.950 -0.240i
0.500 0.500i
1.172 -0.839i
0.500 0.500i
14. gonio bug fix (minimal) test
3.000 4.000i
1.000 0.000i
.. Complex done
520444
1.000 0.000i

View File

@ -0,0 +1,67 @@
Complex numbers performance test for Arduino: 0.1.11
5 constructors 12
set(0,0) 4
c1 + 1 1588
c1 + c2 1608
+= c2 1616
c5 = -c1 260
c1 - 3 1012
c1 - c2 1676
c5 -= c2 1612
c1 * 3 5720
c1 * c2 5444
c5 *= c2 4304
c1 / 3 12188
c1 / c2 12064
c5 /= c2 6476
real() 4
imag() 4
modulus() 68
phase 216
polar() 260
conjugate() 8
reciprocal(); 8008
c_sqr() 4280
c_exp() 41732
c_log() 39484
c_pow(2) 87740
c_sqrt() 8464
c_logn(c4) 72420
c_pow(c5) 61004
c_log10() 40080
c_sin() 57768
c_asin() 74980
c_cos() 57880
c_acos() 73392
c_tan() 128928
c_atan() 66740
c_csc() 70168
c_acsc() 85272
c_sec() 70232
c_asec() 86948
c_cot() 141432
c_acot() 74292
c_sinh() 57764
c_asinh() 64392
c_cosh() 57864
c_acosh() 61956
c_tanh() 128920
c_atanh() 90900
c_csch() 70252
c_acsch() 66284
c_sech() 70220
c_asech() 77312
c_coth() 141352
c_acoth() 98056
2317680
.. Complex done

View File

@ -15,7 +15,7 @@
"type": "git",
"url": "https://github.com/RobTillaart/Arduino.git"
},
"version":"0.1.10",
"version":"0.1.11",
"frameworks": "arduino",
"platforms": "*",
"export": {

View File

@ -1,5 +1,5 @@
name=Complex
version=0.1.10
version=0.1.11
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Library for Complex math.