1/* tio_str-- Test file for mpc_inp_str and mpc_out_str.
2
3Copyright (C) 2009, 2011 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
23#ifdef HAVE_UNISTD_H
24#define _POSIX_C_SOURCE 1 /* apparently needed on Darwin */
25#include <unistd.h> /* for dup, dup2, STDIN_FILENO and STDOUT_FILENO */
26#else
27#define STDIN_FILENO 0
28#define STDOUT_FILENO 1
29#endif
30
31extern unsigned long line_number;
32/* character appearing next in the file, may be EOF */
33extern int nextchar;
34extern const char *rnd_mode[];
35
36static void
37check_file (const char* file_name)
38{
39  FILE *fp;
40
41  int tmp;
42  int base;
43  int inex_re;
44  int inex_im;
45  mpc_t expected, got;
46  mpc_rnd_t rnd = MPC_RNDNN;
47  int inex = 0, expected_inex;
48  size_t expected_size, size;
49  known_signs_t ks = {1, 1};
50
51  fp = open_data_file (file_name);
52
53  mpc_init2 (expected, 53);
54  mpc_init2 (got, 53);
55
56  /* read data file */
57  line_number = 1;
58  nextchar = getc (fp);
59  skip_whitespace_comments (fp);
60
61  while (nextchar != EOF)
62    {
63      /* 1. read a line of data: expected result, base, rounding mode */
64      read_ternary (fp, &inex_re);
65      read_ternary (fp, &inex_im);
66      read_mpc (fp, expected, &ks);
67      if (inex_re == TERNARY_ERROR || inex_im == TERNARY_ERROR)
68         expected_inex = -1;
69      else
70         expected_inex = MPC_INEX (inex_re, inex_im);
71      read_int (fp, &tmp, "size");
72      expected_size = (size_t)tmp;
73      read_int (fp, &base, "base");
74      read_mpc_rounding_mode (fp, &rnd);
75
76      /* 2. read string at the same precision as the expected result */
77      while (nextchar != '"')
78        nextchar = getc (fp);
79      mpfr_set_prec (mpc_realref (got), MPC_PREC_RE (expected));
80      mpfr_set_prec (mpc_imagref (got), MPC_PREC_IM (expected));
81      inex = mpc_inp_str (got, fp, &size, base, rnd);
82
83      /* 3. compare this result with the expected one */
84      if (inex != expected_inex || !same_mpc_value (got, expected, ks)
85          || size != expected_size)
86        {
87          printf ("mpc_inp_str failed (line %lu) with rounding mode %s\n",
88                  line_number, rnd_mode[rnd]);
89          if (inex != expected_inex)
90            printf("     got inexact value: %d\nexpected inexact value: %d\n",
91                   inex, expected_inex);
92          if (size !=  expected_size)
93            printf ("     got size: %lu\nexpected size: %lu\n     ",
94                    (unsigned long int) size, (unsigned long int) expected_size);
95          printf ("    ");
96          MPC_OUT (got);
97          MPC_OUT (expected);
98
99          exit (1);
100        }
101
102      while ((nextchar = getc (fp)) != '"');
103      nextchar = getc (fp);
104
105      skip_whitespace_comments (fp);
106    }
107
108  mpc_clear (expected);
109  mpc_clear (got);
110  close_data_file (fp);
111}
112
113static void
114check_io_str (mpc_ptr read_number, mpc_ptr expected)
115{
116  char tmp_file[] = "mpc_test";
117  FILE *fp;
118  size_t sz;
119
120  if (!(fp = fopen (tmp_file, "w")))
121    {
122      printf ("Error: Could not open file %s in write mode\n", tmp_file);
123      exit (1);
124    }
125
126  mpc_out_str (fp, 10, 0, expected, MPC_RNDNN);
127  fclose (fp);
128
129  if (!(fp = fopen (tmp_file, "r")))
130    {
131      printf ("Error: Could not open file %s in read mode\n", tmp_file);
132      exit (1);
133    };
134  if (mpc_inp_str (read_number, fp, &sz, 10, MPC_RNDNN) == -1)
135    {
136      printf ("Error: mpc_inp_str cannot correctly re-read number "
137              "in file %s\n", tmp_file);
138
139      exit (1);
140    }
141  fclose (fp);
142
143  /* mpc_cmp set erange flag when an operand is a NaN */
144  mpfr_clear_flags ();
145  if (mpc_cmp (read_number, expected) != 0 || mpfr_erangeflag_p())
146    {
147      printf ("Error: inp_str o out_str <> Id\n");
148      MPC_OUT (read_number);
149      MPC_OUT (expected);
150
151      exit (1);
152    }
153}
154
155#ifndef MPC_NO_STREAM_REDIRECTION
156/* test out_str with stream=NULL */
157static void
158check_stdout (mpc_ptr read_number, mpc_ptr expected)
159{
160  char tmp_file[] = "mpc_test";
161  int fd;
162  size_t sz;
163
164  fflush (stdout);
165  fd = dup (STDOUT_FILENO);
166  if (freopen (tmp_file, "w", stdout) == NULL)
167  {
168     printf ("mpc_inp_str cannot redirect stdout\n");
169     exit (1);
170  }
171  mpc_out_str (NULL, 2, 0, expected, MPC_RNDNN);
172  fflush (stdout);
173  dup2 (fd, STDOUT_FILENO);
174  close (fd);
175  clearerr (stdout);
176
177  fflush (stdin);
178  fd = dup (STDIN_FILENO);
179  if (freopen (tmp_file, "r", stdin) == NULL)
180  {
181     printf ("mpc_inp_str cannot redirect stdout\n");
182     exit (1);
183  }
184  if (mpc_inp_str (read_number, NULL, &sz, 2, MPC_RNDNN) == -1)
185    {
186      printf ("mpc_inp_str cannot correctly re-read number "
187              "in file %s\n", tmp_file);
188      exit (1);
189    }
190  mpfr_clear_flags (); /* mpc_cmp set erange flag when an operand is
191                          a NaN */
192  if (mpc_cmp (read_number, expected) != 0 || mpfr_erangeflag_p())
193    {
194      printf ("mpc_inp_str did not read the number which was written by "
195              "mpc_out_str\n");
196      MPC_OUT (read_number);
197      MPC_OUT (expected);
198      exit (1);
199    }
200  fflush (stdin);
201  dup2 (fd, STDIN_FILENO);
202  close (fd);
203  clearerr (stdin);
204}
205#endif /* MPC_NO_STREAM_REDIRECTION */
206
207int
208main (void)
209{
210  mpc_t z, x;
211  mpfr_prec_t prec;
212
213  test_start ();
214
215  mpc_init2 (z, 1000);
216  mpc_init2 (x, 1000);
217
218  check_file ("inp_str.dat");
219
220  for (prec = 2; prec <= 1000; prec+=7)
221    {
222      mpc_set_prec (z, prec);
223      mpc_set_prec (x, prec);
224
225      mpc_set_si_si (x, 1, 1, MPC_RNDNN);
226      check_io_str (z, x);
227
228      mpc_set_si_si (x, -1, 1, MPC_RNDNN);
229      check_io_str (z, x);
230
231      mpfr_set_inf (mpc_realref(x), -1);
232      mpfr_set_inf (mpc_imagref(x), +1);
233      check_io_str (z, x);
234
235      test_default_random (x,  -1024, 1024, 128, 25);
236      check_io_str (z, x);
237    }
238
239#ifndef MPC_NO_STREAM_REDIRECTION
240  mpc_set_si_si (x, 1, -4, MPC_RNDNN);
241  mpc_div_ui (x, x, 3, MPC_RNDDU);
242
243  check_stdout(z, x);
244#endif
245
246  mpc_clear (z);
247  mpc_clear (x);
248
249  test_end ();
250
251  return 0;
252}
253