llvm-mos-sdk
divmod.h
Go to the documentation of this file.
1 #ifndef __SLOW_DIV
2 
3 // Relatively straigtforward implementation of long division in C. Not
4 // particularly tuned for performance, but clear.
5 
6 template <typename T> static inline T udiv(T a, T b) {
7  if (!b || b > a)
8  return 0;
9 
10  // Here b <= a.
11 
12  // Shift b as far left as possible without exceeding a. If the hightest bit of
13  // b is 1, then the next shift, if were performed at a higher bit width, would
14  // make it exceed a.
15  char num_digits_remaining = 0;
16  while (!(b & static_cast<T>(1) << (sizeof(T) * 8 - 1)) && (b << 1) <= a) {
17  b <<= 1;
18  ++num_digits_remaining;
19  }
20 
21  // Since b <= a, the first digit is always 1. This is not counted in
22  // num_digits_remaining.
23  T q = 1;
24  a -= b;
25  b >>= 1;
26 
27  for (; num_digits_remaining; --num_digits_remaining) {
28  // Prepare q to receive the next digit as its LSB.
29  q <<= 1;
30 
31  // If the quotient digit is a 1
32  if (b <= a) {
33  q |= 1;
34 
35  // Subtract out 1 * the divisor.
36  a -= b;
37  }
38 
39  // The next quotient digit corrsponds to one smaller power of 2 times the
40  // divisor.
41  b >>= 1;
42  }
43 
44  return q;
45 }
46 
47 template <typename T> static inline T umod(T a, T b) {
48  if (!b || b > a)
49  return a;
50 
51  // Here b <= a.
52 
53  // Shift b as far left as possible without exceeding a. If the hightest bit of
54  // b is 1, then the next shift, if were performed at a higher bit width, would
55  // make it exceed a.
56  char num_digits_remaining = 0;
57  while (!(b & static_cast<T>(1) << (sizeof(T) * 8 - 1)) && (b << 1) <= a) {
58  b <<= 1;
59  ++num_digits_remaining;
60  }
61 
62  // Since b <= a, the first digit is always 1. This is not counted in
63  // num_digits_remaining.
64  a -= b;
65  b >>= 1;
66 
67  for (; num_digits_remaining; --num_digits_remaining) {
68  // If the quotient digit is a 1
69  if (b <= a) {
70  // Subtract out 1 * the divisor.
71  a -= b;
72  }
73 
74  // The next quotient digit corrsponds to one smaller power of 2 times the
75  // divisor.
76  b >>= 1;
77  }
78 
79  return a;
80 }
81 
82 template <typename T> static inline T udivmod(T a, T b, T *rem) {
83  if (!b || b > a) {
84  *rem = a;
85  return 0;
86  }
87 
88  // Here b <= a.
89 
90  // Shift b as far left as possible without exceeding a. If the hightest bit of
91  // b is 1, then the next shift, if were performed at a higher bit width, would
92  // make it exceed a.
93  char num_digits_remaining = 0;
94  while (!(b & static_cast<T>(1) << (sizeof(T) * 8 - 1)) && (b << 1) <= a) {
95  b <<= 1;
96  ++num_digits_remaining;
97  }
98 
99  // Since b <= a, the first digit is always 1. This is not counted in
100  // num_digits_remaining.
101  T q = 1;
102  a -= b;
103  b >>= 1;
104 
105  for (; num_digits_remaining; --num_digits_remaining) {
106  // Prepare q to receive the next digit as its LSB.
107  q <<= 1;
108 
109  // If the quotient digit is a 1
110  if (b <= a) {
111  q |= 1;
112 
113  // Subtract out 1 * the divisor.
114  a -= b;
115  }
116 
117  // The next quotient digit corrsponds to one smaller power of 2 times the
118  // divisor.
119  b >>= 1;
120  }
121 
122  *rem = a;
123  return q;
124 }
125 
126 #else // __SLOW_DIV
127 
128 // Very slow versions of the division algorithm. Still useful for validating
129 // whether or not breakages are likely to be caused by a miscompile of the
130 // division algorithm.
131 
132 template <typename T> static inline T udiv(T a, T b) {
133  T q = 0;
134  while (a >= b) {
135  a -= b;
136  q++;
137  }
138  return q;
139 }
140 
141 template <typename T> static inline T umod(T a, T b) {
142  while (a >= b)
143  a -= b;
144  return a;
145 }
146 
147 #endif // __SLOW_DIV
148 
149 template <typename T> struct make_unsigned;
150 template <> struct make_unsigned<signed char> {
151  typedef char type;
152 };
153 template <> struct make_unsigned<int> {
154  typedef unsigned type;
155 };
156 template <> struct make_unsigned<long> {
157  typedef unsigned long type;
158 };
159 template <> struct make_unsigned<long long> {
160  typedef unsigned long long type;
161 };
162 
163 // Version of abs that returns INT_MIN for INT_MIN, without undefined behavior.
164 template <typename T>
165 static inline typename make_unsigned<T>::type safe_abs(T a) {
166  typedef typename make_unsigned<T>::type UT;
167  UT int_min = static_cast<UT>(1) << sizeof(UT) * 8 - 1;
168  UT ua = static_cast<UT>(a);
169  return (a >= 0 || ua == int_min) ? ua : static_cast<UT>(-a);
170 }
171 
172 template <typename T> static inline T div(T a, T b) {
173  typedef typename make_unsigned<T>::type UT;
174  T u = static_cast<T>(safe_abs(a) / safe_abs(b));
175  // Negating int_min here is fine, since it's only undefined behavior if the
176  // signed division itself is.
177  return (a < 0 != b < 0) ? -u : u;
178 }
179 
180 template <typename T> static inline T mod(T a, T b) {
181  typedef typename make_unsigned<T>::type UT;
182  T u = static_cast<T>(safe_abs(a) % safe_abs(b));
183  // Negating int_min here is fine, since it's only undefined behavior if the
184  // signed mod itself is.
185  return a < 0 ? -u : u;
186 }
187 
188 template <typename T> static inline T divmod(T a, T b, T *rem) {
189  typedef typename make_unsigned<T>::type UT;
190  UT urem;
191  T uq = static_cast<T>(udivmod(safe_abs(a), safe_abs(b), &urem));
192 
193  // Negating int_min here is fine, since it's only undefined behavior if the
194  // signed division itself is.
195  *rem = a < 0 ? -urem : urem;
196  return (a < 0 != b < 0) ? -uq : uq;
197 }
make_unsigned< long >::type
unsigned long type
Definition: divmod.h:157
make_unsigned< long long >::type
unsigned long long type
Definition: divmod.h:160
make_unsigned< int >::type
unsigned type
Definition: divmod.h:154
div
div_t div(int numer, int denom)
make_unsigned
Definition: divmod.h:149
make_unsigned< signed char >::type
char type
Definition: divmod.h:151