Calculate the magic numbers required to implement a signed integer division by a constant as a sequence of multiplies, adds and shifts. Requires that the divisor not be 0, 1, or -1. Taken from "Hacker's Delight", Henry S. Warren, Jr., chapter 10.
| 1222 | /// the divisor not be 0, 1, or -1. Taken from "Hacker's Delight", Henry S. |
| 1223 | /// Warren, Jr., chapter 10. |
| 1224 | APInt::ms APInt::magic() const { |
| 1225 | const APInt& d = *this; |
| 1226 | unsigned p; |
| 1227 | APInt ad, anc, delta, q1, r1, q2, r2, t; |
| 1228 | APInt signedMin = APInt::getSignedMinValue(d.getBitWidth()); |
| 1229 | struct ms mag; |
| 1230 | |
| 1231 | ad = d.abs(); |
| 1232 | t = signedMin + (d.lshr(d.getBitWidth() - 1)); |
| 1233 | anc = t - 1 - t.urem(ad); // absolute value of nc |
| 1234 | p = d.getBitWidth() - 1; // initialize p |
| 1235 | q1 = signedMin.udiv(anc); // initialize q1 = 2p/abs(nc) |
| 1236 | r1 = signedMin - q1*anc; // initialize r1 = rem(2p,abs(nc)) |
| 1237 | q2 = signedMin.udiv(ad); // initialize q2 = 2p/abs(d) |
| 1238 | r2 = signedMin - q2*ad; // initialize r2 = rem(2p,abs(d)) |
| 1239 | do { |
| 1240 | p = p + 1; |
| 1241 | q1 = q1<<1; // update q1 = 2p/abs(nc) |
| 1242 | r1 = r1<<1; // update r1 = rem(2p/abs(nc)) |
| 1243 | if (r1.uge(anc)) { // must be unsigned comparison |
| 1244 | q1 = q1 + 1; |
| 1245 | r1 = r1 - anc; |
| 1246 | } |
| 1247 | q2 = q2<<1; // update q2 = 2p/abs(d) |
| 1248 | r2 = r2<<1; // update r2 = rem(2p/abs(d)) |
| 1249 | if (r2.uge(ad)) { // must be unsigned comparison |
| 1250 | q2 = q2 + 1; |
| 1251 | r2 = r2 - ad; |
| 1252 | } |
| 1253 | delta = ad - r2; |
| 1254 | } while (q1.ult(delta) || (q1 == delta && r1 == 0)); |
| 1255 | |
| 1256 | mag.m = q2 + 1; |
| 1257 | if (d.isNegative()) mag.m = -mag.m; // resulting magic number |
| 1258 | mag.s = p - d.getBitWidth(); // resulting shift |
| 1259 | return mag; |
| 1260 | } |
| 1261 | |
| 1262 | /// Calculate the magic numbers required to implement an unsigned integer |
| 1263 | /// division by a constant as a sequence of multiplies, adds and shifts. |
nothing calls this directly
no test coverage detected