1 /* 2 3 Copyright 2012-2014, 2016, 2020 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 <assert.h> 21 #include <limits.h> 22 #include <stdlib.h> 23 #include <stdio.h> 24 #include <string.h> 25 26 #include "testutils.h" 27 28 #define MAXBITS 400 29 #define COUNT 2000 30 31 #define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT) 32 #define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS) 33 34 static void 35 test_small (void) 36 { 37 struct { 38 const char *input; 39 const char *decimal; 40 } data[] = { 41 { "183407", "183407" }, 42 { " 763959", "763959 " }, 43 { "9 81999", "981999" }, 44 { "10\t7398 ", "107398" }, 45 { "-9585 44", "-00958544" }, 46 { "-0", "0000" }, 47 { " -000 ", "0" }, 48 { "0704436", "231710" }, 49 /* Check the case of large number of leading zeros. */ 50 { "0000000000000000000000000", "0000000000000000000000000" }, 51 { "000000000000000000000000704436", "000000000000000000000000231710" }, 52 { " 02503517", "689999" }, 53 { "0 1312143", "365667" }, 54 { "-03 274062", "-882738" }, 55 { "012\t242", "005282" }, 56 { "0b11010111110010001111", "883855" }, 57 { " 0b11001010010100001", "103585" }, 58 { "-0b101010110011101111", "-175343" }, 59 { "0b 1111111011011100110", "521958" }, 60 { "0b1 1111110111001000011", "1044035" }, 61 { " 0x53dfc", "343548" }, 62 { "0xfA019", "1024025" }, 63 { "0x 642d1", "410321" }, 64 { "0x5 8067", "360551" }, 65 { "-0xd6Be6", "-879590" }, 66 { "\t0B1110000100000000011", "460803" }, 67 { "0B\t1111110010010100101", "517285" }, 68 { "0B1\t010111101101110100", "359284" }, 69 { "-0B101\t1001101111111001", "-367609" }, 70 { "0B10001001010111110000", "562672" }, 71 { "0Xe4B7e", "936830" }, 72 { "0X1E4bf", "124095" }, 73 { "-0Xfdb90", "-1039248" }, 74 { "0X7fc47", "523335" }, 75 { "0X8167c", "530044" }, 76 /* Some invalid inputs */ 77 { "", NULL }, 78 { "0x", NULL }, 79 { "0b", NULL }, 80 { "0z", NULL }, 81 { "-", NULL }, 82 { "-0x ", NULL }, 83 { "0|1", NULL }, 84 { "4+4", NULL }, 85 { "0ab", NULL }, 86 { "10x0", NULL }, 87 { "0xxab", NULL }, 88 { "ab", NULL }, 89 { "0%#", NULL }, 90 { "$foo", NULL }, 91 { NULL, NULL } 92 }; 93 unsigned i; 94 mpz_t a, b; 95 mpz_init (b); 96 97 for (i = 0; data[i].input; i++) 98 { 99 int res = mpz_init_set_str (a, data[i].input, 0); 100 if (data[i].decimal) 101 { 102 if (res != 0) 103 { 104 fprintf (stderr, "mpz_set_str returned -1, input: %s\n", 105 data[i].input); 106 abort (); 107 } 108 if (mpz_set_str (b, data[i].decimal, 10) != 0) 109 { 110 fprintf (stderr, "mpz_set_str returned -1, decimal input: %s\n", 111 data[i].input); 112 abort (); 113 } 114 if (mpz_cmp (a, b) != 0) 115 { 116 fprintf (stderr, "mpz_set_str failed for input: %s\n", 117 data[i].input); 118 119 dump ("got", a); 120 dump ("ref", b); 121 abort (); 122 } 123 } 124 else if (res != -1) 125 { 126 fprintf (stderr, "mpz_set_str returned %d, invalid input: %s\n", 127 res, data[i].input); 128 abort (); 129 } 130 mpz_clear (a); 131 } 132 133 mpz_clear (b); 134 } 135 136 void 137 testmain (int argc, char **argv) 138 { 139 unsigned i; 140 char *ap; 141 char *bp; 142 char *rp; 143 size_t bn, rn, arn; 144 145 mpz_t a, b; 146 147 FILE *tmp; 148 149 test_small (); 150 151 mpz_init (a); 152 mpz_init (b); 153 154 tmp = tmpfile (); 155 if (!tmp) 156 fprintf (stderr, 157 "Failed to create temporary file. Skipping mpz_out_str tests.\n"); 158 159 if (mpz_out_str (tmp, 63, a) != 0) 160 { 161 printf ("mpz_out_str did not return 0 (error) with base > 62\n"); 162 abort (); 163 } 164 165 if (mpz_out_str (tmp, -37, a) != 0) 166 { 167 printf ("mpz_out_str did not return 0 (error) with base < -37\n"); 168 abort (); 169 } 170 171 for (i = 0; i < COUNT; i++) 172 { 173 int base; 174 for (base = 0; base <= 62; base += 1 + (base == 0)) 175 { 176 hex_random_str_op (MAXBITS, (i&1 || base > 36) ? base: -base, &ap, &rp); 177 if (mpz_set_str (a, ap, 16) != 0) 178 { 179 fprintf (stderr, "mpz_set_str failed on input %s\n", ap); 180 abort (); 181 } 182 183 rn = strlen (rp); 184 arn = rn - (rp[0] == '-'); 185 186 bn = mpz_sizeinbase (a, base ? base : 10); 187 if (bn < arn || bn > (arn + 1)) 188 { 189 fprintf (stderr, "mpz_sizeinbase failed:\n"); 190 dump ("a", a); 191 fprintf (stderr, "r = %s\n", rp); 192 fprintf (stderr, " base %d, correct size %u, got %u\n", 193 base, (unsigned) arn, (unsigned)bn); 194 abort (); 195 } 196 bp = mpz_get_str (NULL, (i&1 || base > 36) ? base: -base, a); 197 if (strcmp (bp, rp)) 198 { 199 fprintf (stderr, "mpz_get_str failed:\n"); 200 dump ("a", a); 201 fprintf (stderr, "b = %s\n", bp); 202 fprintf (stderr, " base = %d\n", base); 203 fprintf (stderr, "r = %s\n", rp); 204 abort (); 205 } 206 207 /* Just a few tests with file i/o. */ 208 if (tmp && i < 20) 209 { 210 size_t tn; 211 rewind (tmp); 212 tn = mpz_out_str (tmp, (i&1 || base > 36) ? base: -base, a); 213 if (tn != rn) 214 { 215 fprintf (stderr, "mpz_out_str, bad return value:\n"); 216 dump ("a", a); 217 fprintf (stderr, "r = %s\n", rp); 218 fprintf (stderr, " base %d, correct size %u, got %u\n", 219 base, (unsigned) rn, (unsigned)tn); 220 abort (); 221 } 222 rewind (tmp); 223 memset (bp, 0, rn); 224 tn = fread (bp, 1, rn, tmp); 225 if (tn != rn) 226 { 227 fprintf (stderr, 228 "fread failed, expected %lu bytes, got only %lu.\n", 229 (unsigned long) rn, (unsigned long) tn); 230 abort (); 231 } 232 233 if (memcmp (bp, rp, rn) != 0) 234 { 235 fprintf (stderr, "mpz_out_str failed:\n"); 236 dump ("a", a); 237 fprintf (stderr, "b = %s\n", bp); 238 fprintf (stderr, " base = %d\n", base); 239 fprintf (stderr, "r = %s\n", rp); 240 abort (); 241 } 242 } 243 244 mpz_set_str (b, rp, base); 245 246 if (mpz_cmp (a, b)) 247 { 248 fprintf (stderr, "mpz_set_str failed:\n"); 249 fprintf (stderr, "r = %s\n", rp); 250 fprintf (stderr, " base = %d\n", base); 251 fprintf (stderr, "r = %s\n", ap); 252 fprintf (stderr, " base = 16\n"); 253 dump ("b", b); 254 dump ("r", a); 255 abort (); 256 } 257 258 /* Test mpn interface */ 259 if (base && mpz_sgn (a)) 260 { 261 size_t i; 262 const char *absr; 263 mp_limb_t t[MAXLIMBS]; 264 size_t tn = mpz_size (a); 265 266 assert (tn <= MAXLIMBS); 267 mpn_copyi (t, a->_mp_d, tn); 268 269 bn = mpn_get_str ((unsigned char *) bp, base, t, tn); 270 if (bn != arn) 271 { 272 fprintf (stderr, "mpn_get_str failed:\n"); 273 fprintf (stderr, "returned length: %lu (bad)\n", (unsigned long) bn); 274 fprintf (stderr, "expected: %lu\n", (unsigned long) arn); 275 fprintf (stderr, " base = %d\n", base); 276 fprintf (stderr, "r = %s\n", ap); 277 fprintf (stderr, " base = 16\n"); 278 dump ("b", b); 279 dump ("r", a); 280 abort (); 281 } 282 absr = rp + (rp[0] == '-'); 283 284 for (i = 0; i < bn; i++) 285 { 286 unsigned char digit = absr[i]; 287 char value; 288 if (digit >= '0' && digit <= '9') 289 value = digit - '0'; 290 else if (digit >= 'a' && digit <= 'z') 291 value = digit - 'a' + ((base > 36) ? 36 : 10); 292 else if (digit >= 'A' && digit <= 'Z') 293 value = digit - 'A' + 10; 294 else 295 { 296 fprintf (stderr, "Internal error in test.\n"); 297 abort(); 298 } 299 if (bp[i] != value) 300 { 301 fprintf (stderr, "mpn_get_str failed:\n"); 302 fprintf (stderr, "digit %lu: %d (bad)\n", (unsigned long) i, bp[i]); 303 fprintf (stderr, "expected: %d\n", value); 304 fprintf (stderr, " base = %d\n", base); 305 fprintf (stderr, "r = %s\n", ap); 306 fprintf (stderr, " base = 16\n"); 307 dump ("b", b); 308 dump ("r", a); 309 abort (); 310 } 311 } 312 tn = mpn_set_str (t, (unsigned char *) bp, bn, base); 313 if (tn != mpz_size (a) || mpn_cmp (t, a->_mp_d, tn)) 314 { 315 fprintf (stderr, "mpn_set_str failed:\n"); 316 fprintf (stderr, "r = %s\n", rp); 317 fprintf (stderr, " base = %d\n", base); 318 fprintf (stderr, "r = %s\n", ap); 319 fprintf (stderr, " base = 16\n"); 320 dump ("r", a); 321 abort (); 322 } 323 } 324 free (ap); 325 free (rp); 326 testfree (bp); 327 } 328 } 329 mpz_clear (a); 330 mpz_clear (b); 331 } 332