1 /* Test conversion using mpz_get_str and mpz_set_str. 2 3 Copyright 1993, 1994, 1996, 1999-2002, 2006, 2007, 2020 Free Software 4 Foundation, Inc. 5 6 This file is part of the GNU MP Library test suite. 7 8 The GNU MP Library test suite is free software; you can redistribute it 9 and/or modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 3 of the License, 11 or (at your option) any later version. 12 13 The GNU MP Library test suite is distributed in the hope that it will be 14 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 16 Public License for more details. 17 18 You should have received a copy of the GNU General Public License along with 19 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> /* for strlen */ 24 #include <ctype.h> /* for tolower */ 25 26 #include "gmp-impl.h" 27 #include "tests.h" 28 29 void debug_mp (mpz_t, int); 30 31 static int str_casecmp (const char *, const char *); 32 33 void 34 string_urandomb (char *bp, size_t len, int base, gmp_randstate_ptr rands) 35 { 36 mpz_t bs; 37 unsigned long bsi; 38 int d, l; 39 const char *collseq = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 40 41 mpz_init (bs); 42 43 mpz_urandomb (bs, rands, 32); 44 bsi = mpz_get_ui (bs); 45 d = bsi % base; 46 while (len != 0) 47 { 48 l = (bsi >> 16) % 20; 49 l = MIN (l, len); 50 51 memset (bp, collseq[d], l); 52 53 len -= l; 54 bp += l; 55 56 mpz_urandomb (bs, rands, 32); 57 bsi = mpz_get_ui (bs); 58 d = bsi & 0xfff; 59 if (d >= base) 60 d = 0; 61 } 62 63 bp[0] = '\0'; 64 mpz_clear (bs); 65 } 66 67 int 68 main (int argc, char **argv) 69 { 70 mpz_t op1, op2; 71 mp_size_t size; 72 int i; 73 int reps = 2000; 74 char *str, *buf, *bp; 75 int base; 76 gmp_randstate_ptr rands; 77 mpz_t bs; 78 unsigned long bsi, size_range; 79 size_t len; 80 81 tests_start (); 82 TESTS_REPS (reps, argv, argc); 83 84 rands = RANDS; 85 86 mpz_init (bs); 87 88 mpz_init (op1); 89 mpz_init (op2); 90 91 for (i = 0; i < reps; i++) 92 { 93 /* 1. Generate random mpz_t and convert to a string and back to mpz_t 94 again. */ 95 mpz_urandomb (bs, rands, 32); 96 size_range = mpz_get_ui (bs) % 17 + 2; /* 2..18 */ 97 mpz_urandomb (bs, rands, size_range); /* 3..262144 bits */ 98 size = mpz_get_ui (bs); 99 mpz_rrandomb (op1, rands, size); 100 101 mpz_urandomb (bs, rands, 1); 102 bsi = mpz_get_ui (bs); 103 if ((bsi & 1) != 0) 104 mpz_neg (op1, op1); 105 106 mpz_urandomb (bs, rands, 32); 107 bsi = mpz_get_ui (bs); 108 base = bsi % 62 + 1; 109 if (base == 1) 110 base = 0; 111 112 str = mpz_get_str ((char *) 0, base, op1); 113 mpz_set_str_or_abort (op2, str, base); 114 115 if (mpz_cmp (op1, op2)) 116 { 117 fprintf (stderr, "ERROR, op1 and op2 different in test %d\n", i); 118 fprintf (stderr, "str = %s\n", str); 119 fprintf (stderr, "base = %d\n", base); 120 fprintf (stderr, "op1 = "); debug_mp (op1, -16); 121 fprintf (stderr, "op2 = "); debug_mp (op2, -16); 122 abort (); 123 } 124 125 (*__gmp_free_func) (str, strlen (str) + 1); 126 127 /* 2. Generate random string and convert to mpz_t and back to a string 128 again. */ 129 mpz_urandomb (bs, rands, 32); 130 size_range = mpz_get_ui (bs) % 16 + 1; /* 1..16 */ 131 mpz_urandomb (bs, rands, size_range); /* 1..65536 digits */ 132 len = mpz_get_ui (bs) + 1; 133 buf = (char *) (*__gmp_allocate_func) (len + 1); 134 if (base == 0) 135 base = 10; 136 string_urandomb (buf, len, base, rands); 137 138 mpz_set_str_or_abort (op1, buf, base); 139 str = mpz_get_str ((char *) 0, base, op1); 140 141 /* Skip over leading zeros, but don't leave the string at zero length. */ 142 for (bp = buf; bp[0] == '0' && bp[1] != '\0'; bp++) 143 ; 144 145 if (str_casecmp (str, bp) != 0) 146 { 147 fprintf (stderr, "ERROR, str and buf different in test %d\n", i); 148 fprintf (stderr, "str = %s\n", str); 149 fprintf (stderr, "buf = %s\n", buf); 150 fprintf (stderr, "base = %d\n", base); 151 fprintf (stderr, "op1 = "); debug_mp (op1, -16); 152 abort (); 153 } 154 155 (*__gmp_free_func) (buf, len + 1); 156 (*__gmp_free_func) (str, strlen (str) + 1); 157 } 158 159 mpz_clear (bs); 160 mpz_clear (op1); 161 mpz_clear (op2); 162 163 tests_end (); 164 exit (0); 165 } 166 167 /* This is similar to POSIX strcasecmp except that we don't do the comparison 168 with unsigned char. We avoid strcasecmp for C standard conformance. */ 169 static int 170 str_casecmp (const char *s1, const char *s2) 171 { 172 size_t i; 173 for (i = 0;; i++) 174 { 175 int c1 = s1[i]; 176 int c2 = s2[i]; 177 if (c1 == 0 || tolower (c1) != tolower (c2)) 178 return c1 - c2; 179 } 180 } 181 182 void 183 debug_mp (mpz_t x, int base) 184 { 185 mpz_out_str (stderr, base, x); fputc ('\n', stderr); 186 } 187