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 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<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')
sign = SIGN(t);
else {
@ -1058,6 +1166,9 @@ static void transcendFunc(char* func, double* tt, int* ttPower)
}
t = ABS(t);
/* Jump to radians for rotation mode */
t = t * M_PI / 180;
while (tPower > 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;