arithutil.cpp 11 KB

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