______________________________

                                         TAKING A GANDER AND HAVINAGO

                                                                 lro
                                        ______________________________


                                                       <2019-01-09 Wed>


Table of Contents
_________________

Mathematics functions
. Squared
. Square root
. power and logarithm
. fractional part of number
Intro to Reverse Polish Notation
Doing Some Maths
Conclusion


I thought today we would implement alot more mathematics functions, and
actually have a look using the RPN calculator for some mathematics, you
know, actually use the thing I wrote.


Mathematics functions
=====================

 So lets round out this calculators mathematics functions so that its
 not just a little usable, but quite usable.


Squared
~~~~~~~

 Now scheme comes with a function for squaring a number but I want to
 keep `init-dict' as lean as possible. So we will implement square by
 duplicating the number on top of the stack and multiplying it by
 itself effectively.

 ,----
 | (squared dup *)
 `----


Square root
~~~~~~~~~~~

 We could write a square root inplementation, but would be difficult
 without flow control structures in our calculator, which I might add
 later.

 ,----
 | ;; to be added to init-dict
 | (cons 'sqrt (lambda (stack dict) (rpn-func sqrt 1 stack)))
 `----


power and logarithm
~~~~~~~~~~~~~~~~~~~

 Another function/s thats in scheme that would be easier to steal.

 ,----
 | ;; to be added to init-dict
 | (cons 'pow (lambda (stack dict) (rpn-func expt 2 stack)))
 | (cons 'log_e (lambda (stack dict) (rpn-func log 1 stack)))
 | ;; for log second argument is base
 | (cons 'log (lambda (stack dict) (rpn-func log 2 stack)))
 `----

 Because the default base for logarithm is e so i'll add two more user
 functions for base 10 and base 2.

 ,----
 | (log_10 10 swap log)
 | (log_2 2 swap log)
 `----


fractional part of number
~~~~~~~~~~~~~~~~~~~~~~~~~

 Getting the fractional part of a number can be implemented using our
 user dictionary.

 ,----
 | (frac dup trunc swap -)
 `----


Intro to Reverse Polish Notation
================================

 If you are unfamiliar with RPN, or postfix notation, its pretty
 simple. When you were taught mathematics you would fo been taught
 infix notation, where the operator is inbetween its arguments. Like
 this:

 ,----
 | 1 + 2
 `----

 Where as with postfix notation, the operator is /after/ its arguments:

 ,----
 | 1 2 +
 `----

 Which has an interesting property that you no longer need parentheses,
 beacause there isn't any operatar precedence rules, when an operator
 is executed, it operates on the top two elements of the stack.

 The wikipedia page for Reverse Polish Notation is pretty good at
 explaining this concept.


Doing Some Maths
================

 So lets do a classic example using the quadratic equation. It takes
 three variables, a, b and c.  So our function should expect those
 three variables to be on the stack.

 Lets recap what the quadratic equation looks like in infix notation:

 ,----
 | (-b +/- sqrt(b^2 - 4 * a * c)) / (2 * a)
 `----

 And if we convert to postfix:

 ,----
 | b square a c 4 * * - sqrt b negate +/- a 2 * /
 `----

 But our final iplementation won't look like that because we need to
 some "stack dancing" to get our variables in the right places.

 First, lets write a quick function that negates a number (makes it
 negative).

 ,----
 | (neg -1 *)
 `----

 And one that rotates the top three numbers on the stack (from xyz to
 zyx)

 ,----
 | (cons 'rot (lambda (stack dict) (let*-values (((var1 stack) (pop stack))
 |                                                                                       ((var2 stack) (pop stack))
 |                                                                                       ((var3 stack) (pop stack)))
 |                                                               (let* ((stack (push var1 stack))
 |                                                                              (stack (push var2 stack)))
 |                                                                     (push var3 stack)))))
 `----

 And have a look at the order in whch our variables are used (head of
 stack to right, will be used first):

 ,----
 | a b c a b
 `----

 And which order they are entered in (head of stack is right):

 ,----
 | a b c
 `----

 So first lets build up our quadratic function. First step is too dup
 both b and a as we need two copies of it. But im only going to dup a
 atm to make things easier down the line.

 ,----
 | (quadratic-eqn swap rot dup rot)
 | ;; now stack is (b a a c)
 `----

 Now we can do 4*a*c, then everything else under the square root.

 ,----
 | (quadratic-eqn swap rot dup rot 4 * *)
 | ;; now stack is (a 4*a*c b)
 |
 | (quadratic-eqn swap rot dup rot 4 * * swap rot dup square swap rot - sqrt)
 | ;; now stack is (a b D) D for discriminant.
 `----


 Next is to negate b and do the plus and minus.

 ,----
 | (quadratic-eqn swap rot dup rot 4 * * swap rot dup square swap rot - sqrt swap neg
 | dup rot dup rot + rot -)
 | ;; now stack is (a A1 A2) A for alsmost answer, just without the /2a.
 `----

 Now divide each answer by 2a

 ,----
 | (quadratic-eqn swap rot dup rot 4 * * swap rot dup square swap rot - sqrt swap neg
 | dup rot dup rot + rot swap - rot 2 * dup rot swap / rot swap /)
 | ;; now stack is (S1 S2) S for solution, the final one.
 `----

 And here is a table with the stack after each operation. A pen and
 paper is _ESSENTIAL_ for rpn programming, you basically do your
 functions by hand or with a table like this one.  Then through it into
 your command line and test it.

  func     stack
           (after func)
 ------------------------
           (a b c)
  swap     (a c b)
  rot      (b c a)
  dup      (b c a a)
  rot      (b a a c)
  4        (b a a c 4)
  *        (b a a 4c)
  *        (b a 4ac)
  swap     (b 4ac a)
  rot      (a 4ac b)
  dup      (a 4ac b b)
  squared  (a 4ac b b^2)
  swap     (a 4ac b^2 b)
  rot      (a b b^2 4ac)
  -        (a b d)
  sqrt     (a b D)
  swap     (a D b)
  neg      (a D -b)
  dup      (a D -b -b)
  rot      (a -b -b D)
  dup      (a -b -b D D)
  rot      (a -b D D -b)
  swap     (a -b D -b D)
  +        (a -b D A1)
  rot      (a A1 D -b)
  swap     (a A1 -b D)
  -        (a A1 A2)
  rot      (A2 A1 a)
  2        (A2 A1 a 2)
  *        (A2 A1 2a)
  dup      (A2 A1 2a 2a)
  rot      (A2 2a 2a A1)
  swap     (A2 2a A1 2a)
  \/       (A2 2a S1)
  rot      (S1 2a A2)
  swap     (S1 A2 2a)
  \/       (S1 S2)

 But what i have run into is a weird bug where the answer to a, b and c
 are all 1 is that /quadratic-eqn/ returns the same complex answer
 twice instead two different complex answers,

 Here is the stack before we minus the discriminant from -b and after:

 ,----
 | ;; before - operation, looks like it should
 | (0+1.7320508075688772i -1 -1+1.7320508075688772i 1)
 |
 | ;; one minus later and BOTH of our discimannats are the same value now ????
 | (-1-1.7320508075688772i -1-1.7320508075688772i 1)
 `----

 Very strange. I can replicate this bevhaviour by entering in the
 definition for /quadratic-eqn/ manually, but have no idea why it
 happens. It doesn't happen to non-complex determinants.

 I will look into this more next time.


Conclusion
==========

 So as you can see, writing functions like this requires alot of stack
 dancing, and thats where all the skill in stack programming is,
 reducing the amount of stack dancing you have to do. I would recommend
 everyone give it a go and see if you can get less function calls then
 I did, I haven't really "optimised" /quadratic-eqn/, but maybe
 something for next time as well as that strange bug.