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