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