COMBINATORIAL_BLAS  1.6
mod_arith_32bit.h
Go to the documentation of this file.
1 /* Copyright (C) 2010 The Trustees of Indiana University. */
2 /* */
3 /* Use, modification and distribution is subject to the Boost Software */
4 /* License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at */
5 /* http://www.boost.org/LICENSE_1_0.txt) */
6 /* */
7 /* Authors: Jeremiah Willcock */
8 /* Andrew Lumsdaine */
9 
10 #ifndef MOD_ARITH_32BIT_H
11 #define MOD_ARITH_32BIT_H
12 
13 #include <stdint.h>
14 #include <assert.h>
15 
16 /* Various modular arithmetic operations for modulus 2^31-1 (0x7FFFFFFF).
17  * These may need to be tweaked to get acceptable performance on some platforms
18  * (especially ones without conditional moves). */
19 
20 static inline uint_fast32_t mod_add(uint_fast32_t a, uint_fast32_t b) {
21  uint_fast32_t x;
22  assert (a <= 0x7FFFFFFE);
23  assert (b <= 0x7FFFFFFE);
24 #if 0
25  return (a + b) % 0x7FFFFFFF;
26 #else
27  x = a + b; /* x <= 0xFFFFFFFC */
28  x = (x >= 0x7FFFFFFF) ? (x - 0x7FFFFFFF) : x;
29  return x;
30 #endif
31 }
32 
33 static inline uint_fast32_t mod_mul(uint_fast32_t a, uint_fast32_t b) {
34  uint_fast64_t temp;
35  uint_fast32_t temp2;
36  assert (a <= 0x7FFFFFFE);
37  assert (b <= 0x7FFFFFFE);
38 #if 0
39  return (uint_fast32_t)((uint_fast64_t)a * b % 0x7FFFFFFF);
40 #else
41  temp = (uint_fast64_t)a * b; /* temp <= 0x3FFFFFFE00000004 */
42  temp2 = (uint_fast32_t)(temp & 0x7FFFFFFF) + (uint_fast32_t)(temp >> 31); /* temp2 <= 0xFFFFFFFB */
43  return (temp2 >= 0x7FFFFFFF) ? (temp2 - 0x7FFFFFFF) : temp2;
44 #endif
45 }
46 
47 static inline uint_fast32_t mod_mac(uint_fast32_t sum, uint_fast32_t a, uint_fast32_t b) {
48  uint_fast64_t temp;
49  uint_fast32_t temp2;
50  assert (sum <= 0x7FFFFFFE);
51  assert (a <= 0x7FFFFFFE);
52  assert (b <= 0x7FFFFFFE);
53 #if 0
54  return (uint_fast32_t)(((uint_fast64_t)a * b + sum) % 0x7FFFFFFF);
55 #else
56  temp = (uint_fast64_t)a * b + sum; /* temp <= 0x3FFFFFFE80000002 */
57  temp2 = (uint_fast32_t)(temp & 0x7FFFFFFF) + (uint_fast32_t)(temp >> 31); /* temp2 <= 0xFFFFFFFC */
58  return (temp2 >= 0x7FFFFFFF) ? (temp2 - 0x7FFFFFFF) : temp2;
59 #endif
60 }
61 
62 static inline uint_fast32_t mod_mac2(uint_fast32_t sum, uint_fast32_t a, uint_fast32_t b, uint_fast32_t c, uint_fast32_t d) {
63  assert (sum <= 0x7FFFFFFE);
64  assert (a <= 0x7FFFFFFE);
65  assert (b <= 0x7FFFFFFE);
66  assert (c <= 0x7FFFFFFE);
67  assert (d <= 0x7FFFFFFE);
68  return mod_mac(mod_mac(sum, a, b), c, d);
69 }
70 
71 static inline uint_fast32_t mod_mac3(uint_fast32_t sum, uint_fast32_t a, uint_fast32_t b, uint_fast32_t c, uint_fast32_t d, uint_fast32_t e, uint_fast32_t f) {
72  uint_fast64_t temp;
73  assert (sum <= 0x7FFFFFFE);
74  assert (a <= 0x7FFFFFFE);
75  assert (b <= 0x7FFFFFFE);
76  assert (c <= 0x7FFFFFFE);
77  assert (d <= 0x7FFFFFFE);
78  assert (e <= 0x7FFFFFFE);
79  assert (f <= 0x7FFFFFFE);
80  return mod_mac2(mod_mac(sum, a, b), c, d, e, f);
81 }
82 
83 static inline uint_fast32_t mod_mac4(uint_fast32_t sum, uint_fast32_t a, uint_fast32_t b, uint_fast32_t c, uint_fast32_t d, uint_fast32_t e, uint_fast32_t f, uint_fast32_t g, uint_fast32_t h) {
84  uint_fast64_t temp;
85  assert (sum <= 0x7FFFFFFE);
86  assert (a <= 0x7FFFFFFE);
87  assert (b <= 0x7FFFFFFE);
88  assert (c <= 0x7FFFFFFE);
89  assert (d <= 0x7FFFFFFE);
90  assert (e <= 0x7FFFFFFE);
91  assert (f <= 0x7FFFFFFE);
92  assert (g <= 0x7FFFFFFE);
93  assert (h <= 0x7FFFFFFE);
94  return mod_mac2(mod_mac2(sum, a, b, c, d), e, f, g, h);
95 }
96 
97 /* The two constants x and y are special cases because they are easier to
98  * multiply by on 32-bit systems. They are used as multipliers in the random
99  * number generator. The techniques for fast multiplication by these
100  * particular values are in L'Ecuyer's papers; we don't use them yet. */
101 
102 static inline uint_fast32_t mod_mul_x(uint_fast32_t a) {
103  return mod_mul(a, 107374182);
104 }
105 
106 static inline uint_fast32_t mod_mul_y(uint_fast32_t a) {
107  return mod_mul(a, 104480);
108 }
109 
110 static inline uint_fast32_t mod_mac_y(uint_fast32_t sum, uint_fast32_t a) {
111  return mod_mac(sum, a, 104480);
112 }
113 
114 #endif /* MOD_ARITH_32BIT_H */