Tristan Matthews | 0a329cc | 2013-07-17 13:20:14 -0400 | [diff] [blame] | 1 | //------------------------------------------------------------------------------
|
| 2 | // File: ArithUtil.cpp
|
| 3 | //
|
| 4 | // Desc: DirectShow base classes - implements helper classes for building
|
| 5 | // multimedia filters.
|
| 6 | //
|
| 7 | // Copyright (c) 1992-2004 Microsoft Corporation. All rights reserved.
|
| 8 | //------------------------------------------------------------------------------
|
| 9 |
|
| 10 | #include <pjmedia-videodev/config.h>
|
| 11 |
|
| 12 | #if defined(PJMEDIA_VIDEO_DEV_HAS_DSHOW) && PJMEDIA_VIDEO_DEV_HAS_DSHOW != 0
|
| 13 |
|
| 14 | #include <streams.h>
|
| 15 |
|
| 16 | //
|
| 17 | // Declare function from largeint.h we need so that PPC can build
|
| 18 | //
|
| 19 |
|
| 20 | //
|
| 21 | // Enlarged integer divide - 64-bits / 32-bits > 32-bits
|
| 22 | //
|
| 23 |
|
| 24 | #ifndef _X86_
|
| 25 |
|
| 26 | #define LLtoU64(x) (*(unsigned __int64*)(void*)(&(x)))
|
| 27 |
|
| 28 | __inline
|
| 29 | ULONG
|
| 30 | WINAPI
|
| 31 | EnlargedUnsignedDivide (
|
| 32 | IN ULARGE_INTEGER Dividend,
|
| 33 | IN ULONG Divisor,
|
| 34 | IN PULONG Remainder
|
| 35 | )
|
| 36 | {
|
| 37 | // return remainder if necessary
|
| 38 | if (Remainder != NULL)
|
| 39 | *Remainder = (ULONG)(LLtoU64(Dividend) % Divisor);
|
| 40 | return (ULONG)(LLtoU64(Dividend) / Divisor);
|
| 41 | }
|
| 42 |
|
| 43 | #else
|
| 44 | __inline
|
| 45 | ULONG
|
| 46 | WINAPI
|
| 47 | EnlargedUnsignedDivide (
|
| 48 | IN ULARGE_INTEGER Dividend,
|
| 49 | IN ULONG Divisor,
|
| 50 | IN PULONG Remainder
|
| 51 | )
|
| 52 | {
|
| 53 | ULONG ulResult;
|
| 54 | _asm {
|
| 55 | mov eax,Dividend.LowPart
|
| 56 | mov edx,Dividend.HighPart
|
| 57 | mov ecx,Remainder
|
| 58 | div Divisor
|
| 59 | or ecx,ecx
|
| 60 | jz short label
|
| 61 | mov [ecx],edx
|
| 62 | label:
|
| 63 | mov ulResult,eax
|
| 64 | }
|
| 65 | return ulResult;
|
| 66 | }
|
| 67 | #endif
|
| 68 |
|
| 69 |
|
| 70 | /* Arithmetic functions to help with time format conversions
|
| 71 | */
|
| 72 |
|
| 73 | #ifdef _M_ALPHA
|
| 74 | // work around bug in version 12.00.8385 of the alpha compiler where
|
| 75 | // UInt32x32To64 sign-extends its arguments (?)
|
| 76 | #undef UInt32x32To64
|
| 77 | #define UInt32x32To64(a, b) (((ULONGLONG)((ULONG)(a)) & 0xffffffff) * ((ULONGLONG)((ULONG)(b)) & 0xffffffff))
|
| 78 | #endif
|
| 79 |
|
| 80 | /* Compute (a * b + d) / c */
|
| 81 | LONGLONG WINAPI llMulDiv(LONGLONG a, LONGLONG b, LONGLONG c, LONGLONG d)
|
| 82 | {
|
| 83 | /* Compute the absolute values to avoid signed arithmetic problems */
|
| 84 | ULARGE_INTEGER ua, ub;
|
| 85 | DWORDLONG uc;
|
| 86 |
|
| 87 | ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
|
| 88 | ub.QuadPart = (DWORDLONG)(b >= 0 ? b : -b);
|
| 89 | uc = (DWORDLONG)(c >= 0 ? c : -c);
|
| 90 | BOOL bSign = (a < 0) ^ (b < 0);
|
| 91 |
|
| 92 | /* Do long multiplication */
|
| 93 | ULARGE_INTEGER p[2];
|
| 94 | p[0].QuadPart = UInt32x32To64(ua.LowPart, ub.LowPart);
|
| 95 |
|
| 96 | /* This next computation cannot overflow into p[1].HighPart because
|
| 97 | the max number we can compute here is:
|
| 98 |
|
| 99 | (2 ** 32 - 1) * (2 ** 32 - 1) + // ua.LowPart * ub.LowPart
|
| 100 | (2 ** 32) * (2 ** 31) * (2 ** 32 - 1) * 2 // x.LowPart * y.HighPart * 2
|
| 101 |
|
| 102 | == 2 ** 96 - 2 ** 64 + (2 ** 64 - 2 ** 33 + 1)
|
| 103 | == 2 ** 96 - 2 ** 33 + 1
|
| 104 | < 2 ** 96
|
| 105 | */
|
| 106 |
|
| 107 | ULARGE_INTEGER x;
|
| 108 | x.QuadPart = UInt32x32To64(ua.LowPart, ub.HighPart) +
|
| 109 | UInt32x32To64(ua.HighPart, ub.LowPart) +
|
| 110 | p[0].HighPart;
|
| 111 | p[0].HighPart = x.LowPart;
|
| 112 | p[1].QuadPart = UInt32x32To64(ua.HighPart, ub.HighPart) + x.HighPart;
|
| 113 |
|
| 114 | if (d != 0) {
|
| 115 | ULARGE_INTEGER ud[2];
|
| 116 | if (bSign) {
|
| 117 | ud[0].QuadPart = (DWORDLONG)(-d);
|
| 118 | if (d > 0) {
|
| 119 | /* -d < 0 */
|
| 120 | ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
|
| 121 | } else {
|
| 122 | ud[1].QuadPart = (DWORDLONG)0;
|
| 123 | }
|
| 124 | } else {
|
| 125 | ud[0].QuadPart = (DWORDLONG)d;
|
| 126 | if (d < 0) {
|
| 127 | ud[1].QuadPart = (DWORDLONG)(LONGLONG)-1;
|
| 128 | } else {
|
| 129 | ud[1].QuadPart = (DWORDLONG)0;
|
| 130 | }
|
| 131 | }
|
| 132 | /* Now do extended addition */
|
| 133 | ULARGE_INTEGER uliTotal;
|
| 134 |
|
| 135 | /* Add ls DWORDs */
|
| 136 | uliTotal.QuadPart = (DWORDLONG)ud[0].LowPart + p[0].LowPart;
|
| 137 | p[0].LowPart = uliTotal.LowPart;
|
| 138 |
|
| 139 | /* Propagate carry */
|
| 140 | uliTotal.LowPart = uliTotal.HighPart;
|
| 141 | uliTotal.HighPart = 0;
|
| 142 |
|
| 143 | /* Add 2nd most ls DWORDs */
|
| 144 | uliTotal.QuadPart += (DWORDLONG)ud[0].HighPart + p[0].HighPart;
|
| 145 | p[0].HighPart = uliTotal.LowPart;
|
| 146 |
|
| 147 | /* Propagate carry */
|
| 148 | uliTotal.LowPart = uliTotal.HighPart;
|
| 149 | uliTotal.HighPart = 0;
|
| 150 |
|
| 151 | /* Add MS DWORDLONGs - no carry expected */
|
| 152 | p[1].QuadPart += ud[1].QuadPart + uliTotal.QuadPart;
|
| 153 |
|
| 154 | /* Now see if we got a sign change from the addition */
|
| 155 | if ((LONG)p[1].HighPart < 0) {
|
| 156 | bSign = !bSign;
|
| 157 |
|
| 158 | /* Negate the current value (ugh!) */
|
| 159 | p[0].QuadPart = ~p[0].QuadPart;
|
| 160 | p[1].QuadPart = ~p[1].QuadPart;
|
| 161 | p[0].QuadPart += 1;
|
| 162 | p[1].QuadPart += (p[0].QuadPart == 0);
|
| 163 | }
|
| 164 | }
|
| 165 |
|
| 166 | /* Now for the division */
|
| 167 | if (c < 0) {
|
| 168 | bSign = !bSign;
|
| 169 | }
|
| 170 |
|
| 171 |
|
| 172 | /* This will catch c == 0 and overflow */
|
| 173 | if (uc <= p[1].QuadPart) {
|
| 174 | return bSign ? (LONGLONG)0x8000000000000000 :
|
| 175 | (LONGLONG)0x7FFFFFFFFFFFFFFF;
|
| 176 | }
|
| 177 |
|
| 178 | DWORDLONG ullResult;
|
| 179 |
|
| 180 | /* Do the division */
|
| 181 | /* If the dividend is a DWORD_LONG use the compiler */
|
| 182 | if (p[1].QuadPart == 0) {
|
| 183 | ullResult = p[0].QuadPart / uc;
|
| 184 | return bSign ? -(LONGLONG)ullResult : (LONGLONG)ullResult;
|
| 185 | }
|
| 186 |
|
| 187 | /* If the divisor is a DWORD then its simpler */
|
| 188 | ULARGE_INTEGER ulic;
|
| 189 | ulic.QuadPart = uc;
|
| 190 | if (ulic.HighPart == 0) {
|
| 191 | ULARGE_INTEGER uliDividend;
|
| 192 | ULARGE_INTEGER uliResult;
|
| 193 | DWORD dwDivisor = (DWORD)uc;
|
| 194 | // ASSERT(p[1].HighPart == 0 && p[1].LowPart < dwDivisor);
|
| 195 | uliDividend.HighPart = p[1].LowPart;
|
| 196 | uliDividend.LowPart = p[0].HighPart;
|
| 197 | #ifndef USE_LARGEINT
|
| 198 | uliResult.HighPart = (DWORD)(uliDividend.QuadPart / dwDivisor);
|
| 199 | p[0].HighPart = (DWORD)(uliDividend.QuadPart % dwDivisor);
|
| 200 | uliResult.LowPart = 0;
|
| 201 | uliResult.QuadPart = p[0].QuadPart / dwDivisor + uliResult.QuadPart;
|
| 202 | #else
|
| 203 | /* NOTE - this routine will take exceptions if
|
| 204 | the result does not fit in a DWORD
|
| 205 | */
|
| 206 | if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
|
| 207 | uliResult.HighPart = EnlargedUnsignedDivide(
|
| 208 | uliDividend,
|
| 209 | dwDivisor,
|
| 210 | &p[0].HighPart);
|
| 211 | } else {
|
| 212 | uliResult.HighPart = 0;
|
| 213 | }
|
| 214 | uliResult.LowPart = EnlargedUnsignedDivide(
|
| 215 | p[0],
|
| 216 | dwDivisor,
|
| 217 | NULL);
|
| 218 | #endif
|
| 219 | return bSign ? -(LONGLONG)uliResult.QuadPart :
|
| 220 | (LONGLONG)uliResult.QuadPart;
|
| 221 | }
|
| 222 |
|
| 223 |
|
| 224 | ullResult = 0;
|
| 225 |
|
| 226 | /* OK - do long division */
|
| 227 | for (int i = 0; i < 64; i++) {
|
| 228 | ullResult <<= 1;
|
| 229 |
|
| 230 | /* Shift 128 bit p left 1 */
|
| 231 | p[1].QuadPart <<= 1;
|
| 232 | if ((p[0].HighPart & 0x80000000) != 0) {
|
| 233 | p[1].LowPart++;
|
| 234 | }
|
| 235 | p[0].QuadPart <<= 1;
|
| 236 |
|
| 237 | /* Compare */
|
| 238 | if (uc <= p[1].QuadPart) {
|
| 239 | p[1].QuadPart -= uc;
|
| 240 | ullResult += 1;
|
| 241 | }
|
| 242 | }
|
| 243 |
|
| 244 | return bSign ? - (LONGLONG)ullResult : (LONGLONG)ullResult;
|
| 245 | }
|
| 246 |
|
| 247 | LONGLONG WINAPI Int64x32Div32(LONGLONG a, LONG b, LONG c, LONG d)
|
| 248 | {
|
| 249 | ULARGE_INTEGER ua;
|
| 250 | DWORD ub;
|
| 251 | DWORD uc;
|
| 252 |
|
| 253 | /* Compute the absolute values to avoid signed arithmetic problems */
|
| 254 | ua.QuadPart = (DWORDLONG)(a >= 0 ? a : -a);
|
| 255 | ub = (DWORD)(b >= 0 ? b : -b);
|
| 256 | uc = (DWORD)(c >= 0 ? c : -c);
|
| 257 | BOOL bSign = (a < 0) ^ (b < 0);
|
| 258 |
|
| 259 | /* Do long multiplication */
|
| 260 | ULARGE_INTEGER p0;
|
| 261 | DWORD p1;
|
| 262 | p0.QuadPart = UInt32x32To64(ua.LowPart, ub);
|
| 263 |
|
| 264 | if (ua.HighPart != 0) {
|
| 265 | ULARGE_INTEGER x;
|
| 266 | x.QuadPart = UInt32x32To64(ua.HighPart, ub) + p0.HighPart;
|
| 267 | p0.HighPart = x.LowPart;
|
| 268 | p1 = x.HighPart;
|
| 269 | } else {
|
| 270 | p1 = 0;
|
| 271 | }
|
| 272 |
|
| 273 | if (d != 0) {
|
| 274 | ULARGE_INTEGER ud0;
|
| 275 | DWORD ud1;
|
| 276 |
|
| 277 | if (bSign) {
|
| 278 | //
|
| 279 | // Cast d to LONGLONG first otherwise -0x80000000 sign extends
|
| 280 | // incorrectly
|
| 281 | //
|
| 282 | ud0.QuadPart = (DWORDLONG)(-(LONGLONG)d);
|
| 283 | if (d > 0) {
|
| 284 | /* -d < 0 */
|
| 285 | ud1 = (DWORD)-1;
|
| 286 | } else {
|
| 287 | ud1 = (DWORD)0;
|
| 288 | }
|
| 289 | } else {
|
| 290 | ud0.QuadPart = (DWORDLONG)d;
|
| 291 | if (d < 0) {
|
| 292 | ud1 = (DWORD)-1;
|
| 293 | } else {
|
| 294 | ud1 = (DWORD)0;
|
| 295 | }
|
| 296 | }
|
| 297 | /* Now do extended addition */
|
| 298 | ULARGE_INTEGER uliTotal;
|
| 299 |
|
| 300 | /* Add ls DWORDs */
|
| 301 | uliTotal.QuadPart = (DWORDLONG)ud0.LowPart + p0.LowPart;
|
| 302 | p0.LowPart = uliTotal.LowPart;
|
| 303 |
|
| 304 | /* Propagate carry */
|
| 305 | uliTotal.LowPart = uliTotal.HighPart;
|
| 306 | uliTotal.HighPart = 0;
|
| 307 |
|
| 308 | /* Add 2nd most ls DWORDs */
|
| 309 | uliTotal.QuadPart += (DWORDLONG)ud0.HighPart + p0.HighPart;
|
| 310 | p0.HighPart = uliTotal.LowPart;
|
| 311 |
|
| 312 | /* Add MS DWORDLONGs - no carry expected */
|
| 313 | p1 += ud1 + uliTotal.HighPart;
|
| 314 |
|
| 315 | /* Now see if we got a sign change from the addition */
|
| 316 | if ((LONG)p1 < 0) {
|
| 317 | bSign = !bSign;
|
| 318 |
|
| 319 | /* Negate the current value (ugh!) */
|
| 320 | p0.QuadPart = ~p0.QuadPart;
|
| 321 | p1 = ~p1;
|
| 322 | p0.QuadPart += 1;
|
| 323 | p1 += (p0.QuadPart == 0);
|
| 324 | }
|
| 325 | }
|
| 326 |
|
| 327 | /* Now for the division */
|
| 328 | if (c < 0) {
|
| 329 | bSign = !bSign;
|
| 330 | }
|
| 331 |
|
| 332 |
|
| 333 | /* This will catch c == 0 and overflow */
|
| 334 | if (uc <= p1) {
|
| 335 | return bSign ? (LONGLONG)0x8000000000000000 :
|
| 336 | (LONGLONG)0x7FFFFFFFFFFFFFFF;
|
| 337 | }
|
| 338 |
|
| 339 | /* Do the division */
|
| 340 |
|
| 341 | /* If the divisor is a DWORD then its simpler */
|
| 342 | ULARGE_INTEGER uliDividend;
|
| 343 | ULARGE_INTEGER uliResult;
|
| 344 | DWORD dwDivisor = uc;
|
| 345 | uliDividend.HighPart = p1;
|
| 346 | uliDividend.LowPart = p0.HighPart;
|
| 347 | /* NOTE - this routine will take exceptions if
|
| 348 | the result does not fit in a DWORD
|
| 349 | */
|
| 350 | if (uliDividend.QuadPart >= (DWORDLONG)dwDivisor) {
|
| 351 | uliResult.HighPart = EnlargedUnsignedDivide(
|
| 352 | uliDividend,
|
| 353 | dwDivisor,
|
| 354 | &p0.HighPart);
|
| 355 | } else {
|
| 356 | uliResult.HighPart = 0;
|
| 357 | }
|
| 358 | uliResult.LowPart = EnlargedUnsignedDivide(
|
| 359 | p0,
|
| 360 | dwDivisor,
|
| 361 | NULL);
|
| 362 | return bSign ? -(LONGLONG)uliResult.QuadPart :
|
| 363 | (LONGLONG)uliResult.QuadPart;
|
| 364 | }
|
| 365 |
|
| 366 | #endif /* PJMEDIA_VIDEO_DEV_HAS_DSHOW */
|