123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- //------------------------------------------------------------------------------
- // File: ArithUtil.cpp
- //
- // Desc: DirectShow base classes - implements helper classes for building
- // multimedia filters.
- //
- // Copyright (c) 1992-2004 Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------------------------
- #include <streams.h>
- //
- // Declare function from largeint.h we need so that PPC can build
- //
- //
- // Enlarged integer divide - 64-bits / 32-bits > 32-bits
- //
- #ifndef _X86_
- #define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
- __inline
- ULONG
- WINAPI
- EnlargedUnsignedDivide (
- IN ULARGE_INTEGER Dividend,
- IN ULONG Divisor,
- IN PULONG Remainder
- )
- {
- // return remainder if necessary
- if (Remainder != NULL)
- *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
- return (ULONG)(LLtoU64(Dividend) / Divisor);
- }
- #else
- __inline
- ULONG
- WINAPI
- EnlargedUnsignedDivide (
- IN ULARGE_INTEGER Dividend,
- IN ULONG Divisor,
- IN PULONG Remainder
- )
- {
- ULONG ulResult;
- _asm {
- mov eax,Dividend.LowPart
- mov edx,Dividend.HighPart
- mov ecx,Remainder
- div Divisor
- or ecx,ecx
- jz short label
- mov [ecx],edx
- label:
- mov ulResult,eax
- }
- return ulResult;
- }
- #endif
- /* Arithmetic functions to help with time format conversions
- */
- #ifdef _M_ALPHA
- // work around bug in version 12.00.8385 of the alpha compiler where
- // UInt32x32To64 sign-extends its arguments (?)
- #undef UInt32x32To64
- #define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
- #endif
- /* Compute (a * b + d) / c */
- LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
- {
- /* Compute the absolute values to avoid signed arithmetic problems */
- ULARGE_INTEGER ua, ub;
- DWORDLONG uc;
- ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
- ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
- uc = (DWORDLONG)(c >= 0 ? c : -c);
- BOOL bSign = (a < 0) ^ (b < 0);
- /* Do long multiplication */
- ULARGE_INTEGER p[2];
- p[0].QuadPart = UInt32x32To64(ua.LowPart, ub.LowPart);
- /* This next computation cannot overflow into p[1].HighPart because
- the max number we can compute here is:
- (2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart
- (2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2
- == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
- == 2 ** 96 - 2 ** 33 + 1
- < 2 ** 96
- */
- ULARGE_INTEGER x;
- x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) +
- UInt32x32To64(ua.HighPart, ub.LowPart) +
- p[0].HighPart;
- p[0].HighPart = x.LowPart;
- p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
- if (d != 0) {
- ULARGE_INTEGER ud[2];
- if (bSign) {
- ud[0].QuadPart = (DWORDLONG)(-d);
- if (d > 0) {
- /* -d < 0 */
- ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
- } else {
- ud[1].QuadPart = (DWORDLONG)0;
- }
- } else {
- ud[0].QuadPart = (DWORDLONG)d;
- if (d < 0) {
- ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
- } else {
- ud[1].QuadPart = (DWORDLONG)0;
- }
- }
- /* Now do extended addition */
- ULARGE_INTEGER uliTotal;
- /* Add ls DWORDs */
- uliTotal.QuadPart = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
- p[0].LowPart = uliTotal.LowPart;
- /* Propagate carry */
- uliTotal.LowPart = uliTotal.HighPart;
- uliTotal.HighPart = 0;
- /* Add 2nd most ls DWORDs */
- uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
- p[0].HighPart = uliTotal.LowPart;
- /* Propagate carry */
- uliTotal.LowPart = uliTotal.HighPart;
- uliTotal.HighPart = 0;
- /* Add MS DWORDLONGs - no carry expected */
- p[1].QuadPart += ud[1].QuadPart + uliTotal.QuadPart;
- /* Now see if we got a sign change from the addition */
- if ((LONG)p[1].HighPart < 0) {
- bSign = !bSign;
- /* Negate the current value (ugh!) */
- p[0].QuadPart = ~p[0].QuadPart;
- p[1].QuadPart = ~p[1].QuadPart;
- p[0].QuadPart += 1;
- p[1].QuadPart += (p[0].QuadPart == 0);
- }
- }
- /* Now for the division */
- if (c < 0) {
- bSign = !bSign;
- }
- /* This will catch c == 0 and overflow */
- if (uc <= p[1].QuadPart) {
- return bSign ? (LONGLONG)0x8000000000000000 :
- (LONGLONG)0x7FFFFFFFFFFFFFFF;
- }
- DWORDLONG ullResult;
- /* Do the division */
- /* If the dividend is a DWORD_LONG use the compiler */
- if (p[1].QuadPart == 0) {
- ullResult = p[0].QuadPart / uc;
- return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
- }
- /* If the divisor is a DWORD then its simpler */
- ULARGE_INTEGER ulic;
- ulic.QuadPart = uc;
- if (ulic.HighPart == 0) {
- ULARGE_INTEGER uliDividend;
- ULARGE_INTEGER uliResult;
- DWORD dwDivisor = (DWORD)uc;
- // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
- uliDividend.HighPart = p[1].LowPart;
- uliDividend.LowPart = p[0].HighPart;
- #ifndef USE_LARGEINT
- uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
- p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
- uliResult.LowPart = 0;
- uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
- #else
- /* NOTE - this routine will take exceptions if
- the result does not fit in a DWORD
- */
- if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
- uliResult.HighPart = EnlargedUnsignedDivide(
- uliDividend,
- dwDivisor,
- &p[0].HighPart);
- } else {
- uliResult.HighPart = 0;
- }
- uliResult.LowPart = EnlargedUnsignedDivide(
- p[0],
- dwDivisor,
- NULL);
- #endif
- return bSign ? -(LONGLONG)uliResult.QuadPart :
- (LONGLONG)uliResult.QuadPart;
- }
- ullResult = 0;
- /* OK - do long division */
- for (int i = 0; i < 64; i++) {
- ullResult <<= 1;
- /* Shift 128 bit p left 1 */
- p[1].QuadPart <<= 1;
- if ((p[0].HighPart & 0x80000000) != 0) {
- p[1].LowPart++;
- }
- p[0].QuadPart <<= 1;
- /* Compare */
- if (uc <= p[1].QuadPart) {
- p[1].QuadPart -= uc;
- ullResult += 1;
- }
- }
- return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
- }
- LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
- {
- ULARGE_INTEGER ua;
- DWORD ub;
- DWORD uc;
- /* Compute the absolute values to avoid signed arithmetic problems */
- ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
- ub = (DWORD)(b >= 0 ? b : -b);
- uc = (DWORD)(c >= 0 ? c : -c);
- BOOL bSign = (a < 0) ^ (b < 0);
- /* Do long multiplication */
- ULARGE_INTEGER p0;
- DWORD p1;
- p0.QuadPart = UInt32x32To64(ua.LowPart, ub);
- if (ua.HighPart != 0) {
- ULARGE_INTEGER x;
- x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
- p0.HighPart = x.LowPart;
- p1 = x.HighPart;
- } else {
- p1 = 0;
- }
- if (d != 0) {
- ULARGE_INTEGER ud0;
- DWORD ud1;
- if (bSign) {
- //
- // Cast d to LONGLONG first otherwise -0x80000000 sign extends
- // incorrectly
- //
- ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
- if (d > 0) {
- /* -d < 0 */
- ud1 = (DWORD)-1;
- } else {
- ud1 = (DWORD)0;
- }
- } else {
- ud0.QuadPart = (DWORDLONG)d;
- if (d < 0) {
- ud1 = (DWORD)-1;
- } else {
- ud1 = (DWORD)0;
- }
- }
- /* Now do extended addition */
- ULARGE_INTEGER uliTotal;
- /* Add ls DWORDs */
- uliTotal.QuadPart = (DWORDLONG)ud0.LowPart + p0.LowPart;
- p0.LowPart = uliTotal.LowPart;
- /* Propagate carry */
- uliTotal.LowPart = uliTotal.HighPart;
- uliTotal.HighPart = 0;
- /* Add 2nd most ls DWORDs */
- uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
- p0.HighPart = uliTotal.LowPart;
- /* Add MS DWORDLONGs - no carry expected */
- p1 += ud1 + uliTotal.HighPart;
- /* Now see if we got a sign change from the addition */
- if ((LONG)p1 < 0) {
- bSign = !bSign;
- /* Negate the current value (ugh!) */
- p0.QuadPart = ~p0.QuadPart;
- p1 = ~p1;
- p0.QuadPart += 1;
- p1 += (p0.QuadPart == 0);
- }
- }
- /* Now for the division */
- if (c < 0) {
- bSign = !bSign;
- }
- /* This will catch c == 0 and overflow */
- if (uc <= p1) {
- return bSign ? (LONGLONG)0x8000000000000000 :
- (LONGLONG)0x7FFFFFFFFFFFFFFF;
- }
- /* Do the division */
- /* If the divisor is a DWORD then its simpler */
- ULARGE_INTEGER uliDividend;
- ULARGE_INTEGER uliResult;
- DWORD dwDivisor = uc;
- uliDividend.HighPart = p1;
- uliDividend.LowPart = p0.HighPart;
- /* NOTE - this routine will take exceptions if
- the result does not fit in a DWORD
- */
- if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
- uliResult.HighPart = EnlargedUnsignedDivide(
- uliDividend,
- dwDivisor,
- &p0.HighPart);
- } else {
- uliResult.HighPart = 0;
- }
- uliResult.LowPart = EnlargedUnsignedDivide(
- p0,
- dwDivisor,
- NULL);
- return bSign ? -(LONGLONG)uliResult.QuadPart :
- (LONGLONG)uliResult.QuadPart;
- }
|