1/* tfma -- test file for mpc_fma.
2
3Copyright (C) 2011, 2012, 2013 INRIA
4
5This file is part of GNU MPC.
6
7GNU MPC is free software; you can redistribute it and/or modify it under
8the terms of the GNU Lesser General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12GNU MPC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
15more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with this program. If not, see http://www.gnu.org/licenses/ .
19*/
20
21#include "mpc-tests.h"
22
23static void
24cmpfma (mpc_srcptr a, mpc_srcptr b, mpc_srcptr c, mpc_rnd_t rnd)
25   /* computes a*b+c with the naive and fast functions using the rounding
26      mode rnd and compares the results and return values.
27      In our current test suite, all input precisions are the same, and we
28      use this precision also for the result.
29   */
30{
31   mpc_t z, t;
32   int   inex_z, inex_t;
33
34   mpc_init2 (z, MPC_MAX_PREC (a));
35   mpc_init2 (t, MPC_MAX_PREC (a));
36
37   inex_z = mpc_fma_naive (z, a, b, c, rnd);
38   inex_t = mpc_fma (t, a, b, c, rnd);
39
40   if (mpc_cmp (z, t) != 0 || inex_z != inex_t) {
41      fprintf (stderr, "fma_naive and fma differ for rnd=(%s,%s)\n",
42               mpfr_print_rnd_mode(MPC_RND_RE(rnd)),
43               mpfr_print_rnd_mode(MPC_RND_IM(rnd)));
44      MPC_OUT (a);
45      MPC_OUT (b);
46      MPC_OUT (c);
47      MPC_OUT (z);
48      MPC_OUT (t);
49      if (inex_z != inex_t) {
50         fprintf (stderr, "inex_re (z): %s\n", MPC_INEX_STR (inex_z));
51         fprintf (stderr, "inex_re (t): %s\n", MPC_INEX_STR (inex_t));
52      }
53      exit (1);
54   }
55
56  mpc_clear (z);
57  mpc_clear (t);
58}
59
60
61static void
62check_random (void)
63{
64   mpfr_prec_t prec;
65   int rnd_re, rnd_im;
66   mpc_t a, b, c;
67
68   mpc_init2 (a, 1000);
69   mpc_init2 (b, 1000);
70   mpc_init2 (c, 1000);
71
72   for (prec = 2; prec < 1000; prec = (mpfr_prec_t) (prec * 1.1 + 1)) {
73      mpc_set_prec (a, prec);
74      mpc_set_prec (b, prec);
75      mpc_set_prec (c, prec);
76
77      test_default_random (a, -1024, 1024, 128, 0);
78      test_default_random (b, -1024, 1024, 128, 0);
79      test_default_random (c, -1024, 1024, 128, 0);
80
81      for (rnd_re = 0; rnd_re < 4; rnd_re ++)
82         for (rnd_im = 0; rnd_im < 4; rnd_im ++)
83            cmpfma (a, b, c, MPC_RND (rnd_re, rnd_im));
84   }
85
86   mpc_clear (a);
87   mpc_clear (b);
88   mpc_clear (c);
89}
90
91#define MPC_FUNCTION_CALL                                               \
92  P[0].mpc_inex =                                                       \
93    mpc_fma (P[1].mpc, P[2].mpc, P[3].mpc, P[4].mpc, P[5].mpc_rnd)
94#define MPC_FUNCTION_CALL_REUSE_OP1                                     \
95  P[0].mpc_inex =                                                       \
96    mpc_fma (P[1].mpc, P[1].mpc, P[3].mpc, P[4].mpc, P[5].mpc_rnd)
97#define MPC_FUNCTION_CALL_REUSE_OP2                                     \
98  P[0].mpc_inex =                                                       \
99    mpc_fma (P[1].mpc, P[2].mpc, P[1].mpc, P[4].mpc, P[5].mpc_rnd)
100#define MPC_FUNCTION_CALL_REUSE_OP3                                     \
101  P[0].mpc_inex =                                                       \
102    mpc_fma (P[1].mpc, P[2].mpc, P[3].mpc, P[1].mpc, P[5].mpc_rnd)
103
104#include "data_check.tpl"
105#include "tgeneric.tpl"
106
107int
108main (void)
109{
110  test_start ();
111
112  check_random (); /* Remove it? */
113
114  data_check_template ("fma.dsc", "fma.dat");
115
116  tgeneric_template ("fma.dsc", 2, 1024, 1, 256);
117
118  test_end ();
119
120  return 0;
121}
122