1/* Exercise mpz_fac_ui and mpz_2fac_ui. 2 3Copyright 2000-2002, 2012, 2015 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library test suite. 6 7The GNU MP Library test suite is free software; you can redistribute it 8and/or modify it under the terms of the GNU General Public License as 9published by the Free Software Foundation; either version 3 of the License, 10or (at your option) any later version. 11 12The GNU MP Library test suite is distributed in the hope that it will be 13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15Public License for more details. 16 17You should have received a copy of the GNU General Public License along with 18the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 20#include <stdio.h> 21#include <stdlib.h> 22#include "gmp-impl.h" 23#include "tests.h" 24 25 26/* Usage: t-fac_ui [x|num] 27 28 With no arguments testing goes up to the initial value of "limit" below. 29 With a number argument tests are carried that far, or with a literal "x" 30 tests are continued without limit (this being meant only for development 31 purposes). */ 32 33 34int 35main (int argc, char *argv[]) 36{ 37 unsigned long n, m; 38 unsigned long limit = 2222; 39 mpz_t df[2], f, r; 40 41 tests_start (); 42 43 if (argc > 1 && argv[1][0] == 'x') 44 limit = ULONG_MAX; 45 else 46 TESTS_REPS (limit, argv, argc); 47 48 /* for small limb testing */ 49 limit = MIN (limit, MP_LIMB_T_MAX); 50 51 mpz_init_set_ui (df[0], 1); /* 0!! = 1 */ 52 mpz_init_set_ui (df[1], 1); /* -1!! = 1 */ 53 mpz_init_set_ui (f, 1); /* 0! = 1 */ 54 mpz_init (r); 55 56 for (n = 0, m = 0; n < limit; n++) 57 { 58 mpz_fac_ui (r, n); 59 MPZ_CHECK_FORMAT (r); 60 61 if (mpz_cmp (f, r) != 0) 62 { 63 printf ("mpz_fac_ui(%lu) wrong\n", n); 64 printf (" got "); mpz_out_str (stdout, 10, r); printf("\n"); 65 printf (" want "); mpz_out_str (stdout, 10, f); printf("\n"); 66 abort (); 67 } 68 69 mpz_2fac_ui (r, n); 70 MPZ_CHECK_FORMAT (r); 71 72 if (mpz_cmp (df[m], r) != 0) 73 { 74 printf ("mpz_2fac_ui(%lu) wrong\n", n); 75 printf (" got "); mpz_out_str (stdout, 10, r); printf("\n"); 76 printf (" want "); mpz_out_str (stdout, 10, df[m]); printf("\n"); 77 abort (); 78 } 79 80 m ^= 1; 81 mpz_mul_ui (df[m], df[m], n+1); /* (n+1)!! = (n-1)!! * (n+1) */ 82 mpz_mul_ui (f, f, n+1); /* (n+1)! = n! * (n+1) */ 83 } 84 85 n = 2097169; /* a prime = 1 mod 4*/ 86 if (n / 2 > MP_LIMB_T_MAX) 87 n = 131041; /* a smaller prime :-) */ 88 mpz_fac_ui (f, n / 2); /* ((n-1)/2)! */ 89 m = mpz_fdiv_ui (f, n); /* ((n-1)/2)! mod n*/ 90 mpz_set_ui (f, m); 91 mpz_mul_ui (f, f, m); /* (((n-1)/2)!)^2 */ 92 m = mpz_fdiv_ui (f, n); /* (((n-1)/2)!)^2 mod n*/ 93 if ( m != n - 1) 94 { 95 printf ("mpz_fac_ui(%lu) wrong\n", n / 2); 96 printf (" al-Haytham's theorem not verified: got %lu, expected %lu.\n", m, n - 1); 97 abort (); 98 } 99 100 mpz_clear (df[0]); 101 mpz_clear (df[1]); 102 mpz_clear (f); 103 mpz_clear (r); 104 105 tests_end (); 106 107 exit (0); 108} 109