coord.c.html

    /*------------------------------------------------------------------------
     * filename - coord.cas         Version 1.0 /DEE 2-92
     *
     * function(s)
     *        rpc - Converts Rectangular to Polar Coordinates
     *        prc - Converts Polar to Rectangular Coordinates
     *        matan2 - Modified Arctangent routine
     *-----------------------------------------------------------------------*/

    #pragma inline
    #include <asmrules.h>

    #include <math.h>
    #include <_math.h>

    /*--------------------------------------------------------------------------*

    Name            matan2 - trigonometric function

    Usage           void matan2(double y, double x);  ST(0) = y, ST(1) = x

    Prototype in    None

    Description
                    matan2  returns ST(0), the  arc tangent   of y/x  and will
                    produce correct results even  when resulting is near pi/2
                    or -pi/2 (x near 0).

    Return value    atan2 returns a value in the range -pi to pi on ST(0).
                    If a ratio of 0/0  is supplied then zero is returned

    *---------------------------------------------------------------------------*/
    static  unsigned short  piBy2 [] = {0xC235, 0x2168, 0xDAA2, 0xC90F, 0x3FFF};

    #pragma warn -rvl
    #pragma warn -use
    void matan2 (double y, double x)
    {
    register        SI, DI;         /* prevent the compiler making its own usage */

    asm     mov     ax, x [6]       /* select MSW of x ..   */
    asm     and     al, 0F0h        /* ignore fraction      */
    asm     mov     bx, y [6]       /* .. and of y          */
    asm     and     bl, 0F0h
    asm     shl     bx, 1           /* discard sign         */
    asm     jz      at2_yIsZero
    asm     shl     ax, 1           /* discard sign         */
    asm     jz      at2_xIsZero
    asm     FDIVRP  ST(1), ST(0)
    asm     _FAST_  (_FATAN_)

    /* convert the simple answer to a four quadrant answer. */

    at2_setQuad:
    asm     test    BY0 (x [7]), 80h                /* the sign bit */
    asm     jz      at2_end

    asm     FLDPI

    asm     test    BY0 (y [7]), 80h
    asm     jz      at2_2ndQuad

    at2_3rdQuad:
    asm     FSUBP   ST(1), ST
    asm     jmp     short   at2_end

    at2_2ndQuad:
    asm     FADDP   ST(1), ST

    at2_end:
            return;

    /*      Special cases.
    */
    at2_yIsZero:
    asm     shl     ax, 1
    asm     jc      at2_retPi               /* x<0, return PI */
    asm     FSTP    ST(1)                   /* else y is result     */
    asm     jmp     short   at2_end

    at2_retPi:                              /* y = 0, x < 0 */
    asm     FCOMPP                          /* discard x and y */
    asm     FLDPI                           /* and return PI */
    asm     jmp     short  at2_end

    at2_xIsZero:                            /* and y is not zero    */
                                            /*      or              */
    at2_yIsInf:                             /* and x is finite      */
    asm     FCOMPP                          /* discard x and y      */
    asm     FLD     tbyte ptr (piBy2)
    asm     test    BY0 (y [7]), 80h        /* check sign of Y */
    asm     jz      at2_HPi                 /* positive - return PI/2 */
    asm     FCHS                            /* negative - return -PI/2 */
    at2_HPi:
    asm     jmp     short   at2_setQuad

    at2_xIsInf:
    asm     FCOMPP                          /* discard x and y      */
    asm     FLDZ
    asm     jmp     short   at2_setQuad

    }
    #pragma warn .rvl
    #pragma warn .use

    /*--------------------------------------------------------------------------*

    Name            rpc - Convert from Rectangular to Polar Coordinates

    Usage           void rpc(double x, double y, double *r, double *theta);

    Prototype in    math.h

    Description     The magnitude is the same result as "hypot" except the input
                    is not checked for the INF value.

                            r = (x^2 + y^2)^.5

                    The angle is in the range of -180 < theta <= 180.

    Return value    The function fills the variables pointed by "r" and "theta".
                    "theta" is in radians.
                    The function provides no error or overflow checking.
    *---------------------------------------------------------------------------*/
    void rpc (double x, double y, double *r, double *theta)
    {
    #if LDATA
    asm     push    ES
    #endif

    asm     FLD     DOUBLE (x)              /* x                            */
    asm     FLD     st(0)                   /* st(1) = x                    */
    asm     FMUL    st,st(0)                /* x^2                          */
    asm     FLD     DOUBLE (y)              /* y                            */
    asm     FLD     st(0)                   /* 0=y,1=y,2=x^2,3=x            */
    asm     FMUL    st,st(0)                /* y^2                          */
    asm     FADDP   st(2),st                /* x^2 + y^2                    */
    asm     FXCH                            /* Switch ST and ST(1)          */
    asm     FSQRT                           /* sqrt (               )       */

    asm     LES_    bx,r
    asm     FSTP    DOUBLE (ES_ [bx])       /* *r = (x^2 + y^2)^.5          */

            matan2(y,x);
    asm     LES_    bx,theta
    asm     FSTP    DOUBLE (ES_ [bx])       /* *theta = matan2(y/x)         */
    asm     FWAIT                           /* Will bomb out w/o this       */

    #if LDATA
    asm     pop     ES
    #endif

    }

    /*--------------------------------------------------------------------------*

    Name            prc - Convert from Polar to Rectangular Coordinates

    Usage           void rpc(double r, double theta, double *x, double *y);

    Prototype in    math.h

    Description     Given the magnitude r, and the angle from the positive x-axis,
                    convert to x and y coordinates.

                            x=r*cos(theta)
                            y=r*sin(theta)

                    The angle is in the range of -180 < theta <= 180.

    Return value    The function fills the variables pointed by "r" and "theta".
                    The function provides no error or overflow checking.
    *---------------------------------------------------------------------------*/
    void prc (double r, double theta, double *x, double *y)
    {

    #if LDATA
    asm     push    ES
    #endif

    asm     FLD     DOUBLE (r)
    asm     FLD     DOUBLE (theta)
    asm     FLD     st(0)
    asm     _FAST_  (_FCOS_)                /* cos(theta)           */
    asm     FMUL    st,st(2)                /* cos(theta)*r         */
    asm     LES_    bx,x
    asm     FSTP    DOUBLE (ES_ [bx])       /* x                    */
    asm     _FAST_  (_FSIN_)
    asm     FMULP                           /* y = r*sin(theta)     */
    asm     LES_    bx,y
    asm     FSTP    DOUBLE (ES_ [bx])       /* y                    */
    asm     FWAIT

    /* Needs quadrant check for y=sqrt(r^2-x^2) */
    asm     FLD     DOUBLE (r)
    asm     FLD     st(0)                   /* r for later          */
    asm     FMUL    st,st(0)                /* r^2                  */
    asm     FLD     DOUBLE (theta)
    asm     _FAST_  (_FCOS_)                /* cos(theta)           */
    asm     FMULP   st(2),st                /* x=r*cos(theta)       */
    asm     FXCH
    asm     FMUL    st,st(0)                /* x^2                  */
    asm     FSUBP                           /* r^2 - x^2            */
    asm     FSQRT                           /* y                    */
    asm     LES_    bx,y
    asm     FSTP    DOUBLE (ES_ [bx])       /* y                    */
    asm     FWAIT                           /* Must have            */
    */

    #if LDATA
    asm     pop     ES
    #endif

    }