1 #define _XOPEN_SOURCE 600
17 #include "subr_random.h"
21 calculp_double_complex(double complex computed, double complex exact)
27 ulp_real = calculp_double(creal(computed), creal(exact));
28 ulp_imag = calculp_double(cimag(computed), cimag(exact));
30 z.parts[0] = ulp_real;
31 z.parts[1] = ulp_imag;
36 static long double complex
37 calculp_long_double_complex(long double complex computedl,
38 long double complex exactl)
40 long_double_complex z;
41 long double ulp_reall;
42 long double ulp_imagl;
44 ulp_reall = calculp_long_double(creall(computedl), creall(exactl));
45 ulp_imagl = calculp_long_double(cimagl(computedl), cimagl(exactl));
47 z.parts[0] = ulp_reall;
48 z.parts[1] = ulp_imagl;
54 populate_complex_vars(const struct fentry *f,
55 double complex *x, double complex *y,
56 long double complex *xl, long double complex *yl,
57 mpc_t mp_x, mpc_t mp_y, mpc_t mp_xl, mpc_t mp_yl)
59 const mpc_rnd_t tonearest = MPC_RNDNN;
60 long double complex txl, tyl;
61 double complex tx, ty;
63 assert(f && x && y && xl && yl);
67 /* Generate random arguments */
70 tx = random_double_complex(FP_NORMAL);
71 txl = random_long_double_complex(FP_NORMAL);
72 } while (!f->f_uc.fp1(tx) || !f->f_uc.fp1(txl));
76 tx = random_double_complex(FP_NORMAL);
77 ty = random_double_complex(FP_NORMAL);
78 txl = random_long_double_complex(FP_NORMAL);
79 tyl = random_long_double_complex(FP_NORMAL);
80 } while (!f->f_uc.fp2(tx, ty) || !f->f_uc.fp2(txl, tyl));
88 DPRINTF(( "x = % .16e + I *% .16e\n", creal (*x), cimag (*x)));
89 DPRINTF(( "y = % .16e + I *% .16e\n", creal (*y), cimag (*y)));
90 DPRINTF(("xl = % .16Le + I *% .16Le\n", creall(*xl), cimagl(*xl)));
91 DPRINTF(("yl = % .16Le + I *% .16Le\n", creall(*yl), cimagl(*yl)));
93 /* Copy arguments to mpc variables */
94 mpc_set_d_d (mp_x, creal (tx), cimag (tx), tonearest);
95 mpc_set_d_d (mp_y, creal (ty), cimag (ty), tonearest);
96 mpc_set_ld_ld(mp_xl, creall(txl), cimagl(txl), tonearest);
97 mpc_set_ld_ld(mp_yl, creall(tyl), cimagl(tyl), tonearest);
101 isbogus(long double complex z)
103 long double real = creall(z);
104 long double imag = cimagl(z);
108 if ((fpclassify(real) != FP_NORMAL) &&
109 (fpclassify(real) != FP_SUBNORMAL))
113 if ((fpclassify(imag) != FP_NORMAL) &&
114 (fpclassify(imag) != FP_SUBNORMAL))
121 getfunctionulp_complex(const struct fentry *f, struct ulp_complex *uc)
123 const mpc_rnd_t tonearest = MPC_RNDNN;
124 const mpfr_rnd_t mpfr_tonearest = MPFR_RNDN;
125 mpc_t mp_exactl, mp_xl, mp_yl;
126 mpc_t mp_exact, mp_x, mp_y;
127 long double complex xl, yl, computedl, exactl, myulpl;
128 double complex x, y, computed, exact, myulp;
131 /* Initialize high precision variables */
132 mpc_init2(mp_exact, 200);
133 mpc_init2(mp_x, 200);
134 mpc_init2(mp_y, 200);
135 mpc_init2(mp_exactl,200);
136 mpc_init2(mp_xl, 200);
137 mpc_init2(mp_yl, 200);
139 ULP_COMPLEX_INIT(uc);
141 for (i = 0; i < NITERATIONS; i++) {
143 printf("Percentage complete: %2.2f\r",
144 (100.0 * i)/NITERATIONS);
148 /* Generate random arguments */
149 DPRINTF(("populate_complex_vars: entering\n"));
150 populate_complex_vars(f, &x, &y, &xl, &yl, mp_x, mp_y, mp_xl, mp_yl);
151 DPRINTF(("populate_complex_vars: left\n"));
154 * Ready to call the mpc*()
155 * The double version ALWAYS exist!
157 char *str_x = mpc_get_str(10, 16, mp_x, tonearest);
158 char *str_y = mpc_get_str(10, 16, mp_y, tonearest);
159 DPRINTF(("f->f_mpc: enter x=%s, y=%s\n", str_x, str_y));
161 f->f_mpc(mp_exact, mp_x, tonearest);
163 f->f_mpc(mp_exact, mp_x, mp_y, tonearest);
165 exact = mpc_get_dc(mp_exact, mpfr_tonearest);
166 DPRINTF(("f->f_mpc: left\n"));
170 /* We can't tell the same for long double functions though */
171 char *str_xl = mpc_get_str(10, 35, mp_xl, tonearest);
172 char *str_yl = mpc_get_str(10, 35, mp_yl, tonearest);
173 DPRINTF(("f->f_mpcl: enter x=%s, y=%s\n", str_xl, str_yl));
174 if (f->f_libml_complex) {
176 f->f_mpc(mp_exactl, mp_xl, tonearest);
178 f->f_mpc(mp_exactl, mp_xl, mp_yl, tonearest);
180 exactl = mpc_get_ldc(mp_exactl, mpfr_tonearest);
182 DPRINTF(("f->f_mpcl: left\n"));
183 mpc_free_str(str_xl);
184 mpc_free_str(str_yl);
186 /* Ready to call the libm*() */
187 if (f->f_narg == 1) {
188 computed = f->f_libm_complex(x);
190 computed = f->f_libm_complex(x, y);
193 if (f->f_libml_complex) {
194 if (f->f_narg == 1) {
195 computedl = f->f_libml_complex(xl);
197 computedl = f->f_libml_complex(xl, yl);
201 /* Skip bogus results */
202 if (!isbogus(computed) && !isbogus(exact)) {
203 myulp = calculp_double_complex(computed, exact);
204 ULP_COMPLEX_UPDATE(uc, myulp);
206 uc->ulp_total.ulp_skipped++;
209 if (f->f_libml_complex) {
210 if (!isbogus(computed) && !isbogus(exact)) {
211 myulpl = calculp_long_double_complex(computedl, exactl);
212 ULP_COMPLEX_UPDATEL(uc, myulpl);
215 uc->ulp_total.ulp_skippedl++;
219 uc->ulp_total.ulp_avg /= (i - uc->ulp_total.ulp_skipped);
225 mpc_clear(mp_exactl);
231 printulps_double_complex(struct ulp_complex uc)
233 if (uc.ulp_total.ulp_max > 9.9 || uc.ulp_total.ulp_min > 9.9) {
234 printf("%-10.4e %-10.4e %-10.4e ",
235 uc.ulp_total.ulp_max,
236 uc.ulp_total.ulp_min,
237 uc.ulp_total.ulp_avg);
239 printf("%-10.4f %-10.4f %-10.4f ",
240 uc.ulp_total.ulp_max,
241 uc.ulp_total.ulp_min,
242 uc.ulp_total.ulp_avg);
244 printf("%5u\n", uc.ulp_total.ulp_skipped);
248 printulps_long_double_complex(struct ulp_complex uc)
250 if (uc.ulp_total.ulp_maxl > 9.9 || uc.ulp_total.ulp_minl > 9.9) {
251 printf("%-10.4e %-10.4e %-10.4e ",
252 (double)uc.ulp_real.ulp_maxl,
253 (double)uc.ulp_real.ulp_minl,
254 (double)uc.ulp_real.ulp_avgl);
257 printf("%5u\n", uc.ulp_total.ulp_skippedl);