GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
lo-utils.cc
Go to the documentation of this file.
1 // utils.cc
2 /*
3 
4 Copyright (C) 1996-2015 John W. Eaton
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include <cctype>
29 #include <cstdlib>
30 #include <cstdio>
31 #include <cstring>
32 #include <cfloat>
33 
34 #include <limits>
35 #include <string>
36 
37 #include <sys/types.h>
38 #include <unistd.h>
39 
40 #include "quit.h"
41 
42 #include "lo-error.h"
43 #include "lo-ieee.h"
44 #include "lo-mappers.h"
45 #include "lo-utils.h"
46 
47 bool xis_int_or_inf_or_nan (double x)
48 { return xisnan (x) || D_NINT (x) == x; }
49 
50 bool xis_one_or_zero (double x)
51 { return x == 0 || x == 1; }
52 
53 bool xis_zero (double x)
54 { return x == 0; }
55 
56 bool xtoo_large_for_float (double x)
57 {
58  return (xfinite (x) && fabs (x) > std::numeric_limits<float>::max ());
59 }
60 
62 {
63  return (xtoo_large_for_float (x.real ())
64  || xtoo_large_for_float (x.imag ()));
65 }
66 
68 { return xisnan (x) || D_NINT (x) == x; }
69 
70 bool xis_one_or_zero (float x)
71 { return x == 0 || x == 1; }
72 
73 bool xis_zero (float x)
74 { return x == 0; }
75 
76 // Save a string.
77 
78 char *
79 strsave (const char *s)
80 {
81  if (! s)
82  return 0;
83 
84  int len = strlen (s);
85  char *tmp = new char [len+1];
86  tmp = strcpy (tmp, s);
87  return tmp;
88 }
89 
90 // This function was adapted from xputenv from Karl Berry's kpathsearch
91 // library.
92 
93 // FIXME: make this do the right thing if we don't have a SMART_PUTENV.
94 
95 void
96 octave_putenv (const std::string& name, const std::string& value)
97 {
98  int new_len = name.length () + value.length () + 2;
99 
100  char *new_item = static_cast<char*> (gnulib::malloc (new_len));
101 
102  sprintf (new_item, "%s=%s", name.c_str (), value.c_str ());
103 
104  // As far as I can see there's no way to distinguish between the
105  // various errors; putenv doesn't have errno values.
106 
107  if (gnulib::putenv (new_item) < 0)
108  (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
109 }
110 
111 std::string
113 {
114  bool eof;
115  return octave_fgets (f, eof);
116 }
117 
118 std::string
119 octave_fgets (FILE *f, bool& eof)
120 {
121  eof = false;
122 
123  std::string retval;
124 
125  int grow_size = 1024;
126  int max_size = grow_size;
127 
128  char *buf = static_cast<char *> (gnulib::malloc (max_size));
129  char *bufptr = buf;
130  int len = 0;
131 
132  do
133  {
134  if (gnulib::fgets (bufptr, grow_size, f))
135  {
136  len = strlen (bufptr);
137 
138  if (len == grow_size - 1)
139  {
140  int tmp = bufptr - buf + grow_size - 1;
141  grow_size *= 2;
142  max_size += grow_size;
143  buf = static_cast<char *> (gnulib::realloc (buf, max_size));
144  bufptr = buf + tmp;
145 
146  if (*(bufptr-1) == '\n')
147  {
148  *bufptr = '\0';
149  retval = buf;
150  }
151  }
152  else if (bufptr[len-1] != '\n')
153  {
154  bufptr[len++] = '\n';
155  bufptr[len] = '\0';
156  retval = buf;
157  }
158  else
159  retval = buf;
160  }
161  else
162  {
163  if (len == 0)
164  {
165  eof = true;
166 
167  free (buf);
168 
169  buf = 0;
170  }
171 
172  break;
173  }
174  }
175  while (retval.empty ());
176 
177  if (buf)
178  free (buf);
179 
180  octave_quit ();
181 
182  return retval;
183 }
184 
185 std::string
187 {
188  bool eof;
189  return octave_fgetl (f, eof);
190 }
191 
192 std::string
193 octave_fgetl (FILE *f, bool& eof)
194 {
195  std::string retval = octave_fgets (f, eof);
196 
197  size_t len = retval.length ();
198 
199  if (retval[len-1] == '\n')
200  retval.resize (len-1);
201 
202  return retval;
203 }
204 
205 // Note that the caller is responsible for repositioning the stream on failure.
206 
207 template <typename T>
208 T
209 read_inf_nan_na (std::istream& is, char c0)
210 {
211  T val = 0.0;
212 
213  switch (c0)
214  {
215  case 'i': case 'I':
216  {
217  char c1 = is.get ();
218  if (c1 == 'n' || c1 == 'N')
219  {
220  char c2 = is.get ();
221  if (c2 == 'f' || c2 == 'F')
222  val = std::numeric_limits<T>::infinity ();
223  else
224  is.setstate (std::ios::failbit);
225  }
226  else
227  is.setstate (std::ios::failbit);
228  }
229  break;
230 
231  case 'n': case 'N':
232  {
233  char c1 = is.get ();
234  if (c1 == 'a' || c1 == 'A')
235  {
236  char c2 = is.get ();
237  if (c2 == 'n' || c2 == 'N')
238  val = std::numeric_limits<T>::quiet_NaN ();
239  else
240  {
241  val = octave_numeric_limits<T>::NA ();
242  if (c2 != EOF)
243  is.putback (c2);
244  }
245  }
246  else
247  is.setstate (std::ios::failbit);
248  }
249  break;
250 
251  default:
252  abort ();
253  }
254 
255  return val;
256 }
257 
258 // Read a double value. Discard any sign on NaN and NA.
259 
260 template <typename T>
261 double
262 octave_read_fp_value (std::istream& is)
263 {
264  T val = 0.0;
265 
266  // FIXME: resetting stream position is likely to fail unless we are
267  // reading from a file.
268  std::ios::streampos pos = is.tellg ();
269 
270  char c1 = ' ';
271 
272  while (isspace (c1))
273  c1 = is.get ();
274 
275  bool neg = false;
276 
277  switch (c1)
278  {
279  case '-':
280  neg = true;
281  // fall through...
282 
283  case '+':
284  {
285  char c2 = 0;
286  c2 = is.get ();
287  if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
288  val = read_inf_nan_na<T> (is, c2);
289  else
290  {
291  is.putback (c2);
292  is >> val;
293  }
294 
295  if (neg && ! is.fail ())
296  val = -val;
297  }
298  break;
299 
300  case 'i': case 'I':
301  case 'n': case 'N':
302  val = read_inf_nan_na<T> (is, c1);
303  break;
304 
305  default:
306  is.putback (c1);
307  is >> val;
308  break;
309  }
310 
311  std::ios::iostate status = is.rdstate ();
312  if (status & std::ios::failbit)
313  {
314  is.clear ();
315  is.seekg (pos);
316  is.setstate (status);
317  }
318 
319  return val;
320 }
321 
322 template <typename T>
323 std::complex<T>
324 octave_read_cx_fp_value (std::istream& is)
325 {
326  T re = 0.0;
327  T im = 0.0;
328 
329  std::complex<T> cx = 0.0;
330 
331  char ch = ' ';
332 
333  while (isspace (ch))
334  ch = is.get ();
335 
336  if (ch == '(')
337  {
338  re = octave_read_value<T> (is);
339  ch = is.get ();
340 
341  if (ch == ',')
342  {
343  im = octave_read_value<T> (is);
344  ch = is.get ();
345 
346  if (ch == ')')
347  cx = std::complex<T> (re, im);
348  else
349  is.setstate (std::ios::failbit);
350  }
351  else if (ch == ')')
352  cx = re;
353  else
354  is.setstate (std::ios::failbit);
355  }
356  else
357  {
358  is.putback (ch);
359  cx = octave_read_value<double> (is);
360  }
361 
362  return cx;
363 }
364 
365 template <> OCTAVE_API double octave_read_value (std::istream& is)
366 {
367  return octave_read_fp_value<double> (is);
368 }
369 
370 template <> OCTAVE_API Complex octave_read_value (std::istream& is)
371 {
372  return octave_read_cx_fp_value<double> (is);
373 }
374 
375 template <> OCTAVE_API float octave_read_value (std::istream& is)
376 {
377  return octave_read_fp_value<float> (is);
378 }
379 
380 template <> OCTAVE_API FloatComplex octave_read_value (std::istream& is)
381 {
382  return octave_read_cx_fp_value<float> (is);
383 }
384 
385 void
386 octave_write_double (std::ostream& os, double d)
387 {
388  if (lo_ieee_is_NA (d))
389  os << "NA";
390  else if (lo_ieee_isnan (d))
391  os << "NaN";
392  else if (lo_ieee_isinf (d))
393  os << (d < 0 ? "-Inf" : "Inf");
394  else
395  os << d;
396 }
397 
398 void
399 octave_write_complex (std::ostream& os, const Complex& c)
400 {
401  os << "(";
402  octave_write_double (os, real (c));
403  os << ",";
404  octave_write_double (os, imag (c));
405  os << ")";
406 }
407 
408 void
409 octave_write_float (std::ostream& os, float d)
410 {
411  if (lo_ieee_is_NA (d))
412  os << "NA";
413  else if (lo_ieee_isnan (d))
414  os << "NaN";
415  else if (lo_ieee_isinf (d))
416  os << (d < 0 ? "-Inf" : "Inf");
417  else
418  os << d;
419 }
420 
421 void
422 octave_write_float_complex (std::ostream& os, const FloatComplex& c)
423 {
424  os << "(";
425  octave_write_float (os, real (c));
426  os << ",";
427  octave_write_float (os, imag (c));
428  os << ")";
429 }
void octave_write_double(std::ostream &os, double d)
Definition: lo-utils.cc:386
std::complex< T > octave_read_cx_fp_value(std::istream &is)
Definition: lo-utils.cc:324
#define lo_ieee_is_NA(x)
Definition: lo-ieee.h:109
void octave_putenv(const std::string &name, const std::string &value)
Definition: lo-utils.cc:96
bool xisnan(double x)
Definition: lo-mappers.cc:144
std::string octave_fgets(FILE *f)
Definition: lo-utils.cc:112
void octave_write_complex(std::ostream &os, const Complex &c)
Definition: lo-utils.cc:399
bool xis_zero(double x)
Definition: lo-utils.cc:53
#define lo_ieee_isinf(x)
Definition: lo-ieee.h:105
F77_RET_T const double const double double * d
#define lo_ieee_isnan(x)
Definition: lo-ieee.h:101
OCTAVE_API double octave_read_value(std::istream &is)
Definition: lo-utils.cc:365
liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
char * strsave(const char *s)
Definition: lo-utils.cc:79
F77_RET_T const double const double * f
T read_inf_nan_na(std::istream &is, char c0)
Definition: lo-utils.cc:209
OCTAVE_API double D_NINT(double x)
Definition: lo-mappers.h:240
double octave_read_fp_value(std::istream &is)
Definition: lo-utils.cc:262
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:233
bool xfinite(double x)
Definition: lo-mappers.cc:152
void octave_write_float(std::ostream &os, float d)
Definition: lo-utils.cc:409
void free(void *)
bool xtoo_large_for_float(double x)
Definition: lo-utils.cc:56
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:162
std::complex< float > FloatComplex
Definition: oct-cmplx.h:30
static MArray< double > const octave_idx_type const octave_idx_type octave_idx_type octave_idx_type octave_idx_type c1
void * malloc(size_t)
std::complex< double > Complex
Definition: oct-cmplx.h:29
void octave_write_float_complex(std::ostream &os, const FloatComplex &c)
Definition: lo-utils.cc:422
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:156
bool xis_one_or_zero(double x)
Definition: lo-utils.cc:50
F77_RET_T const double * x
bool xis_int_or_inf_or_nan(double x)
Definition: lo-utils.cc:47
std::string octave_fgetl(FILE *f)
Definition: lo-utils.cc:186