1 1.1 mrg /* mpn_fib2m -- calculate Fibonacci numbers, modulo m. 2 1.1 mrg 3 1.1 mrg Contributed to the GNU project by Marco Bodrato. 4 1.1 mrg 5 1.1 mrg THE FUNCTIONS IN THIS FILE ARE FOR INTERNAL USE ONLY. THEY'RE ALMOST 6 1.1 mrg CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR COMPLETELY IN 7 1.1 mrg FUTURE GNU MP RELEASES. 8 1.1 mrg 9 1.1 mrg Copyright 2001, 2002, 2005, 2009, 2018 Free Software Foundation, Inc. 10 1.1 mrg 11 1.1 mrg This file is part of the GNU MP Library. 12 1.1 mrg 13 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify 14 1.1 mrg it under the terms of either: 15 1.1 mrg 16 1.1 mrg * the GNU Lesser General Public License as published by the Free 17 1.1 mrg Software Foundation; either version 3 of the License, or (at your 18 1.1 mrg option) any later version. 19 1.1 mrg 20 1.1 mrg or 21 1.1 mrg 22 1.1 mrg * the GNU General Public License as published by the Free Software 23 1.1 mrg Foundation; either version 2 of the License, or (at your option) any 24 1.1 mrg later version. 25 1.1 mrg 26 1.1 mrg or both in parallel, as here. 27 1.1 mrg 28 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but 29 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 30 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 31 1.1 mrg for more details. 32 1.1 mrg 33 1.1 mrg You should have received copies of the GNU General Public License and the 34 1.1 mrg GNU Lesser General Public License along with the GNU MP Library. If not, 35 1.1 mrg see https://www.gnu.org/licenses/. */ 36 1.1 mrg 37 1.1 mrg #include <stdio.h> 38 1.1 mrg #include "gmp-impl.h" 39 1.1 mrg 40 1.1.1.2 mrg 41 1.1.1.2 mrg #if HAVE_NATIVE_mpn_rsblsh1_n || HAVE_NATIVE_mpn_sublsh1_n 42 1.1.1.2 mrg #else 43 1.1 mrg /* Stores |{ap,n}-{bp,n}| in {rp,n}, 44 1.1 mrg returns the sign of {ap,n}-{bp,n}. */ 45 1.1 mrg static int 46 1.1 mrg abs_sub_n (mp_ptr rp, mp_srcptr ap, mp_srcptr bp, mp_size_t n) 47 1.1 mrg { 48 1.1 mrg mp_limb_t x, y; 49 1.1 mrg while (--n >= 0) 50 1.1 mrg { 51 1.1 mrg x = ap[n]; 52 1.1 mrg y = bp[n]; 53 1.1 mrg if (x != y) 54 1.1 mrg { 55 1.1 mrg ++n; 56 1.1 mrg if (x > y) 57 1.1 mrg { 58 1.1 mrg ASSERT_NOCARRY (mpn_sub_n (rp, ap, bp, n)); 59 1.1 mrg return 1; 60 1.1 mrg } 61 1.1 mrg else 62 1.1 mrg { 63 1.1 mrg ASSERT_NOCARRY (mpn_sub_n (rp, bp, ap, n)); 64 1.1 mrg return -1; 65 1.1 mrg } 66 1.1 mrg } 67 1.1 mrg rp[n] = 0; 68 1.1 mrg } 69 1.1 mrg return 0; 70 1.1 mrg } 71 1.1.1.2 mrg #endif 72 1.1 mrg 73 1.1 mrg /* Computes at most count terms of the sequence needed by the 74 1.1 mrg Lucas-Lehmer-Riesel test, indexing backward: 75 1.1 mrg L_i = L_{i+1}^2 - 2 76 1.1 mrg 77 1.1 mrg The sequence is computed modulo M = {mp, mn}. 78 1.1 mrg The starting point is given in L_{count+1} = {lp, mn}. 79 1.1 mrg The scratch pointed by sp, needs a space of at least 3 * mn + 1 limbs. 80 1.1 mrg 81 1.1 mrg Returns the index i>0 if L_i = 0 (mod M) is found within the 82 1.1 mrg computed count terms of the sequence. Otherwise it returns zero. 83 1.1 mrg 84 1.1 mrg Note: (+/-2)^2-2=2, (+/-1)^2-2=-1, 0^2-2=-2 85 1.1 mrg */ 86 1.1 mrg 87 1.1 mrg static mp_bitcnt_t 88 1.1 mrg mpn_llriter (mp_ptr lp, mp_srcptr mp, mp_size_t mn, mp_bitcnt_t count, mp_ptr sp) 89 1.1 mrg { 90 1.1 mrg do 91 1.1 mrg { 92 1.1 mrg mpn_sqr (sp, lp, mn); 93 1.1 mrg mpn_tdiv_qr (sp + 2 * mn, lp, 0, sp, 2 * mn, mp, mn); 94 1.1 mrg if (lp[0] < 5) 95 1.1 mrg { 96 1.1 mrg /* If L^2 % M < 5, |L^2 % M - 2| <= 2 */ 97 1.1 mrg if (mn == 1 || mpn_zero_p (lp + 1, mn - 1)) 98 1.1 mrg return (lp[0] == 2) ? count : 0; 99 1.1 mrg else 100 1.1 mrg MPN_DECR_U (lp, mn, 2); 101 1.1 mrg } 102 1.1 mrg else 103 1.1 mrg lp[0] -= 2; 104 1.1 mrg } while (--count != 0); 105 1.1 mrg return 0; 106 1.1 mrg } 107 1.1 mrg 108 1.1 mrg /* Store the Lucas' number L[n] at lp (maybe), computed modulo m. lp 109 1.1 mrg and scratch should have room for mn*2+1 limbs. 110 1.1 mrg 111 1.1 mrg Returns the size of L[n] normally. 112 1.1 mrg 113 1.1 mrg If F[n] is zero modulo m, or L[n] is, returns 0 and lp is 114 1.1 mrg undefined. 115 1.1 mrg */ 116 1.1 mrg 117 1.1 mrg static mp_size_t 118 1.1 mrg mpn_lucm (mp_ptr lp, mp_srcptr np, mp_size_t nn, mp_srcptr mp, mp_size_t mn, mp_ptr scratch) 119 1.1 mrg { 120 1.1 mrg int neg; 121 1.1 mrg mp_limb_t cy; 122 1.1 mrg 123 1.1 mrg ASSERT (! MPN_OVERLAP_P (lp, MAX(2*mn+1,5), scratch, MAX(2*mn+1,5))); 124 1.1 mrg ASSERT (nn > 0); 125 1.1 mrg 126 1.1 mrg neg = mpn_fib2m (lp, scratch, np, nn, mp, mn); 127 1.1 mrg 128 1.1 mrg /* F[n] = +/-{lp, mn}, F[n-1] = +/-{scratch, mn} */ 129 1.1 mrg if (mpn_zero_p (lp, mn)) 130 1.1 mrg return 0; 131 1.1 mrg 132 1.1 mrg if (neg) /* One sign is opposite, use sub instead of add. */ 133 1.1 mrg { 134 1.1 mrg #if HAVE_NATIVE_mpn_rsblsh1_n || HAVE_NATIVE_mpn_sublsh1_n 135 1.1 mrg #if HAVE_NATIVE_mpn_rsblsh1_n 136 1.1 mrg cy = mpn_rsblsh1_n (lp, lp, scratch, mn); /* L[n] = +/-(2F[n-1]-(-F[n])) */ 137 1.1 mrg #else 138 1.1 mrg cy = mpn_sublsh1_n (lp, lp, scratch, mn); /* L[n] = -/+(F[n]-(-2F[n-1])) */ 139 1.1 mrg if (cy != 0) 140 1.1 mrg cy = mpn_add_n (lp, lp, mp, mn) - cy; 141 1.1 mrg #endif 142 1.1 mrg if (cy > 1) 143 1.1 mrg cy += mpn_add_n (lp, lp, mp, mn); 144 1.1 mrg #else 145 1.1 mrg cy = mpn_lshift (scratch, scratch, mn, 1); /* 2F[n-1] */ 146 1.1 mrg if (UNLIKELY (cy)) 147 1.1 mrg cy -= mpn_sub_n (lp, scratch, lp, mn); /* L[n] = +/-(2F[n-1]-(-F[n])) */ 148 1.1 mrg else 149 1.1 mrg abs_sub_n (lp, lp, scratch, mn); 150 1.1 mrg #endif 151 1.1 mrg ASSERT (cy <= 1); 152 1.1 mrg } 153 1.1 mrg else 154 1.1 mrg { 155 1.1 mrg #if HAVE_NATIVE_mpn_addlsh1_n 156 1.1 mrg cy = mpn_addlsh1_n (lp, lp, scratch, mn); /* L[n] = +/-(2F[n-1]+F[n])) */ 157 1.1 mrg #else 158 1.1 mrg cy = mpn_lshift (scratch, scratch, mn, 1); 159 1.1 mrg cy+= mpn_add_n (lp, lp, scratch, mn); 160 1.1 mrg #endif 161 1.1 mrg ASSERT (cy <= 2); 162 1.1 mrg } 163 1.1 mrg while (cy || mpn_cmp (lp, mp, mn) >= 0) 164 1.1 mrg cy -= mpn_sub_n (lp, lp, mp, mn); 165 1.1 mrg MPN_NORMALIZE (lp, mn); 166 1.1 mrg return mn; 167 1.1 mrg } 168 1.1 mrg 169 1.1 mrg int 170 1.1 mrg mpn_strongfibo (mp_srcptr mp, mp_size_t mn, mp_ptr scratch) 171 1.1 mrg { 172 1.1 mrg mp_ptr lp, sp; 173 1.1 mrg mp_size_t en; 174 1.1 mrg mp_bitcnt_t b0; 175 1.1 mrg TMP_DECL; 176 1.1 mrg 177 1.1 mrg #if GMP_NUMB_BITS % 4 == 0 178 1.1 mrg b0 = mpn_scan0 (mp, 0); 179 1.1 mrg #else 180 1.1 mrg { 181 1.1 mrg mpz_t m = MPZ_ROINIT_N(mp, mn); 182 1.1 mrg b0 = mpz_scan0 (m, 0); 183 1.1 mrg } 184 1.1 mrg if (UNLIKELY (b0 == mn * GMP_NUMB_BITS)) 185 1.1 mrg { 186 1.1 mrg en = 1; 187 1.1 mrg scratch [0] = 1; 188 1.1 mrg } 189 1.1 mrg else 190 1.1 mrg #endif 191 1.1 mrg { 192 1.1 mrg int cnt = b0 % GMP_NUMB_BITS; 193 1.1 mrg en = b0 / GMP_NUMB_BITS; 194 1.1 mrg if (LIKELY (cnt != 0)) 195 1.1 mrg mpn_rshift (scratch, mp + en, mn - en, cnt); 196 1.1 mrg else 197 1.1 mrg MPN_COPY (scratch, mp + en, mn - en); 198 1.1 mrg en = mn - en; 199 1.1 mrg scratch [0] |= 1; 200 1.1 mrg en -= scratch [en - 1] == 0; 201 1.1 mrg } 202 1.1 mrg TMP_MARK; 203 1.1 mrg 204 1.1 mrg lp = TMP_ALLOC_LIMBS (4 * mn + 6); 205 1.1 mrg sp = lp + 2 * mn + 3; 206 1.1 mrg en = mpn_lucm (sp, scratch, en, mp, mn, lp); 207 1.1 mrg if (en != 0 && LIKELY (--b0 != 0)) 208 1.1 mrg { 209 1.1 mrg mpn_sqr (lp, sp, en); 210 1.1 mrg lp [0] |= 2; /* V^2 + 2 */ 211 1.1 mrg if (LIKELY (2 * en >= mn)) 212 1.1 mrg mpn_tdiv_qr (sp, lp, 0, lp, 2 * en, mp, mn); 213 1.1 mrg else 214 1.1 mrg MPN_ZERO (lp + 2 * en, mn - 2 * en); 215 1.1 mrg if (! mpn_zero_p (lp, mn) && LIKELY (--b0 != 0)) 216 1.1 mrg b0 = mpn_llriter (lp, mp, mn, b0, lp + mn + 1); 217 1.1 mrg } 218 1.1 mrg TMP_FREE; 219 1.1 mrg return (b0 != 0); 220 1.1 mrg } 221