home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / midiplyr / muldiv32.h < prev    next >
C/C++ Source or Header  |  1997-10-05  |  8KB  |  240 lines

  1. /*****************************************************************************
  2. *
  3. *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  4. *  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
  5. *  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR
  6. *  A PARTICULAR PURPOSE.
  7. *
  8. *  Copyright (C) 1993 - 1997 Microsoft Corporation. All Rights Reserved.
  9. *
  10. ******************************************************************************
  11. *
  12. *  MulDiv32.h
  13. *
  14. *  Description:
  15. *      math routines for 32 bit signed and unsiged numbers.
  16. *
  17. *      MulDiv32(a,b,c) = (a * b) / c         (round down, signed)
  18. *
  19. *      MulDivRD(a,b,c) = (a * b) / c         (round down, unsigned)
  20. *      MulDivRN(a,b,c) = (a * b + c/2) / c   (round nearest, unsigned)
  21. *      MulDivRU(a,b,c) = (a * b + c-1) / c   (round up, unsigned)
  22. *
  23. *****************************************************************************/
  24.  
  25. #ifndef _INC_MULDIV32
  26. #define _INC_MULDIV32
  27.  
  28.  
  29. #ifndef INLINE
  30. #define INLINE __inline
  31. #endif
  32.  
  33.  
  34. #ifdef _WIN32
  35.  
  36.     //----------------------------------------------------------------------;
  37.     //
  38.     //  Win 32
  39.     //
  40.     //----------------------------------------------------------------------;
  41.  
  42.     #ifdef _X86_
  43.     
  44.         //
  45.         //  Use 32-bit x86 assembly.
  46.         //
  47.  
  48.         #pragma warning(disable:4035 4704)
  49.  
  50.         #define MulDivRN MulDiv    // Doesn't work with /Ox; MSVC20 messes up 
  51.                                 // the inline asm code, instead of including 
  52.                                 // it prolog/verbatim/epilog. 
  53.                                 // So use the Windows function for now
  54.         #if 0
  55.         INLINE LONG MulDiv32(LONG a,LONG b,LONG c)
  56.         {
  57.             _asm     mov     eax,dword ptr a  //  mov  eax, a
  58.             _asm     mov     ebx,dword ptr b  //  mov  ebx, b
  59.             _asm     mov     ecx,dword ptr c  //  mov  ecx, c
  60.             _asm     imul    ebx              //  imul ebx
  61.             _asm     idiv    ecx              //  idiv ecx
  62.             _asm     shld     edx, eax, 16     //  shld edx, eax, 16
  63.  
  64.         } // MulDiv32()
  65.  
  66.         INLINE DWORD MulDivRN(DWORD a,DWORD b,DWORD c)
  67.         {
  68.             _asm     mov     eax,dword ptr a  //  mov  eax, a
  69.             _asm     mov     ebx,dword ptr b  //  mov  ebx, b
  70.             _asm     mov     ecx,dword ptr c  //  mov  ecx, c
  71.             _asm     mul     ebx              //  mul  ebx
  72.             _asm     mov     ebx,ecx          //  mov  ebx,ecx
  73.             _asm     shr     ebx,1            //  sar  ebx,1
  74.             _asm     add     eax,ebx          //  add  eax,ebx
  75.             _asm     adc     edx,0            //  adc  edx,0
  76.             _asm     div     ecx              //  div  ecx
  77.             _asm     shld    edx, eax, 16     //  shld edx, eax, 16
  78.  
  79.         } // MulDiv32()
  80.  
  81.         INLINE DWORD MulDivRU(DWORD a,DWORD b,DWORD c)
  82.         {
  83.             _asm     mov     eax,dword ptr a  //  mov  eax, a
  84.             _asm     mov     ebx,dword ptr b  //  mov  ebx, b
  85.             _asm     mov     ecx,dword ptr c  //  mov  ecx, c
  86.             _asm     mul     ebx              //  mul  ebx
  87.             _asm     mov     ebx,ecx          //  mov  ebx,ecx
  88.             _asm     dec     ebx              //  dec  ebx
  89.             _asm     add     eax,ebx          //  add  eax,ebx
  90.             _asm     adc     edx,0            //  adc  edx,0
  91.             _asm     div     ecx              //  div  ecx
  92.             _asm     shld    edx, eax, 16     //  shld edx, eax, 16
  93.  
  94.         } // MulDivRU32()
  95.  
  96.         INLINE DWORD MulDivRD(DWORD a,DWORD b,DWORD c)
  97.         {
  98.             _asm     mov     eax,dword ptr a  //  mov  eax, a
  99.             _asm     mov     ebx,dword ptr b  //  mov  ebx, b
  100.             _asm     mov     ecx,dword ptr c  //  mov  ecx, c
  101.             _asm     mul     ebx              //  mul  ebx
  102.             _asm     div     ecx              //  div  ecx
  103.             _asm     shld    edx, eax, 16     //  shld edx, eax, 16
  104.  
  105.         } // MulDivRD32()
  106.         #endif
  107.  
  108.         #pragma warning(default:4035 4704)
  109.  
  110.  
  111.     #else
  112.  
  113.         //
  114.         //  Use C9 __int64 support for Daytona RISC platforms.
  115.         //
  116.  
  117.         INLINE LONG MulDiv32( LONG a, LONG b, LONG c )
  118.         {
  119.             return (LONG)( Int32x32To64(a,b) / c );
  120.         }
  121.  
  122.  
  123.         INLINE DWORD MulDivRD( DWORD a, DWORD b, DWORD c )
  124.         {
  125.             return (DWORD)( UInt32x32To64(a,b) / c );
  126.         }
  127.  
  128.  
  129.         INLINE DWORD MulDivRN( DWORD a, DWORD b, DWORD c )
  130.         {
  131.             return (DWORD)( (UInt32x32To64(a,b)+c/2) / c );
  132.         }
  133.  
  134.  
  135.         INLINE DWORD MulDivRU( DWORD a, DWORD b, DWORD c )
  136.         {
  137.             return (DWORD)( (UInt32x32To64(a,b)+c-1) / c );
  138.         }
  139.  
  140.     #endif
  141.  
  142.  
  143. #else
  144.  
  145.     //----------------------------------------------------------------------;
  146.     //
  147.     //  Win 16
  148.     //
  149.     //----------------------------------------------------------------------;
  150.  
  151.     #pragma warning(disable:4035 4704)
  152.  
  153.     //
  154.     //  Compile for 16-bit - we can use x86 with proper opcode prefixes
  155.     //        to get 32-bit instructions.
  156.     //
  157.  
  158.     INLINE LONG MulDiv32(LONG a,LONG b,LONG c)
  159.     {
  160.         _asm _emit 0x66 _asm    mov     ax,word ptr a   //  mov  eax, a
  161.         _asm _emit 0x66 _asm    mov     bx,word ptr b   //  mov  ebx, b
  162.         _asm _emit 0x66 _asm    mov     cx,word ptr c   //  mov  ecx, c
  163.         _asm _emit 0x66 _asm    imul    bx              //  imul ebx
  164.         _asm _emit 0x66 _asm    idiv    cx              //  idiv ecx
  165.         _asm _emit 0x66                                 //  shld edx, eax, 16
  166.         _asm _emit 0x0F
  167.         _asm _emit 0xA4
  168.         _asm _emit 0xC2
  169.         _asm _emit 0x10
  170.  
  171.     } // MulDiv32()
  172.  
  173.     INLINE DWORD MulDivRN(DWORD a,DWORD b,DWORD c)
  174.     {
  175.         _asm _emit 0x66 _asm    mov     ax,word ptr a   //  mov  eax, a
  176.         _asm _emit 0x66 _asm    mov     bx,word ptr b   //  mov  ebx, b
  177.         _asm _emit 0x66 _asm    mov     cx,word ptr c   //  mov  ecx, c
  178.         _asm _emit 0x66 _asm    mul     bx              //  mul  ebx
  179.         _asm _emit 0x66 _asm    mov     bx,cx           //  mov  ebx,ecx
  180.         _asm _emit 0x66 _asm    shr     bx,1            //  sar  ebx,1
  181.         _asm _emit 0x66 _asm    add     ax,bx           //  add  eax,ebx
  182.         _asm _emit 0x66 _asm    adc     dx,0            //  adc  edx,0
  183.         _asm _emit 0x66 _asm    div     cx              //  div  ecx
  184.         _asm _emit 0x66                                 //  shld edx, eax, 16
  185.         _asm _emit 0x0F
  186.         _asm _emit 0xA4
  187.         _asm _emit 0xC2
  188.         _asm _emit 0x10
  189.  
  190.     } // MulDiv32()
  191.  
  192.     INLINE DWORD MulDivRU(DWORD a,DWORD b,DWORD c)
  193.     {
  194.         _asm _emit 0x66 _asm    mov     ax,word ptr a   //  mov  eax, a
  195.         _asm _emit 0x66 _asm    mov     bx,word ptr b   //  mov  ebx, b
  196.         _asm _emit 0x66 _asm    mov     cx,word ptr c   //  mov  ecx, c
  197.         _asm _emit 0x66 _asm    mul     bx              //  mul  ebx
  198.         _asm _emit 0x66 _asm    mov     bx,cx           //  mov  ebx,ecx
  199.         _asm _emit 0x66 _asm    dec     bx              //  dec  ebx
  200.         _asm _emit 0x66 _asm    add     ax,bx           //  add  eax,ebx
  201.         _asm _emit 0x66 _asm    adc     dx,0            //  adc  edx,0
  202.         _asm _emit 0x66 _asm    div     cx              //  div  ecx
  203.         _asm _emit 0x66                                 //  shld edx, eax, 16
  204.         _asm _emit 0x0F
  205.         _asm _emit 0xA4
  206.         _asm _emit 0xC2
  207.         _asm _emit 0x10
  208.  
  209.     } // MulDivRU32()
  210.  
  211.  
  212.     INLINE DWORD MulDivRD(DWORD a,DWORD b,DWORD c)
  213.     {
  214.         _asm _emit 0x66 _asm    mov     ax,word ptr a   //  mov  eax, a
  215.         _asm _emit 0x66 _asm    mov     bx,word ptr b   //  mov  ebx, b
  216.         _asm _emit 0x66 _asm    mov     cx,word ptr c   //  mov  ecx, c
  217.         _asm _emit 0x66 _asm    mul     bx              //  mul  ebx
  218.         _asm _emit 0x66 _asm    div     cx              //  div  ecx
  219.         _asm _emit 0x66                                 //  shld edx, eax, 16
  220.         _asm _emit 0x0F
  221.         _asm _emit 0xA4
  222.         _asm _emit 0xC2
  223.         _asm _emit 0x10
  224.  
  225.     } // MulDivRD32()
  226.  
  227.     #pragma warning(default:4035 4704)
  228.  
  229. #endif
  230.  
  231.  
  232. //
  233. //  some code references these by other names.
  234. //
  235. #define muldiv32    MulDivRN
  236. #define muldivrd32  MulDivRD
  237. #define muldivru32  MulDivRU
  238.  
  239. #endif  // _INC_MULDIV32
  240.