| /*- | |
| * SPDX-License-Identifier: BSD-3-Clause | |
| * | |
| * Copyright (c) 1992, 1993 | |
| * The Regents of the University of California. All rights reserved. | |
| * | |
| * This software was developed by the Computer Systems Engineering group | |
| * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | |
| * contributed to Berkeley. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions | |
| * are met: | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution. | |
| * 3. Neither the name of the University nor the names of its contributors | |
| * may be used to endorse or promote products derived from this software | |
| * without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| * SUCH DAMAGE. | |
| */ | |
| #if defined(LIBC_SCCS) && !defined(lint) | |
| static char sccsid[] = "@(#)qdivrem.c 8.1 (Berkeley) 6/4/93"; | |
| #endif /* LIBC_SCCS and not lint */ | |
| #include <sys/cdefs.h> | |
| __FBSDID("$FreeBSD$"); | |
| /* | |
| * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed), | |
| * section 4.3.1, pp. 257--259. | |
| */ | |
| #include "quad.h" | |
| #define B (1L << HALF_BITS) /* digit base */ | |
| /* Combine two `digits' to make a single two-digit number. */ | |
| #define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b)) | |
| /* select a type for digits in base B: use unsigned short if they fit */ | |
| #if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff | |
| typedef unsigned short digit; | |
| #else | |
| typedef u_long digit; | |
| #endif | |
| /* | |
| * Shift p[0]..p[len] left `sh' bits, ignoring any bits that | |
| * `fall out' the left (there never will be any such anyway). | |
| * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS. | |
| */ | |
| static void | |
| shl(digit *p, int len, int sh) | |
| { | |
| int i; | |
| for (i = 0; i < len; i++) | |
| p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh)); | |
| p[i] = LHALF(p[i] << sh); | |
| } | |
| /* | |
| * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v. | |
| * | |
| * We do this in base 2-sup-HALF_BITS, so that all intermediate products | |
| * fit within u_long. As a consequence, the maximum length dividend and | |
| * divisor are 4 `digits' in this base (they are shorter if they have | |
| * leading zeros). | |
| */ | |
| u_quad_t | |
| __qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq) | |
| { | |
| union uu tmp; | |
| digit *u, *v, *q; | |
| digit v1, v2; | |
| u_long qhat, rhat, t; | |
| int m, n, d, j, i; | |
| digit uspace[5], vspace[5], qspace[5]; | |
| /* | |
| * Take care of special cases: divide by zero, and u < v. | |
| */ | |
| if (vq == 0) { | |
| /* divide by zero. */ | |
| static volatile const unsigned int zero = 0; | |
| tmp.ul[H] = tmp.ul[L] = 1 / zero; | |
| if (arq) | |
| *arq = uq; | |
| return (tmp.q); | |
| } | |
| if (uq < vq) { | |
| if (arq) | |
| *arq = uq; | |
| return (0); | |
| } | |
| u = &uspace[0]; | |
| v = &vspace[0]; | |
| q = &qspace[0]; | |
| /* | |
| * Break dividend and divisor into digits in base B, then | |
| * count leading zeros to determine m and n. When done, we | |
| * will have: | |
| * u = (u[1]u[2]...u[m+n]) sub B | |
| * v = (v[1]v[2]...v[n]) sub B | |
| * v[1] != 0 | |
| * 1 < n <= 4 (if n = 1, we use a different division algorithm) | |
| * m >= 0 (otherwise u < v, which we already checked) | |
| * m + n = 4 | |
| * and thus | |
| * m = 4 - n <= 2 | |
| */ | |
| tmp.uq = uq; | |
| u[0] = 0; | |
| u[1] = HHALF(tmp.ul[H]); | |
| u[2] = LHALF(tmp.ul[H]); | |
| u[3] = HHALF(tmp.ul[L]); | |
| u[4] = LHALF(tmp.ul[L]); | |
| tmp.uq = vq; | |
| v[1] = HHALF(tmp.ul[H]); | |
| v[2] = LHALF(tmp.ul[H]); | |
| v[3] = HHALF(tmp.ul[L]); | |
| v[4] = LHALF(tmp.ul[L]); | |
| for (n = 4; v[1] == 0; v++) { | |
| if (--n == 1) { | |
| u_long rbj; /* r*B+u[j] (not root boy jim) */ | |
| digit q1, q2, q3, q4; | |
| /* | |
| * Change of plan, per exercise 16. | |
| * r = 0; | |
| * for j = 1..4: | |
| * q[j] = floor((r*B + u[j]) / v), | |
| * r = (r*B + u[j]) % v; | |
| * We unroll this completely here. | |
| */ | |
| t = v[2]; /* nonzero, by definition */ | |
| q1 = u[1] / t; | |
| rbj = COMBINE(u[1] % t, u[2]); | |
| q2 = rbj / t; | |
| rbj = COMBINE(rbj % t, u[3]); | |
| q3 = rbj / t; | |
| rbj = COMBINE(rbj % t, u[4]); | |
| q4 = rbj / t; | |
| if (arq) | |
| *arq = rbj % t; | |
| tmp.ul[H] = COMBINE(q1, q2); | |
| tmp.ul[L] = COMBINE(q3, q4); | |
| return (tmp.q); | |
| } | |
| } | |
| /* | |
| * By adjusting q once we determine m, we can guarantee that | |
| * there is a complete four-digit quotient at &qspace[1] when | |
| * we finally stop. | |
| */ | |
| for (m = 4 - n; u[1] == 0; u++) | |
| m--; | |
| for (i = 4 - m; --i >= 0;) | |
| q[i] = 0; | |
| q += 4 - m; | |
| /* | |
| * Here we run Program D, translated from MIX to C and acquiring | |
| * a few minor changes. | |
| * | |
| * D1: choose multiplier 1 << d to ensure v[1] >= B/2. | |
| */ | |
| d = 0; | |
| for (t = v[1]; t < B / 2; t <<= 1) | |
| d++; | |
| if (d > 0) { | |
| shl(&u[0], m + n, d); /* u <<= d */ | |
| shl(&v[1], n - 1, d); /* v <<= d */ | |
| } | |
| /* | |
| * D2: j = 0. | |
| */ | |
| j = 0; | |
| v1 = v[1]; /* for D3 -- note that v[1..n] are constant */ | |
| v2 = v[2]; /* for D3 */ | |
| do { | |
| digit uj0, uj1, uj2; | |
| /* | |
| * D3: Calculate qhat (\^q, in TeX notation). | |
| * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and | |
| * let rhat = (u[j]*B + u[j+1]) mod v[1]. | |
| * While rhat < B and v[2]*qhat > rhat*B+u[j+2], | |
| * decrement qhat and increase rhat correspondingly. | |
| * Note that if rhat >= B, v[2]*qhat < rhat*B. | |
| */ | |
| uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */ | |
| uj1 = u[j + 1]; /* for D3 only */ | |
| uj2 = u[j + 2]; /* for D3 only */ | |
| if (uj0 == v1) { | |
| qhat = B; | |
| rhat = uj1; | |
| goto qhat_too_big; | |
| } else { | |
| u_long n = COMBINE(uj0, uj1); | |
| qhat = n / v1; | |
| rhat = n % v1; | |
| } | |
| while (v2 * qhat > COMBINE(rhat, uj2)) { | |
| qhat_too_big: | |
| qhat--; | |
| if ((rhat += v1) >= B) | |
| break; | |
| } | |
| /* | |
| * D4: Multiply and subtract. | |
| * The variable `t' holds any borrows across the loop. | |
| * We split this up so that we do not require v[0] = 0, | |
| * and to eliminate a final special case. | |
| */ | |
| for (t = 0, i = n; i > 0; i--) { | |
| t = u[i + j] - v[i] * qhat - t; | |
| u[i + j] = LHALF(t); | |
| t = (B - HHALF(t)) & (B - 1); | |
| } | |
| t = u[j] - t; | |
| u[j] = LHALF(t); | |
| /* | |
| * D5: test remainder. | |
| * There is a borrow if and only if HHALF(t) is nonzero; | |
| * in that (rare) case, qhat was too large (by exactly 1). | |
| * Fix it by adding v[1..n] to u[j..j+n]. | |
| */ | |
| if (HHALF(t)) { | |
| qhat--; | |
| for (t = 0, i = n; i > 0; i--) { /* D6: add back. */ | |
| t += u[i + j] + v[i]; | |
| u[i + j] = LHALF(t); | |
| t = HHALF(t); | |
| } | |
| u[j] = LHALF(u[j] + t); | |
| } | |
| q[j] = qhat; | |
| } while (++j <= m); /* D7: loop on j. */ | |
| /* | |
| * If caller wants the remainder, we have to calculate it as | |
| * u[m..m+n] >> d (this is at most n digits and thus fits in | |
| * u[m+1..m+n], but we may need more source digits). | |
| */ | |
| if (arq) { | |
| if (d) { | |
| for (i = m + n; i > m; --i) | |
| u[i] = (u[i] >> d) | | |
| LHALF(u[i - 1] << (HALF_BITS - d)); | |
| u[i] = 0; | |
| } | |
| tmp.ul[H] = COMBINE(uspace[1], uspace[2]); | |
| tmp.ul[L] = COMBINE(uspace[3], uspace[4]); | |
| *arq = tmp.q; | |
| } | |
| tmp.ul[H] = COMBINE(qspace[1], qspace[2]); | |
| tmp.ul[L] = COMBINE(qspace[3], qspace[4]); | |
| return (tmp.q); | |
| } |