Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Implement x^y in calculator

Change-Id: I868b703131675876bd91198b8a53a921152aecba

authored by

Moshe Piekarski and committed by
Aidan MacDonald
9ccae042 a3f2b64a

+173 -3
+173 -3
apps/plugins/calculator.c
··· 720 720 double operandTwo, int powerTwo); 721 721 static void doAdd (double* operandOne, int* powerOne, 722 722 double operandTwo, int powerTwo); 723 + static void doExponent(double* operandOne, int* powerOne, 724 + double operandTwo, int powerTwo); 723 725 static void printResult(void); 724 726 static void formatResult(void); 725 727 static void oneOperand(void); 726 728 727 729 static void drawLines(void); 728 730 static void drawButtons(int group); 731 + 732 + double strtod(const char *nptr, char **endptr); 733 + long long atoll(const char *nptr); 734 + 735 + /* ----------------------------------------------------------------------- 736 + Standard library function 737 + ----------------------------------------------------------------------- */ 738 + double 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 775 + long 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 + } 729 800 730 801 /* ----------------------------------------------------------------------- 731 802 Handy functions ··· 1049 1120 } 1050 1121 1051 1122 /* ----------------------------------------------------------------------- 1123 + exponentiate in scientific number format 1124 + ----------------------------------------------------------------------- */ 1125 + static 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 + /* ----------------------------------------------------------------------- 1052 1208 Handles all one operand calculations 1053 1209 ----------------------------------------------------------------------- */ 1054 1210 static void oneOperand(void) ··· 1191 1347 } 1192 1348 else 1193 1349 calStatus = cal_error; 1350 + break; 1351 + case '^': 1352 + doExponent(&operand, &operandPower, result, power); 1194 1353 break; 1195 1354 default: /* ' ' */ 1196 1355 switchOperands(); /* counter switchOperands() below */ ··· 1684 1843 #ifdef CALCULATOR_OPERATORS 1685 1844 case_cycle_operators: /* F2 shortkey entrance */ 1686 1845 #endif 1687 - calStatus = cal_normal; 1846 + if (calStatus == cal_typing || 1847 + calStatus == cal_dotted) 1848 + calStatus = cal_normal; 1688 1849 formatResult(); 1689 1850 operand = result; 1690 1851 operandPower = power; ··· 1740 1901 break; 1741 1902 1742 1903 case sci_xy: 1743 - /*Not implemented yet 1744 - Maybe it could use x^y = exp(y*ln(x))*/ 1904 + if(!operInputted) {twoOperands(); operInputted = true;} 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 1915 break; 1746 1916 1747 1917 case sci_sci: