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