1/* Test that routines allow reusing a source variable as destination. 2 3Copyright 1996, 2000-2002, 2012, 2015 Free Software Foundation, Inc. 4 5This file is part of the GNU MP Library test suite. 6 7The GNU MP Library test suite is free software; you can redistribute it 8and/or modify it under the terms of the GNU General Public License as 9published by the Free Software Foundation; either version 3 of the License, 10or (at your option) any later version. 11 12The GNU MP Library test suite is distributed in the hope that it will be 13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15Public License for more details. 16 17You should have received a copy of the GNU General Public License along with 18the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 20#include <stdio.h> 21#include <stdlib.h> 22#include <string.h> 23 24#include "gmp-impl.h" 25#include "tests.h" 26 27#if __GMP_LIBGMP_DLL 28 29/* FIXME: When linking to a DLL libgmp, mpq_add etc can't be used as 30 initializers for global variables because they're effectively global 31 variables (function pointers) themselves. Perhaps calling a test 32 function successively with mpq_add etc would be better. */ 33 34int 35main (void) 36{ 37 printf ("Test suppressed for windows DLL\n"); 38 exit (0); 39} 40 41 42#else /* ! DLL_EXPORT */ 43 44#ifndef SIZE 45#define SIZE 16 46#endif 47 48void dump_abort (const char *, mpq_t, mpq_t); 49 50typedef void (*dss_func) (mpq_ptr, mpq_srcptr, mpq_srcptr); 51 52dss_func dss_funcs[] = 53{ 54 mpq_div, mpq_add, mpq_mul, mpq_sub, 55}; 56 57const char *dss_func_names[] = 58{ 59 "mpq_div", "mpq_add", "mpq_mul", "mpq_sub", 60}; 61 62typedef void (*ds_func) (mpq_ptr, mpq_srcptr); 63 64ds_func ds_funcs[] = 65{ 66 mpq_abs, mpq_neg, 67}; 68 69const char *ds_func_names[] = 70{ 71 "mpq_abs", "mpq_neg", 72}; 73 74typedef void (*dsi_func) (mpq_ptr, mpq_srcptr, unsigned long int); 75 76dsi_func dsi_funcs[] = 77{ 78 mpq_mul_2exp, mpq_div_2exp 79}; 80 81const char *dsi_func_names[] = 82{ 83 "mpq_mul_2exp", "mpq_div_2exp" 84}; 85 86int 87main (int argc, char **argv) 88{ 89 int i; 90 int pass, reps = 100; 91 mpq_t in1, in2, out1; 92 unsigned long int randbits, in2i; 93 mpq_t res1, res2; 94 gmp_randstate_ptr rands; 95 96 tests_start (); 97 98 TESTS_REPS (reps, argv, argc); 99 100 rands = RANDS; 101 102 mpq_init (in1); 103 mpq_init (in2); 104 mpq_init (out1); 105 mpq_init (res1); 106 mpq_init (res2); 107 108 for (pass = 1; pass <= reps; pass++) 109 { 110 randbits = urandom (); 111 112 if (randbits & 1) 113 { 114 mpq_clear (in1); 115 mpq_init (in1); 116 } 117 randbits >>= 1; 118 mpz_errandomb (mpq_numref(in1), rands, 512L); 119 mpz_errandomb_nonzero (mpq_denref(in1), rands, 512L); 120 if (randbits & 1) 121 mpz_neg (mpq_numref(in1),mpq_numref(in1)); 122 randbits >>= 1; 123 mpq_canonicalize (in1); 124 125 if (randbits & 1) 126 { 127 mpq_clear (in2); 128 mpq_init (in2); 129 } 130 randbits >>= 1; 131 mpz_errandomb (mpq_numref(in2), rands, 512L); 132 mpz_errandomb_nonzero (mpq_denref(in2), rands, 512L); 133 if (randbits & 1) 134 mpz_neg (mpq_numref(in2),mpq_numref(in2)); 135 randbits >>= 1; 136 mpq_canonicalize (in2); 137 138 for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++) 139 { 140 /* Don't divide by 0. */ 141 if (i == 0 && mpq_cmp_ui (in2, 0, 1) == 0) 142 continue; 143 144 if (randbits & 1) 145 { 146 mpq_clear (res1); 147 mpq_init (res1); 148 } 149 randbits >>= 1; 150 151 (dss_funcs[i]) (res1, in1, in2); 152 MPQ_CHECK_FORMAT(res1); 153 154 mpq_set (out1, in1); 155 (dss_funcs[i]) (out1, out1, in2); 156 MPQ_CHECK_FORMAT(out1); 157 158 if (mpq_cmp (res1, out1) != 0) 159 dump_abort (dss_func_names[i], res1, out1); 160 161 mpq_set (out1, in2); 162 (dss_funcs[i]) (out1, in1, out1); 163 MPQ_CHECK_FORMAT(out1); 164 165 if (mpq_cmp (res1, out1) != 0) 166 dump_abort (dss_func_names[i], res1, out1); 167 168 mpq_set (out1, in2); 169 (dss_funcs[i]) (res1, out1, in2); 170 MPQ_CHECK_FORMAT(res1); 171 172 (dss_funcs[i]) (res2, in2, in2); 173 MPQ_CHECK_FORMAT(res2); 174 175 (dss_funcs[i]) (out1, out1, out1); 176 MPQ_CHECK_FORMAT(out1); 177 178 if (mpq_cmp (res1, res2) != 0) 179 dump_abort (dss_func_names[i], res1, res2); 180 if (mpq_cmp (res1, out1) != 0) 181 dump_abort (dss_func_names[i], res1, out1); 182 } 183 184 for (i = 0; i < sizeof (ds_funcs) / sizeof (ds_func); i++) 185 { 186 if (randbits & 1) 187 { 188 mpq_clear (res1); 189 mpq_init (res1); 190 } 191 randbits >>= 1; 192 (ds_funcs[i]) (res1, in1); 193 MPQ_CHECK_FORMAT(res1); 194 195 mpq_set (out1, in1); 196 (ds_funcs[i]) (out1, out1); 197 MPQ_CHECK_FORMAT(out1); 198 199 if (mpq_cmp (res1, out1) != 0) 200 dump_abort (ds_func_names[i], res1, out1); 201 } 202 203 in2i = urandom () % 65536; 204 for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++) 205 { 206 if (randbits & 1) 207 { 208 mpq_clear (res1); 209 mpq_init (res1); 210 } 211 randbits >>= 1; 212 213 (dsi_funcs[i]) (res1, in1, in2i); 214 MPQ_CHECK_FORMAT(res1); 215 216 mpq_set (out1, in1); 217 (dsi_funcs[i]) (out1, out1, in2i); 218 MPQ_CHECK_FORMAT(out1); 219 220 if (mpq_cmp (res1, out1) != 0) 221 dump_abort (dsi_func_names[i], res1, out1); 222 } 223 224 } 225 226 mpq_clear (in1); 227 mpq_clear (in2); 228 mpq_clear (out1); 229 mpq_clear (res1); 230 mpq_clear (res2); 231 232 tests_end (); 233 exit (0); 234} 235 236void 237dump_abort (const char *name, mpq_t res1, mpq_t res2) 238{ 239 printf ("failure in %s:\n", name); 240 mpq_trace (" res1 ", res1); 241 mpq_trace (" res2 ", res2); 242 abort (); 243} 244 245#endif /* ! DLL_EXPORT */ 246