Austin Schuh | dace2a6 | 2020-08-18 10:56:48 -0700 | [diff] [blame] | 1 | /* Test mpn_fib2m. |
| 2 | |
| 3 | Copyright 2018 Free Software Foundation, Inc. |
| 4 | |
| 5 | This file is part of the GNU MP Library test suite. |
| 6 | |
| 7 | The GNU MP Library test suite is free software; you can redistribute it |
| 8 | and/or modify it under the terms of the GNU General Public License as |
| 9 | published by the Free Software Foundation; either version 3 of the License, |
| 10 | or (at your option) any later version. |
| 11 | |
| 12 | The GNU MP Library test suite is distributed in the hope that it will be |
| 13 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
| 15 | Public License for more details. |
| 16 | |
| 17 | You should have received a copy of the GNU General Public License along with |
| 18 | the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ |
| 19 | |
| 20 | #include <stdio.h> |
| 21 | #include <stdlib.h> |
| 22 | |
| 23 | #include "gmp-impl.h" |
| 24 | #include "tests.h" |
| 25 | |
| 26 | #define MAX_K_BITS 16 |
| 27 | #define MAX_K (1L << MAX_K_BITS) |
| 28 | #define MIN_K 1 |
| 29 | |
| 30 | #define MAX_MN 20 |
| 31 | #define MAX_KN 30 |
| 32 | |
| 33 | #define COUNT 200 |
| 34 | |
| 35 | static int |
| 36 | test_fib2_fib2m (int count, gmp_randstate_ptr rands) |
| 37 | { |
| 38 | int test; |
| 39 | mp_ptr fk, fks1, fkm, fks1m, mp, qp; |
| 40 | mp_size_t mn, fn, size, max_mn; |
| 41 | TMP_DECL; |
| 42 | |
| 43 | size = MPN_FIB2_SIZE (MAX_K); |
| 44 | max_mn = size / 4 + 10; |
| 45 | ASSERT (max_mn < size); |
| 46 | |
| 47 | TMP_MARK; |
| 48 | fk = TMP_ALLOC_LIMBS (size); |
| 49 | fks1 = TMP_ALLOC_LIMBS (size); |
| 50 | qp = TMP_ALLOC_LIMBS (size); |
| 51 | mp = TMP_ALLOC_LIMBS (max_mn); |
| 52 | fkm = 1 + TMP_ALLOC_LIMBS (max_mn * 2 + 1 + 2); |
| 53 | fks1m = 1 + TMP_ALLOC_LIMBS (max_mn * 2 + 1 + 2); |
| 54 | |
| 55 | for (test = 1; test <= count; ++test) |
| 56 | { |
| 57 | mp_limb_t fk_before, fk_after, fk1_before, fk1_after; |
| 58 | int signflip; |
| 59 | unsigned long k; |
| 60 | |
| 61 | k = MIN_K + |
| 62 | gmp_urandomm_ui (rands, test < MAX_K_BITS ? |
| 63 | MAX_K >> test : (MAX_K - MIN_K)); |
| 64 | |
| 65 | fn = mpn_fib2_ui (fk, fks1, k); |
| 66 | do { |
| 67 | mn = gmp_urandomm_ui (rands, MAX_K) % (fn / 4 + 10); |
| 68 | } while (mn == 0); |
| 69 | ASSERT (mn <= max_mn); |
| 70 | mpn_random2 (mp, mn); |
| 71 | ASSERT (mp [mn - 1] != 0); |
| 72 | |
| 73 | if (fn >= mn) |
| 74 | { |
| 75 | mpn_tdiv_qr (qp, fk, 0, fk, fn, mp, mn); |
| 76 | mpn_tdiv_qr (qp, fks1, 0, fks1, fn, mp, mn); |
| 77 | } |
| 78 | else |
| 79 | { |
| 80 | MPN_ZERO (fk + fn, mn - fn); |
| 81 | MPN_ZERO (fks1 + fn, mn - fn); |
| 82 | } |
| 83 | |
| 84 | mpn_random2 (fkm - 1, 2*mn+1+2); |
| 85 | fk_before = fkm [-1]; |
| 86 | fk_after = fkm [2 * mn + 1]; |
| 87 | |
| 88 | mpn_random2 (fks1m - 1, 2*mn+1+2); |
| 89 | fk1_before = fks1m [-1]; |
| 90 | fk1_after = fks1m [2 * mn + 1]; |
| 91 | |
| 92 | qp [0] = k; |
| 93 | signflip = mpn_fib2m (fkm, fks1m, qp, 1, mp, mn); |
| 94 | if (fkm [-1] != fk_before || fkm [2 * mn + 1] != fk_after |
| 95 | || fks1m [-1] != fk1_before || fks1m [2 * mn + 1] != fk1_after) |
| 96 | { |
| 97 | printf ("REDZONE violation in test %d, k = %lu, mn = %u\n", |
| 98 | test, k, (unsigned) mn); |
| 99 | if (fkm[-1] != fk_before) |
| 100 | { |
| 101 | printf ("before fkm:"); mpn_dump (fkm - 1, 1); |
| 102 | printf ("keep: "); mpn_dump (&fk_before, 1); |
| 103 | } |
| 104 | if (fkm[2 * mn + 1] != fk_after) |
| 105 | { |
| 106 | printf ("after fkm:"); mpn_dump (fkm + 2 * mn + 1, 1); |
| 107 | printf ("keep: "); mpn_dump (&fk_after, 1); |
| 108 | } |
| 109 | if (fks1m[-1] != fk1_before) |
| 110 | { |
| 111 | printf ("before fks1m:"); mpn_dump (fks1m - 1, 1); |
| 112 | printf ("keep: "); mpn_dump (&fk1_before, 1); |
| 113 | } |
| 114 | if (fks1m[2 * mn + 1] != fk1_after) |
| 115 | { |
| 116 | printf ("after fks1m:"); mpn_dump (fks1m + 2 * mn + 1, 1); |
| 117 | printf ("keep: "); mpn_dump (&fk1_after, 1); |
| 118 | } |
| 119 | abort(); |
| 120 | } |
| 121 | |
| 122 | if (mpn_cmp (fkm, fk, mn) != 0) |
| 123 | { |
| 124 | if (mpn_sub_n (fk, mp, fk, mn) || mpn_cmp (fkm, fk, mn) != 0) |
| 125 | { |
| 126 | printf ("ERROR(k) in test %d, k = %lu, mn = %u\n", |
| 127 | test, k, (unsigned) mn); |
| 128 | mpn_dump (fk, mn); |
| 129 | mpn_dump (fkm, mn); |
| 130 | mpn_dump (mp, mn); |
| 131 | abort(); |
| 132 | } |
| 133 | signflip ^= 1; |
| 134 | } |
| 135 | |
| 136 | if (mpn_cmp (fks1m, fks1, mn) != 0) |
| 137 | { |
| 138 | if (mpn_sub_n (fks1, mp, fks1, mn) || mpn_cmp (fks1m, fks1, mn) != 0) |
| 139 | { |
| 140 | printf ("ERROR(k-1) in test %d, k = %lu, mn = %u\n", |
| 141 | test, k, (unsigned) mn); |
| 142 | mpn_dump (fks1, mn); |
| 143 | mpn_dump (fks1m, mn); |
| 144 | mpn_dump (mp, mn); |
| 145 | abort(); |
| 146 | } |
| 147 | signflip ^= 1; |
| 148 | } |
| 149 | |
| 150 | if (signflip != 0 && ! mpn_zero_p (fks1m, mn) && ! mpn_zero_p (fkm, mn)) |
| 151 | { |
| 152 | if ((mp [0] & 1) == 0) /* Should we test only odd modulus-es? */ |
| 153 | { |
| 154 | if (! mpn_lshift (fks1m, fks1m, mn, 1) && |
| 155 | mpn_cmp (mp, fks1m, mn) == 0) |
| 156 | continue; |
| 157 | if (! mpn_lshift (fkm, fkm, mn, 1) && |
| 158 | mpn_cmp (mp, fkm, mn) == 0) |
| 159 | continue; |
| 160 | } |
| 161 | printf ("ERROR(sign) in test %d, k = %lu, mn = %u\n", |
| 162 | test, k, (unsigned) mn); |
| 163 | abort(); |
| 164 | } |
| 165 | } |
| 166 | TMP_FREE; |
| 167 | return 0; |
| 168 | } |
| 169 | |
| 170 | static int |
| 171 | test_fib2m_2exp (int count, gmp_randstate_ptr rands) |
| 172 | { |
| 173 | int test; |
| 174 | mp_ptr fka, fks1a, fkb, fks1b, mp, kp; |
| 175 | TMP_DECL; |
| 176 | |
| 177 | TMP_MARK; |
| 178 | kp = TMP_ALLOC_LIMBS (MAX_KN); |
| 179 | mp = TMP_ALLOC_LIMBS (MAX_MN); |
| 180 | fka = 1 + TMP_ALLOC_LIMBS (MAX_MN * 2 + 1 + 2); |
| 181 | fks1a = 1 + TMP_ALLOC_LIMBS (MAX_MN * 2 + 1 + 2); |
| 182 | fkb = 1 + TMP_ALLOC_LIMBS (MAX_MN * 2 + 1 + 2); |
| 183 | fks1b = 1 + TMP_ALLOC_LIMBS (MAX_MN * 2 + 1 + 2); |
| 184 | |
| 185 | for (test = 1; test <= count; ++test) |
| 186 | { |
| 187 | mp_limb_t fka_before, fka_after, fk1a_before, fk1a_after; |
| 188 | mp_limb_t fkb_before, fkb_after, fk1b_before, fk1b_after; |
| 189 | mp_size_t mn, kn; |
| 190 | int signflip; |
| 191 | mp_bitcnt_t exp2; |
| 192 | |
| 193 | mn = gmp_urandomm_ui (rands, MAX_MN - 1) + 1; |
| 194 | mpn_random2 (mp, mn); |
| 195 | |
| 196 | exp2 = MIN_K + 1 + gmp_urandomm_ui (rands, MAX_KN * GMP_NUMB_BITS - MIN_K - 1); |
| 197 | |
| 198 | kn = BITS_TO_LIMBS (exp2); |
| 199 | MPN_ZERO (kp, kn - 1); |
| 200 | kp [kn - 1] = CNST_LIMB (1) << ((exp2 - 1) % GMP_NUMB_BITS); |
| 201 | |
| 202 | mpn_random2 (fka - 1, 2*mn+1+2); |
| 203 | fka_before = fka [-1]; |
| 204 | fka_after = fka [2 * mn + 1]; |
| 205 | |
| 206 | mpn_random2 (fks1a - 1, 2*mn+1+2); |
| 207 | fk1a_before = fks1a [-1]; |
| 208 | fk1a_after = fks1a [2 * mn + 1]; |
| 209 | |
| 210 | signflip = mpn_fib2m (fka, fks1a, kp, kn, mp, mn); |
| 211 | if (fka [-1] != fka_before || fka [2 * mn + 1] != fka_after |
| 212 | || fks1a [-1] != fk1a_before || fks1a [2 * mn + 1] != fk1a_after) |
| 213 | { |
| 214 | printf ("REDZONE(a) violation in test %d, exp2 = %lu\n", test, exp2); |
| 215 | if (fka[-1] != fka_before) |
| 216 | { |
| 217 | printf ("before fka:"); mpn_dump (fka - 1, 1); |
| 218 | printf ("keep: "); mpn_dump (&fka_before, 1); |
| 219 | } |
| 220 | if (fka[2 * mn + 1] != fka_after) |
| 221 | { |
| 222 | printf ("after fka:"); mpn_dump (fka + 2 * mn + 1, 1); |
| 223 | printf ("keep: "); mpn_dump (&fka_after, 1); |
| 224 | } |
| 225 | if (fks1a[-1] != fk1a_before) |
| 226 | { |
| 227 | printf ("before fks1a:"); mpn_dump (fks1a - 1, 1); |
| 228 | printf ("keep: "); mpn_dump (&fk1a_before, 1); |
| 229 | } |
| 230 | if (fks1a[2 * mn + 1] != fk1a_after) |
| 231 | { |
| 232 | printf ("after fks1a:"); mpn_dump (fks1a + 2 * mn + 1, 1); |
| 233 | printf ("keep: "); mpn_dump (&fk1a_after, 1); |
| 234 | } |
| 235 | abort(); |
| 236 | } |
| 237 | |
| 238 | if (signflip && ! mpn_zero_p (fks1a, mn)) |
| 239 | mpn_sub_n (fks1a, mp, fks1a, mn); |
| 240 | if (mpn_sub_n (fka, fka, fks1a, mn)) |
| 241 | ASSERT_CARRY (mpn_add_n (fka, fka, mp, mn)); |
| 242 | |
| 243 | mpn_sub_1 (kp, kp, kn, 1); |
| 244 | ASSERT (exp2 % GMP_NUMB_BITS == 1 || kp [kn - 1] != 0); |
| 245 | kn -= kp [kn - 1] == 0; |
| 246 | |
| 247 | mpn_random2 (fkb - 1, 2*mn+1+2); |
| 248 | fkb_before = fkb [-1]; |
| 249 | fkb_after = fkb [2 * mn + 1]; |
| 250 | |
| 251 | mpn_random2 (fks1b - 1, 2*mn+1+2); |
| 252 | fk1b_before = fks1b [-1]; |
| 253 | fk1b_after = fks1b [2 * mn + 1]; |
| 254 | |
| 255 | signflip = mpn_fib2m (fkb, fks1b, kp, kn, mp, mn); |
| 256 | if (fkb [-1] != fkb_before || fkb [2 * mn + 1] != fkb_after |
| 257 | || fks1b [-1] != fk1b_before || fks1b [2 * mn + 1] != fk1b_after) |
| 258 | { |
| 259 | printf ("REDZONE(b) violation in test %d, exp2 = %lu\n", test, exp2); |
| 260 | if (fkb[-1] != fkb_before) |
| 261 | { |
| 262 | printf ("before fkb:"); mpn_dump (fkb - 1, 1); |
| 263 | printf ("keep: "); mpn_dump (&fkb_before, 1); |
| 264 | } |
| 265 | if (fkb[2 * mn + 1] != fkb_after) |
| 266 | { |
| 267 | printf ("after fkb:"); mpn_dump (fkb + 2 * mn + 1, 1); |
| 268 | printf ("keep: "); mpn_dump (&fkb_after, 1); |
| 269 | } |
| 270 | if (fks1b[-1] != fk1b_before) |
| 271 | { |
| 272 | printf ("before fks1b:"); mpn_dump (fks1b - 1, 1); |
| 273 | printf ("keep: "); mpn_dump (&fk1b_before, 1); |
| 274 | } |
| 275 | if (fks1b[2 * mn + 1] != fk1b_after) |
| 276 | { |
| 277 | printf ("after fks1b:"); mpn_dump (fks1b + 2 * mn + 1, 1); |
| 278 | printf ("keep: "); mpn_dump (&fk1b_after, 1); |
| 279 | } |
| 280 | abort(); |
| 281 | } |
| 282 | |
| 283 | if (mpn_cmp (fks1a, fkb, mn) != 0) |
| 284 | { |
| 285 | if (mpn_sub_n (fkb, mp, fkb, mn) || mpn_cmp (fks1a, fkb, mn) != 0) |
| 286 | { |
| 287 | printf ("ERROR(k) in test %d, exp2 = %lu\n", test, exp2); |
| 288 | mpn_dump (fks1a, mn); |
| 289 | mpn_dump (fkb, mn); |
| 290 | mpn_dump (mp, mn); |
| 291 | abort(); |
| 292 | } |
| 293 | signflip ^= 1; |
| 294 | } |
| 295 | |
| 296 | if (mpn_cmp (fka, fks1b, mn) != 0) |
| 297 | { |
| 298 | if (mpn_sub_n (fks1b, mp, fks1b, mn) || mpn_cmp (fka, fks1b, mn) != 0) |
| 299 | { |
| 300 | printf ("ERROR(k-1) in test %d, exp2 = %lu\n", test, exp2); |
| 301 | mpn_dump (fka, mn); |
| 302 | mpn_dump (fks1b, mn); |
| 303 | mpn_dump (mp, mn); |
| 304 | abort(); |
| 305 | } |
| 306 | signflip ^= 1; |
| 307 | } |
| 308 | |
| 309 | if (signflip != 0 && ! mpn_zero_p (fks1b, mn) && ! mpn_zero_p (fkb, mn)) |
| 310 | { |
| 311 | if ((mp [0] & 1) == 0) /* Should we test only odd modulus-es? */ |
| 312 | { |
| 313 | if (! mpn_lshift (fks1b, fks1b, mn, 1) && |
| 314 | mpn_cmp (mp, fks1b, mn) == 0) |
| 315 | continue; |
| 316 | if (! mpn_lshift (fkb, fkb, mn, 1) && |
| 317 | mpn_cmp (mp, fkb, mn) == 0) |
| 318 | continue; |
| 319 | } |
| 320 | printf ("ERROR(sign) in test %d, exp2 = %lu\n", |
| 321 | test, exp2); |
| 322 | abort(); |
| 323 | } |
| 324 | } |
| 325 | TMP_FREE; |
| 326 | return 0; |
| 327 | } |
| 328 | |
| 329 | int |
| 330 | main (int argc, char **argv) |
| 331 | { |
| 332 | int count = COUNT; |
| 333 | gmp_randstate_ptr rands; |
| 334 | |
| 335 | tests_start (); |
| 336 | TESTS_REPS (count, argv, argc); |
| 337 | rands = RANDS; |
| 338 | |
| 339 | test_fib2_fib2m (count / 2, rands); |
| 340 | test_fib2m_2exp (count / 2, rands); |
| 341 | |
| 342 | tests_end (); |
| 343 | exit (0); |
| 344 | } |