Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
11 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. dblint.h
  5. Abstract:
  6. Support primitives for bignum package.
  7. --*/
  8. /*
  9. File: dblint.h. Supplement to bignum.h
  10. This file has declarations related to
  11. double-precision integers,
  12. such as typedefs, constants, and primitive operations.
  13. Before #including this, one should #define
  14. digit_t -- typedef for single-precision integers.
  15. RADIX_BITS -- Number of bits per digit_t.
  16. and identify which compiler one is using.
  17. Constants defined herein include
  18. DBLINT_BUILTIN -- 1 if compiler directly
  19. supports double integers, 0 if not.
  20. DBLINT_HIGH_INDEX (optional) -- When DBLINT_BUILTIN == 1,
  21. this is 0 if compiler stores
  22. the most significant half of a
  23. dblint_t datum first, and 1
  24. if compiler stores the least
  25. significant half first. See
  26. HIGH_DIGIT and MAKE_DBLINT below.
  27. If this is not defined, then HIGH_DIGIT
  28. and MAKE_DBLINT are defined using
  29. shifts by RADIX_BITS. If the compiler
  30. optimizes such shifts, then
  31. leave DBLINT_HIGH_INDEX undefined.
  32. The dblint_t type is unsigned and holds
  33. twice as many bits as a digit_t datum.
  34. If (DBLINT_BUILTIN = 1),
  35. then use the type already in the language.
  36. Otherwise (DBLINT_BUILTIN = 0)
  37. construct one of our own,
  38. using a struct with two digit_t fields.
  39. Let u, u1, u2 have type digit_t and
  40. d, d1, d2 have type dblint_t.
  41. The following primitives are defined,
  42. whether we use the built-in type or our own type:
  43. DBLINT(u) -- Convert u from type digit_t to type dblint_t.
  44. DBLINT_ADD(d1, d2) -- Sum d1 + d2.
  45. DBLINT_EQ(d1, d2) -- Test whether d1 == d2.
  46. DBLINT_GE(d1, d2) -- Test whether d1 >= d2.
  47. DBLINT_GT(d1, d2) -- Test whether d1 > d2.
  48. DBLINT_LE(d1, d2) -- Test whether d1 >= d2.
  49. DBLINT_LT(d1, d2) -- Test whether d1 > d2.
  50. DBLINT_NE(d1, d2) -- Test whether d1 <> d2.
  51. DBLINT_SUB(d1, d2) -- Difference d1 - d2.
  52. DPRODUU(u1, u2) -- Product of u1 and u2, as a dblint_t.
  53. HPRODUU(u1, u2) -- Most significant half of product
  54. of u1 and u2, as a digit_t.
  55. HIGH_DIGIT(d) -- Most significant half of d.
  56. LOW_DIGIT(d) -- Least significant half of d.
  57. MAKE_DBLINT(u1, u2) -- Construct a dblint_t
  58. whose most significant half is u1 and
  59. whose least significant half is u2.
  60. */
  61. #if COMPILER == COMPILER_GCC
  62. #define DBLINT_BUILTIN 1
  63. typedef unsigned long long dblint_t;
  64. #define DBLINT_HIGH_INDEX 0
  65. /* GCC on SPARC stores high half of dblint_t first */
  66. #endif
  67. #if COMPILER == COMPILER_VC && RADIX_BITS == 32
  68. #define DBLINT_BUILTIN 1
  69. typedef unsigned __int64 dblint_t;
  70. #if TARGET == TARGET_ALPHA
  71. /* If the Alpha is using RADIX_BITS == 32,
  72. then use the shift instruction
  73. for HIGH_DIGIT and MAKE_DBLINT */
  74. #else
  75. #define DBLINT_HIGH_INDEX 1
  76. /* Visual C++ on ix86 stores low half of dblint_t first */
  77. #endif
  78. #endif
  79. #ifndef DBLINT_BUILTIN
  80. /* No language support -- simulate using structs */
  81. #define DBLINT_BUILTIN 0
  82. typedef struct {
  83. digit_t high;
  84. digit_t low;
  85. } dblint_t;
  86. #endif
  87. typedef const dblint_t dblint_tc;
  88. #if DBLINT_BUILTIN
  89. /*
  90. If language has support for double-length integers, use it.
  91. Good compilers will inline these simple operations.
  92. */
  93. #define DBLINT(u) ((dblint_t)(u))
  94. #define DBLINT_ADD(d1, d2) ((d1) + (d2))
  95. #define DBLINT_EQ( d1, d2) ((d1) == (d2))
  96. #define DBLINT_GE( d1, d2) ((d1) >= (d2))
  97. #define DBLINT_GT( d1, d2) ((d1) > (d2))
  98. #define DBLINT_LE( d1, d2) ((d1) <= (d2))
  99. #define DBLINT_LT( d1, d2) ((d1) < (d2))
  100. #define DBLINT_NE( d1, d2) ((d1) != (d2))
  101. #define DBLINT_SUB(d1, d2) ((d1) - (d2))
  102. #if COMPILER == COMPILER_GCC
  103. #define DPRODUU(u1, u2) (DBLINT(u1) * DBLINT(u2))
  104. #endif
  105. #if COMPILER == COMPILER_VC
  106. /*
  107. A problem in Visual C/C++ 4.0 (x86 version, 1995)
  108. prevents proper inlining of the DPRODUU function
  109. if we code it in a straightforward way. Specifically,
  110. if we have two nearby references DPRODUU(x, y)
  111. and DPRODUU(x, z), where one argument (here x) is
  112. repeated, then the compiler calls library function
  113. __allmul rather than emit a MUL instruction.
  114. The -volatile- keyword inhibits the compiler from
  115. recognizing the repeated subexpression DBLINT(x),
  116. and circumvents the problem, alas with extra memory
  117. references.
  118. x86 version of VC 4.1 adds an __emulu function
  119. */
  120. static inline dblint_t DPRODUU(digit_tc u1, digit_tc u2)
  121. {
  122. #if TARGET == TARGET_IX86
  123. #if _MFC_VER < 0x0410
  124. volatile digit_tc u1copy = u1, u2copy = u2;
  125. return DBLINT(u1copy) * DBLINT(u2copy);
  126. #else
  127. #pragma intrinsic(__emulu)
  128. return __emulu(u1, u2);
  129. #endif
  130. #elif TARGET == TARGET_MIPS
  131. #pragma intrinsic(__emulu)
  132. return __emulu(u1, u2);
  133. #else
  134. return DBLINT(u1) * DBLINT(u2);
  135. #endif
  136. }
  137. #endif
  138. #define LOW_DIGIT(d) ((digit_t)(d))
  139. #ifdef DBLINT_HIGH_INDEX
  140. #if DBLINT_HIGH_INDEX < 0 || DBLINT_HIGH_INDEX > 1
  141. #error "Illegal value of DBLINT_HIGH_INDEX"
  142. #endif
  143. static inline digit_t HIGH_DIGIT(dblint_tc d)
  144. {
  145. dblint_tc dcopy = d;
  146. return ((digit_tc*)&dcopy)[DBLINT_HIGH_INDEX];
  147. }
  148. static inline dblint_t MAKE_DBLINT(digit_tc high, digit_tc low)
  149. {
  150. dblint_t build = low;
  151. ((digit_t*)&build)[DBLINT_HIGH_INDEX] = high;
  152. return build;
  153. }
  154. #else /* DBLINT_HIGH_INDEX */
  155. #define HIGH_DIGIT(d) ((digit_t)((d) >> RADIX_BITS))
  156. #define MAKE_DBLINT(high, low) \
  157. ( (DBLINT(high) << RADIX_BITS) | DBLINT(low) )
  158. #endif /* DBLINT_HIGH_INDEX */
  159. #else /* DBLINT_BUILTIN */
  160. static inline dblint_t DBLINT(digit_tc d)
  161. {
  162. dblint_t answer;
  163. answer.low = d;
  164. answer.high = 0;
  165. return answer;
  166. }
  167. static inline dblint_t DBLINT_ADD(dblint_tc d1, dblint_tc d2)
  168. {
  169. dblint_t answer;
  170. answer.low = d1.low + d2.low;
  171. answer.high = d1.high + d2.high + (answer.low < d1.low);
  172. return answer;
  173. }
  174. static inline BOOL DBLINT_EQ(dblint_tc d1, dblint_tc d2)
  175. {
  176. return (d1.high == d2.high && d1.low == d2.low);
  177. }
  178. static inline BOOL DBLINT_GE(dblint_tc d1, dblint_tc d2)
  179. {
  180. return (d1.high == d2.high ? d1.low >= d2.low
  181. : d1.high >= d2.high);
  182. }
  183. static inline BOOL DBLINT_GT(dblint_tc d1, dblint_tc d2)
  184. {
  185. return (d1.high == d2.high ? d1.low > d2.low
  186. : d1.high > d2.high);
  187. }
  188. #define DBLINT_LE(d1, d2) DBLINT_GE(d2, d1)
  189. #define DBLINT_LT(d1, d2) DBLINT_GT(d2, d1)
  190. static inline BOOL DBLINT_NE(dblint_tc d1, dblint_tc d2)
  191. {
  192. return (d1.high != d2.high || d1.low != d2.low);
  193. }
  194. static inline dblint_t DBLINT_SUB(dblint_tc d1, dblint_tc d2)
  195. {
  196. dblint_t answer;
  197. answer.low = d1.low - d2.low;
  198. answer.high = d1.high - d2.high - (d1.low < d2.low);
  199. return answer;
  200. }
  201. #define HIGH_DIGIT(d) ((d).high)
  202. #define LOW_DIGIT(d) ((d).low)
  203. static inline dblint_t MAKE_DBLINT(digit_tc high, digit_tc low)
  204. {
  205. dblint_t answer;
  206. answer.low = low;
  207. answer.high = high;
  208. return answer;
  209. }
  210. #if TARGET == TARGET_ALPHA
  211. #pragma intrinsic(__UMULH)
  212. #define HPRODUU(u1, u2) __UMULH(u1, u2)
  213. static inline dblint_t DPRODUU(digit_tc u1, digit_tc u2)
  214. {
  215. dblint_t answer;
  216. answer.high = HPRODUU(u1, u2); /* Upper product */
  217. answer.low = u1*u2; /* Lower product */
  218. return answer;
  219. }
  220. #else
  221. static inline dblint_t DPRODUU(digit_tc u1, digit_tc u2)
  222. /*
  223. Multiply two single-precision operands,
  224. return double precision product.
  225. This will normally be replaced by an assembly language routine.
  226. unless the top half of the product is available in C.
  227. */
  228. {
  229. dblint_t answer;
  230. digit_tc u1bot = u1 & RADIX_HALFMASK_BOTTOM, u1top = u1 >> HALF_RADIX_BITS;
  231. digit_tc u2bot = u2 & RADIX_HALFMASK_BOTTOM, u2top = u2 >> HALF_RADIX_BITS;
  232. digit_tc low = u1bot * u2bot;
  233. digit_t mid1 = u1bot * u2top;
  234. digit_tc mid2 = u1top * u2bot;
  235. digit_tc high = u1top * u2top;
  236. /*
  237. Each half-word product is bounded by
  238. (SQRT(RADIX) - 1)^2 = RADIX - 2*SQRT(RADIX) + 1,
  239. so we can add two half-word operands
  240. to any product without risking integer overflow.
  241. */
  242. mid1 += (mid2 & RADIX_HALFMASK_BOTTOM) + (low >> HALF_RADIX_BITS);
  243. answer.high = high + (mid1 >> HALF_RADIX_BITS)
  244. + (mid2 >> HALF_RADIX_BITS);
  245. answer.low = (low & RADIX_HALFMASK_BOTTOM) + (mid1 << HALF_RADIX_BITS);
  246. return answer;
  247. }
  248. #endif /* multiplication */
  249. #endif /* DBLINT_BUILTIN */
  250. #ifndef HPRODUU
  251. #define HPRODUU(u1, u2) HIGH_DIGIT(DPRODUU(u1, u2))
  252. #endif
  253. /*
  254. The DBLINT_SUM, MULTIPLY_ADD1. MULTIPLY_ADD2
  255. functions take single-length (digit_t) operands and
  256. return double-length (dblint_t) results.
  257. Overflow is impossible.
  258. */
  259. #if TARGET == TARGET_ALPHA && RADIX_BITS == 64 && !DBLINT_BUILT_IN
  260. static inline dblint_t DBLINT_SUM(digit_tc d1, digit_tc d2)
  261. {
  262. dblint_t answer;
  263. answer.low = d1 + d2;
  264. answer.high = (answer.low < d1);
  265. return answer;
  266. }
  267. static inline dblint_t MULTIPLY_ADD1(digit_tc d1, digit_tc d2, digit_tc d3)
  268. {
  269. dblint_t answer;
  270. digit_t ah, al;
  271. al = d1*d2;
  272. ah = __UMULH(d1, d2);
  273. al += d3;
  274. answer.high = ah + (al < d3);
  275. answer.low = al;
  276. return answer;
  277. }
  278. static inline dblint_t MULTIPLY_ADD2(digit_tc d1, digit_tc d2,
  279. digit_tc d3, digit_tc d4)
  280. {
  281. dblint_t answer;
  282. digit_t ah, al, bh, bl;
  283. al = d1*d2;
  284. ah = __UMULH(d1, d2);
  285. bl = d3 + d4;
  286. bh = (bl < d3);
  287. answer.low = al + bl;
  288. answer.high = ah + bh + (answer.low < al);
  289. return answer;
  290. }
  291. #else
  292. #define DBLINT_SUM(d1, d2) DBLINT_ADD(DBLINT(d1), DBLINT(d2))
  293. /* d1 + d2 */
  294. #define MULTIPLY_ADD1(d1, d2, d3) \
  295. DBLINT_ADD(DPRODUU(d1, d2), DBLINT(d3));
  296. /* d1*d2 + d3 */
  297. #define MULTIPLY_ADD2(d1, d2, d3, d4) \
  298. DBLINT_ADD(DBLINT_ADD(DPRODUU(d1, d2), DBLINT(d3)), \
  299. DBLINT(d4))
  300. /* d1*d2 + d3 + d4 */
  301. #endif