386atan.inc

来自「开放源码的编译器open watcom 1.6.0版的源代码」· INC 代码 · 共 380 行 · 第 1/2 页

INC
380
字号
;*****************************************************************************
;*
;*                            Open Watcom Project
;*
;*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
;*
;*  ========================================================================
;*
;*    This file contains Original Code and/or Modifications of Original
;*    Code as defined in and that are subject to the Sybase Open Watcom
;*    Public License version 1.0 (the 'License'). You may not use this file
;*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
;*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
;*    provided with the Original Code and Modifications, and is also
;*    available at www.sybase.com/developer/opensource.
;*
;*    The Original Code and all software distributed under the License are
;*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
;*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
;*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
;*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
;*    NON-INFRINGEMENT. Please see the License for the specific language
;*    governing rights and limitations under the License.
;*
;*  ========================================================================
;*
;* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
;*               DESCRIBE IT HERE!
;*
;*****************************************************************************


        modstart  386atan

        xref    __FLDAC         ; add constant from stack
        xref    __FLDD          ; divide
        xref    ___LDA          ; add
        xref    ___LDD          ; divide
        xref    ___LDM          ; multiply
        xref    __OddPoly       ; evaluate polynomial

        xdefp   __fpatan        ; calc atan2(y,x)
;;/*
;;        atan - compute arctangent
;;
;;        Uses the following identities
;;        *****************************
;;
;;        arctan(x) = - arctan( - x )
;;
;;        arctan(x) = pi/2 - arctan( 1/x )
;;
;;        arctan(x) = arctan( (x*sqrt(3)-1) / (x+sqrt(3)) ) + pi/6
;;*/
;;
;;#include <math.h>
;;#include "pi.h"
;;
;;#define FALSE           0
;;#define TRUE            1
;;
;;tan15 dt      0.2679491924311227
;;sqrt3:
;;      dt      1.7320508075688772936
;;
;;extern  int             _sgn(double);   /* get sign of x */
;;extern  double          _OddPoly(double, double *, int);
;;
;;
;;static  double          AtanPoly[] = {
        align   2
AtanPoly dt      0.0443895157187
        dt      -0.06483193510303
        dt       0.0767936869066
        dt      -0.0909037114191074    ; -0.09090371144275426
        dt       0.11111097898051048
        dt      -0.14285714102825545
        dt       0.1999999999872945
        dt      -0.3333333333332993
        dt       1.0
;;};


;;double atan2( double y, double x )  - compute arctan(y/x)
;;
;;NOTE: x,y cannot both be 0
;;
;;case 1: y = 0    if x < 0 return pi, otherwise return 0
;;
;;case 2: x = 0    if y < 0 return -pi/2, otherwise return pi/2
;;
;;otherwise: compute z = atan( y/x )
;;               if y >= 0 and z < 0 return z + pi
;;               if y <  0 and z > 0 return z - pi
;;               else return z
;;
;;double atan2( double y, double x )
;;/********************************/
;;    {
;;        register int    sgnx;   /* sgn(x) */
;;        register int    sgny;   /* sgn(y) */
;;
;;        sgny = _sgn( y );
;;        sgnx = _sgn( x );
;;        if( sgny == 0 ) {               /* case 1 */
;;            if( sgnx == 0 ) {
;;                x = _matherr( DOMAIN, "atan2", &y, &x, 0.0 );
;;            } else if( sgnx < 0 ) {
;;                x = Pi;
;;            } else {
;;                x = 0.0;
;;            }
;;        } else if( sgnx == 0 ) {        /* case 2 */
;;            if( sgny < 0 ) {
;;                x = -Piby2;
;;            } else {
;;                x = Piby2;
;;            }
;;        } else {
;;            x = atan( y / x );
;;            sgnx = _sgn( x );
;;            if( sgny >= 0 ) {
;;                if( sgnx < 0 ) {
;;                    x += Pi;
;;                }
;;            } else {
;;                if( sgnx > 0 ) {
;;                    x -= Pi;
;;                }
;;            }
;;        }
;;        return( x );
;;    }
;;
;;  input:
;;      EAX - pointer to Y
;;      EDX - pointer to X
;;      EBX - pointer to result
;;
        defp    __fpatan
        push    EDI                     ; save registers
        push    ESI                     ; ...
        push    ECX                     ; ...
        mov     EDI,EAX                 ; save address of y
        mov     CX,8[EDI]               ; get sgn(y)
        _guess                          ; guess: y == 0
          shl   CX,1                    ; - get rid of sign bit
          _quif ne                      ; - quit if y != 0
          test  byte ptr 9[EDX],80h     ; - if x < 0.0
          _if   ne                      ; - then
            mov   word ptr 8[EBX],PI_EXP; - - return pi
            mov   dword ptr 4[EBX],PI_HW; - - ...
            mov   dword ptr  [EBX],PI_LW; - - ...
          _else                         ; - else
            mov   word ptr 8[EBX],0     ; - - return 0.0
            mov   dword ptr 4[EBX],0    ; - - ...
            mov   dword ptr  [EBX],0    ; - - ...
          _endif                        ; - endif
        _admit                          ; guess: x == 0
          mov   CX,8[EDX]               ; - get sgn(x)
          shl   CX,1                    ; - quit if x != 0
          _quif ne                      ; - ...
          mov   AX,8[EDI]               ; - get sign of y
          and   AX,8000h                ; - ...
          or    AX,PIBY2_EXP            ; - return (+/-) pi/2
          mov   word ptr 8[EBX],AX      ; - ...
          mov   dword ptr 4[EBX],PI_HW  ; - ...
          mov   dword ptr  [EBX],PI_LW  ; - ...
        _admit                          ; admit: calc. arctan( y / x )
          mov   CH,9[EDI]               ; - save sign of y
          call  __FLDD                  ; - calc. result = y/x
          mov   EAX,EBX                 ; - point to argument
          call  __atan                  ; - calc. atan(y/x)
          mov   DL,9[EBX]               ; - get sign of result
          or    CH,CH                   ; - quit if y < 0.0
          _quif s                       ; - ...
          or    DL,DL                   ; - if result < 0
          _if   s                       ; - then
            mov   EAX,EBX               ; - - calc. x += pi
            push  PI_EXP                ; - - ...
            push  PI_HW                 ; - - ...
            push  PI_LW                 ; - - ...
            call  __FLDAC               ; - - ...
          _endif                        ; - endif
        _admit                          ; admit: y < 0.0
          or    DL,DL                   ; - if result > 0
          _if   g                       ; - then
            mov   EAX,EBX               ; - - calc. x -= pi
            push  8000h+PI_EXP          ; - - ...
            push  PI_HW                 ; - - ...

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?