Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

192 lines
5.9 KiB

  1. //==========================================================================;
  2. //
  3. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4. // KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5. // IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6. // PURPOSE.
  7. //
  8. // Copyright (c) 1993, 1994 Microsoft Corporation. All Rights Reserved.
  9. //
  10. //--------------------------------------------------------------------------;
  11. //
  12. // muldiv32.c
  13. //
  14. // Description: math routines for 32 bit signed and unsiged numbers.
  15. //
  16. // MulDiv32(a,b,c) = (a * b) / c (round down, signed)
  17. //
  18. // MulDivRD(a,b,c) = (a * b) / c (round down, unsigned)
  19. // MulDivRN(a,b,c) = (a * b + c/2) / c (round nearest, unsigned)
  20. // MulDivRU(a,b,c) = (a * b + c-1) / c (round up, unsigned)
  21. //
  22. // History:
  23. // 9/21/93 cjp [curtisp]
  24. // 9/23/93 stl [toddla]
  25. //
  26. //==========================================================================;
  27. #include <windows.h>
  28. #include "muldiv32.h"
  29. #if !defined(_WIN32) && !defined(_WIN32)
  30. #pragma warning(disable:4035 4704)
  31. #define ASM66 _asm _emit 0x66 _asm
  32. #define DB _asm _emit
  33. #define EAX_TO_DXAX \
  34. DB 0x66 \
  35. DB 0x0F \
  36. DB 0xA4 \
  37. DB 0xC2 \
  38. DB 0x10
  39. //--------------------------------------------------------------------------;
  40. //
  41. // LONG MulDiv32(a,b,c) = (a * b) / c
  42. //
  43. //--------------------------------------------------------------------------;
  44. LONG FAR PASCAL MulDiv32(LONG a,LONG b,LONG c)
  45. {
  46. ASM66 mov ax,word ptr a // mov eax, a
  47. ASM66 mov bx,word ptr b // mov ebx, b
  48. ASM66 mov cx,word ptr c // mov ecx, c
  49. ASM66 imul bx // imul ebx
  50. ASM66 idiv cx // idiv ecx
  51. EAX_TO_DXAX
  52. } // MulDiv32()
  53. //--------------------------------------------------------------------------;
  54. //
  55. // DWORD MulDivRN(a,b,c) = (a * b + c/2) / c
  56. //
  57. //--------------------------------------------------------------------------;
  58. DWORD FAR PASCAL MulDivRN(DWORD a,DWORD b,DWORD c)
  59. {
  60. ASM66 mov ax,word ptr a // mov eax, a
  61. ASM66 mov bx,word ptr b // mov ebx, b
  62. ASM66 mov cx,word ptr c // mov ecx, c
  63. ASM66 mul bx // mul ebx
  64. ASM66 mov bx,cx // mov ebx,ecx
  65. ASM66 shr bx,1 // sar ebx,1
  66. ASM66 add ax,bx // add eax,ebx
  67. ASM66 adc dx,0 // adc edx,0
  68. ASM66 div cx // div ecx
  69. EAX_TO_DXAX
  70. } // MulDiv32()
  71. //--------------------------------------------------------------------------;
  72. //
  73. // DWORD MulDivRU(a,b,c) = (a * b + c-1) / c
  74. //
  75. //--------------------------------------------------------------------------;
  76. DWORD FAR PASCAL MulDivRU(DWORD a,DWORD b,DWORD c)
  77. {
  78. ASM66 mov ax,word ptr a // mov eax, a
  79. ASM66 mov bx,word ptr b // mov ebx, b
  80. ASM66 mov cx,word ptr c // mov ecx, c
  81. ASM66 mul bx // mul ebx
  82. ASM66 mov bx,cx // mov ebx,ecx
  83. ASM66 dec bx // dec ebx
  84. ASM66 add ax,bx // add eax,ebx
  85. ASM66 adc dx,0 // adc edx,0
  86. ASM66 div cx // div ecx
  87. EAX_TO_DXAX
  88. } // MulDivRU32()
  89. //--------------------------------------------------------------------------;
  90. //
  91. // DWORD MulDivRD(a,b,c) = (a * b) / c
  92. //
  93. //--------------------------------------------------------------------------;
  94. DWORD FAR PASCAL MulDivRD(DWORD a,DWORD b,DWORD c)
  95. {
  96. ASM66 mov ax,word ptr a // mov eax, a
  97. ASM66 mov bx,word ptr b // mov ebx, b
  98. ASM66 mov cx,word ptr c // mov ecx, c
  99. ASM66 mul bx // mul ebx
  100. ASM66 div cx // div ecx
  101. EAX_TO_DXAX
  102. } // MulDivRD32()
  103. #pragma warning(default:4035 4704)
  104. #else // _WIN32
  105. #include <largeint.h>
  106. //--------------------------------------------------------------------------;
  107. //
  108. // LONG MulDiv32(a,b,c) = (a * b) / c
  109. //
  110. //--------------------------------------------------------------------------;
  111. LONG FAR PASCAL MulDiv32(LONG a,LONG b,LONG c)
  112. {
  113. LARGE_INTEGER lRemain;
  114. return LargeIntegerDivide(
  115. EnlargedIntegerMultiply(a,b),
  116. ConvertLongToLargeInteger(c),
  117. &lRemain).LowPart;
  118. } // MulDiv32()
  119. //--------------------------------------------------------------------------;
  120. //
  121. // DWORD MulDivRD(a,b,c) = (a * b) / c
  122. //
  123. //--------------------------------------------------------------------------;
  124. DWORD FAR PASCAL MulDivRD(DWORD a,DWORD b,DWORD c)
  125. {
  126. return ExtendedLargeIntegerDivide(
  127. EnlargedUnsignedMultiply(a,b), c, &a).LowPart;
  128. } // MulDivRD()
  129. //--------------------------------------------------------------------------;
  130. //
  131. // DWORD MulDivRU(a,b,c) = (a * b + c-1) / c
  132. //
  133. //--------------------------------------------------------------------------;
  134. DWORD FAR PASCAL MulDivRU(DWORD a,DWORD b,DWORD c)
  135. {
  136. return ExtendedLargeIntegerDivide(
  137. LargeIntegerAdd(
  138. EnlargedUnsignedMultiply(a,b),
  139. ConvertUlongToLargeInteger(c-1)),
  140. c,&a).LowPart;
  141. } // MulDivRU()
  142. #if 0 // we use Win32 GDI MulDiv function, not this.
  143. //--------------------------------------------------------------------------;
  144. //
  145. // DWORD MulDivRN(a,b,c) = (a * b + c/2) / c
  146. //
  147. //--------------------------------------------------------------------------;
  148. DWORD FAR PASCAL MulDivRN(DWORD a,DWORD b,DWORD c)
  149. {
  150. return ExtendedLargeIntegerDivide(
  151. LargeIntegerAdd(
  152. EnlargedUnsignedMultiply(a,b),
  153. ConvertUlongToLargeInteger(c/2)),
  154. c,&a).LowPart;
  155. } // MulDivRN()
  156. #endif
  157. #endif // _WIN32