1/* Test that routines allow reusing a source variable as destination. 2 3Copyright 1996, 2000-2002, 2012 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, mpf_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 mpf_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 48#ifndef EXPO 49#define EXPO 32 50#endif 51 52void dump_abort (const char *, mpf_t, mpf_t); 53 54typedef void (*dss_func) (mpf_ptr, mpf_srcptr, mpf_srcptr); 55 56dss_func dss_funcs[] = 57{ 58 mpf_div, mpf_add, mpf_mul, mpf_sub, 59}; 60 61const char *dss_func_names[] = 62{ 63 "mpf_div", "mpf_add", "mpf_mul", "mpf_sub", 64}; 65 66typedef void (*dsi_func) (mpf_ptr, mpf_srcptr, unsigned long int); 67 68dsi_func dsi_funcs[] = 69{ 70 mpf_div_ui, mpf_add_ui, mpf_mul_ui, mpf_sub_ui, 71 mpf_mul_2exp, mpf_div_2exp, mpf_pow_ui 72}; 73 74const char *dsi_func_names[] = 75{ 76 "mpf_div_ui", "mpf_add_ui", "mpf_mul_ui", "mpf_sub_ui", 77 "mpf_mul_2exp", "mpf_div_2exp", "mpf_pow_ui" 78}; 79 80typedef void (*dis_func) (mpf_ptr, unsigned long int, mpf_srcptr); 81 82dis_func dis_funcs[] = 83{ 84 mpf_ui_div, mpf_ui_sub, 85}; 86 87const char *dis_func_names[] = 88{ 89 "mpf_ui_div", "mpf_ui_sub", 90}; 91 92int 93main (int argc, char **argv) 94{ 95 int i; 96 int pass, reps = 10000; 97 mpf_t in1, in2, out1; 98 unsigned long int in1i, in2i; 99 mpf_t res1, res2, res3; 100 mp_size_t bprec = 100; 101 102 tests_start (); 103 104 if (argc > 1) 105 { 106 reps = strtol (argv[1], 0, 0); 107 if (argc > 2) 108 bprec = strtol (argv[2], 0, 0); 109 } 110 111 mpf_set_default_prec (bprec); 112 113 mpf_init (in1); 114 mpf_init (in2); 115 mpf_init (out1); 116 mpf_init (res1); 117 mpf_init (res2); 118 mpf_init (res3); 119 120 for (pass = 1; pass <= reps; pass++) 121 { 122 mpf_random2 (in1, urandom () % SIZE - SIZE/2, urandom () % EXPO); 123 mpf_random2 (in2, urandom () % SIZE - SIZE/2, urandom () % EXPO); 124 125 for (i = 0; i < sizeof (dss_funcs) / sizeof (dss_func); i++) 126 { 127 /* Don't divide by 0. */ 128 if (i == 0 && mpf_cmp_ui (in2, 0) == 0) 129 continue; 130 131 (dss_funcs[i]) (res1, in1, in2); 132 133 mpf_set (out1, in1); 134 (dss_funcs[i]) (out1, out1, in2); 135 mpf_set (res2, out1); 136 137 mpf_set (out1, in2); 138 (dss_funcs[i]) (out1, in1, out1); 139 mpf_set (res3, out1); 140 141 if (mpf_cmp (res1, res2) != 0) 142 dump_abort (dss_func_names[i], res1, res2); 143 if (mpf_cmp (res1, res3) != 0) 144 dump_abort (dss_func_names[i], res1, res3); 145 } 146 147 in2i = urandom (); 148 for (i = 0; i < sizeof (dsi_funcs) / sizeof (dsi_func); i++) 149 { 150 unsigned long this_in2i = in2i; 151 152 /* Don't divide by 0. */ 153 if (dsi_funcs[i] == mpf_div_ui && this_in2i == 0) 154 continue; 155 156 /* Avoid overflow/underflow in the exponent. */ 157 if (dsi_funcs[i] == mpf_mul_2exp || dsi_funcs[i] == mpf_div_2exp) 158 this_in2i %= 0x100000; 159 else if (dsi_funcs[i] == mpf_pow_ui) 160 this_in2i %= 0x1000; 161 162 (dsi_funcs[i]) (res1, in1, this_in2i); 163 164 mpf_set (out1, in1); 165 (dsi_funcs[i]) (out1, out1, this_in2i); 166 mpf_set (res2, out1); 167 168 if (mpf_cmp (res1, res2) != 0) 169 dump_abort (dsi_func_names[i], res1, res2); 170 } 171 172 in1i = urandom (); 173 for (i = 0; i < sizeof (dis_funcs) / sizeof (dis_func); i++) 174 { 175 /* Don't divide by 0. */ 176 if (dis_funcs[i] == mpf_ui_div 177 && mpf_cmp_ui (in2, 0) == 0) 178 continue; 179 180 (dis_funcs[i]) (res1, in1i, in2); 181 182 mpf_set (out1, in2); 183 (dis_funcs[i]) (out1, in1i, out1); 184 mpf_set (res2, out1); 185 186 if (mpf_cmp (res1, res2) != 0) 187 dump_abort (dis_func_names[i], res1, res2); 188 } 189 190 } 191 192 mpf_clear (in1); 193 mpf_clear (in2); 194 mpf_clear (out1); 195 mpf_clear (res1); 196 mpf_clear (res2); 197 mpf_clear (res3); 198 199 tests_end (); 200 exit (0); 201} 202 203void 204dump_abort (const char *name, mpf_t res1, mpf_t res2) 205{ 206 printf ("failure in %s:\n", name); 207 mpf_dump (res1); 208 mpf_dump (res2); 209 abort (); 210} 211 212#if 0 213void mpf_abs (mpf_ptr, mpf_srcptr); 214void mpf_sqrt (mpf_ptr, mpf_srcptr); 215void mpf_neg (mpf_ptr, mpf_srcptr); 216#endif 217 218#endif /* ! DLL_EXPORT */ 219