diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c index 0be13311f5..167f018981 100644 --- a/apps/plugins/calculator.c +++ b/apps/plugins/calculator.c @@ -1028,12 +1028,13 @@ static double myLn (double a) { /* ----------------------------------------------------------------------- transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method - transcendFunc can do sin,cos,log,exp + transcendFunc can do sin,cos,log,exp,asin,acos,atan input parameter is angle ----------------------------------------------------------------------- */ static void transcendFunc(char* func, double* tt, int* ttPower) { - double t = (*tt)*M_PI/180; int tPower = *ttPower; + double t = (*tt); + int tPower = *ttPower; int sign = 1; int n = 50; /* n <=50, tables are all <= 50 */ int j; @@ -1050,6 +1051,113 @@ static void transcendFunc(char* func, double* tt, int* ttPower) *ttPower = 0; calStatus = cal_normal; + /* Powerscale */ + while (tPower > 0){ + t *= 10; + tPower--; + } + while (tPower < 0) { + t /= 10; + tPower++; + } + + /* Vectoring mode */ + if(func[0] == 'a' || func[0] == 'A') { + if(func[1] == 's' || func[1] == 'S') { /* arcsin */ + /* arcsin input must be in [-1, 1] */ + if(t < -1.0 || t > 1.0) { + calStatus = cal_error; + return; + } + /* Avoid division by zero */ + if(t == 1.0) { + *tt = 90.0; /* arcsin(1) = 90° */ + return; + } + if(t == -1.0) { + *tt = -90.0; /* arcsin(-1) = -90° */ + return; + } + + /* Vectoring mode */ + /* Start with vector (sqrt(1-t^2), t) and find its angle */ + double magnitude = mySqrt(1.0 - t*t); + x = magnitude; + y = t; + z = 0.0; + + /* Vectoring mode: drive y to 0 */ + for (j = 1; j < n + 2; j++) { + if(y >= 0) { + /* Rotate clockwise (negative direction) */ + xt = x + y * cordicTable[j-1][0]; + yt = y - x * cordicTable[j-1][0]; + zt = z - cordicTable[j-1][1]; + } else { + /* Rotate anticlockwise (positive direction) */ + xt = x - y * cordicTable[j-1][0]; + yt = y + x * cordicTable[j-1][0]; + zt = z + cordicTable[j-1][1]; + } + x = xt; + y = yt; + z = zt; + } + *tt = z * 180/M_PI * -1; /* Convert to degrees and invert sign */ + return; + } + else if(func[1] == 'c' || func[1] == 'C') { /* arccos */ + /* arccos input must be in [-1, 1] */ + if(t < -1.0 || t > 1.0) { + calStatus = cal_error; + return; + } + /* For arccos: use arcsin relationship: arccos(t) = π/2 - arcsin(t) */ + double arcsin_input = t; + int arcsin_power = 0; + + /* Save current function context */ + char original_func[3]; + strncpy(original_func, func, 3); + + transcendFunc("asin", &arcsin_input, &arcsin_power); + + if (calStatus == cal_error) { + return; + } + + /* arccos(t) = 90° - arcsin(t) */ + /* arcsin_input now contains arcsin(t) in degrees */ + double arccos_degrees = 90.0 - arcsin_input; + *tt = arccos_degrees; + return; + } + else if(func[1] == 't' || func[1] == 'T') { /* arctan */ + /* start with x=1, y=input, z=0 and drive y to 0 */ + x = 1.0; + y = t; + z = 0.0; + + /* Vectoring mode: drive y to 0 */ + for (j=1; j 0){ t *= 10; tPower--; @@ -1290,6 +1401,15 @@ static void oneOperand(void) case sci_tan: transcendFunc("tan", &result, &power); break; + case sci_asin: + transcendFunc("asin", &result, &power); + break; + case sci_acos: + transcendFunc("acos", &result, &power); + break; + case sci_atan: + transcendFunc("atan", &result, &power); + break; case sci_fac: if (power<0 || power>8 || result<0 ) calStatus = cal_error; diff --git a/docs/CREDITS b/docs/CREDITS index 3ed3cdb9c8..7abfdf6ac9 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -743,6 +743,7 @@ Pavlo Rudy Yannic Schmidt Hairo R. Carela Sergio Delgado +Cameron John Peck The libmad team The wavpack team