Add arcsin, arccos and arctan to calculator

Change-Id: I9aaded58718ae410239678abe6cf6196286bc7f8
This commit is contained in:
Cameron Peck 2025-10-13 23:37:04 +01:00
parent 9aa6a35b3f
commit bfcd8270c9
2 changed files with 123 additions and 2 deletions

View file

@ -1028,12 +1028,13 @@ static double myLn (double a) {
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method 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 input parameter is angle
----------------------------------------------------------------------- */ ----------------------------------------------------------------------- */
static void transcendFunc(char* func, double* tt, int* ttPower) 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 sign = 1;
int n = 50; /* n <=50, tables are all <= 50 */ int n = 50; /* n <=50, tables are all <= 50 */
int j; int j;
@ -1050,6 +1051,113 @@ static void transcendFunc(char* func, double* tt, int* ttPower)
*ttPower = 0; *ttPower = 0;
calStatus = cal_normal; 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<n+2; j++){
if(y < 0) {
/* Rotate anticlockwise */
xt = x - y*cordicTable[j-1][0];
yt = y + x*cordicTable[j-1][0];
zt = z + cordicTable[j-1][1];
} else {
/* Rotate clockwise */
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 back to degrees and invert sign */
return;
}
}
if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T') if( func[0] =='s' || func[0] =='S'|| func[0] =='t' || func[0] =='T')
sign = SIGN(t); sign = SIGN(t);
else { else {
@ -1058,6 +1166,9 @@ static void transcendFunc(char* func, double* tt, int* ttPower)
} }
t = ABS(t); t = ABS(t);
/* Jump to radians for rotation mode */
t = t * M_PI / 180;
while (tPower > 0){ while (tPower > 0){
t *= 10; t *= 10;
tPower--; tPower--;
@ -1290,6 +1401,15 @@ static void oneOperand(void)
case sci_tan: case sci_tan:
transcendFunc("tan", &result, &power); transcendFunc("tan", &result, &power);
break; 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: case sci_fac:
if (power<0 || power>8 || result<0 ) if (power<0 || power>8 || result<0 )
calStatus = cal_error; calStatus = cal_error;

View file

@ -743,6 +743,7 @@ Pavlo Rudy
Yannic Schmidt Yannic Schmidt
Hairo R. Carela Hairo R. Carela
Sergio Delgado Sergio Delgado
Cameron John Peck
The libmad team The libmad team
The wavpack team The wavpack team