home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / sdk / mapi / win16 / dev / common / math64.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-11  |  8.2 KB  |  281 lines

  1. /*
  2.  *  MATH64.C
  3.  *  
  4.  *  64-bit integer arithmetic
  5.  *
  6.  *  Copyright 1993-1995 Microsoft Corporation. All Rights Reserved.
  7.  */
  8.  
  9. #pragma warning(disable:4001)   /* single line comments */
  10. #pragma warning(disable:4054)   /* cast function pointer to data pointer */
  11. #pragma warning(disable:4100)   /* unreferenced formal parameter */
  12. #pragma warning(disable:4127)   /* conditional expression is constant */
  13. #pragma warning(disable:4201)   /* nameless struct/union */
  14. #pragma warning(disable:4204)   /* non-constant aggregate initializer */
  15. #pragma warning(disable:4209)   /* benign typedef redefinition */
  16. #pragma warning(disable:4214)   /* bit field types other than int */
  17. #pragma warning(disable:4505)   /* unreferenced local function removed */
  18. #pragma warning(disable:4514)   /* unreferenced inline function removed */
  19. #pragma warning(disable:4702)   /* unreachable code */
  20. #pragma warning(disable:4704)   /* inline assembler turns off global optimizer */
  21. #pragma warning(disable:4705)   /* statement has no effect */
  22. #pragma warning(disable:4706)   /* assignment within conditional expression */
  23. #pragma warning(disable:4710)   /* function not expanded */
  24. #pragma warning(disable:4115)   /* named type def in parens */
  25.  
  26. #ifdef WIN32
  27. #define INC_OLE2 /* Get the OLE2 stuff */
  28. #define INC_RPC  /* harmless on Windows NT; Windows 95 needs it */
  29. #endif
  30. #include <windows.h>
  31. #pragma warning(disable:4001)   /* single line comments */
  32. #include <windowsx.h>
  33. #include <mapiwin.h>
  34. #include <mapidbg.h>
  35. #ifdef WIN32
  36. #include <objerror.h>
  37. #include <objbase.h>
  38. #endif
  39. #if defined (WIN16) || defined (DOS)
  40. #include <compobj.h>
  41. #endif
  42. #include <mapiutil.h>
  43. #include <mapiperf.h>
  44.  
  45. #include <_mapiwin.h>
  46.  
  47. #pragma SEGMENT(MAPI_Util)
  48.  
  49. /*  Unsigned 64-bit add */
  50. STDAPI_(FILETIME) 
  51. FtAddFt(FILETIME ft1, FILETIME ft2)
  52. {
  53.     FILETIME    ft;
  54.  
  55.     ft.dwLowDateTime = ft1.dwLowDateTime + ft2.dwLowDateTime;
  56.     ft.dwHighDateTime = ft1.dwHighDateTime + ft2.dwHighDateTime +
  57.         ((ft.dwLowDateTime < ft1.dwLowDateTime ||
  58.             ft.dwLowDateTime < ft2.dwLowDateTime) ?
  59.                 1L : 0L);
  60.  
  61.     return ft;
  62. }
  63.  
  64. STDAPI_(FILETIME) 
  65. FtAdcFt(FILETIME ft1, FILETIME ft2, WORD FAR *pwCarry)
  66. {
  67.     FILETIME    ft;
  68.     WORD        wCarry;
  69.  
  70.     wCarry = (WORD) (pwCarry ? *pwCarry : 0);
  71.  
  72.     ft.dwLowDateTime = ft1.dwLowDateTime + ft2.dwLowDateTime + wCarry;
  73.     wCarry = (WORD) (((ft.dwLowDateTime < ft1.dwLowDateTime ||
  74.         ft.dwLowDateTime < ft2.dwLowDateTime)) ?
  75.             1 : 0);
  76.  
  77.     ft.dwHighDateTime = ft1.dwHighDateTime + ft2.dwHighDateTime + wCarry;
  78.     if (pwCarry)
  79.         *pwCarry = (WORD) (((ft.dwHighDateTime < ft1.dwHighDateTime ||
  80.             ft.dwHighDateTime < ft2.dwHighDateTime)) ?
  81.                 1 : 0);
  82.  
  83.     return ft;
  84. }
  85.  
  86.  
  87. /*  Unsigned 64-bit subtract */
  88. STDAPI_(FILETIME)
  89. FtSubFt(FILETIME ftMinuend, FILETIME ftSubtrahend)
  90. {
  91.     FILETIME ft;
  92.  
  93.     ft = FtNegFt(ftSubtrahend);
  94.     return FtAddFt(ftMinuend, ft);
  95. }
  96.  
  97. /*  Unsigned 32 by 64-bit multiply */
  98. STDAPI_(FILETIME)
  99. FtMulDw(DWORD dw, FILETIME ft)
  100. {
  101.     FILETIME    ftProd = { 0, 0 };
  102.  
  103.     while (dw)
  104.     {
  105.         if (dw & 1)
  106.             ftProd = FtAddFt(ftProd, ft);
  107.         ft.dwHighDateTime <<= 1;
  108.         if (ft.dwLowDateTime & 0x80000000)
  109.             ft.dwHighDateTime |= 1;
  110.         ft.dwLowDateTime <<= 1;
  111.         dw >>= 1;
  112.     }
  113.     return ftProd;
  114. }
  115.  
  116. /*  Unsigned 32 by 32-bit multiply
  117.  *  Uses FILETIME as a convenient structure to hold the 64 bit result
  118.  */
  119. STDAPI_(FILETIME)
  120. FtMulDwDw(DWORD dw1, DWORD dw2)
  121. {
  122.     FILETIME    ftProd;
  123.     DWORD       dwAccum1;
  124.     DWORD       dwAccum2;
  125.  
  126.     //  Based on the formula
  127.     //  Product = (dw1/2**16) * (dw2/2**16) * (2**32)
  128.     //          + (dw1/2**16) * Remainder(dw2/2**16) * (2**16)
  129.     //          + Remainder(dw1/2**16) * (dw2/2**16) * (2**16)
  130.     //          + Remainder(dw1/2**16) * Remainder(dw2/2**16)
  131.  
  132.     //    (dw1/2**16) * (dw2/2**16) * (2**32)
  133.     dwAccum2 = dw2 >> 16;
  134.     dwAccum1 = dw1 >> 16;
  135.     ftProd.dwHighDateTime = dwAccum1 * dwAccum2;
  136.  
  137.     //  + (dw1/2**16) * Remainder(dw2/2**16) * (2**16)
  138.     dwAccum1 *= dw2 & 0xFFFF;
  139.     ftProd.dwHighDateTime += dwAccum1 >> 16;
  140.     ftProd.dwLowDateTime = dwAccum1 << 16;
  141.  
  142.     //  + Remainder(dw1/2**16) * (dw2/2**16) * (2**16)
  143.     dwAccum2 *= dw1 & 0xFFFF;
  144.     ftProd.dwHighDateTime += dwAccum2 >> 16;
  145.     dwAccum2 <<= 16;
  146.     dwAccum1 = ftProd.dwLowDateTime;
  147.     ftProd.dwLowDateTime += dwAccum2;
  148.     if (   (ftProd.dwLowDateTime < dwAccum1)
  149.         || (ftProd.dwLowDateTime < dwAccum2))
  150.     {
  151.         ftProd.dwHighDateTime++;
  152.     }
  153.  
  154.     //  + Remainder(dw1/2**16) * Remainder(dw2/2**16)
  155.     dwAccum2 = (dw1 & 0xFFFF) * (dw2 & 0xFFFF);
  156.     dwAccum1 = ftProd.dwLowDateTime;
  157.     ftProd.dwLowDateTime += dwAccum2;
  158.     if (   (ftProd.dwLowDateTime < dwAccum1)
  159.         || (ftProd.dwLowDateTime < dwAccum2))
  160.     {
  161.         ftProd.dwHighDateTime++;
  162.     }
  163.  
  164.     return ftProd;
  165. }
  166.  
  167.  
  168. /*  64-bit two's complement */
  169. STDAPI_(FILETIME)
  170. FtNegFt(FILETIME ft)
  171. {
  172.  
  173.     ft.dwLowDateTime = ~(ft.dwLowDateTime) + 1;
  174.     ft.dwHighDateTime = ~(ft.dwHighDateTime) +
  175.         (ft.dwLowDateTime ? 0 : 1);
  176.  
  177.     return ft;
  178. }
  179.  
  180. /*  Unsigned 64-bit by 32-bit divide
  181.  *  Uses FILETIME as a convenient structure to hold the 64 bit Dividend.
  182.  */
  183. STDAPI_(DWORD)
  184. DwDivFtDw(FILETIME ftDividend, DWORD dwDivisor)
  185. {
  186.     DWORD       dwQuotient;
  187.     int         exp;
  188.  
  189.     if (   !dwDivisor
  190.         || (ftDividend.dwHighDateTime >= dwDivisor))
  191.     {
  192.         //  Overflow
  193.         return (DWORD) -1;
  194.     }
  195.  
  196.     if (!ftDividend.dwHighDateTime)
  197.     {
  198.         //  32 by 32 divide
  199.         return (ftDividend.dwHighDateTime / dwDivisor);
  200.     }
  201.  
  202.     //  Well it's not going to be trivial so let's do a simple
  203.     //  shift and subtract division
  204.  
  205.     //  We go through this once for the HighDWord subtract which will
  206.     //  always fail and 32 times to shift the LowDWord through
  207.     //  NOTE!   We want to end up with Remainder/2 NOT Remainder (for rounding)
  208.     exp = 33;
  209.     dwQuotient = 0;
  210.     while (exp--)
  211.     {
  212.         //  Multiply the quotient by two for the next digit
  213.         dwQuotient <<= 1;
  214.  
  215.         //  See if this digit should be set (ie can subtract divisor
  216.         if (ftDividend.dwHighDateTime >= dwDivisor)
  217.         {
  218.             dwQuotient++;
  219.             ftDividend.dwHighDateTime -= dwDivisor;
  220.         }
  221.  
  222.         //  Multiply the dividend by two to prepare for the next digit
  223.         ftDividend.dwHighDateTime <<= 1;
  224.         if (ftDividend.dwLowDateTime & 0x80000000)
  225.         {
  226.             ftDividend.dwHighDateTime |= 1;
  227.         }
  228.         ftDividend.dwLowDateTime <<= 1;
  229.     }
  230.  
  231.     //  Round to the NEAREST integer
  232.     //  Note that we already multiplied the Dividend by two above
  233.     if (ftDividend.dwHighDateTime >= dwDivisor)
  234.     {
  235.         dwQuotient++;
  236.     }
  237.  
  238.     return dwQuotient;
  239. }
  240.  
  241. /*  ftMagicDivisor is the reciprocal of the thing we want to divide by. */
  242. /*  So this works by multiplying, then shifting down. */
  243.  
  244. STDAPI_(FILETIME)
  245. FtDivFtBogus(FILETIME Dividend, FILETIME MagicDivisor, CHAR ShiftCount)
  246. {
  247.     FILETIME    ft1;
  248.     FILETIME    ftAcc;
  249.     WORD        wCarry1 = 0;
  250.     WORD        wCarry2 = 0;
  251.  
  252.     Assert(ShiftCount <= 31);
  253.  
  254.     ft1 = FtMulDwDw(MagicDivisor.dwLowDateTime, Dividend.dwLowDateTime);
  255.     /*  Low dword of result falls off */
  256.     ftAcc.dwLowDateTime = ft1.dwHighDateTime;
  257.     ftAcc.dwHighDateTime = 0;
  258.  
  259.     ft1 = FtMulDwDw(MagicDivisor.dwHighDateTime, Dividend.dwLowDateTime);
  260.     ftAcc = FtAdcFt(ftAcc, ft1, &wCarry1);
  261.  
  262.     ft1 = FtMulDwDw(MagicDivisor.dwLowDateTime, Dividend.dwHighDateTime);
  263.     ftAcc = FtAdcFt(ftAcc, ft1, &wCarry2);
  264.  
  265.     ft1 = FtMulDwDw(MagicDivisor.dwHighDateTime, Dividend.dwHighDateTime);
  266.     ftAcc.dwLowDateTime = ftAcc.dwHighDateTime;
  267.     ftAcc.dwHighDateTime = wCarry2 + wCarry1;
  268.     ftAcc = FtAddFt(ftAcc, ft1);
  269.  
  270.     /*  At this point, ftAcc.dwLowDateTime has the low 32 bits of the product, */
  271.     /*  and ft2 has the next 64 bits. Take the high 64 bits, shifted */
  272.     /*  right by the ShiftCount. */
  273.  
  274.     ftAcc.dwLowDateTime = (ftAcc.dwLowDateTime >> ShiftCount) |
  275.         (ftAcc.dwHighDateTime << (32 - ShiftCount));
  276.     ftAcc.dwHighDateTime >>= ShiftCount;
  277.  
  278.     return ftAcc;
  279. }
  280.  
  281.