Hello all!
I'm developing a scientific RPN calculator with OLED Display, ATTINY85, 16 keys and a CR2032 battery - and I'm almost done.
As (flash) memory is (always) short (8.192 bytes) I have to implement a lot of functions by using the calculator itself (and not some bloated math library).
This can be done by calling basic subroutines (one byte commands) for stack operations.
For example to calculate the cosine of x (cos(x)) I have to use the (intrinsic) sine function and calculating sqrt(1-sin(x)*sin(x)) with stack operations - and use these steps:
Code:
SIN ENTER * CHS 1 + SQRT
Many other functions are implemented like this:
Code:
COS (Cosine)
COMMANDS (5): SIN ENTER * CHS 1 + SQRT
Converts 4 mem - to: -
stack[] --------- -----
(incl. 3 t - - cos(x) = sqrt(1 - sin(x)*sin(x))
mem) 2 z - -
from: 1 y - -
0 x x cos(x)
TAN (Tangent)
COMMANDS (9): SIN ENTER ENTER * CHS 1 + SQRT /
Converts 4 mem - to: -
stack[] --------- ----- sin(x) sin(x)
(incl. 3 t - - tan(x) = ------ = -----------------------
mem) 2 z - - cos(x) sqrt(1 - sin(x)*sin(x))
from: 1 y - -
0 x x tan(x)
ACOS (Arcus Cosine)
COMMANDS (4): ASIN CHS 90 +
Converts 4 mem - to: -
stack[] --------- ------
(incl. 3 t - - acos(x) = 90 - asin(x)
mem) 2 z - -
from: 1 y - -
0 x x acos(x)
ATAN (Arcus Tangent)
COMMANDS (10): ENTER ENTER ENTER * 1 + SQRT INV * ASIN
Converts 4 mem - to: -
stack[] --------- ------ x
(incl. 3 t - - atan(x) = asin( ------------- )
mem) 2 z - - sqrt(1 + x*x)
from: 1 y - -
0 x x atan(x)
PV (Present Value)
COMMANDS (14): CHS SWAP ENTER 1 + SWAP ROT SWAP PWR CHS 1 + ROTup /
Converts 4 mem - to: -
stack[] --------- ------- 1 - (1+i)^-n
(incl. 3 t - - PV(i,n) = ------------
mem) 2 z - - i
from: 1 y i -
0 x n PV(i,n)
GAMMA (due to formula of Nemes)
COMMANDS (46): 1 + ENTER ENTER INV EXP ENTER INV CHS + 2 / * SWAP 6 PWR 810 * INV
+ LN * 2 / SWAP CHS + ROT ROT LN SWAP .5 - * + .9189385 + EXP
Converts 4 mem - to: -
stack[] --------- --- ln(2PI) x
(incl. 3 t - - ln(x!) = ------- + (x-1/2)*ln(x) - x + - * ln(x*sinh(1/x) + 1/(810*x^6))
mem) 2 z - - 2 2
from: 1 y - -
0 x x x!
SINH (Hyperbolic Sine)
COMMANDS (9): ENTER ENTER EXP SWAP CHS EXP - 2 /
Converts 4 mem - to: -
stack[] --------- ------- exp(x) - exp(-x)
(incl. 3 t - - sinh(x) = ----------------
mem) 2 z - - 2
from: 1 y - -
0 x x sinh(x)
COSH (Hyperbolic Cosine)
COMMANDS (9): ENTER ENTER EXP SWAP CHS EXP + 2 /
Converts 4 mem - to: -
stack[] --------- ------- exp(x) + exp(-x)
(incl. 3 t - - cosh(x) = ----------------
mem) 2 z - - 2
from: 1 y - -
0 x x cosh(x)
TANH (Hyperbolic Tangent)
COMMANDS (12): 2 * CHS EXP ENTER CHS 1 + SWAP 1 + /
Converts 4 mem - to: -
stack[] --------- ------- exp(x) - exp(-x)
(incl. 3 t - - tanh(x) = ----------------
mem) 2 z - - exp(x) + exp(-x)
from: 1 y - -
0 x x tanh(x)
ASINH (Area Hyperbolic Sine)
COMMANDS (8): ENTER ENTER * 1 + SQRT + LN
Converts 4 mem - to: -
stack[] --------- --------
(incl. 3 t - - asinh(x) = ln(x + sqrt(x*x + 1))
mem) 2 z - -
from: 1 y - -
0 x x asinh(x)
ACOSH (Area Hyperbolic Cosine)
COMMANDS (8): ENTER ENTER * 1 - SQRT + LN
Converts 4 mem - to: -
stack[] --------- --------
(incl. 3 t - - acosh(x) = ln(x + sqrt(x*x - 1))
mem) 2 z - -
from: 1 y - -
0 x x acosh(x)
ATANH (Area Hyperbolic Tangent)
COMMANDS (11): ENTER ENTER 1 + SWAP CHS 1 + / SQRT LN
Converts 4 mem - to: -
stack[] --------- -------- 1 + x
(incl. 3 t - - atanh(x) = ln(sqrt(-----))
mem) 2 z - - 1 - x
from: 1 y - -
0 x x atanh(x)
SUM (Prepare stack/arguments for summarizing)
COMMANDS (12): 1 STO ROT ENTER ENTER * ROT * ROT SWAP SQRT SUM1
Converts 4 mem - to: 1 and where
stack[] --------- --- SUM1 adds
(incl. 3 t - x*y stack[i]
mem) 2 z - x*x to
from: 1 y y y sum[i]
0 x x x
ND (Normal Distribution: Probability Density and Cumulative Distribution Function)
COMMANDS (38): ENTER ENTER ENTER * * .07 * CHS SWAP 1.6 * CHS + EXP 1 + INV
SWAP ENTER * CHS 2 / EXP 0.3989423 *
Converts 4 mem - to: - (x)
stack[] --------- --- CDF = integral(PDF) = 1/(1 + exp(-0.07*x^3 - 1.6*x))
(incl. 3 t - - (-inf)
mem) 2 z - -
from: 1 y - CDF PDF = 1/sqrt(2*PI) * exp(-x*x/2)
0 x x PDF
R2P (Rectangular to Polar Coordinates)
COMMANDS (14): ENTER * SWAP ENTER ENTER ROT * + SQRT ENTER ROT / ASIN ROTup
Converts 4 mem - to: -
stack[] --------- --- r = sqrt(x*x + y*y)
(incl. 3 t - -
mem) 2 z - - y
from: 1 y y a a = atan(---)
0 x x r x
P2R (Polar to Rectangular Coordinates)
COMMANDS (15): SWAP SIN ENTER ENTER * CHS 1 + SQRT ROT * ROT * SWAP ROT
Converts 4 mem - to: -
stack[] --------- --- y = r * sin(a)
(incl. 3 t - -
mem) 2 z - -
from: 1 y a y x = r * cos(a)
0 x r x
STAT (Statistik, Mean Value, Standard Deviation)
COMMANDS (16): SWAP ROT ENTER RCL / ENTER ROT * CHS + RCL 1 - / SQRT SWAP
Converts 4 mem n to: - XX - X^2 / n
stack[] --------- --- d = sqrt(--------------)
(incl. 3 t XY - n - 1
mem) 2 z XX -
from: 1 y Y d m = X / n
0 x X m
QE (Quadratic Equation)
COMMANDS (25): SWAP 2 / CHS ENTER ENTER * SWAP ROT SWAP - SQRT ROT ROT
ENTER ROTup ENTER ROT SWAP ROT - ROT + SWAP ROT
Converts 4 mem - to: -
stack[] --------- --- y = x*x + p *x + q
(incl. 3 t - -
mem) 2 z - - x1 = -p/2 + sqrt((p/2)^2 - q)
from: 1 y p x2
0 x q x1 x2 = -p/2 - sqrt((p/2)^2 - q)
LR (Linear Regression)
COMMANDS (33): SUM2STACK * SWAP RCL * ROTup RCL * ROTup SHADOWSAVE
SUM2STACK ENTER * SHADOWLOAD1
SWAP ROT - ROT - ROTup / ENTER ENTER ENTER SHADOWSAVE
SUM2STACK SHADOWLOAD2 ROTup * - RCL / SWAP
Converts 4 mem n to: -
stack[] --------- --- y = a * x + b
(incl. 3 t XY -
mem) 2 z XX - a = (XY*n - X*Y) / (XX*n - X*X)
from: 1 y Y b
0 x X a b = (Y - X*a) / n
This already works but it is far from beeing optimized - because I'm not really a specialist in stack operations.
Unfortunately every operation costs 2 bytes of flash memory - and - slows down the code execution (running with a slow framerate (to save battery power) of 10 fps every calculation step needs 100 milliseconds).
So please help me to optimize those stack operations - every better sequence of commands or any idea is highly appreciated.
Thanks in advance.
deetee