; math_sin_sec.asm
;
; Assembly language source for the sine 
; and secant functions:


            include math.inc
            include aoalib.inc
            
; sin-                                                          
;                                                               
; The x87 fsin instruction requires the operand to be in the    
; range -2**63..2**63. If it is outside this range, the sin     
; instruction leaves ST0 unchanged and sets the C2 flag in the  
; FP status register. This function will handle the case of     
; st0 being outside this range (it will compute the remainder   
; of st0 divided by 2pi prior to computing fsin).               



            .code
math_sin    proc
            push    rax

; Because the vast majority of the time, sin/cos
; is invoked for small values (e.g., less than 360 degrees),
; we'll just execute fsin and adjust things if fsin
; fails.
            
            fsin
            fstsw   ax
            test    ah, 100b
            jz      goodSin
                    
; sin failed. We need to reduce the value
; to a range smaller than _/+2**63. We'll
; put it in the range -2pi..+2pi.
;
; Get the value into the range -2pi..2pi:

            fldpi   ; Compute 2pi (the divisor)
            fldpi
            faddp
            fld     st(1)
mod2pi:
            fprem1
            fstsw   ax      ; Determine if we are done (c2=0)
            and     ah, 100b
            jnz     mod2pi
            
            fstp    st(2)
            fstp    st(0)                   

; Okay, now that we've got it in range,
; recompute the sin value.
             
            fsin                    
            
goodSin:
            pop     rax
            ret
math_sin    endp


; The secant is just 1/sin.

math_sec    proc
            call    math_sin
            fld1
            fdivrp
            ret
math_sec    endp

            end