Last modified on 28 October 2010, at 22:48

The Science of Programming/Auld Lang Sine

You have, in all likelihood, previously made acquaintance with sines and cosines. Sinusoids (which include sines and cosines) are periodic functions. Periodic functions have the following property:

    f\,(x) = f\,(x + p) = f\,(x + 2p) = ... 
   

for all x and certain values of p. The smallest value of p for which the above equation holds is known as the period of the function.

If you not familiar with sines and cosine functions, this is what a sine wave looks like:

Ch15-figure01.png

Note that for sine waves without phase and frequency shifts (as above), when x is zero, the amplitude (y-value) of the sine wave is zero (with a rising slope). The wave reaches zero again (with a rising slope) x = 2π. Contrast this with the cosine wave:

Ch15-figure02.png

Unlike the sine wave, which has zero-crossings at multiples of π, the cosine wave has peaks and troughs at multiples of π. As with the sine wave, the period, or peak to peak length, is 2π.

The general sine waveEdit

If you look closely at the two waves, you'll see that the cosine is just the sine wave shifted \frac{\pi}{2} units to the left. So, we can define cosine in terms of sine:

    \cos(x) = \sin(x + \frac{\pi}{2}) 

Note that mathematicians often abbreviate sine to sin and cosine to cos. The above illustrates one of the common ways to modify a sine wave: shifting the phase of the wave, for which the symbol \theta is often used:

    y = \sin(x + \theta); 

Another modification is to change the amplitude of a sine wave or, on other words, to change how high and how low the peaks range. The variable a is used to indicate amplitude, so the formula for a sine wave that allows amplitude modification is:

    y = a \sin(x + \theta); 

Finally, it is common to change the frequency of sine waves, or how many peaks (or troughs) are in a given region. The variable \omega is often used for this task:

    y = a \sin(\omega x + \theta); 

If we set \omega to 2, we will get twice as many peaks (or troughs) within a given region. The inverse of frequency is period, so setting \omega to 2 will shorten the peak to peak distance by half. In the particular case of frequency 2, the period of the sine wave would be π.

Here's a neat trick. If you want to find the location of the 'first' zero crossing, of a general sign wave of this form, change the sign of both the phase shift and the operator combining it with x and then factor out \omega. For cosine, with unit amplitude and frequency doubled, we have:

    \cos(x) = \sin(2x + \frac{\pi}{2}) 
    
    \cos(x) = \sin(2x - (-\frac{\pi}{2})) 
    
    \cos(x) = \sin(2[x - (-\frac{\frac{\pi}{2}}{2})]) 
    
    \cos(x) = \sin(2[x - (-\frac{\pi}{4})]) 

This version of cosine has its first zero crossing at x = -\frac{\pi}{4}. [1] In other words, to find the first zero crossing, divide the phase shift by the frequency and negate it (assuming that the phase shift is being added in).

Implementing the general sine waveEdit

Sway has the functions sin and cos built-in, but these functions assume amplitude = 1, frequency = 1, and phase shift = 0. [2] To implement sine and cosine, we will take our usual object approach:

   function sine(amp,freq,shift)
       {
       function value(x)
           {
           amp * sin(freq * x + shift);
           }
       this;
       }
    
   function cosine(amp,freq,shift)
       {
       sine(amp,freq,shift + (pi() / 2));
       }

Note how we make cosine a wrapper for sine as cosine is just sine with a phase shift.

Let's take that little trick we learned in the previous section for finding the 'first' zero crossing and implement it:

   function sine(amp,freq,shift)
       {
       function value(x) { ... }
       function firstZero()
           {
           // phase shift is added in so just divide and negate
           -(real(shift) / freq);
           }
       this;
       }

Let's see if it works for cosine with frequency 2:

   var w = cose(1,2,0);
    
   sway> -(pi() / 4);
   REAL_NUMBER: -0.7853981634
   
   sway> w . firstZero();
   REAL_NUMBER: -0.7853981634

Good. Let's also check that the value of the sine wave is indeed zero at that point:

   sway> var fz = w . firstZero();
   REAL_NUMBER: -0.7853981634
    
   sway> w . value(fz);
   w . value(fz) is 0.000000e+00

Bingo!

Differentiating sine and cosineEdit

As SPT points out in Chapter XV in CMT, the derivative of sine is cosine and the derivative of cosine is the negative of sine.

Using the first rule, we can add a diff function to the sine constructor. Of course, in keeping with our unassuming differentiation system, we need to pass in independent and with-respect-to variables, as appropriate:

   function sine(amp,freq,shift)
       {
       function value(x) { ... }
       function firstZero() { ... }
       function diff()
           {
           cosine(amp,freq,shift);
           }
       this;
       }

Of course, this implementation assumes that the independent variable and the with-respect-to variable are one and the same. It also assumes that the independent variable is just a symbol. As such, we could not construct a sine wave of the form;

    y = 3 \sin(2 x^2 + pi) 

To do so, we will have to take the same approach as for terms, by allowing the independent variable to be a differentiable object. Recall the term constructor:

   function term(a,iv,n)
       {
       function value(x) { ... }
       function toString() { ... }
       function diff(wrtv)
           {
           if (n == 0)
               {
               constant(0);
               }
           else
               {
               term(a * n,iv,n - 1) times iv . diff(wrtv);
               }
           }
       
       if (iv is :SYMBOL) { iv = variable(iv); }
       this;
       }

Recall also how the diff function implements the chain rule. We will need to follow the same strategy for our sine constructor:

   function sine(amp,freq,iv,shift)
       {
       function value(x) { ... }
       function firstZero() { ... }
       function diff(wrtv)
           {
           cosine(amp,freq,iv,shift) times iv . diff(wrtv);
           }
        
       if (iv is :SYMBOL,iv = variable(iv));
       this;
       }

All that's left for us to do is implement our visualization for sine (and, of course, test):

   function toString()
       {
       "" + amp +
           " sin(" + freq +
               "(" + iv . toString() + ")"
               + shift + ")";
       }

What is -sin?Edit

According to CMT, the derivative of sine is cosine and the derivative of cosine is -sin. Therefore, the second derivative of sine is -sine.

QuestionsEdit

1. What is the difference between the function \sin(x + \frac{\pi}{2}) and the function \sin(x) + \frac{\pi}{2}?

2. Why can't we name sine and cosine constructors sin and cos?

3. Add the following simplification to the sine constructor. If the phase shift is equal to or greater than 2 π, subract off 2 π.

4. Explain why the previous simplification is mathematically valid.

5. Simplify the construction of sine objects so that a zero object is generated if the amplitude is zero.

6. Simplify the construction of sine objects so that a constant term object is generated if the frequency is zero.

7. Simplify the visualization of sine objects so that the amplitude, frequency, and phase shift are omitted if they are 1, 1, and 0, respectively.

8. Find and add other visualization mods. Hint: what should your visualization look like if the frequency is != 1 but the independent variable is a term with a coefficient != 1?

FootnotesEdit

  1. Contrast this with the cosine wave with unit amplitude and frequency (shown at the beginning of this chapter), which has a zero crossing at x = -\frac{\pi}{2}.
  2. There is also a generalized cosine function: y = a \cos(\omega x + \theta). Of course, this is equal to a \sin(\omega x + \frac{\pi}{2} + \theta).


The Rich Get Richer · Do What You Can