/* hmmmacro.h			CIC Proprietary
 *-----------------------------------------------------------------------------
 * SCCS Version %I%, %U% %G%
 *-----------------------------------------------------------------------------
 * Moved some macros from other header files in US recognizer to here.
 *
 * J. Wang          30-Sep-96   Initial.
 *-----------------------------------------------------------------------------
 */
#ifndef HMMMACRO_H
#define HMMMACRO_H

#define strkcpy(inP,outP) *(outP) = *(inP);

/* ANG32L_MACRO                 CIC Proprietary
 *-----------------------------------------------------------------------------
 * MACRO that calculates an angle (given dxL, dyL as input) and returns a
 * value in the range 0-31.  The relationship between the value returned and
 * the actual angle computed is  -->  value returned  =  angle / 11.25.  The
 * angle branch point is taken to be zero, so the angle range is from 0 to 360
 * (NOT 0 to 180 and 0 to -180 as in previous programs).  The factor of 11.25
 * arises because 11.25 = 360/32.
 *
 * inputs:      dxL = (x1 - xo)   --    the x difference value
 *              dyL = (x1 - xo)   --    the y difference value
 *
 * output:      angle             --    the calculated angle [arctan(dx, dy)]
 *
 * j.s. ostrem      Nov. 25, 1992       Macro version of ang32L.c (1st version)
 * j.s. ostrem      Mar.  1, 1993       Minor reversions
 * j.s. ostrem      Aug. 27, 1993       Minor change to improve speed
 *-----------------------------------------------------------------------------
 * This macro does the following:
 *
 * First, determine the angle in the range 0 to 90 degrees.  Note: in the code
 * below we are checking the following conditions for the ratio absdyL / absdxL
 * (when absdyL < absdxL)
 *
 * angle
 *   0   ratio < 102/512                (0     to 11.25 degrees)
 *   1   102/512 <= ratio < 212/512     (11.25 to 22.5  degrees)
 *   2   212/512 <= ratio < 342/512     (22.5  to 37.5  degrees)
 *   3   342/512 <= ratio               (37.5  to 45.0  degrees)
 *
 * When absdxL < absdyL the ratio absdxL / absdyL is checked in the same
 * way except that the angle values assigned are 7, 6, 5, 4 instead of
 * 0, 1, 2, 3.
 *
 * angle
 *   7   ratio < 102/512                (78.75 to 90.0  degrees)
 *   6   102/512 <= ratio < 212/512     (67.5  to 78.75 degrees)
 *   5   212/512 <= ratio < 342/512     (56.25 to 67.5  degrees)
 *   4   342/512 <= ratio               (45.0  to 56.25 degrees)
 *
 * Finally, depending upon the sign of dxL and dyL, the angle value is
 * adjusted to the right quadrant.
 *
 *-----------------------------------------------------------------------------
 */

#define ANG32L_MACRO(dxL, dyL, angle) \
    { \
    LONG  absdxL; \
    LONG  absdyL; \
    LONG  valueL; \
    absdxL = abs(dxL); \
    absdyL = abs(dyL); \
    if ((absdxL > 1) || (absdyL > 1)) \
        { \
        if (absdyL > absdxL) \
            { \
            valueL = absdyL; \
            absdyL = absdxL; \
            absdxL = valueL; \
            angle  = 7; \
            } \
        else \
            angle  = 0; \
        absdyL <<= 9; \
        valueL = (absdxL << 5) + (absdxL << 1); \
        valueL = (valueL << 1) + valueL; \
        if (absdyL < valueL) \
            angle -= 0; \
        else if (absdyL < ((valueL << 1) + (absdxL << 3))) \
            angle -= 1; \
        else if (absdyL < ((valueL << 2) - (absdxL << 6) - (absdxL << 1))) \
            angle -= 2; \
        else \
            angle -= 3; \
        if (angle < 0) \
            angle = -angle; \
        if ((dxL) < 0) \
            (angle) = 15 - (angle); \
        if ((dyL) < 0) \
            (angle) = 31 - (angle); \
        } \
    else \
        angle = 0; \
    }

/* RAWDIS_MACRO                 CIC Proprietary
 *-----------------------------------------------------------------------------
 * Macro to calculate Euclidean distance given the x and y differences,
 * dx and dy respectively.
 *
 * NOTE:  Must include the following in the calling program
 *
 *        1. IMPORT COUNT sqrttb[];
 *
 * inputs:      dx      --    the x difference value
 *              dy      --    the y difference value
 *
 * output:      disL    --    the calculated euclidean distance x 512
 *
 * Note particulaly that the output disL is scaled up by 512
 *
 * j. s. ostrem     Nov 23, 1992        Macro version of rawdis (actually taken
 *                                      from ~ostrem/lib/jsolib/eucdis.c, a
 *                                      better version of rawdis)
 * D. Hwang     14-Oct-93       Implement Dan Illowsky's new fast C version.
 *-----------------------------------------------------------------------------
 */
#define RAWDIS_MACRO(i, j, ax, ay, disL) \
    { \
    COUNT dx, dy, temp, scaleFactor; \
    IMPORT COUNT sqrttb[]; \
    IMPORT COUNT distIndexTbl[]; \
    dx = ax[i] - ax[j]; \
    dy = ay[i] - ay[j]; \
    if (dx < 0) \
        dx = -dx; \
    if (dy < 0) \
        dy = -dy; \
    if ((dx == 0) || (dy == 0)) \
        disL = ((ULONG)dx + (ULONG)dy) << 9; \
    else \
        { \
        if (dx > dy) \
            { \
            temp = dx; \
            dx   = dy; \
            dy   = temp; \
            } \
        if (dy <= 25) \
            disL = (LONG) sqrttb[dx + distIndexTbl[dy]]; \
        else \
            { \
            scaleFactor = (dy + 24) / 25; \
            dx  = (dx + (scaleFactor >> 1)) / scaleFactor; \
            dy  = (dy + (scaleFactor >> 1)) / scaleFactor; \
            if (dx == 0) \
                disL = ((LONG)scaleFactor) * (((LONG)dy) << 9); \
            else \
                disL = scaleFactor * ((LONG) sqrttb[dx + distIndexTbl[dy]]); \
            } \
        } \
    }

#endif
