Welcome to the NavList Message Boards.

NavList:

A Community Devoted to the Preservation and Practice of Celestial Navigation and Other Methods of Traditional Wayfinding

Compose Your Message

Message:αβγ
Message:abc
Add Images & Files
    Name or NavList Code:
    Email:
       
    Reply
    Computing sine & cosine part 1
    From: Paul Hirose
    Date: 2025 Jul 9, 16:27 -0700

    In the old days applications didn't always run on a computer able to
    calculate sines etc. in hardware. Remember when a deluxe machine had a
    387 on the motherboard? So, if you called sin() the compiler would
    include a routine which used the primitive operators of the language (+,
    -, etc.) to calculate the function. A book by P.J. Plaugher ("The
    Standard C Library," 1992) provides C language source code for a full
    set of math functions. I thought it would be interesting to look at his
    sine and cosine function.
    
    The first operation is subtract a whole multiple of π/2 (90°) to reduce
    argument x (radians) to the interval [-π/4, +π/4], i.e., -45° to +45°.
    The whole multiple is the 90° quadrant in which x lies. Quadrant 0 is
    -45 to +45, quadrant 1 is 45 to 135, etc. Quadrant number is computed by
    multiplying x by 2/π (in degrees, equivalent to division by 90). Round
    the result to the nearest whole number.
    
    However, the obvious method to remove whole multiples of π/2 loses
    accuracy, especially if x is large. It's easier to see this if we
    imagine a large x and a calculator with only 6 digits. Suppose x =
    899.188 radians. That angle is in quadrant 572, and (π/2 * 572) =
    898.498. When you subtract that from x, the result is 0.690. The last
    digit is wrong by 2.5 units.
    
    A more accurate result is possible with our 6-digit calculator if we
    split π/2 into components c1 = 1.57 and c2 = 7.96327e-4. Their sum is
    π/2. To remove 572 quadrants from x:
    
    x = 899.188 - 572 * c1 - 572 * c2
    x = 899.188 - 898.040 - 0.455499
    x = 0.692501
    
    That's more accurate. It could be argued that 6 decimal places is fake
    precision since x is known to only .001. Well, we can't improve the
    precision of the argument, but we can try to extract the maximum from
    what has been supplied.
    
    The computer implementation by Plaugher uses the same principle, but
    with the 64-bit double precision floating point format. Constant c1 is
    defined in a non-obvious way:
    
    c1 = 3294198.0 / 2097152.0
    
    The numerator is an integer of 22 bits. The denominator is 2 to the 21st
    power. Thus, to form the constant c1, simply shift the binary point of
    the numerator 21 places to the left. That gives the first 22 bits of
    π/2. The other bits are 0.
    
    If you try to initialize c1 with a numeric literal (1.570...) that exact
    bit pattern is not guaranteed since a decimal fraction doesn't have an
    exact binary representation (except special cases such as 0.25).
    
    Constant c2 = 3.139164786504813217e-7. It supplies the remaining digits
    of π/2. I.e., c1 + c2 = π/2 to high precision. Then Plaugher does this
    to reduce angle x to the interval [-π/4, +π/4]:
    
    x = (x - quadrant * c1) - quadrant * c2
    
    He doesn't explain the parentheses, but I think their purpose is to
    force the order of evaluation. If you change the order of the
    subtractions in my 6-digit example there's a loss of accuracy.
    
    But parentheses do not guarantee order of evaluation in the C language.
    As explained by Harbison and Steele ("C, A Reference Manual," 1991), a
    compiler is allowed to disregard parentheses and re-arrange expressions
    to a mathematically equivalent sequence. For example, if your code says
    (a + b) + (c + d) it might execute, right to left, as a + d + b + c.
    They say the only way to be sure of evaluation order is use temporary
    variables. Thus, I added a double precision temporary variable to the
    Plaugher code:
    
    double temp = x - quadrant * c1;
    x = temp - quadrant * c2;
    
    I have explained the adjustment of the argument at length to make clear
    why it's a bad idea to remove whole circles to "help" a trig function.
    It knows how to do that, and probably does a better job than you.
    
    In the second part I'll show Plaugher's sine and cosine expressions.
    
    --
    Paul Hirose
    sofajpl.com
    

       
    Reply
    Browse Files

    Drop Files

    NavList

    What is NavList?

    Join / Get NavList ID Code

    Name:
    (please, no nicknames or handles)
    Email:
    Do you want to receive all group messages by email?
    Yes No

    A NavList ID Code guarantees your identity in NavList posts and allows faster posting of messages.

    Retrieve a NavList ID Code

    Enter the email address associated with your NavList messages. Your NavList code will be emailed to you immediately.
    Email:

    Email Settings

    NavList ID Code:

    Custom Index

    Subject:
    Author:
    Start date: (yyyymm dd)
    End date: (yyyymm dd)

    Visit this site
    Visit this site
    Visit this site
    Visit this site
    Visit this site
    Visit this site