1 /* Alpha mpn_divexact_1 -- mpn by limb exact division.
3 THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST
4 CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN
5 FUTURE GNU MP RELEASES.
7 Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
9 This file is part of the GNU MP Library.
11 The GNU MP Library is free software; you can redistribute it and/or modify
12 it under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or (at your
14 option) any later version.
16 The GNU MP Library is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19 License for more details.
21 You should have received a copy of the GNU Lesser General Public License
22 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
36 /* The dependent chain is as follows (the same as modexact), and this is
37 what the code runs as.
41 23 13 7 mulq q = y * inverse
42 23 15 7 umulh h = high (q * d)
46 The time to load src[i+1] and establish x hides under the umulh latency. */
49 mpn_divexact_1 (mp_ptr dst, mp_srcptr src, mp_size_t size, mp_limb_t divisor)
51 mp_limb_t inverse, lshift_mask, s, sr, s_next, c, h, x, y, q, dummy;
52 unsigned rshift, lshift;
55 ASSERT (divisor != 0);
56 ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size));
57 ASSERT_MPN (src, size);
58 ASSERT_LIMB (divisor);
60 s_next = *src++; /* src[0] */
64 if ((divisor & 1) == 0)
66 count_trailing_zeros (rshift, divisor);
67 lshift_mask = MP_LIMB_T_MAX;
71 binvert_limb (inverse, divisor);
76 sr = s_next >> rshift;
79 if (LIKELY (size != 0))
83 s_next = *src++; /* src[i+1] */
84 s = sr | ((s_next << lshift) & lshift_mask);
87 sr = s_next >> rshift;
93 umul_ppmm (h, dummy, q, divisor);
103 *dst = q; /* dst[size-1] */