Skip to main content
Mod Moved Comments To Chat
Bounty Ended with 50 reputation awarded by Starship
Better parentheses
Source Link
Nathan Tuggy
  • 4.6k
  • 5
  • 36
  • 44

$$\begin{aligned} C_{5/2} &= .0363551 \approx \big(\frac\pi2\big)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2} &= -.3216147 \approx -\big(\frac\pi2\big)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2} &= .7853134 \approx \frac\pi2 \cdot \frac12\\ \end{aligned}$$$$\begin{aligned} C_{5/2} &= .0363551 \approx \left(\frac\pi2\right)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2} &= -.3216147 \approx -\left(\frac\pi2\right)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2} &= .7853134 \approx \frac\pi2 \cdot \frac12\\ \end{aligned}$$

$$\begin{aligned} C_{5/2} &= .0363551 \approx \big(\frac\pi2\big)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2} &= -.3216147 \approx -\big(\frac\pi2\big)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2} &= .7853134 \approx \frac\pi2 \cdot \frac12\\ \end{aligned}$$

$$\begin{aligned} C_{5/2} &= .0363551 \approx \left(\frac\pi2\right)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2} &= -.3216147 \approx -\left(\frac\pi2\right)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2} &= .7853134 \approx \frac\pi2 \cdot \frac12\\ \end{aligned}$$

Fixed 2 minor LaTeX typos. Aligned a block of LaTeX for easier reading.
Source Link

$$ C_{5/2}= .0363551 \approx \big(\frac\pi2\big)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2}= -.3216147 \approx -\big(\frac\pi2\big)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2}= .7853134 \approx \frac\pi2 \cdot \frac12\\ $$$$\begin{aligned} C_{5/2} &= .0363551 \approx \big(\frac\pi2\big)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2} &= -.3216147 \approx -\big(\frac\pi2\big)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2} &= .7853134 \approx \frac\pi2 \cdot \frac12\\ \end{aligned}$$

In this plot the differences between $sin(\pi x)$$\sin(\pi x)$ and the approximations (Apollo/Taylor) is displayed. One can see, that the Taylor approximation is much worse for $x\geq .3$, but much better for $x\leq .1$. Mathematically, this is not a huge surprise, because Taylor approximations are only locally defined, and therefore they are often only useful close to a single point (here $x=0$x=0$).

$$ C_{5/2}= .0363551 \approx \big(\frac\pi2\big)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2}= -.3216147 \approx -\big(\frac\pi2\big)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2}= .7853134 \approx \frac\pi2 \cdot \frac12\\ $$

In this plot the differences between $sin(\pi x)$ and the approximations (Apollo/Taylor) is displayed. One can see, that the Taylor approximation is much worse for $x\geq .3$, but much better for $x\leq .1$. Mathematically, this is not a huge surprise, because Taylor approximations are only locally defined, and therefore they are often only useful close to a single point (here $x=0).

$$\begin{aligned} C_{5/2} &= .0363551 \approx \big(\frac\pi2\big)^5 \cdot \frac1{2\cdot 5!}\\ C_{3/2} &= -.3216147 \approx -\big(\frac\pi2\big)^3 \cdot \frac1{2\cdot 3!}\\ C_{1/2} &= .7853134 \approx \frac\pi2 \cdot \frac12\\ \end{aligned}$$

In this plot the differences between $\sin(\pi x)$ and the approximations (Apollo/Taylor) is displayed. One can see, that the Taylor approximation is much worse for $x\geq .3$, but much better for $x\leq .1$. Mathematically, this is not a huge surprise, because Taylor approximations are only locally defined, and therefore they are often only useful close to a single point (here $x=0$).

Copy edited (e.g. ref. <http://en.wikipedia.org/wiki/Python_%28programming_language%29>).
Source Link

Since the Apollo 11 Codecode is on GithubGitHub, I was able to find the code that looks like an implementation of sine and cosine functions: see here for the command module and here for the lunar lander (it looks like it is the same code).

 # Page 1102
            BLOCK   02

# SINGLE PRECISION SINE AND COSINE

            COUNT*  $$/INTER
SPCOS       AD      HALF            # ARGUMENTS SCALED AT PI
SPSIN       TS      TEMK
            TCF     SPT
            CS      TEMK
SPT         DOUBLE
            TS      TEMK
            TCF     POLLEY
            XCH     TEMK
            INDEX   TEMK
            AD      LIMITS
            COM
            AD      TEMK
            TS      TEMK
            TCF     POLLEY
            TCF     ARG90
POLLEY      EXTEND
            MP      TEMK
            TS      SQ
            EXTEND
            MP      C5/2
            AD      C3/2
            EXTEND
            MP      SQ
            AD      C1/2
            EXTEND
            MP      TEMK
            DDOUBL
            TS      TEMK
            TC      Q
ARG90       INDEX   A
            CS      LIMITS
            TC      Q       # RESULT SCALED AT 1.
 

indicates, that the following is indeed an implementation of the sine and cosine functions. Information

Information about the type of assembler used, can be found on Wikipedia.

The subroutine SPSIN actually calculates $\sin(\pi x)$, and SPCOS calculates $\cos(\pi x)$. The

The subroutine SPCOS first adds one half to the input, and then proceeds to calculate the sine    (this is valid because of $\cos(\pi x) = \sin(\pi (x+\tfrac12))$). The The argument is doubled at the beginbeginning of the SPT subroutine. That That is why we now have to calculate $\sin(\tfrac\pi2 y)$ for $y=2x$.

The subroutine POLLEY calculates an almost Taylor polynomial approximation of $\sin(\tfrac\pi2 x)$. First First, we store $x^2$ in the register SQ (where $x$ denotes the input). This This is used to calculate the polynomial $$ ((( C_{5/2} x^2 ) + C_{3/2} ) x^2 + C_{1/2}) x. $$ The values for the constants can be found in the same githubGitHub repository and are

which look like the first Taylor coefficients for the function $\frac12 \sin(\tfrac\pi2 x)$. These

These values are not exact! So this is a polynomial approximation, which is very close to the Taylor approximation, but even better (see below, also thanks to @uhoh and @zch).

As for the scaling (first halve, then double, ...), @Christopher mentioned in the comments, that the 16-Bit Fixedbit fixed-Pointpoint number could only store values from -1 to +1. Therefore, scaling is necessary. See here for a source and further details on the data representation. Details for the assembler instructions can be found on the same page.

A short@uhoh wrote some python scriptPython code that varies, which compares the coefficients to minimize errors over the interval $-\tfrac\pi2 \leq x \leq \tfrac\pi2$ returns values very close to the $C_{1/2}, C_{3/2}, C_{5/2}$ from the Apollo code, rather than with the proper Taylor coefficients expanded about zeroand calculates the optimal coefficients (based on the maximal error for $-\tfrac\pi2 \leq x \leq \tfrac\pi2$ and quadratic error on that domain). This tends to confirm It shows that these have been optimized for best performance over the interval, though it remainsApollo coefficients are closer to be seen exactly what performance measure was optimizedthe optimal coefficients than the Taylor coefficients.

In this plot the differences between $sin(\pi x)$ and the approximations (Apollo/Taylor) is displayed. One One can see, that the Taylor approximation is much worse for $x\geq .3$, but but much better for $x\leq .1$. Mathematically Mathematically, this is not a huge surprise, because Taylor approximations are only locally defined, and therefore they are often only useful close to a single point (here $x=0).

Note that for this polynomial approximation you only need four multiplications and two additions (MP and AD in the code). For For the Apollo Guidance ComputerApollo Guidance Computer, Memorymemory and CPU cycles were only available in small numbers.

There are some ways to increase accuracy and input range, which would have been available for them, but it would result in more code and more computation time. For example, exploiting symmetry and periodicity of sine and cosine, using the Taylor expansion for cosine, or simply adding more terms of the Taylor expansion would have improved the accuracy and would also allowhave allowed for arbitrary large input values.

Since the Apollo 11 Code is on Github, I was able to find the code that looks like an implementation of sine and cosine functions: see here for the command module and here for the lunar lander (it looks like it is the same code).

 # Page 1102
            BLOCK   02

# SINGLE PRECISION SINE AND COSINE

            COUNT*  $$/INTER
SPCOS       AD      HALF            # ARGUMENTS SCALED AT PI
SPSIN       TS      TEMK
            TCF     SPT
            CS      TEMK
SPT         DOUBLE
            TS      TEMK
            TCF     POLLEY
            XCH     TEMK
            INDEX   TEMK
            AD      LIMITS
            COM
            AD      TEMK
            TS      TEMK
            TCF     POLLEY
            TCF     ARG90
POLLEY      EXTEND
            MP      TEMK
            TS      SQ
            EXTEND
            MP      C5/2
            AD      C3/2
            EXTEND
            MP      SQ
            AD      C1/2
            EXTEND
            MP      TEMK
            DDOUBL
            TS      TEMK
            TC      Q
ARG90       INDEX   A
            CS      LIMITS
            TC      Q       # RESULT SCALED AT 1.
 

indicates, that the following is indeed an implementation of the sine and cosine functions. Information about the type of assembler used, can be found on Wikipedia

The subroutine SPSIN actually calculates $\sin(\pi x)$, and SPCOS calculates $\cos(\pi x)$. The subroutine SPCOS first adds one half to the input, and then proceeds to calculate the sine  (this is valid because of $\cos(\pi x) = \sin(\pi (x+\tfrac12))$). The argument is doubled at the begin of the SPT subroutine. That is why we now have to calculate $\sin(\tfrac\pi2 y)$ for $y=2x$.

The subroutine POLLEY calculates an almost Taylor polynomial approximation of $\sin(\tfrac\pi2 x)$. First, we store $x^2$ in the register SQ (where $x$ denotes the input). This is used to calculate the polynomial $$ ((( C_{5/2} x^2 ) + C_{3/2} ) x^2 + C_{1/2}) x. $$ The values for the constants can be found in the same github repository and are

which look like the first Taylor coefficients for the function $\frac12 \sin(\tfrac\pi2 x)$. These values are not exact! So this is a polynomial approximation, which very close to the Taylor approximation, but even better (see below, also thanks to @uhoh and @zch).

As for the scaling (first halve, then double, ...), @Christopher mentioned in the comments, that the 16-Bit Fixed-Point number could only store values from -1 to +1. Therefore, scaling is necessary. See here for a source and further details on the data representation. Details for the assembler instructions can be found on the same page.

A short python script that varies the coefficients to minimize errors over the interval $-\tfrac\pi2 \leq x \leq \tfrac\pi2$ returns values very close to the $C_{1/2}, C_{3/2}, C_{5/2}$ from the Apollo code, rather than the proper Taylor coefficients expanded about zero. This tends to confirm that these have been optimized for best performance over the interval, though it remains to be seen exactly what performance measure was optimized.

In this plot the differences between $sin(\pi x)$ and the approximations (Apollo/Taylor) is displayed. One can see, that the Taylor approximation is much worse for $x\geq .3$, but much better for $x\leq .1$. Mathematically, this is not a huge surprise, because Taylor approximations are only locally defined, and therefore they are often only useful close to a single point (here $x=0).

Note that for this polynomial approximation you only need four multiplications and two additions (MP and AD in the code). For the Apollo Guidance Computer, Memory and CPU cycles were only available in small numbers.

There are some ways to increase accuracy and input range, which would have been available for them, but would result in more code and more computation time. For example, exploiting symmetry and periodicity of sine and cosine, using the Taylor expansion for cosine, or simply adding more terms of the Taylor expansion would have improved the accuracy and would also allow for arbitrary large input values.

Since the Apollo 11 code is on GitHub, I was able to find the code that looks like an implementation of sine and cosine functions: see here for the command module and here for the lunar lander (it looks like it is the same code).

 # Page 1102
            BLOCK   02

# SINGLE PRECISION SINE AND COSINE

            COUNT*  $$/INTER
SPCOS       AD      HALF            # ARGUMENTS SCALED AT PI
SPSIN       TS      TEMK
            TCF     SPT
            CS      TEMK
SPT         DOUBLE
            TS      TEMK
            TCF     POLLEY
            XCH     TEMK
            INDEX   TEMK
            AD      LIMITS
            COM
            AD      TEMK
            TS      TEMK
            TCF     POLLEY
            TCF     ARG90
POLLEY      EXTEND
            MP      TEMK
            TS      SQ
            EXTEND
            MP      C5/2
            AD      C3/2
            EXTEND
            MP      SQ
            AD      C1/2
            EXTEND
            MP      TEMK
            DDOUBL
            TS      TEMK
            TC      Q
ARG90       INDEX   A
            CS      LIMITS
            TC      Q       # RESULT SCALED AT 1.

indicates, that the following is indeed an implementation of the sine and cosine functions.

Information about the type of assembler used, can be found on Wikipedia.

The subroutine SPSIN actually calculates $\sin(\pi x)$, and SPCOS calculates $\cos(\pi x)$.

The subroutine SPCOS first adds one half to the input, and then proceeds to calculate the sine  (this is valid because of $\cos(\pi x) = \sin(\pi (x+\tfrac12))$). The argument is doubled at the beginning of the SPT subroutine. That is why we now have to calculate $\sin(\tfrac\pi2 y)$ for $y=2x$.

The subroutine POLLEY calculates an almost Taylor polynomial approximation of $\sin(\tfrac\pi2 x)$. First, we store $x^2$ in the register SQ (where $x$ denotes the input). This is used to calculate the polynomial $$ ((( C_{5/2} x^2 ) + C_{3/2} ) x^2 + C_{1/2}) x. $$ The values for the constants can be found in the same GitHub repository and are

which look like the first Taylor coefficients for the function $\frac12 \sin(\tfrac\pi2 x)$.

These values are not exact! So this is a polynomial approximation, which is very close to the Taylor approximation, but even better (see below, also thanks to @uhoh and @zch).

As for the scaling (first halve, then double, ...), @Christopher mentioned in the comments, that the 16-bit fixed-point number could only store values from -1 to +1. Therefore, scaling is necessary. See here for a source and further details on the data representation. Details for the assembler instructions can be found on the same page.

@uhoh wrote some Python code, which compares the coefficients $C_{1/2}, C_{3/2}, C_{5/2}$ from the Apollo code with the Taylor coefficients and calculates the optimal coefficients (based on the maximal error for $-\tfrac\pi2 \leq x \leq \tfrac\pi2$ and quadratic error on that domain). It shows that the Apollo coefficients are closer to the optimal coefficients than the Taylor coefficients.

In this plot the differences between $sin(\pi x)$ and the approximations (Apollo/Taylor) is displayed. One can see, that the Taylor approximation is much worse for $x\geq .3$, but much better for $x\leq .1$. Mathematically, this is not a huge surprise, because Taylor approximations are only locally defined, and therefore they are often only useful close to a single point (here $x=0).

Note that for this polynomial approximation you only need four multiplications and two additions (MP and AD in the code). For the Apollo Guidance Computer, memory and CPU cycles were only available in small numbers.

There are some ways to increase accuracy and input range, which would have been available for them, but it would result in more code and more computation time. For example, exploiting symmetry and periodicity of sine and cosine, using the Taylor expansion for cosine, or simply adding more terms of the Taylor expansion would have improved the accuracy and would also have allowed for arbitrary large input values.

walked back on some of the conclusions from the minimization script
Source Link
uhoh
  • 151k
  • 56
  • 505
  • 1.6k
Loading
added 2 characters in body
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
use almost-Taylor instead of Taylor
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
edited body
Source Link
peterh
  • 3.3k
  • 4
  • 28
  • 41
Loading
added 662 characters in body
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
deleted 4 characters in body
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
added 158 characters in body
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
add cosine plot
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
add plot
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
added 401 characters in body
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
added 313 characters in body
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
code explanation
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading
Source Link
supinf
  • 2.2k
  • 1
  • 9
  • 7
Loading