1/* test mpz_divisible_p and mpz_divisible_ui_p 2 3Copyright 2001, 2009 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library. 6 7The GNU MP Library is free software; you can redistribute it and/or modify 8it under the terms of the GNU Lesser General Public License as published by 9the Free Software Foundation; either version 3 of the License, or (at your 10option) any later version. 11 12The GNU MP Library is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 14or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15License for more details. 16 17You should have received a copy of the GNU Lesser General Public License 18along 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 28void 29check_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 64void 65check_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 113void 114check_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 151int 152main (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