We seek to generate a one-sided discrete-time cosine (or sine) signal
with fixed-frequency *w*_{0} of the form

Consider a one-sided continuous-time analog-amplitude cosine of frequency
*f*_{0} in Hz

There are three common methods in software to generate a one-sided discrete-time sinusoidal waveform on chip:

- Math library function call (e.g. in C)
- Difference equation
- Lookup table

`cos`

or
`sin`

function (which requires `math.h`

).
The calculation is performed in double-precision floating-point
arithmetic.
There is no standard on how the cos and sin C math library functions
are actually implemented.
On a desktop computer, precision of the calculation is often the primary concern. Hence, additional computation is used to obtain higher accuracy in numerical calculations. In an embedded scenario, implementation complexity is generally at a premium, so alternate methods are typically employed to compute cosine and sine values other than a call to a C math library function.

In a desktop scenario, the C function for `cos(theta)`

could be implemented by the following steps:

- Compute
*x*= theta modulo 2 pi - Compute a ratio of two 10th-order polynomials in
*x*that approximate the cosine function

Version 1.8 of the freely distributable
GNU Scientific Library (GSL)
implements the cosine as the function `gsl_sf_cos_e`

, where sf means
special function, in the file `specfunc/trig.c`

.
The implementation uses a Chebyshev approximation over one-eighth
of the period for cosine and sine:

- Compute
*x*= theta modulo (pi/4) and the octant (0-7) of theta - Compute an 11th-order polynomial in
*x*that approximates the cosine function over one octant

For each cosine (or sine) value computed, the difference
equation would need to compute 2 multiplications and 3 additions.
In addition, 2 coefficients would need to be stored in memory.
Two previous values of *y*[*n*] and one previous value of *x*[*n*]
would be stored in memory.
Calculations could be performed in floating-point or
fixed-point arithmetic.

One way to reduce the accumulation of precision loss in cosine sample
calculations is to * reboot* the filter after each period
of samples has been calculated.
Reboot means to reset the filter to its initial state and run the filter
again.

- Complex-valued sinusoid of fixed frequency
*w*_{0}occurs when*a*= exp(j*w*_{0}).*y*[*n*] = C exp(j*w*_{0}*n*)*u*[*n*]. - Real-valued sinusoid of fixed frequency
*w*_{0}= pi occurs when*a*= exp(j pi) = -1.*y*[*n*] = C (-1)^{n}= C cos(pi*n*)*u*[*n*]. This is a special case of #1.

A lookup table of one period would contain *L* entries.
The entries could be in either floating-point or fixed-point format.
Using symmetry of the cosine over one period, one could store
one-half of the period, or even one-fourth of the period,
provided that *L* is divisible by 2 or 4, respectively.

Some programmable digital signal processors have read-only memory (ROM)
lookup tables of `cos(theta)`

and `sin(theta)`

available on chip.
One can interpolate values in these lookup tables to generate
cosine and sine signals of different frequencies.

Method | MACs per cosine sample | Read-only memory (words) | Writable memory (words) | Cosine quality in floating-point | Cosine quality in fixed-point |

C function call | 22 | 22 | 1 | Second best | Not applicable |

Difference equation | 2 | 2 | 3 | Worst | Second best |

Lookup table | 0 | L
| 0 | Best | Best |

MACs means multiplication-accumulation operations.
*L* is the period of the cosine signal.
Additional memory can be saved in the lookup table method by
storing one-half or even one-fourth of the period by using
symmetry properties of the cosine signal, but at a small
increase in computation.

Last updated 06/07/22. Send comments to bevans@ece.utexas.edu