summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoshe Piekarski <dev.rockbox@melachim.net>2021-05-12 23:11:54 -0400
committerAidan MacDonald <amachronic@protonmail.com>2021-06-16 19:50:14 +0000
commit9ccae0421a356c79d3d6cdbdbd9798a60f8d1ed7 (patch)
tree37ff6458b0c5b1a1dee2da869c57fbcebc70bd6f
parenta3f2b64a467c10307ba32ac5e7cd06f5fc27b47f (diff)
downloadrockbox-9ccae0421a356c79d3d6cdbdbd9798a60f8d1ed7.tar.gz
rockbox-9ccae0421a356c79d3d6cdbdbd9798a60f8d1ed7.zip
Implement x^y in calculator
Change-Id: I868b703131675876bd91198b8a53a921152aecba
-rw-r--r--apps/plugins/calculator.c176
1 files changed, 173 insertions, 3 deletions
diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c
index ebf7098d65..45d3643a70 100644
--- a/apps/plugins/calculator.c
+++ b/apps/plugins/calculator.c
@@ -720,6 +720,8 @@ static void doMultiple(double* operandOne, int* powerOne,
720 double operandTwo, int powerTwo); 720 double operandTwo, int powerTwo);
721static void doAdd (double* operandOne, int* powerOne, 721static void doAdd (double* operandOne, int* powerOne,
722 double operandTwo, int powerTwo); 722 double operandTwo, int powerTwo);
723static void doExponent(double* operandOne, int* powerOne,
724 double operandTwo, int powerTwo);
723static void printResult(void); 725static void printResult(void);
724static void formatResult(void); 726static void formatResult(void);
725static void oneOperand(void); 727static void oneOperand(void);
@@ -727,6 +729,75 @@ static void oneOperand(void);
727static void drawLines(void); 729static void drawLines(void);
728static void drawButtons(int group); 730static void drawButtons(int group);
729 731
732double strtod(const char *nptr, char **endptr);
733long long atoll(const char *nptr);
734
735/* -----------------------------------------------------------------------
736Standard library function
737----------------------------------------------------------------------- */
738double strtod(const char *nptr, char **endptr)
739{
740 double out;
741 long mantissa;
742 int length=0, end=0;
743 mantissa=atoll(nptr);
744 while(!end)
745 {
746 switch(*nptr)
747 {
748 case '\0':
749 end=1;
750 break;
751 case ',':
752 case '.':
753 case '\'':
754 end=1;
755 default:
756 nptr++;
757 }
758 }
759 out=atoll(nptr);
760 while( (*nptr == '0')||(*nptr == '1')||(*nptr == '2')||(*nptr == '3')||(*nptr == '4')||
761 (*nptr == '5')||(*nptr == '6')||(*nptr == '7')||(*nptr == '8')||(*nptr == '9') )
762 {
763 nptr++;
764 length++;
765 }
766 for(;length;length--)
767 out /= 10;
768 out += mantissa;
769 if(endptr != NULL)
770 *endptr=(char *) nptr;
771 return out;
772}
773
774// WARNING Unsafe: Use strtoll instead
775long long atoll(const char *nptr)
776{
777 long long result=0;
778 char negative=0;
779 while( (*nptr == ' ') || (*nptr == '\f') || (*nptr == '\n')||
780 (*nptr == '\r') || (*nptr == '\t') || (*nptr == '\v') )
781 nptr++;
782 if(*nptr == '+')
783 nptr++;
784 if(*nptr == '-')
785 {
786 negative++;
787 nptr++;
788 }
789 while (*nptr)
790 {
791 if( (*nptr < '0') || (*nptr > '9') )
792 break;
793 result *=10;
794 result+= (*(nptr++) -'0');
795 }
796 if(negative)
797 result = 0 - result;
798 return result;
799}
800
730/* ----------------------------------------------------------------------- 801/* -----------------------------------------------------------------------
731Handy functions 802Handy functions
732----------------------------------------------------------------------- */ 803----------------------------------------------------------------------- */
@@ -1049,6 +1120,91 @@ static void doMultiple(double* operandOne, int* powerOne,
1049} 1120}
1050 1121
1051/* ----------------------------------------------------------------------- 1122/* -----------------------------------------------------------------------
1123exponentiate in scientific number format
1124----------------------------------------------------------------------- */
1125static void doExponent(double* operandOne, int* powerOne,
1126 double operandTwo, int powerTwo)
1127{
1128 char negative=0;
1129 char *lastDigit;
1130 char negativeBuffer[25];
1131 if (*operandOne == 0)
1132 {
1133 if (operandTwo == 0)
1134 {
1135 calStatus=cal_error; // result is undefined
1136 }
1137 else{
1138 *powerOne = 0;
1139 *operandOne = 0;
1140 }
1141 return;
1142 }
1143 if (operandTwo == 0)
1144 {
1145 *powerOne = 1;
1146 *operandOne = 0.1;
1147 return;
1148 }
1149 if (operandTwo < 0)
1150 {
1151 negative+=2;
1152 operandTwo= ABS(operandTwo);
1153 }
1154 if (*operandOne < 0)
1155 {
1156#if MEMORYSIZE < 8
1157 calStatus=cal_error;
1158 return;
1159#else
1160 if(powerTwo < 0)
1161 {
1162 calStatus=cal_error; // result is imaginary
1163 return;
1164 }
1165
1166 /*Truncate operandTwo to three places past the radix
1167 in order to eliminate floating point artifacts
1168 (function should set error if truncating a non-integer) */
1169 rb->snprintf(negativeBuffer, 25, "%.*f", powerTwo+3, operandTwo);
1170 operandTwo = strtod(negativeBuffer, NULL);
1171
1172 /*Truncate operandTwo to powerTwo digits by way of string
1173 in order to confirm operandTwo *10^powerTwo is an integer*/
1174 rb->snprintf(negativeBuffer, 25, "%.*f", powerTwo, operandTwo);
1175
1176 if(strtod(negativeBuffer, &lastDigit) != operandTwo)
1177 {
1178 calStatus=cal_error; // result is imaginary
1179 return;
1180 }
1181 if(rb->atoi(lastDigit-1) % 2)
1182 negative++;
1183#endif
1184 }
1185 (*operandOne) = myLn(ABS(*operandOne)) + (double) (*powerOne) * 2.302585092994046;
1186 (*powerOne) = 0;
1187 doMultiple(operandOne, powerOne, ABS(operandTwo), powerTwo);
1188 while(*powerOne)
1189 {
1190 if(*powerOne > 0)
1191 {
1192 (*operandOne) *= 10;
1193 (*powerOne) --;
1194 }
1195 else{
1196 (*operandOne) /= 10;
1197 (*powerOne) ++;
1198 }
1199 }
1200 (*operandOne) = myExp(*operandOne);
1201 if(negative & 2)
1202 (*operandOne) = 1/(*operandOne);
1203 if(negative & 1)
1204 *operandOne = -(*operandOne);
1205}
1206
1207/* -----------------------------------------------------------------------
1052Handles all one operand calculations 1208Handles all one operand calculations
1053----------------------------------------------------------------------- */ 1209----------------------------------------------------------------------- */
1054static void oneOperand(void) 1210static void oneOperand(void)
@@ -1192,6 +1348,9 @@ static void twoOperands(void)
1192 else 1348 else
1193 calStatus = cal_error; 1349 calStatus = cal_error;
1194 break; 1350 break;
1351 case '^':
1352 doExponent(&operand, &operandPower, result, power);
1353 break;
1195 default: /* ' ' */ 1354 default: /* ' ' */
1196 switchOperands(); /* counter switchOperands() below */ 1355 switchOperands(); /* counter switchOperands() below */
1197 break; 1356 break;
@@ -1684,7 +1843,9 @@ static void basicButtonsProcess(void){
1684#ifdef CALCULATOR_OPERATORS 1843#ifdef CALCULATOR_OPERATORS
1685 case_cycle_operators: /* F2 shortkey entrance */ 1844 case_cycle_operators: /* F2 shortkey entrance */
1686#endif 1845#endif
1687 calStatus = cal_normal; 1846 if (calStatus == cal_typing ||
1847 calStatus == cal_dotted)
1848 calStatus = cal_normal;
1688 formatResult(); 1849 formatResult();
1689 operand = result; 1850 operand = result;
1690 operandPower = power; 1851 operandPower = power;
@@ -1740,8 +1901,17 @@ static void sciButtonsProcess(void){
1740 break; 1901 break;
1741 1902
1742 case sci_xy: 1903 case sci_xy:
1743 /*Not implemented yet 1904 if(!operInputted) {twoOperands(); operInputted = true;}
1744 Maybe it could use x^y = exp(y*ln(x))*/ 1905 oper = '^';
1906#ifdef CALCULATOR_OPERATORS
1907 case_cycle_operators: /* F2 shortkey entrance */
1908#endif
1909 if (calStatus == cal_typing ||
1910 calStatus == cal_dotted)
1911 calStatus = cal_normal;
1912 formatResult();
1913 operand = result;
1914 operandPower = power;
1745 break; 1915 break;
1746 1916
1747 case sci_sci: 1917 case sci_sci: