1 /* 2 3 Copyright 2012-2014, 2016, 2018, 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 #include "../mini-mpq.h" 28 29 #define MAXBITS 400 30 #define COUNT 2000 31 32 #define GMP_LIMB_BITS (sizeof(mp_limb_t) * CHAR_BIT) 33 #define MAXLIMBS ((MAXBITS + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS) 34 35 static void 36 test_small (void) 37 { 38 struct { 39 const char *input; 40 const char *decimal; 41 } data[] = { 42 { "1832407/3", "1832407/3" }, 43 { " 2763959/6", "2763959/6 " }, 44 { "4 981 999 / 1 8", "4981999/18" }, 45 { "10\t73981/30 ", "1073981/30" }, 46 { "958 544 /1", "00958544/01" }, 47 { "-0", "0000" }, 48 { " -000 ", "0/ 1" }, 49 { "0704436/011", "231710/9" }, 50 /* Check the case of large number of leading zeros. */ 51 { "0000000000000000000000000/1", "0/0000000000000000000000001" }, 52 { "000000000000000704436/000011", "0000000000000000231710/00009" }, 53 { " 012/ 02503517", "10/689999" }, 54 { "0b 10/0 1312143", "2/365667" }, 55 { "-03 274062/0x1", "-882738/1" }, 56 { "012\t242", "005282" }, 57 { "9/0b11010111110010001111", "9/883855" }, 58 { "022/ 0b11001010010100001", "18/103585" }, 59 { "-0b101010110011101111/0x12", "-175343/18" }, 60 { "-05/0b 111 1111 0110 1110 0110", "-5/521958" }, 61 { "0b 011 111 110 111 001 000 011/0b00110", "1044035/6" }, 62 { " 0x53dfc", "343548" }, 63 { "-0x00012/0x000fA019", "-18/1024025" }, 64 { "0x 642d1", "410321" }, 65 { "0x5 8067/0Xa", "360551/10" }, 66 { "-0xd6Be6/3", "-879590/3" }, 67 { "\t0B1110000100000000011", "460803" }, 68 { "0B\t1111110010010100101", "517285" }, 69 { "-0x 00 2d/0B1\t010111101101110100", "-45/359284" }, 70 { "-0B101\t1001101111111001", "-367609" }, 71 { "0B10001001010111110000/0xf", "562672/15" }, 72 { "0Xe4B7e/1", "936830" }, 73 { "0X1E4bf/0X1", "124095" }, 74 { "-0Xfdb90/05", "-1039248/5" }, 75 { "0b010/0X7fc47", "2/523335" }, 76 { "15/0X8167c", "15/530044" }, 77 /* Some invalid inputs */ 78 { "", NULL }, 79 { "0x", NULL }, 80 { "0b", NULL }, 81 { "0z", NULL }, 82 { "-", NULL }, 83 { "/0x ", NULL }, 84 { "0|1", NULL }, 85 { "/", NULL }, 86 { "0ab", NULL }, 87 { "10x0", NULL }, 88 { "1/0xxab", NULL }, 89 { "0/ab", NULL }, 90 { "0/#", NULL }, 91 { "$foo/1", NULL }, 92 { NULL, NULL } 93 }; 94 unsigned i; 95 mpq_t a, b; 96 mpq_init (a); 97 mpq_init (b); 98 99 for (i = 0; data[i].input; i++) 100 { 101 int res = mpq_set_str (a, data[i].input, 0); 102 if (data[i].decimal) 103 { 104 if (res != 0) 105 { 106 fprintf (stderr, "mpq_set_str returned -1, input: %s\n", 107 data[i].input); 108 abort (); 109 } 110 if (mpq_set_str (b, data[i].decimal, 10) != 0) 111 { 112 fprintf (stderr, "mpq_set_str returned -1, decimal input: %s\n", 113 data[i].input); 114 abort (); 115 } 116 if (!mpq_equal (a, b)) 117 { 118 fprintf (stderr, "mpq_set_str failed for input: %s\n", 119 data[i].input); 120 121 dump ("got_num", mpq_numref (a)); 122 dump ("got_den", mpq_denref (a)); 123 dump ("ref_num", mpq_numref (b)); 124 dump ("ref_den", mpq_denref (b)); 125 abort (); 126 } 127 } 128 else if (res != -1) 129 { 130 fprintf (stderr, "mpq_set_str returned %d, invalid input: %s\n", 131 res, data[i].input); 132 abort (); 133 } 134 } 135 136 mpq_clear (a); 137 mpq_clear (b); 138 } 139 140 void 141 testmain (int argc, char **argv) 142 { 143 unsigned i; 144 char *ap; 145 char *bp; 146 char *rp; 147 size_t rn, arn; 148 149 mpq_t a, b; 150 151 FILE *tmp; 152 153 test_small (); 154 155 mpq_init (a); 156 mpq_init (b); 157 158 tmp = tmpfile (); 159 if (!tmp) 160 fprintf (stderr, 161 "Failed to create temporary file. Skipping mpq_out_str tests.\n"); 162 163 if (mpq_out_str (tmp, 63, a) != 0) 164 { 165 printf ("mpq_out_str did not return 0 (error) with base > 62\n"); 166 abort (); 167 } 168 169 if (mpq_out_str (tmp, -37, a) != 0) 170 { 171 printf ("mpq_out_str did not return 0 (error) with base < -37\n"); 172 abort (); 173 } 174 175 for (i = 0; i < COUNT/60; i++) 176 { 177 int base; 178 for (base = 2; base <= 62; ++base) 179 { 180 hex_mpq_random_str_op (MAXBITS, (i&1 || base > 36) ? base: -base, &ap, &rp); 181 if (mpq_set_str (a, ap, 16) != 0) 182 { 183 fprintf (stderr, "mpq_set_str failed on input %s\n", ap); 184 abort (); 185 } 186 187 rn = strlen (rp); 188 arn = rn - (rp[0] == '-'); 189 190 bp = mpq_get_str (NULL, (i&1 || base > 36) ? base: -base, a); 191 if (strcmp (bp, rp)) 192 { 193 fprintf (stderr, "mpz_get_str failed:\n"); 194 dump ("a_num", mpq_numref (a)); 195 dump ("a_den", mpq_denref (a)); 196 fprintf (stderr, "b = %s\n", bp); 197 fprintf (stderr, " base = %d\n", base); 198 fprintf (stderr, "r = %s\n", rp); 199 abort (); 200 } 201 202 /* Just a few tests with file i/o. */ 203 if (tmp && i < 20) 204 { 205 size_t tn; 206 rewind (tmp); 207 tn = mpq_out_str (tmp, (i&1 || base > 36) ? base: -base, a); 208 if (tn != rn) 209 { 210 fprintf (stderr, "mpq_out_str, bad return value:\n"); 211 dump ("a_num", mpq_numref (a)); 212 dump ("a_den", mpq_denref (a)); 213 fprintf (stderr, "r = %s\n", rp); 214 fprintf (stderr, " base %d, correct size %u, got %u\n", 215 base, (unsigned) rn, (unsigned)tn); 216 abort (); 217 } 218 rewind (tmp); 219 memset (bp, 0, rn); 220 tn = fread (bp, 1, rn, tmp); 221 if (tn != rn) 222 { 223 fprintf (stderr, 224 "fread failed, expected %lu bytes, got only %lu.\n", 225 (unsigned long) rn, (unsigned long) tn); 226 abort (); 227 } 228 229 if (memcmp (bp, rp, rn) != 0) 230 { 231 fprintf (stderr, "mpq_out_str failed:\n"); 232 dump ("a_num", mpq_numref (a)); 233 dump ("a_den", mpq_denref (a)); 234 fprintf (stderr, "b = %s\n", bp); 235 fprintf (stderr, " base = %d\n", base); 236 fprintf (stderr, "r = %s\n", rp); 237 abort (); 238 } 239 } 240 241 mpq_set_str (b, rp, base); 242 243 if (!mpq_equal (a, b)) 244 { 245 fprintf (stderr, "mpq_set_str failed:\n"); 246 fprintf (stderr, "r = %s\n", rp); 247 fprintf (stderr, " base = %d\n", base); 248 fprintf (stderr, "r = %s\n", ap); 249 fprintf (stderr, " base = 16\n"); 250 dump ("b_num", mpq_numref (b)); 251 dump ("b_den", mpq_denref (b)); 252 dump ("r_num", mpq_numref (a)); 253 dump ("r_den", mpq_denref (a)); 254 abort (); 255 } 256 257 free (ap); 258 free (rp); 259 testfree (bp); 260 } 261 } 262 mpq_clear (a); 263 mpq_clear (b); 264 } 265