home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Zone / VRZONE.ISO / mac / PC / PCGLOVE / GLOVE / OBJGLV.ZIP / SRC / DEMO4B / INT / INTMATHX.CPP < prev    next >
C/C++ Source or Header  |  1992-10-31  |  13KB  |  774 lines

  1. /* Routines for moving, scaling and rotating objects */
  2. /* Matrix math, 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. #include <stdio.h>
  16. #include "3dstruct.hpp"
  17.  
  18. #define XFSC 536870912   /* 2**29 for shifting xform coeffs to long */
  19.  
  20. /*************** TRIGNOMETRIC FUNCTIONS *****************/
  21.  
  22. /* (from inttrig.c) */
  23.  
  24. extern long isine(long x);
  25. extern long icosine(long x);
  26. extern long arcsine(long x);
  27. extern long arccosine(long x);
  28. extern long arctan2(long y, long x);
  29.  
  30. /*************** MATRIX MANIPULATION *****************/
  31.  
  32. /* (from matrix.c) */
  33.  
  34. #define RXYZ 1        /* matrix rotation types */
  35. #define RYXZ 0          /* ONLY RYXZ guaranteed to be tested */
  36. #define RXZY 2
  37. #define RZYX 5
  38. #define RZXY 4
  39. #define RYZX 6
  40.  
  41. extern void matrix_point(MATRIX m, long *xp, long *yp, long *zp);
  42. extern void matrix_rotate(MATRIX m, long *xp, long *yp, long *zp);
  43. extern void cross_column(MATRIX m, int col);
  44. extern long m_mult(long a, long b);    /* perform mult. by matrix element */
  45. extern long dot_prod_29(long a, long b, long c, long x, long y, long z);
  46. extern void matrix_mult(MATRIX a, MATRIX b, MATRIX c);
  47. extern void matrix_product(MATRIX a, MATRIX b, MATRIX c);
  48. extern void matrix_transpose(MATRIX a, MATRIX b);
  49. extern void inverse_matrix(MATRIX a, MATRIX b);
  50. extern void identity_matrix(MATRIX m);
  51. extern void matrix_copy(MATRIX m, MATRIX n);
  52. extern void matrix_rot_copy(MATRIX m, MATRIX n);
  53.  
  54.                /* create rotation/translation */
  55.                /* "matrix" from angle data    */
  56.  
  57. /******************** APPLY MATRIX TO OBJECTS **************/
  58.  
  59. void matmove_rep(REP *rep, MATRIX m)
  60. {
  61.  int i;
  62.  VERTEX *v = rep->verts;     /* use "matrix" to rotate then translate */
  63.  POLY   *p = rep->polys;
  64.  int vs = sizeof(VERTEX);
  65.  int ps = sizeof(POLY);
  66.  int vc = rep->nverts;
  67.  int pc = rep->npolys;
  68.  long rx,ry,rz;
  69.  
  70.  asm {
  71.     .386
  72.     push    ds
  73.     push    si
  74.     push    di
  75.     push    cx
  76.     push    dx
  77.     lds    si,DWORD PTR m
  78.  
  79.     les    di,DWORD PTR v   /* rotate/translate all vertices */
  80.       }
  81. vconv:
  82.  asm {
  83.     mov    eax,ds:[si]
  84.     imul    DWORD PTR es:[di].(VERTEX)ox
  85.     mov    ecx,edx
  86.     mov    ebx,eax
  87.     mov    eax,ds:[si+4]
  88.     imul    DWORD PTR es:[di].(VERTEX)oy
  89.     add    ebx,eax
  90.     adc    ecx,edx
  91.     mov    eax,ds:[si+8]
  92.     imul    DWORD PTR es:[di].(VERTEX)oz
  93.     add    eax,ebx
  94.     adc    edx,ecx
  95.     shrd    eax,edx,29
  96.     adc    eax,ds:[si+36]
  97.     mov    es:[di].(VERTEX)x,eax
  98.  
  99.     mov    eax,ds:[si+12]
  100.     imul    DWORD PTR es:[di].(VERTEX)ox
  101.     mov    ecx,edx
  102.     mov    ebx,eax
  103.     mov    eax,ds:[si+16]
  104.     imul    DWORD PTR es:[di].(VERTEX)oy
  105.     add    ebx,eax
  106.     adc    ecx,edx
  107.     mov    eax,ds:[si+20]
  108.     imul    DWORD PTR es:[di].(VERTEX)oz
  109.     add    eax,ebx
  110.     adc    edx,ecx
  111.     shrd    eax,edx,29
  112.     adc    eax,ds:[si+40]
  113.     mov    es:[di].(VERTEX)y,eax
  114.  
  115.     mov    eax,ds:[si+24]
  116.     imul    DWORD PTR es:[di].(VERTEX)ox
  117.     mov    ecx,edx
  118.     mov    ebx,eax
  119.     mov    eax,ds:[si+28]
  120.     imul    DWORD PTR es:[di].(VERTEX)oy
  121.     add    ebx,eax
  122.     adc    ecx,edx
  123.     mov    eax,ds:[si+32]
  124.     imul    DWORD PTR es:[di].(VERTEX)oz
  125.     add    eax,ebx
  126.     adc    edx,ecx
  127.     shrd    eax,edx,29
  128.     adc    eax,ds:[si+44]
  129.     mov    es:[di].(VERTEX)z,eax
  130.  
  131.     add    di,vs
  132.     dec     WORD PTR vc
  133.     jz      vconve
  134.     jmp    vconv
  135.      }
  136. vconve:
  137.  asm {
  138.     les    di,DWORD PTR p      /* rotate all normals */
  139.      }
  140. pconv:
  141.  asm {
  142.     mov    eax,ds:[si]
  143.     imul    DWORD PTR es:[di].(POLY)onormalx
  144.     mov    ecx,edx
  145.     mov    ebx,eax
  146.     mov    eax,ds:[si+4]
  147.     imul    DWORD PTR es:[di].(POLY)onormaly
  148.     add    ebx,eax
  149.     adc    ecx,edx
  150.     mov    eax,ds:[si+8]
  151.     imul    DWORD PTR es:[di].(POLY)onormalz
  152.     add    eax,ebx
  153.     adc    edx,ecx
  154.     shrd    eax,edx,29
  155.     adc    eax,0
  156.     mov    es:[di].(POLY)normalx,eax
  157.  
  158.     mov    eax,ds:[si+12]
  159.     imul    DWORD PTR es:[di].(POLY)onormalx
  160.     mov    ecx,edx
  161.     mov    ebx,eax
  162.     mov    eax,ds:[si+16]
  163.     imul    DWORD PTR es:[di].(POLY)onormaly
  164.     add    ebx,eax
  165.     adc    ecx,edx
  166.     mov    eax,ds:[si+20]
  167.     imul    DWORD PTR es:[di].(POLY)onormalz
  168.     add    eax,ebx
  169.     adc    edx,ecx
  170.     shrd    eax,edx,29
  171.     adc    eax,0
  172.     mov    es:[di].(POLY)normaly,eax
  173.  
  174.     mov    eax,ds:[si+24]
  175.     imul    DWORD PTR es:[di].(POLY)onormalx
  176.     mov    ecx,edx
  177.     mov    ebx,eax
  178.     mov    eax,ds:[si+28]
  179.     imul    DWORD PTR es:[di].(POLY)onormaly
  180.     add    ebx,eax
  181.     adc    ecx,edx
  182.     mov    eax,ds:[si+32]
  183.     imul    DWORD PTR es:[di].(POLY)onormalz
  184.     add    eax,ebx
  185.     adc    edx,ecx
  186.     shrd    eax,edx,29
  187.     adc    eax,0
  188.     mov    es:[di].(POLY)normalz,eax
  189.  
  190.     add    di,ps
  191.     dec     WORD PTR pc
  192.     jz      pconve
  193.     jmp    pconv
  194.             }
  195. pconve:
  196.  asm {
  197.     pop    dx
  198.     pop    cx
  199.     pop    di
  200.     pop    si
  201.     pop    ds
  202.          }
  203.  
  204.  rep->update_count++;
  205. }
  206.  
  207.  
  208. void matmove_osphere(OBJECT *obj, MATRIX m)
  209. {
  210.  asm {                            /* rotate/translate sphere center */
  211.     .386
  212.     push    ds
  213.     push    si
  214.     push    di
  215.     push    cx
  216.     push    dx
  217.     lds    si,DWORD PTR m
  218.  
  219.     les    di,DWORD PTR obj
  220.     mov    eax,ds:[si]
  221.     imul    DWORD PTR es:[di].(OBJECT)osphx
  222.     mov    ecx,edx
  223.     mov    ebx,eax
  224.     mov    eax,ds:[si+4]
  225.     imul    DWORD PTR es:[di].(OBJECT)osphy
  226.     add    ebx,eax
  227.     adc    ecx,edx
  228.     mov    eax,ds:[si+8]
  229.     imul    DWORD PTR es:[di].(OBJECT)osphz
  230.     add    eax,ebx
  231.     adc    edx,ecx
  232.     shrd    eax,edx,29
  233.     adc    eax,ds:[si+36]
  234.     mov    es:[di].(OBJECT)sphx,eax
  235.  
  236.     mov    eax,ds:[si+12]
  237.     imul    DWORD PTR es:[di].(OBJECT)osphx
  238.     mov    ecx,edx
  239.     mov    ebx,eax
  240.     mov    eax,ds:[si+16]
  241.     imul    DWORD PTR es:[di].(OBJECT)osphy
  242.     add    ebx,eax
  243.     adc    ecx,edx
  244.     mov    eax,ds:[si+20]
  245.     imul    DWORD PTR es:[di].(OBJECT)osphz
  246.     add    eax,ebx
  247.     adc    edx,ecx
  248.     shrd    eax,edx,29
  249.     adc    eax,ds:[si+40]
  250.     mov    es:[di].(OBJECT)sphy,eax
  251.  
  252.     mov    eax,ds:[si+24]
  253.     imul    DWORD PTR es:[di].(OBJECT)osphx
  254.     mov    ecx,edx
  255.     mov    ebx,eax
  256.     mov    eax,ds:[si+28]
  257.     imul    DWORD PTR es:[di].(OBJECT)osphy
  258.     add    ebx,eax
  259.     adc    ecx,edx
  260.     mov    eax,ds:[si+32]
  261.     imul    DWORD PTR es:[di].(OBJECT)osphz
  262.     add    eax,ebx
  263.     adc    edx,ecx
  264.     shrd    eax,edx,29
  265.     adc    eax,ds:[si+44]
  266.     mov    es:[di].(OBJECT)sphz,eax
  267.  
  268.     pop    dx
  269.     pop    cx
  270.     pop    di
  271.     pop    si
  272.     pop    ds
  273.          }
  274.  
  275.  obj->update_count++;
  276. }
  277.                                                             /* works as if only current rep existed */
  278.  
  279. void apply_matrix(OBJECT *obj, MATRIX m)
  280. {
  281.  REP *rep = obj->current_rep;
  282.  if(rep==NULL) return;
  283.  
  284.  matmove_osphere(obj, m);
  285.  matmove_rep(rep, m);
  286.  obj->update_count++;
  287.  rep->update_count++;
  288. }
  289.  
  290.  
  291.                  /* used to compute floor/ceiling of areas */
  292.  
  293. long plane_y(long a, long b, long c, long d, long x, long z)
  294. {
  295.  /* computes (Ax + Cz + D)/-B */
  296.  
  297.  long result;
  298.  
  299.  asm {
  300.     push    si
  301.     push    di
  302.  
  303.     mov    eax,a
  304.     imul    DWORD PTR x
  305.     mov    esi,eax
  306.     mov    edi,edx
  307.  
  308.     mov    eax,c
  309.     imul    DWORD PTR z
  310.     add    eax,esi
  311.     adc    edx,edi
  312.  
  313.     add    eax,DWORD PTR d
  314.     adc    edx,0
  315.     idiv    DWORD PTR b
  316.     mov    result,eax
  317.  
  318.     pop    di
  319.     pop    si
  320.          }
  321.  return result;
  322. }
  323.  
  324.  
  325.  
  326. /************ COLLISION DETECTION AND SELECTION ***********/
  327.  
  328. long sphere_pretest(OBJECT *obj, long x, long y, long z)
  329. {
  330.  long dist = 0;     /* returns 0x7FFFFFFF if not in, else (D) */
  331.  
  332.  long sx = obj->sphx;
  333.  long sy = obj->sphy;
  334.  long sz = obj->sphz;
  335.  long sr = obj->sphr;
  336.  
  337.  asm {
  338.     push    cx
  339.  
  340.     mov    eax,sx   /* x bounds */
  341.     sub    eax,x
  342.     cmp    eax,sr
  343.     jg    notin
  344.     neg    eax
  345.     cmp    eax,sr
  346.     jg    notin
  347.  
  348.     mov    eax,sy   /* y bounds */
  349.     sub    eax,y
  350.     cmp    eax,sr
  351.     jg    notin
  352.     neg    eax
  353.     cmp    eax,sr
  354.     jg    notin
  355.  
  356.     mov    eax,sz   /* z bounds */
  357.     sub    eax,z
  358.     cmp    eax,sr
  359.     jg    notin
  360.     neg    eax
  361.     cmp    eax,sr
  362.     jg    notin
  363.  
  364.     imul    eax      /* square of distance to center */
  365.     mov    ebx,eax
  366.     mov    ecx,edx
  367.  
  368.     mov    eax,sx
  369.     sub    eax,x
  370.     imul    eax
  371.     add    ebx,eax
  372.     adc    ecx,edx
  373.  
  374.     mov    eax,sy
  375.     sub    eax,y
  376.     imul    eax
  377.     add    ebx,eax
  378.     adc    ecx,edx
  379.  
  380.     mov    eax,sr   /* square of radius */
  381.     imul    eax
  382.     cmp    edx,ecx
  383.     ja    in
  384.     jb    notin
  385.     cmp    eax,ebx
  386.     jae    in
  387.          }
  388. notin:                   /* outside of sphere */
  389.  asm pop cx;
  390.  return 0x7FFFFFFF;      /* big never wins */
  391.  
  392. in:
  393.  asm {
  394.     test    ebx,-1         /* shift so denom. is 32-bit or less */
  395.     jz    nolo1
  396.     mov    eax,edx
  397.     xor    edx,edx
  398.     mov    ebx,ecx
  399.     xor    ecx,ecx
  400.      }
  401. nolo1:
  402.  asm {
  403.     mov    eax,x    /* abs(x-sx)+abs(y-sy)+abs(z-sz) approx. dist from center */
  404.     sub    eax,sx
  405.     cdq
  406.     xor    eax,edx
  407.     sub    eax,edx
  408.     mov    ebx,eax
  409.  
  410.     mov    eax,x
  411.     sub    eax,sx
  412.     cdq
  413.     xor    eax,edx
  414.     sub    eax,edx
  415.     add    ebx,eax
  416.  
  417.     mov    eax,x
  418.     sub    eax,sx
  419.     cdq
  420.     xor    eax,edx
  421.     sub    eax,edx
  422.     add    ebx,eax
  423.  
  424.     mov    dist, ebx
  425.     pop    cx
  426.          }
  427.  return dist;      /* for comparison between objects: smallest wins */
  428. }
  429.  
  430.  
  431.  
  432. /************* POLYGON NORMAL COMPUTATION *************/
  433.  
  434.       /* returns abs(x1-x2) + abs(y1-y2) + abs(z1-z2) */
  435.  
  436. long big_dist(long x1, long y1, long z1,
  437.            long x2, long y2, long z2 )
  438. {
  439.  long dist;
  440.  
  441.  asm {
  442.     mov     eax,x1
  443.     sub    eax,x2
  444.     cdq
  445.     xor    eax,edx
  446.     sub    eax,edx
  447.     mov    ecx,eax
  448.  
  449.     mov     eax,y1
  450.     sub    eax,y2
  451.     cdq
  452.     xor    eax,edx
  453.     sub    eax,edx
  454.     add    ecx,eax
  455.  
  456.     mov     eax,z1
  457.     sub    eax,z2
  458.     cdq
  459.     xor    eax,edx
  460.     sub    eax,edx
  461.     add    ecx,eax
  462.  
  463.     mov    dist,ecx
  464.      }
  465.  return dist;
  466. }
  467.  
  468.  
  469.     /* compute, unitize (3.29 format) normal to plane.   */
  470.     /* returns -1 if normal is zero, else log2(length)   */
  471.  
  472. int find_normal(long x1, long y1, long z1,
  473.         long x2, long y2, long z2,
  474.         long x3, long y3, long z3,
  475.         long *xn, long *yn, long *zn)
  476. {
  477.  long xh, xl, yh, yl, zh, zl;
  478.  long xah, xal, yah, yal, zah, zal;
  479.  int length;
  480.  
  481.  extern int sqrtable[1024];
  482.  
  483.  asm {
  484.     push    dx
  485.     push    cx
  486.     push    si
  487.     push    di
  488.  
  489.     mov    eax,y2        /* compute 64-bit cross product   */
  490.     sub    eax,y1        /* and also abs. value for shifts */
  491.     mov    ecx,z3
  492.     sub    ecx,z2
  493.     imul    ecx
  494.     mov    edi,edx
  495.     mov    esi,eax
  496.     mov    eax,y3
  497.     sub    eax,y2
  498.     mov    ecx,z2
  499.     sub    ecx,z1
  500.     imul    ecx
  501.     sub    esi,eax
  502.     sbb    edi,edx
  503.     mov    xh,edi
  504.     mov    xl,esi
  505.     jge    stax
  506.     not    edi
  507.     not    esi
  508.     add    esi,1
  509.     adc    edi,0
  510.      }
  511. stax:
  512.  asm {
  513.     mov    xah,edi
  514.     mov    xal,esi
  515.  
  516.     mov    eax,z2
  517.     sub    eax,z1
  518.     mov    ecx,x3
  519.     sub    ecx,x2
  520.     imul    ecx
  521.     mov    edi,edx
  522.     mov    esi,eax
  523.     mov    eax,z3
  524.     sub    eax,z2
  525.     mov    ecx,x2
  526.     sub    ecx,x1
  527.     imul    ecx
  528.     sub    esi,eax
  529.     sbb    edi,edx
  530.     mov    yh,edi
  531.     mov    yl,esi
  532.     jge    stay
  533.     not    edi
  534.     not    esi
  535.     add    esi,1
  536.     adc    edi,0
  537.      }
  538. stay:
  539.  asm {
  540.     mov    yah,edi
  541.     mov    yal,esi
  542.  
  543.     mov    eax,x2
  544.     sub    eax,x1
  545.     mov    ecx,y3
  546.     sub    ecx,y2
  547.     imul    ecx
  548.     mov    edi,edx
  549.     mov    esi,eax
  550.     mov    eax,x3
  551.     sub    eax,x2
  552.     mov    ecx,y2
  553.     sub    ecx,y1
  554.     imul    ecx
  555.     sub    esi,eax
  556.     sbb    edi,edx
  557.     mov    zh,edi
  558.     mov    zl,esi
  559.     jge    staz
  560.     not    edi
  561.     not    esi
  562.     add    esi,1
  563.     adc    edi,0
  564.      }
  565. staz:
  566.  asm {
  567.     mov    zah,edi
  568.     mov    zal,esi
  569.      }
  570.  
  571.  asm {                    /* now normalize to 3.29 */
  572.     or    esi,yal
  573.     or    esi,xal
  574.     or    edi,yah
  575.     or    edi,xah
  576.     jz    zero_h
  577.  
  578.     xor    ax,ax           /* ax is shift count */
  579.     test    edi,0FFFF0000h  /* top word not zero: cnvt to 1.n <3.29> */
  580.     jz    z16h
  581.     add    ax,16
  582.     shr    edi,16
  583.      }
  584. z16h:
  585.  asm {
  586.     test    di,0FF00h
  587.     jz    z8h
  588.     add    ax,8
  589.     shr    edi,8
  590.      }
  591. z8h:
  592.  asm {
  593.     shl    edi,8       /* most ecomonical pos'n */
  594.     bsr    cx,di       /* get exact shift */
  595.     sub    cx,5
  596.     add     cx,ax
  597.  
  598.     mov    eax,xh      /* convert cross product to 1.n */
  599.     shrd    xl,eax,cl
  600.     mov    eax,yh
  601.     shrd    yl,eax,cl
  602.     mov    eax,zh
  603.     shrd    zl,eax,cl
  604.  
  605.     add    cx,29
  606.     mov    length,cx
  607.  
  608.     jmp    dshnorm
  609.          }
  610.  
  611. zero_h:
  612.  asm {
  613.     or    esi,esi
  614.     jz    zero_normal
  615.     mov    ax,24
  616.     test    esi,0FFFF0000h  /* top word is zero: cnvt to 1.n <3.29> */
  617.     jz    z16l
  618.     sub    ax,16
  619.     shr    esi,16
  620.      }
  621. z16l:
  622.  asm {
  623.     test    si,0FF00h
  624.     jz    z8l
  625.     sub    ax,8
  626.     shr    esi,8
  627.      }
  628. z8l:
  629.  asm {
  630.     shl    esi,8       /* most ecomonical pos'n */
  631.     bsr    cx,si       /* get exact shift */
  632.     neg    cx
  633.     add    cx,13
  634.     add    cx,ax
  635.  
  636.     jz    noshiftl
  637.     jg    lshiftl
  638.  
  639.     neg    cx
  640.     mov    eax,xh      /* convert cross product to 1.n   */
  641.     shrd    xl,eax,cl   /* need ext. for borderline cases */
  642.     mov    eax,yh
  643.     shrd    yl,eax,cl
  644.     mov    eax,zh
  645.     shrd    zl,eax,cl
  646.      }
  647. noshiftl:
  648.  asm {
  649.     add    cx,29
  650.     mov    length,cx
  651.  
  652.     jmp    dshnorm
  653.      }
  654. lshiftl:
  655.  asm {
  656.     shl    DWORD PTR xl,cl
  657.     shl    DWORD PTR yl,cl
  658.     shl    DWORD PTR zl,cl
  659.  
  660.     mov    ax,29
  661.     sub    ax,cx
  662.     mov    length,ax
  663.      }
  664. dshnorm:  goto finish;
  665.  
  666. zero_normal:
  667.  asm {
  668.     pop    di
  669.     pop    si
  670.     pop    cx
  671.     pop    dx
  672.      }
  673.  *xn = *yn = *zn = -1;
  674.  return 0;
  675.  
  676. finish:             /* compute magnitude, convert to unit length */
  677.  
  678.  asm {
  679.     mov    eax,xl            /* compute squares */
  680.     sar    eax,16
  681.     imul    ax
  682.     mov    bx,dx
  683.     mov    cx,ax
  684.  
  685.     mov    eax,yl
  686.     sar    eax,16
  687.     imul    ax
  688.     add    cx,ax
  689.     adc    bx,dx
  690.  
  691.     mov    eax,zl
  692.     sar    eax,16
  693.     imul    ax
  694.     add    cx,ax
  695.     adc    bx,dx
  696.  
  697.     shr    bx,4             /* magnitude << 13 */
  698.     shl    bx,1
  699.     mov    cx,sqrtable[bx]
  700.     movzx    ecx,cx
  701.  
  702.     mov    eax,xl           /* scale cross product */
  703.     cdq
  704.     shld    edx,eax,13
  705.     shl    eax,13
  706.     idiv    ecx
  707.     mov    xl,eax
  708.  
  709.     mov    eax,yl
  710.     cdq
  711.     shld    edx,eax,13
  712.     shl    eax,13
  713.     idiv    ecx
  714.     mov    yl,eax
  715.  
  716.     mov    eax,zl
  717.     cdq
  718.     shld    edx,eax,13
  719.     shl    eax,13
  720.     idiv    ecx
  721.     mov    zl,eax
  722.  
  723.     pop    di
  724.     pop    si
  725.     pop    cx
  726.     pop    dx
  727.      }
  728.  
  729.  *xn = -xl;     /* left-hand coordinate system */
  730.  *yn = -yl;
  731.  *zn = -zl;
  732.  
  733.  return length;
  734. }
  735.  
  736.  
  737. long scale_16(long s, long a, long x)    /* perform scaling by 16.16 number */
  738. {
  739.  long result;
  740.  
  741.  asm {
  742.     mov    eax,DWORD PTR x
  743.     add eax,DWORD PTR a
  744.     imul    DWORD PTR s
  745.     shrd    eax,edx,16
  746.     adc    eax,0
  747.     mov    DWORD PTR result,eax
  748.      }
  749.  return result;
  750. }
  751.  
  752. long calc_scale_16(long a, long b, long s)   /* compute 16.16 scaling factor */
  753. {
  754.  long result = 0;
  755.  
  756.  asm {
  757.     mov    ebx,DWORD PTR a
  758.     sub    ebx,DWORD PTR b
  759.     je    cdiv
  760.     mov    eax, DWORD PTR s
  761.     cdq
  762.     shld    edx,eax,17
  763.     shl    eax,17
  764.     idiv  ebx
  765.     mov    DWORD PTR result,eax
  766.          }
  767. cdiv:
  768.  return result;
  769. }
  770.  
  771.  
  772.  
  773.  
  774.