github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpz/t-bin.c (about) 1 /* Exercise mpz_bin_ui and mpz_bin_uiui. 2 3 Copyright 2000, 2001, 2010, 2012 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 #include "gmp.h" 23 #include "gmp-impl.h" 24 #include "tests.h" 25 26 /* Default number of generated tests. */ 27 #define COUNT 700 28 29 void 30 try_mpz_bin_ui (mpz_srcptr want, mpz_srcptr n, unsigned long k) 31 { 32 mpz_t got; 33 34 mpz_init (got); 35 mpz_bin_ui (got, n, k); 36 MPZ_CHECK_FORMAT (got); 37 if (mpz_cmp (got, want) != 0) 38 { 39 printf ("mpz_bin_ui wrong\n"); 40 printf (" n="); mpz_out_str (stdout, 10, n); printf ("\n"); 41 printf (" k=%lu\n", k); 42 printf (" got="); mpz_out_str (stdout, 10, got); printf ("\n"); 43 printf (" want="); mpz_out_str (stdout, 10, want); printf ("\n"); 44 abort(); 45 } 46 mpz_clear (got); 47 } 48 49 50 void 51 try_mpz_bin_uiui (mpz_srcptr want, unsigned long n, unsigned long k) 52 { 53 mpz_t got; 54 55 mpz_init (got); 56 mpz_bin_uiui (got, n, k); 57 MPZ_CHECK_FORMAT (got); 58 if (mpz_cmp (got, want) != 0) 59 { 60 printf ("mpz_bin_uiui wrong\n"); 61 printf (" n=%lu\n", n); 62 printf (" k=%lu\n", k); 63 printf (" got="); mpz_out_str (stdout, 10, got); printf ("\n"); 64 printf (" want="); mpz_out_str (stdout, 10, want); printf ("\n"); 65 abort(); 66 } 67 mpz_clear (got); 68 } 69 70 71 void 72 samples (void) 73 { 74 static const struct { 75 const char *n; 76 unsigned long k; 77 const char *want; 78 } data[] = { 79 80 { "0", 123456, "0" }, 81 { "1", 543210, "0" }, 82 { "2", 123321, "0" }, 83 { "3", 234567, "0" }, 84 { "10", 23456, "0" }, 85 86 /* negatives, using bin(-n,k)=bin(n+k-1,k) */ 87 { "-1", 0, "1" }, 88 { "-1", 1, "-1" }, 89 { "-1", 2, "1" }, 90 { "-1", 3, "-1" }, 91 { "-1", 4, "1" }, 92 93 { "-2", 0, "1" }, 94 { "-2", 1, "-2" }, 95 { "-2", 2, "3" }, 96 { "-2", 3, "-4" }, 97 { "-2", 4, "5" }, 98 { "-2", 5, "-6" }, 99 { "-2", 6, "7" }, 100 101 { "-3", 0, "1" }, 102 { "-3", 1, "-3" }, 103 { "-3", 2, "6" }, 104 { "-3", 3, "-10" }, 105 { "-3", 4, "15" }, 106 { "-3", 5, "-21" }, 107 { "-3", 6, "28" }, 108 109 /* A few random values */ 110 { "41", 20, "269128937220" }, 111 { "62", 37, "147405545359541742" }, 112 { "50", 18, "18053528883775" }, 113 { "149", 21, "19332950844468483467894649" }, 114 }; 115 116 mpz_t n, want; 117 int i; 118 119 mpz_init (n); 120 mpz_init (want); 121 122 for (i = 0; i < numberof (data); i++) 123 { 124 mpz_set_str_or_abort (n, data[i].n, 0); 125 mpz_set_str_or_abort (want, data[i].want, 0); 126 127 try_mpz_bin_ui (want, n, data[i].k); 128 129 if (mpz_fits_ulong_p (n)) 130 try_mpz_bin_uiui (want, mpz_get_ui (n), data[i].k); 131 } 132 133 mpz_clear (n); 134 mpz_clear (want); 135 } 136 137 138 /* Test some bin(2k,k) cases. This produces some biggish numbers to 139 exercise the limb accumulating code. */ 140 void 141 twos (int count) 142 { 143 mpz_t n, want; 144 unsigned long k; 145 146 mpz_init (n); 147 mpz_init (want); 148 149 mpz_set_ui (want, (unsigned long) 2); 150 for (k = 1; k < count; k++) 151 { 152 mpz_set_ui (n, 2*k); 153 try_mpz_bin_ui (want, n, k); 154 155 try_mpz_bin_uiui (want, 2*k, k); 156 157 mpz_mul_ui (want, want, 2*(2*k+1)); 158 mpz_fdiv_q_ui (want, want, k+1); 159 } 160 161 mpz_clear (n); 162 mpz_clear (want); 163 } 164 165 /* Test some random bin(n,k) cases. This produces some biggish 166 numbers to exercise the limb accumulating code. */ 167 void 168 randomwalk (int count) 169 { 170 mpz_t n_z, want; 171 unsigned long n, k, i, r; 172 int tests; 173 gmp_randstate_ptr rands; 174 175 rands = RANDS; 176 mpz_init (n_z); 177 mpz_init (want); 178 179 k = 3; 180 n = 12; 181 mpz_set_ui (want, (unsigned long) 220); /* binomial(12,3) = 220 */ 182 183 for (tests = 1; tests < count; tests++) 184 { 185 r = gmp_urandomm_ui (rands, 62) + 1; 186 for (i = r & 7; i > 0; i--) 187 { 188 n++; k++; 189 mpz_mul_ui (want, want, n); 190 mpz_fdiv_q_ui (want, want, k); 191 } 192 for (i = r >> 3; i > 0; i--) 193 { 194 n++; 195 mpz_mul_ui (want, want, n); 196 mpz_fdiv_q_ui (want, want, n - k); 197 } 198 199 mpz_set_ui (n_z, n); 200 try_mpz_bin_ui (want, n_z, k); 201 202 try_mpz_bin_uiui (want, n, k); 203 } 204 205 mpz_clear (n_z); 206 mpz_clear (want); 207 } 208 209 210 /* Test all bin(n,k) cases, with 0 <= k <= n + 1 <= count. */ 211 void 212 smallexaustive (unsigned int count) 213 { 214 mpz_t n_z, want; 215 unsigned long n, k; 216 217 mpz_init (n_z); 218 mpz_init (want); 219 220 for (n = 0; n < count; n++) 221 { 222 mpz_set_ui (want, (unsigned long) 1); 223 mpz_set_ui (n_z, n); 224 for (k = 0; k <= n; k++) 225 { 226 try_mpz_bin_ui (want, n_z, k); 227 try_mpz_bin_uiui (want, n, k); 228 mpz_mul_ui (want, want, n - k); 229 mpz_fdiv_q_ui (want, want, k + 1); 230 } 231 try_mpz_bin_ui (want, n_z, k); 232 try_mpz_bin_uiui (want, n, k); 233 } 234 235 mpz_clear (n_z); 236 mpz_clear (want); 237 } 238 239 int 240 main (int argc, char **argv) 241 { 242 int count; 243 244 if (argc > 1) 245 { 246 char *end; 247 count = strtol (argv[1], &end, 0); 248 if (*end || count <= 0) 249 { 250 fprintf (stderr, "Invalid test count: %s.\n", argv[1]); 251 return 1; 252 } 253 } 254 else 255 count = COUNT; 256 257 tests_start (); 258 259 samples (); 260 smallexaustive (count >> 4); 261 twos (count >> 1); 262 randomwalk (count - (count >> 1)); 263 264 tests_end (); 265 exit (0); 266 }