Annotation of OpenXM_contrib/gmp/mpn/generic/diveby3.c, Revision 1.1.1.2
1.1 maekawa 1: /* mpn_divexact_by3 -- mpn division by 3, expecting no remainder. */
2:
3: /*
1.1.1.2 ! ohara 4: Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
1.1 maekawa 5:
6: This file is part of the GNU MP Library.
7:
8: The GNU MP Library is free software; you can redistribute it and/or modify
9: it under the terms of the GNU Lesser General Public License as published by
10: the Free Software Foundation; either version 2.1 of the License, or (at your
11: option) any later version.
12:
13: The GNU MP Library is distributed in the hope that it will be useful, but
14: WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16: License for more details.
17:
18: You should have received a copy of the GNU Lesser General Public License
19: along with the GNU MP Library; see the file COPYING.LIB. If not, write to
20: the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
21: MA 02111-1307, USA.
22: */
23:
24:
25: #include "gmp.h"
26: #include "gmp-impl.h"
27:
28:
29: /* The "c += ..."s are adding the high limb of 3*l to c. That high limb
30: will be 0, 1 or 2. Doing two separate "+="s seems to turn out better
31: code on gcc (as of 2.95.2 at least).
32:
33: When a subtraction of a 0,1,2 carry value causes a borrow, that leaves a
1.1.1.2 ! ohara 34: limb value of either 0xFF...FF or 0xFF...FE and the multiply by
! 35: MODLIMB_INVERSE_3 gives 0x55...55 or 0xAA...AA respectively, producing a
! 36: further borrow of only 0 or 1 respectively. Hence the carry out of each
! 37: stage and for the return value is always only 0, 1 or 2.
! 38:
! 39: This implementation has each multiply successively dependent due to the
! 40: "l=s-c", but the multiply src[i]*MODLIMB_INVERSE_3 could be scheduled
! 41: back as far as desired, and the effect of the "-c" applied by subtracting
! 42: 0, 1 or 2 copies or MODLIMB_INVERSE_3 from the product. With some good
! 43: scheduling in assembler it might come down to a dependent chain of maybe
! 44: 5 simple operations per limb. */
1.1 maekawa 45:
46: mp_limb_t
47: mpn_divexact_by3c (mp_ptr dst, mp_srcptr src, mp_size_t size, mp_limb_t c)
48: {
49: mp_size_t i;
50:
51: ASSERT (size >= 1);
1.1.1.2 ! ohara 52: ASSERT (c == 0 || c == 1 || c == 2);
! 53: ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size));
1.1 maekawa 54:
55: i = 0;
56: do
57: {
58: mp_limb_t l, s;
59:
60: s = src[i];
61: l = s - c;
62: c = (l > s);
63:
1.1.1.2 ! ohara 64: l = (l * MODLIMB_INVERSE_3) & GMP_NUMB_MASK;
1.1 maekawa 65: dst[i] = l;
66:
1.1.1.2 ! ohara 67: c += (l > GMP_NUMB_MAX/3);
! 68: c += (l > (GMP_NUMB_MAX/3)*2);
1.1 maekawa 69: }
70: while (++i < size);
71:
72: return c;
73: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>