home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / REND386 / JIREND / INTTRIG.C < prev    next >
C/C++ Source or Header  |  1993-04-11  |  6KB  |  293 lines

  1. /* Routines for trignometry */
  2. /* assembly by Dave Stampe */
  3.   
  4. /* Copyright 1992 by Dave Stampe and Bernie Roehl.
  5.     May be freely used to write software for release into the public domain;
  6.     all commercial endeavours MUST contact Bernie Roehl and Dave Stampe
  7.     for permission to incorporate any part of this software into their
  8.     products!
  9.  */
  10.   
  11. /* Contact: broehl@sunee.waterloo.edu or dstampe@sunee.waterloo.edu */
  12.   
  13. #pragma inline
  14.   
  15.   
  16. /*************** TRIGNOMETRIC FUNCTIONS *****************/
  17.   
  18. #define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  19.   
  20. extern long sintable[258];
  21. extern long atantable[258];    /* <3.29> args -> <16.16> angle */
  22.   
  23.   
  24. long isine(long angle)           /* returns <3.29> sine of <16.16> angle */
  25. {
  26.    long result;
  27.   
  28. /* return(XFSC * sin(3.14159/180*angle/65536.0));*/
  29.   
  30.    asm {
  31.       .386
  32.       mov   eax,angle
  33.       mov   edx,5B05B05Bh
  34.       imul  edx
  35.       shrd  eax,edx,29     /* convert so 90 deg -> 256 */
  36.       adc   eax,0              /* 2 upper bits = quadrant  */
  37.       mov   angle,eax          /* 16 lsb used to interp.   */
  38.    }
  39.   
  40.    asm {
  41.       mov   ebx,eax
  42.       mov   esi,eax
  43.       mov   edx,eax
  44.   
  45.       shr   ebx,14             /* 8 bit 2.84*degree index */
  46.       and   ebx,03FCh
  47.       test    esi,01000000h
  48.       jz forward
  49.       not   edx
  50.       xor   ebx,03FCh
  51.    }
  52.    forward:
  53.    asm {
  54.       mov   ecx,DWORD PTR ds:sintable[bx]
  55.       mov   eax,DWORD PTR ds:sintable+4[bx]  /* lookup this, next entry */
  56.       sub   eax,ecx
  57.   
  58.       and   edx,0000FFFFh       /* compute interp. factor */
  59.       mul     edx
  60.       shrd  eax,edx,16
  61.       adc   ecx,eax             /* add in */
  62.   
  63.       test    esi,02000000h
  64.       jz positive
  65.       neg   ecx
  66.    }
  67.    positive:
  68.    asm {
  69.       mov   result,ecx
  70.    }
  71.    return result;
  72. }
  73.   
  74.   
  75. long icosine(long angle)
  76. {
  77.    return isine(90*65536L + angle);
  78. }
  79.   
  80.   
  81. /************ INVERSE TRIG FUNCTIONS *************/
  82.   
  83. long arcsine(long x)      /* <3.29> args -> <16.16> angle */
  84. {                         /* have to use table in reverse */
  85.    int sign = 0;            /* because slope varies widely  */
  86.    long result;
  87.    long *stp = &sintable[0];
  88.   
  89.    if(x==0) return 0;
  90.    if(x<0)
  91.    {
  92.       sign++;
  93.       x = -x;
  94.    }
  95.    if(x>=XFSC)
  96.    {
  97.       result = 90*65536L;
  98.       goto ret90;
  99.    }
  100.   
  101.    asm {
  102.       push  si
  103.       push  di
  104.       push  dx
  105.       push  cx
  106.   
  107.       mov   bx,WORD PTR stp      /* fast binary search sine table */
  108.       xor   ecx,ecx
  109.       mov   eax,x
  110.       cmp   eax,[bx+512]
  111.       jb b1
  112.       add   ebx,512
  113.       or ecx,00800000h
  114.    }
  115.    b1:
  116.    asm {
  117.       cmp   eax,[bx+256]
  118.       jb b2
  119.       add   ebx,256
  120.       or ecx,00400000h
  121.    }
  122.    b2:
  123.    asm {
  124.       cmp   eax,[bx+128]
  125.       jb b3
  126.       add   ebx,128
  127.       or ecx,00200000h
  128.    }
  129.    b3:
  130.    asm {
  131.       cmp   eax,[bx+64]
  132.       jb b4
  133.       add   ebx,64
  134.       or ecx,00100000h
  135.    }
  136.    b4:
  137.    asm {
  138.       cmp   eax,[bx+32]
  139.       jb b5
  140.       add   ebx,32
  141.       or ecx,00080000h
  142.    }
  143.    b5:
  144.    asm {
  145.       cmp   eax,[bx+16]
  146.       jb b6
  147.       add   ebx,16
  148.       or ecx,00040000h
  149.    }
  150.    b6:
  151.    asm {
  152.       cmp   eax,[bx+8]
  153.       jb b7
  154.       add   ebx,8
  155.       or ecx,00020000h
  156.    }
  157.    b7:
  158.    asm {
  159.       cmp   eax,[bx+4]
  160.       jb b8
  161.       add   ebx,4
  162.       or ecx,00010000h
  163.    }
  164.    b8:
  165.    asm {
  166.       sub   eax,[bx]
  167.       je nointerp
  168.       mov   esi,[bx+4]
  169.       sub   esi,[bx]
  170.       je okinterp
  171.       cmp   eax,esi
  172.       jb okinterp
  173.       add   ecx,00010000h
  174.       jmp   nointerp
  175.    }
  176.    okinterp:
  177.    asm {
  178.       cdq
  179.       shld  edx,eax,16
  180.       shl   eax,16
  181.       idiv  esi
  182.       mov   cx,ax
  183.    }
  184.    nointerp:
  185.    asm {
  186.       mov   eax,05A000000h    /* convert to <16.16> angle */
  187.       imul  ecx
  188.       mov   result,edx
  189.   
  190.       pop   cx
  191.       pop   dx
  192.       pop   di
  193.       pop   si
  194.    }
  195.   
  196.    ret90:
  197.    return (sign) ? -result : result;
  198. }
  199.   
  200.   
  201. long arccosine(long x)
  202. {
  203.    return(90*65536L - arcsine(x));
  204. }
  205.   
  206.                    /* we can use a table for atan  */
  207.                 /* as slope is fairly constant  */
  208. long arctan2(long y, long x)
  209. {
  210.    long result;
  211.    int sx = 0;
  212.    int sy = 0;
  213.    int g45 = 0;
  214.   
  215.    if(x<0)           /* extract signs */
  216.    {
  217.       sx++;
  218.       x = -x;
  219.    }
  220.    if(y<0)           /* look for trivial solutions */
  221.    {
  222.       sy++;
  223.       y = -y;
  224.    }
  225.    if(x==0)
  226.    {
  227.       result = 90*65536L;
  228.       goto retconst;
  229.    }
  230.    if(y==0)
  231.    {
  232.       result = 0;
  233.       goto retconst;
  234.    }
  235.   
  236.    if(y>x)    /* confine to single octant */
  237.    {
  238.       g45++;
  239.       result = x;
  240.       x = y;
  241.       y = result;
  242.    }
  243.   
  244.    asm {
  245.       mov   edx,y
  246.       xor   eax,eax
  247.       mov   ebx,x
  248.       cmp   edx,ebx
  249.       jne   non45
  250.       mov   eax,02D0000h   /* 45 degrees */
  251.       mov   result,eax
  252.       jmp   retconst
  253.    }
  254.    non45:
  255.    asm {
  256.       push  si
  257.       push  di
  258.   
  259.       shrd  eax,edx,8      /* shift so it will divide OK */
  260.       shr   edx,8
  261.       idiv  ebx            /* y/x << 24 */
  262.       mov   ebx,eax
  263.       shr   ebx,14         /* top 8 bits are index into table */
  264.       and   ebx,03FCh
  265.       mov   edi,DWORD PTR atantable[bx]
  266.       mov   esi,DWORD PTR atantable+4[bx]
  267.       sub   esi,edi
  268.       and   eax,0000FFFFh  /* bottom 16 bits interpolate */
  269.       mul   esi
  270.       shr   eax,16
  271.       add   eax,edi
  272.       mov   result,eax
  273.   
  274.       pop   di
  275.       pop   si
  276.    }
  277.   
  278.    if(g45) result = 90*65536L - result;
  279.   
  280.    retconst:
  281.    if(sx)
  282.    {
  283.       if(sy) return result - 180*65536L;
  284.       else   return 180*65536L - result;
  285.    }
  286.    else
  287.    {
  288.       if(sy) return -result;
  289.       else   return  result;
  290.    }
  291. }
  292.   
  293.