Source code of Windows XP (NT5)
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.7 KiB

//==========================================================================;
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1993, 1994 Microsoft Corporation. All Rights Reserved.
//
//--------------------------------------------------------------------------;
//
// muldiv32.c
//
// Description: math routines for 32 bit signed and unsiged numbers.
//
// MulDiv32(a,b,c) = (a * b) / c (round down, signed)
//
// MulDivRD(a,b,c) = (a * b) / c (round down, unsigned)
// MulDivRN(a,b,c) = (a * b + c/2) / c (round nearest, unsigned)
// MulDivRU(a,b,c) = (a * b + c-1) / c (round up, unsigned)
//
// History:
// 9/21/93 cjp [curtisp]
// 9/23/93 stl [toddla]
//
//==========================================================================;
#include <windows.h>
#include "muldiv32.h"
#if !defined(_WIN32) && !defined(_WIN32)
#pragma warning(disable:4035 4704)
#define ASM66 _asm _emit 0x66 _asm
#define DB _asm _emit
#define EAX_TO_DXAX \
DB 0x66 \
DB 0x0F \
DB 0xA4 \
DB 0xC2 \
DB 0x10
//--------------------------------------------------------------------------;
//
// LONG MulDiv32(a,b,c) = (a * b) / c
//
//--------------------------------------------------------------------------;
LONG FAR PASCAL MulDiv32(LONG a,LONG b,LONG c)
{
ASM66 mov ax,word ptr a // mov eax, a
ASM66 mov bx,word ptr b // mov ebx, b
ASM66 mov cx,word ptr c // mov ecx, c
ASM66 imul bx // imul ebx
ASM66 idiv cx // idiv ecx
EAX_TO_DXAX
} // MulDiv32()
//--------------------------------------------------------------------------;
//
// DWORD MulDivRN(a,b,c) = (a * b + c/2) / c
//
//--------------------------------------------------------------------------;
DWORD FAR PASCAL MulDivRN(DWORD a,DWORD b,DWORD c)
{
ASM66 mov ax,word ptr a // mov eax, a
ASM66 mov bx,word ptr b // mov ebx, b
ASM66 mov cx,word ptr c // mov ecx, c
ASM66 mul bx // mul ebx
ASM66 mov bx,cx // mov ebx,ecx
ASM66 shr bx,1 // sar ebx,1
ASM66 add ax,bx // add eax,ebx
ASM66 adc dx,0 // adc edx,0
ASM66 div cx // div ecx
EAX_TO_DXAX
} // MulDiv32()
//--------------------------------------------------------------------------;
//
// DWORD MulDivRU(a,b,c) = (a * b + c-1) / c
//
//--------------------------------------------------------------------------;
DWORD FAR PASCAL MulDivRU(DWORD a,DWORD b,DWORD c)
{
ASM66 mov ax,word ptr a // mov eax, a
ASM66 mov bx,word ptr b // mov ebx, b
ASM66 mov cx,word ptr c // mov ecx, c
ASM66 mul bx // mul ebx
ASM66 mov bx,cx // mov ebx,ecx
ASM66 dec bx // dec ebx
ASM66 add ax,bx // add eax,ebx
ASM66 adc dx,0 // adc edx,0
ASM66 div cx // div ecx
EAX_TO_DXAX
} // MulDivRU32()
//--------------------------------------------------------------------------;
//
// DWORD MulDivRD(a,b,c) = (a * b) / c
//
//--------------------------------------------------------------------------;
DWORD FAR PASCAL MulDivRD(DWORD a,DWORD b,DWORD c)
{
ASM66 mov ax,word ptr a // mov eax, a
ASM66 mov bx,word ptr b // mov ebx, b
ASM66 mov cx,word ptr c // mov ecx, c
ASM66 mul bx // mul ebx
ASM66 div cx // div ecx
EAX_TO_DXAX
} // MulDivRD32()
#pragma warning(default:4035 4704)
#else // _WIN32
#include <largeint.h>
//--------------------------------------------------------------------------;
//
// LONG MulDiv32(a,b,c) = (a * b) / c
//
//--------------------------------------------------------------------------;
LONG FAR PASCAL MulDiv32(LONG a,LONG b,LONG c)
{
LARGE_INTEGER lRemain;
return LargeIntegerDivide(
EnlargedIntegerMultiply(a,b),
ConvertLongToLargeInteger(c),
&lRemain).LowPart;
} // MulDiv32()
//--------------------------------------------------------------------------;
//
// DWORD MulDivRD(a,b,c) = (a * b) / c
//
//--------------------------------------------------------------------------;
DWORD FAR PASCAL MulDivRD(DWORD a,DWORD b,DWORD c)
{
return ExtendedLargeIntegerDivide(
EnlargedUnsignedMultiply(a,b), c, &a).LowPart;
} // MulDivRD()
//--------------------------------------------------------------------------;
//
// DWORD MulDivRU(a,b,c) = (a * b + c-1) / c
//
//--------------------------------------------------------------------------;
DWORD FAR PASCAL MulDivRU(DWORD a,DWORD b,DWORD c)
{
return ExtendedLargeIntegerDivide(
LargeIntegerAdd(
EnlargedUnsignedMultiply(a,b),
ConvertUlongToLargeInteger(c-1)),
c,&a).LowPart;
} // MulDivRU()
#if 0 // we use Win32 GDI MulDiv function, not this.
//--------------------------------------------------------------------------;
//
// DWORD MulDivRN(a,b,c) = (a * b + c/2) / c
//
//--------------------------------------------------------------------------;
DWORD FAR PASCAL MulDivRN(DWORD a,DWORD b,DWORD c)
{
return ExtendedLargeIntegerDivide(
LargeIntegerAdd(
EnlargedUnsignedMultiply(a,b),
ConvertUlongToLargeInteger(c/2)),
c,&a).LowPart;
} // MulDivRN()
#endif
#endif // _WIN32