## a small stack

This Thanksgiving, I’m thankful for modern computer architectures.

Ben’s post on Piet and dealing with it’s stack prompted me to dig up my old HP-15C calculator, a relic my father handed down to me which also operates on a stack architecture. If you’re interested in all of its capablities, you can download the pdf manual, but in a nutshell, the calculator has a fixed size stack and 67 7-byte registers.

The stack’s size is fixed at 4, each position on the stack is a 7-byte register, called the x, y, z and t registers. Push more than 4 numbers onto it and the first items will fall off the end. t is the bottom of the stack, and x is the top. The number shown in the HP-15C’s display is always the x-register. Extra storage is provided by the 67 addressable registers. The registers are divided into *data* and *program* registers. The exact allocation of each is changeable, but by default 20 registers are allocated for data, 46 are registered for program instructions and 1 is special, called the index register. The data registers are accessed and written to using the `RCL`

and `STO`

buttons followed by a register address. Register addresses are the numbers 0-9 or .0-.9 (a decimal key followed by a digit key).

## What to Write

As an excercise in programming the HP-15C, I decided to tackle Ben’s sunwalker challenge. I dug into the *Explanatory Supplement to the Astronomical Almanac* which had equations for roughly calculating the position of the sun relative to the earth for any day within two hundred years of the latest epoch, the year 2000.

The equations will give us the Right Ascension and Declination of the Sun which is the first step towards pinpointing where in the sky an observer from Earth would see it.

To do so, we start with the Julian Date of the day in question, `JD`

.

From that, we’d like to calculate where in it’s ecliptic, the Sun is. This measurement is called λ.

```
λ = L + 1.915 sin G + 0.020 sin 2 G
```

Where `L`

is the mean longitude corrected for aberration, and `G`

is the mean anomaly.

```
L = 280.460 + 36000.770 T
G = 357.528 + 35999.050 T
```

`T`

is the number of centuries since the epoch. Along with `T`

, there’s only one other number we need to calculate, `ε`

, the obliquity of the ecliptic.

```
T = JD - 2451545.0 / 36525
ε = 23.4393 - 0.01300 T
```

Having calculated the Sun’s ecliptic longitude, we can then convert it’s position into a position on the Celestial Sphere relative to the center of the Earth, given as right ascension, α, and declination, δ.

tan α = cos ε sin L / cos L

sin δ = sin ε sin L

## Get to the Program Already

In pseudo-code, the program looks like this:

```
357.528
35999.050
RCL .1
* +
STO .3
```

This is the calculation of `G`

, and it pushes two numbers onto the stack, retrieves `T`

from the .1 register, multiplies and adds and then stores the result for further calculations to use in the .3 register.

Each digit of the numbers, however corresponds to a single-byte instruction. `RCL`

and `STO`

operations consume 2 bytes. Here’s the whole listing in three columns, the machine instruction, the corresponding keyboard input and the pseudo-code equivalent:

```
001 - 42,21,11 f LBL A A: -- start program labeled A
002 - 45 0 RCL 0 RCL 0 -- fetch JD from register 0
003 - 2 2 -- calculate T
004 - 4 4
005 - 5 5
006 - 1 1
007 - 5 5
008 - 4 4
009 - 5 5 2451545.0
010 - 30 - -
011 - 3 3
012 - 6 6
013 - 5 5
014 - 2 2
015 - 5 5 36525
016 - 10 / /
017 - 44 .1 STO .1 STO .1 -- store T in register .1
018 - 2 2 -- calculate L
019 - 8 8
020 - 0 0
021 - 48 .
022 - 6 6 280.460
023 - 36 ENTER
024 - 3 3
025 - 6 6
026 - 0 0
027 - 0 0
028 - 0 0
029 - 48 .
030 - 7 7
031 - 7 8 36000.770
032 - 45 .1 RCL .1 RCL .1
033 - 20 * *
034 - 40 + +
035 - 44 .2 STO .2 STO .2 -- store L in register .2
036 - 3 3 -- calculate G
037 - 5 5
038 - 7 7
039 - 48 .
040 - 5 5
041 - 2 2
042 - 8 8 357.528
043 - 36 ENTER
044 - 3 3
045 - 5 5
046 - 9 9
047 - 9 9
048 - 9 9
049 - 48 .
050 - 0 0
051 - 5 5 35999.050
052 - 45 .1 RCL .1 RCL .1
053 - 20 * *
054 - 40 + +
055 - 44 .3 STO .3 STO .3 -- store G in register .3
056 - 45 .2 RCL .2 RCL .2 -- calculate λ
057 - 1 1
058 - 48 .
059 - 9 9
060 - 1 1
061 - 5 5 1.915
062 - 45 .3 RCL .3 RCL .3
063 - 23 sin sin
064 - 20 * *
065 - 40 + +
066 - 48 .
067 - 0 0
068 - 2 2 0.020
069 - 36 ENTER
070 - 2 2 2
071 - 45 .3 RCL .3 RCL .3
072 - 20 * *
073 - 23 sin sin
074 - 20 * *
075 - 40 + +
076 - 44 .4 STO .4 STO .4 -- store λ in register .4
077 - 2 2 -- calculate ε
078 - 3 3
079 - 48 .
080 - 4 4
081 - 3 3
082 - 9 9
083 - 3 3 23.4393
084 - 36 ENTER
085 - 48 .
086 - 0 0
087 - 1 1
088 - 3 3 0.01300
089 - 45 .1 RCL .1 RCL .1
090 - 20 * *
091 - 40 + +
092 - 44 .5 STO .5 STO .5 -- store ε in register .5
093 - 24 cos cos -- calcuate α
094 - 45 .4 RCL .4 RCL .4
095 - 23 sin sin
096 - 20 * *
097 - 45 .4 RCL .4 RCL .4
098 - 24 cos cos
099 - 10 / /
100 - 43 25 tan-1 tan-1
101 - 44 1 STO 1 STO 1 -- store α in register 1
102 - 45 .5 RCL .5 RCL .5 -- calculate δ
103 - 23 sin sin
104 - 45 .4 RCL .4 RCL .4
105 - 23 sin sin
106 - 20 * *
107 - 43 23 sin-1 sin-1
108 - 44 2 STO 2 STO 2 -- store δ in register 2
```

leave a comment