1 /* test mpz_divisible_p and mpz_divisible_ui_p 2 3 Copyright 2001, 2009 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library. 6 7 The GNU MP Library is free software; you can redistribute it and/or modify 8 it under the terms of the GNU Lesser General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or (at your 10 option) any later version. 11 12 The GNU MP Library is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 License for more details. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ 19 20 #include <stdio.h> 21 #include <stdlib.h> 22 23 #include "gmp.h" 24 #include "gmp-impl.h" 25 #include "tests.h" 26 27 28 void 29 check_one (mpz_srcptr a, mpz_srcptr d, int want) 30 { 31 int got; 32 33 if (mpz_fits_ulong_p (d)) 34 { 35 unsigned long u = mpz_get_ui (d); 36 got = (mpz_divisible_ui_p (a, u) != 0); 37 if (want != got) 38 { 39 printf ("mpz_divisible_ui_p wrong\n"); 40 printf (" expected %d got %d\n", want, got); 41 mpz_trace (" a", a); 42 printf (" d=%lu\n", u); 43 mp_trace_base = -16; 44 mpz_trace (" a", a); 45 printf (" d=0x%lX\n", u); 46 abort (); 47 } 48 } 49 50 got = (mpz_divisible_p (a, d) != 0); 51 if (want != got) 52 { 53 printf ("mpz_divisible_p wrong\n"); 54 printf (" expected %d got %d\n", want, got); 55 mpz_trace (" a", a); 56 mpz_trace (" d", d); 57 mp_trace_base = -16; 58 mpz_trace (" a", a); 59 mpz_trace (" d", d); 60 abort (); 61 } 62 } 63 64 void 65 check_data (void) 66 { 67 static const struct { 68 const char *a; 69 const char *d; 70 int want; 71 72 } data[] = { 73 74 { "0", "1", 1 }, 75 { "123", "1", 1 }, 76 { "-123", "1", 1 }, 77 78 { "0", "2", 1 }, 79 { "1", "2", 0 }, 80 { "2", "2", 1 }, 81 { "-2", "2", 1 }, 82 { "0x100000000000000000000000000000000", "2", 1 }, 83 { "0x100000000000000000000000000000001", "2", 0 }, 84 85 { "0x3333333333333333", "3", 1 }, 86 { "0x3333333333333332", "3", 0 }, 87 { "0x33333333333333333333333333333333", "3", 1 }, 88 { "0x33333333333333333333333333333332", "3", 0 }, 89 90 /* divisor changes from 2 to 1 limb after stripping 2s */ 91 { "0x3333333300000000", "0x180000000", 1 }, 92 { "0x33333333333333330000000000000000", "0x18000000000000000", 1 }, 93 { "0x133333333333333330000000000000000", "0x18000000000000000", 0 }, 94 }; 95 96 mpz_t a, d; 97 int i; 98 99 mpz_init (a); 100 mpz_init (d); 101 102 for (i = 0; i < numberof (data); i++) 103 { 104 mpz_set_str_or_abort (a, data[i].a, 0); 105 mpz_set_str_or_abort (d, data[i].d, 0); 106 check_one (a, d, data[i].want); 107 } 108 109 mpz_clear (a); 110 mpz_clear (d); 111 } 112 113 void 114 check_random (int reps) 115 { 116 gmp_randstate_ptr rands = RANDS; 117 mpz_t a, d, r; 118 int i; 119 int want; 120 121 mpz_init (a); 122 mpz_init (d); 123 mpz_init (r); 124 125 for (i = 0; i < reps; i++) 126 { 127 mpz_erandomb (a, rands, 1 << 19); 128 mpz_erandomb_nonzero (d, rands, 1 << 18); 129 130 mpz_fdiv_r (r, a, d); 131 132 want = (mpz_sgn (r) == 0); 133 check_one (a, d, want); 134 135 mpz_sub (a, a, r); 136 check_one (a, d, 1); 137 138 if (mpz_cmpabs_ui (d, 1L) == 0) 139 continue; 140 141 mpz_add_ui (a, a, 1L); 142 check_one (a, d, 0); 143 } 144 145 mpz_clear (a); 146 mpz_clear (d); 147 mpz_clear (r); 148 } 149 150 151 int 152 main (int argc, char *argv[]) 153 { 154 int reps = 100; 155 156 tests_start (); 157 158 if (argc == 2) 159 reps = atoi (argv[1]); 160 161 check_data (); 162 check_random (reps); 163 164 tests_end (); 165 exit (0); 166 } 167