Re: A89: sine and cosine


[Prev][Next][Index][Thread]

Re: A89: sine and cosine





> hello.  is there a way to use the sine and cosine functions using asm?  right
> now all i can think of is making a chart of values from 0 - 90, but i am
> hoping that there is a better way.  thanks.

That method is very useful, but it isn't the only solution.  Assuming
that
you don't have enough time to compute approximations each time you get a
sine or cosine, your best choice is to generate a table in memory when
the
program starts.  The basic principle behind this is from calculus:
basically, the rate of change of the value of sine equals the value of
the
cosine, and the rate of change of cosine is negative the value of sine.
Of course, this is only true with respect to smooth curves, not
approximate
values.  However, if you take this in very small steps, you can get a
good
approximation.  Essentially, use a formula like:

sin(x+0.01)=sin(x)+0.01*cos(x)
cos(x+0.01)=cos(x)-0.01*sin(x)

This is dealing in radians.  If your tables will have 256 elements which
correspond to the entire periods of the functions (2PI radians), then
the
multiplier would be 2PI / 256, about 0.0245.  However, due to problems
such as round-off error, you may want to look at the resulting tables
and
make this value slightly higher or lower than it really should be to
account for that.  

Below is a routine that I have actually used (writing 3D effects on the
Amiga computer) for this purpose.  It generates an interleaved table of
sines and cosines; that is, the sine of a number, then it's cosine, then
the sine of the next value, and so on.  It uses 1024 steps, and values
are stored as fixed point numbers multiplied by 1024, giving the
equivalent of about 3 decimal places of detail.  I also included the
routine to calculate sine and cosine values by extracting from the
table.  This routine will generate the table in less than 1/10 of a
second, and it's accurate enough that it seemed to me to result in
rendering of equal quality to that I had when using pre-made tables.

; Here, trigtbl must be 4096 bytes of free memory.  Call this routine
; once to generate the table.

ti_code:        lea     trigtbl,a0
                moveq   #0,d0
                move.w  #1024,d1
                move.w  #1023,d4
gentt:          move.w  d0,(a0)+
                move.w  d1,(a0)+
                move.w  d0,d2
                muls    #-402,d2
                swap    d2
                add.w   d2,d1
                move.w  d1,d3
                muls    #402,d3 
                swap    d3
                add.w   d3,d0
                dbra    d4,gentt
                rts

; This computes the sine and cosine of a value.  It takes D2 as a
; value from 0 to 1023 specifying the angle, where 1024 of this unit
; represents a full circle.  It returns the sine in D2 and cosine in
; D3.  Both are fixed-point integers, scaled up 10 bits (by a factor
; of 1024).

sincos:         lea.l   trigtbl,a2
                add.w   d2,d2
                add.w   d2,d2
                add.w   d2,a2
                move.w  (a2)+,d2
                move.w  (a2)+,d3
                rts          

; For even more precision, use this generating routine instead.  It
; makes a table in the same format, but with much more internal
; precision, and is thus slower (taking a noticeable fraction of a
; second to execute).

trig_init:      move.l  #2560000,d0             ;d0 = cosine
                moveq   #0,d1                   ;d1 = sine
                move.w  #652,d6                 ;divisor for calc
                move.w  #2500,d7                ;divisor for store
                lea     trig_256,a0
                move.l  #1023,d4
trigpc1:        moveq   #3,d5
trigpc2:        move.l  d0,d2
                move.l  d1,d3
                divs    d6,d2
                ext.l   d2
                divs    d6,d3
                ext.l   d3
                sub.l   d3,d0
                add.l   d2,d1
                dbra    d5,trigpc2
                move.l  d0,d2
                divs    d7,d2
                move.l  d1,d3
                divs    d7,d3
                move.w  d3,4096(a0)
                asr.w   #2,d3
                move.w  d3,(a0)+
                move.w  d2,4096(a0)
                asr.w   #2,d2
                move.w  d2,(a0)+
                dbra    d4,trigpc1
                rts


Follow-Ups: References: