diff options
author | Ophir LOJKINE <pere.jobs@gmail.com> | 2012-10-19 22:25:54 +0200 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2012-10-19 23:05:25 +0200 |
commit | e86991f484f29891b969e851680f66e1948542fa (patch) | |
tree | 7fb652879f9ee863cb07a605102f426bdc499ddf /apps/plugins/calculator.c | |
parent | 9b8a6642e2abb15ec063f72d155792b1d17beb2c (diff) | |
download | rockbox-e86991f484f29891b969e851680f66e1948542fa.tar.gz rockbox-e86991f484f29891b969e851680f66e1948542fa.zip |
Implements exponential and logarithm in calculator plugin
exponential implementation uses the series
e^x = 1 + x + x^2/2 + x^3/6 + ...
natural logarithm uses
ln(a) = 2 * ( (a-1)/(a+1) + 1/3 * ((a-1)/(a+1))^3 +... )
log10 uses
log10(a) = ln(a)/ln(10)
Change-Id: I7303404b2b5a2bf60aad0706ca964a7cea19a27c
Reviewed-on: http://gerrit.rockbox.org/333
Reviewed-by: Frank Gevaerts <frank@gevaerts.be>
Diffstat (limited to 'apps/plugins/calculator.c')
-rw-r--r-- | apps/plugins/calculator.c | 75 |
1 files changed, 74 insertions, 1 deletions
diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c index 9e9aa220bf..1e07d23a2e 100644 --- a/apps/plugins/calculator.c +++ b/apps/plugins/calculator.c | |||
@@ -823,6 +823,41 @@ static double mySqrt(double square) | |||
823 | 823 | ||
824 | return root; | 824 | return root; |
825 | } | 825 | } |
826 | |||
827 | /*Uses the sequence sum(x^k/k!) that tends to exp(x)*/ | ||
828 | static double myExp (double x) { | ||
829 | unsigned int k=0; | ||
830 | double res=0, xPow=1,fact=1,toAdd; | ||
831 | |||
832 | do { | ||
833 | toAdd = xPow/fact; | ||
834 | res += toAdd; | ||
835 | xPow *= x; //xPow = x^k | ||
836 | k++; | ||
837 | fact*=k; //fact = k! | ||
838 | } while (ABS(toAdd) > MINIMUM && xPow<1e302); | ||
839 | return res; | ||
840 | } | ||
841 | |||
842 | /*myLn : uses the series ln(a) = 2 * ∑(1/(2n+1) * ((a-1)/(a+1))^(2k+1) )*/ | ||
843 | static double myLn (double a) { | ||
844 | unsigned int k=1; | ||
845 | double res=0,xPow,xSquare,fract=1,toAdd; | ||
846 | |||
847 | xPow = (a-1)/(a+1); | ||
848 | xSquare = xPow*xPow; | ||
849 | |||
850 | do { | ||
851 | toAdd = fract*xPow; | ||
852 | res += toAdd; | ||
853 | xPow *= xSquare; // ((a-1)/(a+1))^k | ||
854 | k+=2; | ||
855 | fract=1./k; | ||
856 | } while (ABS(toAdd) > MINIMUM); | ||
857 | return res * 2; | ||
858 | } | ||
859 | |||
860 | |||
826 | /* ----------------------------------------------------------------------- | 861 | /* ----------------------------------------------------------------------- |
827 | transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method | 862 | transcendFunc uses CORDIC (COordinate Rotation DIgital Computer) method |
828 | transcendFunc can do sin,cos,log,exp | 863 | transcendFunc can do sin,cos,log,exp |
@@ -951,6 +986,7 @@ Handles all one operand calculations | |||
951 | static void oneOperand(void) | 986 | static void oneOperand(void) |
952 | { | 987 | { |
953 | int k = 0; | 988 | int k = 0; |
989 | |||
954 | if (buttonGroup == basicButtons){ | 990 | if (buttonGroup == basicButtons){ |
955 | switch(CAL_BUTTON){ | 991 | switch(CAL_BUTTON){ |
956 | case btn_sqr: | 992 | case btn_sqr: |
@@ -1024,6 +1060,40 @@ static void oneOperand(void) | |||
1024 | } | 1060 | } |
1025 | } | 1061 | } |
1026 | break; | 1062 | break; |
1063 | case sci_exp: | ||
1064 | /*Uses the sequence (1+a/n)^n -> exp(a) */ | ||
1065 | if (power>3 || result > 1e3) calStatus = cal_error; | ||
1066 | else { | ||
1067 | while(power < 0) { | ||
1068 | result /= 10; | ||
1069 | power++; | ||
1070 | } | ||
1071 | while (power > 0){ | ||
1072 | power--; | ||
1073 | result*=10; | ||
1074 | } | ||
1075 | result = myExp(result); | ||
1076 | calStatus = cal_normal; | ||
1077 | } | ||
1078 | break; | ||
1079 | case sci_ln: | ||
1080 | if (result<=0) calStatus = cal_error; | ||
1081 | else { | ||
1082 | //ln(a*10^n) = ln(a) + n*ln(10), with ln(10) ≈ 2.30 | ||
1083 | result = myLn(result) + power * 2.302585092994046; | ||
1084 | power=0; | ||
1085 | calStatus = cal_normal; | ||
1086 | } | ||
1087 | break; | ||
1088 | case sci_log: | ||
1089 | if (result<=0) calStatus = cal_error; | ||
1090 | else { | ||
1091 | //log10(a+10^n) = ln(a)/ln(10) + n, with ln(10) ≈ 2.30 | ||
1092 | result = myLn(result)/2.302585092994046 + power; | ||
1093 | power=0; | ||
1094 | calStatus = cal_normal; | ||
1095 | } | ||
1096 | break; | ||
1027 | default: | 1097 | default: |
1028 | calStatus = cal_toDo; | 1098 | calStatus = cal_toDo; |
1029 | break; /* just for the safety */ | 1099 | break; /* just for the safety */ |
@@ -1601,7 +1671,10 @@ static void sciButtonsProcess(void){ | |||
1601 | calStatus = cal_normal; | 1671 | calStatus = cal_normal; |
1602 | break; | 1672 | break; |
1603 | 1673 | ||
1604 | case sci_xy: break; | 1674 | case sci_xy: |
1675 | /*Not implemented yet | ||
1676 | Maybe it could use x^y = exp(y*ln(x))*/ | ||
1677 | break; | ||
1605 | 1678 | ||
1606 | case sci_sci: | 1679 | case sci_sci: |
1607 | buttonGroup = basicButtons; | 1680 | buttonGroup = basicButtons; |