From 61807b8afa4bd77f473a12d206c95e3b073aa217 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Jul 2019 17:59:40 +0200 Subject: [PATCH] Clean up code Clean up code --- sonoff/support_float.ino | 243 ++++++++++++++++++--------------------- 1 file changed, 115 insertions(+), 128 deletions(-) diff --git a/sonoff/support_float.ino b/sonoff/support_float.ino index bdee68d44..3809fd6ec 100644 --- a/sonoff/support_float.ino +++ b/sonoff/support_float.ino @@ -1,7 +1,7 @@ /* - support_float.ino - support for Sonoff-Tasmota + support_float.ino - Small floating point support for Sonoff-Tasmota - Copyright (C) 2019 Theo Arends + Copyright (C) 2019 Theo Arends and Stephan Hadinger This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,11 +20,11 @@ #ifdef ARDUINO_ESP8266_RELEASE_2_3_0 // Functions not available in 2.3.0 -static const float Zero[] = { 0.0, -0.0 }; - // https://code.woboq.org/userspace/glibc/sysdeps/ieee754/flt-32/e_fmodf.c.html float fmodf(float x, float y) { + const float Zero[] = { 0.0, -0.0 }; + int32_t hx = (int32_t)x; int32_t hy = (int32_t)y; @@ -145,7 +145,7 @@ double TaylorLog(double x) double totalValue = 0; double powe = 1; double y; - for (uint32_t count = 0; count < 10; count++) { // Experimental number of 10 iterations + for (uint32_t count = 0; count < 10; count++) { // Experimental number of 10 iterations z *= step; y = (1 / powe) * z; totalValue = totalValue + y; @@ -165,12 +165,11 @@ double TaylorLog(double x) return totalValue; } -// All code adapted from: http://www.ganssle.com/approx.htm - -/// ======================================== -// The following code implements approximations to various trig functions. +// Following code adapted from: http://www.ganssle.com/approx.htm +// ============================================================== +// The following code implements approximations to various trig functions. // -// This is demo code to guide developers in implementing their own approximation +// This is demo code to guide developers in implementing their own approximation // software. This code is merely meant to illustrate algorithms. inline float sinf(float x) { return sin_52(x); } @@ -183,24 +182,23 @@ inline float sqrtf(float x) { return sqrt1(x); } inline float powf(float x, float y) { return FastPrecisePow(x, y); } // Math constants we'll use -double const f_pi=3.1415926535897932384626433; // f_pi -double const f_twopi=2.0*f_pi; // f_pi times 2 -double const f_two_over_pi= 2.0/f_pi; // 2/f_pi -double const f_halfpi=f_pi/2.0; // f_pi divided by 2 -double const f_threehalfpi=3.0*f_pi/2.0; // f_pi times 3/2, used in tan routines -double const f_four_over_pi=4.0/f_pi; // 4/f_pi, used in tan routines -double const f_qtrpi=f_pi/4.0; // f_pi/4.0, used in tan routines -double const f_sixthpi=f_pi/6.0; // f_pi/6.0, used in atan routines -double const f_tansixthpi=tan(f_sixthpi); // tan(f_pi/6), used in atan routines -double const f_twelfthpi=f_pi/12.0; // f_pi/12.0, used in atan routines -double const f_tantwelfthpi=tan(f_twelfthpi); // tan(f_pi/12), used in atan routines +double const f_pi = 3.1415926535897932384626433; // f_pi +double const f_twopi = 2.0 * f_pi; // f_pi times 2 +double const f_two_over_pi = 2.0 / f_pi; // 2/f_pi +double const f_halfpi = f_pi / 2.0; // f_pi divided by 2 +double const f_threehalfpi = 3.0 * f_pi / 2.0; // f_pi times 3/2, used in tan routines +double const f_four_over_pi = 4.0 / f_pi; // 4/f_pi, used in tan routines +double const f_qtrpi = f_pi / 4.0; // f_pi/4.0, used in tan routines +double const f_sixthpi = f_pi / 6.0; // f_pi/6.0, used in atan routines +double const f_tansixthpi = tan(f_sixthpi); // tan(f_pi/6), used in atan routines +double const f_twelfthpi = f_pi / 12.0; // f_pi/12.0, used in atan routines +double const f_tantwelfthpi = tan(f_twelfthpi); // tan(f_pi/12), used in atan routines -// ********************************************************* +// ******************************************************************* // *** -// *** Routines to compute sine and cosine to 5.2 digits -// *** of accuracy. +// *** Routines to compute sine and cosine to 5.2 digits of accuracy. // *** -// ********************************************************* +// ******************************************************************* // // cos_52s computes cosine (x) // @@ -215,50 +213,46 @@ double const f_tantwelfthpi=tan(f_twelfthpi); // tan(f_pi/12), used in atan rout // float cos_52s(float x) { -const float c1= 0.9999932946; -const float c2=-0.4999124376; -const float c3= 0.0414877472; -const float c4=-0.0012712095; + const float c1 = 0.9999932946; + const float c2 = -0.4999124376; + const float c3 = 0.0414877472; + const float c4 = -0.0012712095; -float x2; // The input argument squared - -x2=x * x; -return (c1 + x2*(c2 + x2*(c3 + c4*x2))); + float x2 = x * x; // The input argument squared + return (c1 + x2 * (c2 + x2 * (c3 + c4 * x2))); } - // -// This is the main cosine approximation "driver" +// This is the main cosine approximation "driver" // It reduces the input argument's range to [0, f_pi/2], // and then calls the approximator. // See the notes for an explanation of the range reduction. // -float cos_52(float x){ - int quad; // what quadrant are we in? - - x=fmodf(x, f_twopi); // Get rid of values > 2* f_pi - if(x<0)x=-x; // cos(-x) = cos(x) - quad=int(x * (float)f_two_over_pi); // Get quadrant # (0 to 3) we're in - switch (quad){ - case 0: return cos_52s(x); - case 1: return -cos_52s((float)f_pi-x); - case 2: return -cos_52s(x-(float)f_pi); - case 3: return cos_52s((float)f_twopi-x); - } +float cos_52(float x) +{ + x = fmodf(x, f_twopi); // Get rid of values > 2* f_pi + if (x < 0) { x = -x; } // cos(-x) = cos(x) + int quad = int(x * (float)f_two_over_pi); // Get quadrant # (0 to 3) we're in + switch (quad) { + case 0: return cos_52s(x); + case 1: return -cos_52s((float)f_pi - x); + case 2: return -cos_52s(x-(float)f_pi); + case 3: return cos_52s((float)f_twopi - x); + } } // -// The sine is just cosine shifted a half-f_pi, so +// The sine is just cosine shifted a half-f_pi, so // we'll adjust the argument and call the cosine approximation. // -float sin_52(float x){ - return cos_52((float)f_halfpi-x); +float sin_52(float x) +{ + return cos_52((float)f_halfpi - x); } -// ********************************************************* +// ******************************************************************* // *** -// *** Routines to compute tangent to 5.6 digits -// *** of accuracy. +// *** Routines to compute tangent to 5.6 digits of accuracy. // *** -// ********************************************************* +// ******************************************************************* // // tan_56s computes tan(f_pi*x/4) // @@ -272,18 +266,15 @@ float sin_52(float x){ // float tan_56s(float x) { -const float c1=-3.16783027; -const float c2= 0.134516124; -const float c3=-4.033321984; + const float c1 = -3.16783027; + const float c2 = 0.134516124; + const float c3 = -4.033321984; -float x2; // The input argument squared - -x2=x * x; -return (x*(c1 + c2 * x2)/(c3 + x2)); + float x2 = x * x; // The input argument squared + return (x * (c1 + c2 * x2) / (c3 + x2)); } - // -// This is the main tangent approximation "driver" +// This is the main tangent approximation "driver" // It reduces the input argument's range to [0, f_pi/4], // and then calls the approximator. // See the notes for an explanation of the range reduction. @@ -293,29 +284,27 @@ return (x*(c1 + c2 * x2)/(c3 + x2)); // which it will at x=f_pi/2 and x=3*f_pi/2. If this is a problem // in your application, take appropriate action. // -float tan_56(float x){ - int octant; // what octant are we in? - - x=fmodf(x, (float)f_twopi); // Get rid of values >2 *f_pi - octant=int(x * (float)f_four_over_pi); // Get octant # (0 to 7) - switch (octant){ - case 0: return tan_56s(x *(float)f_four_over_pi); - case 1: return 1.0f/tan_56s(((float)f_halfpi-x) *(float)f_four_over_pi); - case 2: return -1.0f/tan_56s((x-(float)f_halfpi) *(float)f_four_over_pi); - case 3: return - tan_56s(((float)f_pi-x) *(float)f_four_over_pi); - case 4: return tan_56s((x-(float)f_pi) *(float)f_four_over_pi); - case 5: return 1.0f/tan_56s(((float)f_threehalfpi-x)*(float)f_four_over_pi); - case 6: return -1.0f/tan_56s((x-(float)f_threehalfpi)*(float)f_four_over_pi); - case 7: return - tan_56s(((float)f_twopi-x) *(float)f_four_over_pi); - } +float tan_56(float x) +{ + x = fmodf(x, (float)f_twopi); // Get rid of values >2 *f_pi + int octant = int(x * (float)f_four_over_pi); // Get octant # (0 to 7) + switch (octant){ + case 0: return tan_56s(x * (float)f_four_over_pi); + case 1: return 1.0f / tan_56s(((float)f_halfpi - x) * (float)f_four_over_pi); + case 2: return -1.0f / tan_56s((x-(float)f_halfpi) * (float)f_four_over_pi); + case 3: return - tan_56s(((float)f_pi - x) * (float)f_four_over_pi); + case 4: return tan_56s((x-(float)f_pi) * (float)f_four_over_pi); + case 5: return 1.0f / tan_56s(((float)f_threehalfpi - x) * (float)f_four_over_pi); + case 6: return -1.0f / tan_56s((x-(float)f_threehalfpi) * (float)f_four_over_pi); + case 7: return - tan_56s(((float)f_twopi - x) * (float)f_four_over_pi); + } } -// ********************************************************* +// ******************************************************************* // *** -// *** Routines to compute arctangent to 6.6 digits -// *** of accuracy. +// *** Routines to compute arctangent to 6.6 digits of accuracy. // *** -// ********************************************************* +// ******************************************************************* // // atan_66s computes atan(x) // @@ -326,81 +315,79 @@ float tan_56(float x){ // float atan_66s(float x) { -const float c1=1.6867629106; -const float c2=0.4378497304; -const float c3=1.6867633134; + const float c1 = 1.6867629106; + const float c2 = 0.4378497304; + const float c3 = 1.6867633134; -float x2; // The input argument squared - -x2=x * x; -return (x*(c1 + x2*c2)/(c3 + x2)); + float x2 = x * x; // The input argument squared + return (x * (c1 + x2 * c2) / (c3 + x2)); } - // -// This is the main arctangent approximation "driver" +// This is the main arctangent approximation "driver" // It reduces the input argument's range to [0, f_pi/12], // and then calls the approximator. // -// -float atan_66(float x){ - float y; // return from atan__s function - bool complement= false; // true if arg was >1 - bool region= false; // true depending on region arg is in - bool sign= false; // true if arg was < 0 +float atan_66(float x) +{ + float y; // return from atan__s function + bool complement= false; // true if arg was >1 + bool region= false; // true depending on region arg is in + bool sign= false; // true if arg was < 0 - if (x <0 ){ - x=-x; - sign=true; // arctan(-x)=-arctan(x) + if (x < 0) { + x = -x; + sign = true; // arctan(-x)=-arctan(x) } - if (x > 1.0){ - x=1.0/x; // keep arg between 0 and 1 - complement=true; + if (x > 1.0) { + x = 1.0 / x; // keep arg between 0 and 1 + complement = true; } - if (x > (float)f_tantwelfthpi){ - x = (x-(float)f_tansixthpi)/(1+(float)f_tansixthpi*x); // reduce arg to under tan(f_pi/12) - region=true; + if (x > (float)f_tantwelfthpi) { + x = (x - (float)f_tansixthpi) / (1 + (float)f_tansixthpi * x); // reduce arg to under tan(f_pi/12) + region = true; } - y=atan_66s(x); // run the approximation - if (region) y+=(float)f_sixthpi; // correct for region we're in - if (complement)y=(float)f_halfpi-y; // correct for 1/x if we did that - if (sign)y=-y; // correct for negative arg + y = atan_66s(x); // run the approximation + if (region) { y += (float)f_sixthpi; } // correct for region we're in + if (complement) { y = (float)f_halfpi-y; } // correct for 1/x if we did that + if (sign) { y = -y; } // correct for negative arg return (y); } -float asinf1(float x) { - float d = 1.0f - x*x; - if (d < 0.0f) { return nanf(""); } - return 2 * atan_66(x / (1 + sqrt1(d))); +float asinf1(float x) +{ + float d = 1.0f - x * x; + if (d < 0.0f) { return NAN; } + return 2 * atan_66(x / (1 + sqrt1(d))); } -float acosf1(float x) { - float d = 1.0f - x*x; - if (d < 0.0f) { return nanf(""); } - float y = asinf1(sqrt1(d)); - if (x >= 0.0f) { - return y; - } else { - return (float)f_pi - y; - } +float acosf1(float x) +{ + float d = 1.0f - x * x; + if (d < 0.0f) { return NAN; } + float y = asinf1(sqrt1(d)); + if (x >= 0.0f) { + return y; + } else { + return (float)f_pi - y; + } } // https://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi float sqrt1(const float x) { - union - { + union { int i; float x; } u; u.x = x; - u.i = (1<<29) + (u.i >> 1) - (1<<22); + u.i = (1 << 29) + (u.i >> 1) - (1 << 22); // Two Babylonian Steps (simplified from:) // u.x = 0.5f * (u.x + x/u.x); // u.x = 0.5f * (u.x + x/u.x); - u.x = u.x + x/u.x; - u.x = 0.25f*u.x + x/u.x; + u.x = u.x + x / u.x; + u.x = 0.25f * u.x + x / u.x; return u.x; }