home *** CD-ROM | disk | FTP | other *** search
- ; Date: Wed, 15 May 1996 22:27:55 -0400 (EDT)
- ; From: Jingyang Xu [br00416@bingsuns.cc.binghamton.edu]
- ; Subject: LZ: Trig Routines: SIN/COS/TAN
-
- ; Someone asked me about these and here are the bug-free version of my
- ; sin/cos/tan routines:
-
- ; Note that sin and cos uses the same table and tan uses its own table.
- ; The arguments to sinx and cosx are: a=multiplier bc=angle
- ; and the return is now in bc: b=integer part c=fractional part.
- ; So bc is a 16 bit signed number, the key here is signed - if the high bit
- ; of b is set, that means bc is the twos complement of the positive value
- ; of bc.
- ; For the tangent routine. de is the multiplier (this is a 16 bit
- ; multiplier) and hl is the angle. I think it returns the result in hl, in
- ; the same format as that for bc.
-
- AdjustAngleinBC:
- xor a
- cp b
- jr z,Alldone
- ld h,b
- ld l,c
- ld bc,360
- and a
- sbc hl,bc
- jr nc,AAHalfDone
- add hl,bc
- AAHalfDone:
- ld b,h
- ld c,l
- jr Alldone
- Alldone:
- ret
-
- sinx:
- push af ;save argument
- ld d,1 ;d=1, use for later
- ld hl,180
- and a ;clear carry
- sbc hl,bc
- jr nc,LessE180 ;is angle greater than 180 degrees?
-
- Great180:
- ld h,b ;
- ld l,c ;load bc into hl
- ld bc,180 ;
- and a ; bc=bc-180
- sbc hl,bc ;
- ld b,h ;
- ld c,l ;load hl into bc
- inc d ; d=2, remember negated
- LessE180: ;0<=bc<=180 -> 0 is in b and 0<=c<=180
- ld a,d ;save d
- ld de,(PROGRAM_ADDR)
- ld hl,Trig_Look_Up ;hl=addr of table
- add hl,de
- ld d,a ;restore d
- ld a,c ;load angle into accumulator
- cp 90 ;is it 90 degrees?
- jr nz,not90
- ld a,128 ;if 90 degrees, sin90=1
- jr sinloaded
- not90:
- sub 90
- jr nc,Greater90 ;is angle less than or greater than 90
- Less90:
- add hl,bc ;if less than, go directly to table
- ld a,(hl)
- jr sinloaded
- Greater90:
- ld a,180 ;if greater, sin(x)=sin(180-x)
- sub c ;subtract from 180
- ld c,a
- add hl,bc ;read from table
- ld a,(hl)
- sinloaded: ;x/128 is in a, d will determine sign
- ld b,a ;save result
- pop af ;get multiplicand back
- bit 7,a ;test to see if a is negative
- jr z,apositive
- neg ;if negative, negate
- inc d ;store negative memory in d
- apositive: ;now we want a*b/128
- ld e,a ;save a
- ld a,b ;
- cp 0 ;see if e=0
- jr z,multiplyby0 ;
- ld c,0
- xor a
- sinmultiplyloop:
- add a,e
- jr nc,nocarry ;multipy a by b
- inc c ;16bit result in ca
- nocarry:
- djnz sinmultiplyloop
- rl a ;shift ca to the left
- rl c ;ca/128 now in c
- ld b,c
- ld c,a
- dec d
- jr z,sinxend
- and a
- ld hl,0
- sbc hl,bc
- ld b,h
- ld c,l
- dec d
- jr z,sinxend
- and a
- ld hl,0
- sbc hl,bc
- ld b,h
- ld c,l
- dec d
- jr z,sinxend
- multiplyby0:
- ld bc,0
- sinxend:
- ret
-
- cosx:
- ld hl,90
- add hl,bc
- ld b,h
- ld c,l
- ld d,a
- CALL_(AdjustAngleinBC)
- ld a,d
- CALL_(sinx)
- ret
-
- Trig_Look_Up:
- .db 0,2,4,6,8,11,13,15,17,20
- .db 22,24,26,28,30,33,35,37,39,41
- .db 43,45,47,50,52,54,56,58,60,62
- .db 64,65,67,69,71,73,75,77,78,80
- .db 82,83,85,87,88,90,92,93,95,96
- .db 98,99,100,102,103,104,106,107,108,109
- .db 110,111,113,114,115,116,116,117,118,119
- .db 120,121,121,122,123,123,124,124,125,125
- .db 126,126,126,127,127,127,127,127,127,127
-
- tanx: ;multiplier in de, angle in hl
- push de
- push de ;save multiplier
-
- ld b,h ;make another copy of angle in bc
- ld c,l ;
-
- ld de,180 ;subtract 180 from
- and a ;angle to see if it is
- sbc hl,de ;greater than 180
-
- jr c,tanLess180 ;if not, goto tanless180
-
- ld b,h ;if greater than 180, load angle
- ld c,l ;minus 180 into bc
- tanLess180: ;bc has the semi-reference
- inc d ;load 1 into d
- ld hl,90 ;subtract angle from 90
- and a ;to see if it is less than
- sbc hl,bc ;90
- jr nc,tanLess90 ;if so, jump to tanless90
- ld hl,180 ;if greater, load 180 into hl
- and a ;subtract angle from it
- sbc hl,bc ;
- inc d ;load 2 into d
- ld b,h ;save final reference in bc
- ld c,l ;
- tanLess90: ;already has reference angle
- sla c ;multiply bc by 2
- rl b ;
- ld a,d ;preserves d
- ld de,(PROGRAM_ADDR) ;reference the table
- ld hl,Tan_Table ;
- add hl,de ;
- add hl,bc ;
- ld d,(hl) ;
- inc hl ;load result into de
- ld e,(hl) ;
- ld h,a ;whatever we had in d before
- dec h ;see if h=1 or 2
- jr z,tanNotNegative ;if 1, positive
- set 7,d ;if result negative, then tell it so
- tanNotNegative: ;guess what
- pop hl ;get multiplier
- CALL_(MulDEbyHL) ;multiply the result by the multiplier
- push af
- ld h,c
- ld l,d
- bit 7,e
- jr z,TanRoundDown
- inc hl
- TanRoundDown:
- pop af
- jr z,ResPositive
- ex de,hl
- ld hl,0
- and a
- sbc hl,de
- pop de
- ret
- ResPositive:
- pop de
- ret
-
- MulDEbyHL:
- ld ix,TempLine
- bit 7,d
- jr z,DEPositive
- res 7,d
- bit 7,h
- jr z,HLPositive
- res 7,h
- jr DEPositive
- HLPositive:
- set 7,h
- DEPositive:
- ld (ix+0),h
- ld (ix+1),l
- ld b,8
- xor a
- ld c,a
- ld hl,0
- MulLoop1:
- rrc (ix+1)
- jr nc,NoAdd1
- add hl,de
- adc a,c
- NoAdd1:
- sla e
- rl d
- rl c
- djnz MulLoop1
- ld b,7
- ld e,d
- ld d,c
- ld c,0
- rl c
- ld (ix+5),l
- ld l,h
- ld h,a
- xor a
- MulLoop2:
- rrc (ix+0)
- jr nc,NoAdd2
- add hl,de
- adc a,c
- NoAdd2:
- sla e
- rl d
- rl c
- djnz MulLoop2
- ld b,a
- ld c,h
- ld d,l
- ld e,(ix+5)
- bit 0,(ix+0)
- ret
-
- Tan_Table:
- .db 0,0,0,4,0,9,0,13,0,18,0,22,0,27,0,31,0,36,0,41
- .db 0,45,0,50,0,54,0,59,0,64,0,69,0,73,0,78,0,83,0,88
- .db 0,93,0,98,0,103,0,109,0,114,0,119,0,125,0,130,0,136,0,142
- .db 0,148,0,154,0,160,0,166,0,173,0,179,0,186,0,193,0,200,0,207
- .db 0,215,0,223,0,231,0,239,0,247,1,0,1,9,1,19,1,28,1,38
- .db 1,49,1,60,1,72,1,84,1,96,1,110,1,124,1,138,1,154,1,170
- .db 1,187,1,206,1,225,1,246,2,13,2,37,2,63,2,91,2,122,2,155
- .db 2,191,2,231,3,20,3,69,3,125,3,187,4,3,4,85,4,180,5,37
- .db 5,172,6,80,7,30,8,37,9,132,11,110,14,77,19,21,28,163,57,74
-
-