bsqrtinv.c revision 1.1 1 1.1 mrg /* mpn_bsqrtinv, compute r such that r^2 * y = 1 (mod 2^{b+1}).
2 1.1 mrg
3 1.1 mrg Contributed to the GNU project by Martin Boij (as part of perfpow.c).
4 1.1 mrg
5 1.1 mrg Copyright 2009, 2010, 2012 Free Software Foundation, Inc.
6 1.1 mrg
7 1.1 mrg This file is part of the GNU MP Library.
8 1.1 mrg
9 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
10 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
11 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
12 1.1 mrg option) any later version.
13 1.1 mrg
14 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
15 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 1.1 mrg License for more details.
18 1.1 mrg
19 1.1 mrg You should have received a copy of the GNU Lesser General Public License
20 1.1 mrg along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */
21 1.1 mrg
22 1.1 mrg #include "gmp.h"
23 1.1 mrg #include "gmp-impl.h"
24 1.1 mrg
25 1.1 mrg /* Compute r such that r^2 * y = 1 (mod 2^{b+1}).
26 1.1 mrg Return non-zero if such an integer r exists.
27 1.1 mrg
28 1.1 mrg Iterates
29 1.1 mrg r' <-- (3r - r^3 y) / 2
30 1.1 mrg using Hensel lifting. Since we divide by two, the Hensel lifting is
31 1.1 mrg somewhat degenerates. Therefore, we lift from 2^b to 2^{b+1}-1.
32 1.1 mrg
33 1.1 mrg FIXME:
34 1.1 mrg (1) Simplify to do precision book-keeping in limbs rather than bits.
35 1.1 mrg
36 1.1 mrg (2) Rewrite iteration as
37 1.1 mrg r' <-- r - r (r^2 y - 1) / 2
38 1.1 mrg and take advantage of zero low part of r^2 y - 1.
39 1.1 mrg
40 1.1 mrg (3) Use wrap-around trick.
41 1.1 mrg
42 1.1 mrg (4) Use a small table to get starting value.
43 1.1 mrg */
44 1.1 mrg int
45 1.1 mrg mpn_bsqrtinv (mp_ptr rp, mp_srcptr yp, mp_bitcnt_t bnb, mp_ptr tp)
46 1.1 mrg {
47 1.1 mrg mp_ptr tp2, tp3;
48 1.1 mrg mp_limb_t k;
49 1.1 mrg mp_size_t bn, order[GMP_LIMB_BITS + 1];
50 1.1 mrg int i, d;
51 1.1 mrg
52 1.1 mrg ASSERT (bnb > 0);
53 1.1 mrg
54 1.1 mrg bn = 1 + bnb / GMP_LIMB_BITS;
55 1.1 mrg
56 1.1 mrg tp2 = tp + bn;
57 1.1 mrg tp3 = tp + 2 * bn;
58 1.1 mrg k = 3;
59 1.1 mrg
60 1.1 mrg rp[0] = 1;
61 1.1 mrg if (bnb == 1)
62 1.1 mrg {
63 1.1 mrg if ((yp[0] & 3) != 1)
64 1.1 mrg return 0;
65 1.1 mrg }
66 1.1 mrg else
67 1.1 mrg {
68 1.1 mrg if ((yp[0] & 7) != 1)
69 1.1 mrg return 0;
70 1.1 mrg
71 1.1 mrg d = 0;
72 1.1 mrg for (; bnb != 2; bnb = (bnb + 2) >> 1)
73 1.1 mrg order[d++] = bnb;
74 1.1 mrg
75 1.1 mrg for (i = d - 1; i >= 0; i--)
76 1.1 mrg {
77 1.1 mrg bnb = order[i];
78 1.1 mrg bn = 1 + bnb / GMP_LIMB_BITS;
79 1.1 mrg
80 1.1 mrg mpn_mul_1 (tp, rp, bn, k);
81 1.1 mrg
82 1.1 mrg mpn_powlo (tp2, rp, &k, 1, bn, tp3);
83 1.1 mrg mpn_mullo_n (rp, yp, tp2, bn);
84 1.1 mrg
85 1.1 mrg #if HAVE_NATIVE_mpn_rsh1sub_n
86 1.1 mrg mpn_rsh1sub_n (rp, tp, rp, bn);
87 1.1 mrg #else
88 1.1 mrg mpn_sub_n (tp2, tp, rp, bn);
89 1.1 mrg mpn_rshift (rp, tp2, bn, 1);
90 1.1 mrg #endif
91 1.1 mrg }
92 1.1 mrg }
93 1.1 mrg return 1;
94 1.1 mrg }
95