GNU Octave  4.2.1
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-2017 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 #if defined (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 "quit.h"
38 
39 #include "lo-error.h"
40 #include "lo-ieee.h"
41 #include "lo-mappers.h"
42 #include "lo-utils.h"
43 #include "putenv-wrapper.h"
44 
45 bool xis_int_or_inf_or_nan (double x)
46 { return octave::math::isnan (x) || octave::math::x_nint (x) == x; }
47 
48 bool xis_one_or_zero (double x)
49 { return x == 0 || x == 1; }
50 
51 bool xis_zero (double x)
52 { return x == 0; }
53 
54 bool xtoo_large_for_float (double x)
55 {
56  return (octave::math::finite (x)
57  && fabs (x) > std::numeric_limits<float>::max ());
58 }
59 
61 {
62  return (xtoo_large_for_float (x.real ())
63  || xtoo_large_for_float (x.imag ()));
64 }
65 
67 { return octave::math::isnan (x) || octave::math::x_nint (x) == x; }
68 
69 bool xis_one_or_zero (float x)
70 { return x == 0 || x == 1; }
71 
72 bool xis_zero (float x)
73 { return x == 0; }
74 
75 // Save a string.
76 
77 char *
78 strsave (const char *s)
79 {
80  if (! s)
81  return 0;
82 
83  int len = strlen (s);
84  char *tmp = new char [len+1];
85  tmp = strcpy (tmp, s);
86  return tmp;
87 }
88 
89 // This function was adapted from xputenv from Karl Berry's kpathsearch
90 // library.
91 
92 // FIXME: make this do the right thing if we don't have a SMART_PUTENV.
93 
94 void
96 {
97  int new_len = name.length () + value.length () + 2;
98 
99  // FIXME: This leaks memory, but so would a call to setenv.
100  // Short of extreme measures to track memory, altering the environment
101  // always leaks memory, but the saving grace is that the leaks are small.
102  char *new_item = static_cast<char*> (std::malloc (new_len));
103 
104  sprintf (new_item, "%s=%s", name.c_str (), value.c_str ());
105 
106  // As far as I can see there's no way to distinguish between the
107  // various errors; putenv doesn't have errno values.
108 
109  if (octave_putenv_wrapper (new_item) < 0)
110  (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
111 }
112 
115 {
116  bool eof;
117  return octave_fgets (f, eof);
118 }
119 
121 octave_fgets (FILE *f, bool& eof)
122 {
123  eof = false;
124 
126 
127  int grow_size = 1024;
128  int max_size = grow_size;
129 
130  char *buf = static_cast<char *> (std::malloc (max_size));
131  char *bufptr = buf;
132  int len = 0;
133 
134  do
135  {
136  if (std::fgets (bufptr, grow_size, f))
137  {
138  len = strlen (bufptr);
139 
140  if (len == grow_size - 1)
141  {
142  int tmp = bufptr - buf + grow_size - 1;
143  grow_size *= 2;
144  max_size += grow_size;
145  buf = static_cast<char *> (std::realloc (buf, max_size));
146  bufptr = buf + tmp;
147 
148  if (*(bufptr-1) == '\n')
149  {
150  *bufptr = '\0';
151  retval = buf;
152  }
153  }
154  else if (bufptr[len-1] != '\n')
155  {
156  bufptr[len++] = '\n';
157  bufptr[len] = '\0';
158  retval = buf;
159  }
160  else
161  retval = buf;
162  }
163  else
164  {
165  if (len == 0)
166  {
167  eof = true;
168 
169  free (buf);
170 
171  buf = 0;
172  }
173 
174  break;
175  }
176  }
177  while (retval.empty ());
178 
179  if (buf)
180  free (buf);
181 
182  octave_quit ();
183 
184  return retval;
185 }
186 
189 {
190  bool eof;
191  return octave_fgetl (f, eof);
192 }
193 
195 octave_fgetl (FILE *f, bool& eof)
196 {
197  std::string retval = octave_fgets (f, eof);
198 
199  size_t len = retval.length ();
200 
201  if (retval[len-1] == '\n')
202  retval.resize (len-1);
203 
204  return retval;
205 }
206 
207 // Note that the caller is responsible for repositioning the stream on failure.
208 
209 template <typename T>
210 T
211 read_inf_nan_na (std::istream& is, char c0)
212 {
213  T val = 0.0;
214 
215  switch (c0)
216  {
217  case 'i': case 'I':
218  {
219  char c1 = is.get ();
220  if (c1 == 'n' || c1 == 'N')
221  {
222  char c2 = is.get ();
223  if (c2 == 'f' || c2 == 'F')
224  val = std::numeric_limits<T>::infinity ();
225  else
226  is.setstate (std::ios::failbit);
227  }
228  else
229  is.setstate (std::ios::failbit);
230  }
231  break;
232 
233  case 'n': case 'N':
234  {
235  char c1 = is.get ();
236  if (c1 == 'a' || c1 == 'A')
237  {
238  char c2 = is.get ();
239  if (c2 == 'n' || c2 == 'N')
240  val = std::numeric_limits<T>::quiet_NaN ();
241  else
242  {
244  if (c2 != std::istream::traits_type::eof ())
245  is.putback (c2);
246  }
247  }
248  else
249  is.setstate (std::ios::failbit);
250  }
251  break;
252 
253  default:
254  abort ();
255  }
256 
257  return val;
258 }
259 
260 // Read a double value. Discard any sign on NaN and NA.
261 
262 template <typename T>
263 double
264 octave_read_fp_value (std::istream& is)
265 {
266  T val = 0.0;
267 
268  // FIXME: resetting stream position is likely to fail unless we are
269  // reading from a file.
270  std::ios::streampos pos = is.tellg ();
271 
272  char c1 = ' ';
273 
274  while (isspace (c1))
275  c1 = is.get ();
276 
277  bool neg = false;
278 
279  switch (c1)
280  {
281  case '-':
282  neg = true;
283  // fall through...
284 
285  case '+':
286  {
287  char c2 = 0;
288  c2 = is.get ();
289  if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
290  val = read_inf_nan_na<T> (is, c2);
291  else
292  {
293  is.putback (c2);
294  is >> val;
295  }
296 
297  if (neg && ! is.fail ())
298  val = -val;
299  }
300  break;
301 
302  case 'i': case 'I':
303  case 'n': case 'N':
304  val = read_inf_nan_na<T> (is, c1);
305  break;
306 
307  default:
308  is.putback (c1);
309  is >> val;
310  break;
311  }
312 
313  std::ios::iostate status = is.rdstate ();
314  if (status & std::ios::failbit)
315  {
316  is.clear ();
317  is.seekg (pos);
318  is.setstate (status);
319  }
320 
321  return val;
322 }
323 
324 template <typename T>
325 std::complex<T>
327 {
328  T re = 0.0;
329  T im = 0.0;
330 
331  std::complex<T> cx = 0.0;
332 
333  char ch = ' ';
334 
335  while (isspace (ch))
336  ch = is.get ();
337 
338  if (ch == '(')
339  {
340  re = octave_read_value<T> (is);
341  ch = is.get ();
342 
343  if (ch == ',')
344  {
345  im = octave_read_value<T> (is);
346  ch = is.get ();
347 
348  if (ch == ')')
349  cx = std::complex<T> (re, im);
350  else
351  is.setstate (std::ios::failbit);
352  }
353  else if (ch == ')')
354  cx = re;
355  else
356  is.setstate (std::ios::failbit);
357  }
358  else
359  {
360  is.putback (ch);
361  cx = octave_read_value<double> (is);
362  }
363 
364  return cx;
365 }
366 
367 template <> OCTAVE_API double octave_read_value (std::istream& is)
368 {
369  return octave_read_fp_value<double> (is);
370 }
371 
372 template <> OCTAVE_API Complex octave_read_value (std::istream& is)
373 {
374  return octave_read_cx_fp_value<double> (is);
375 }
376 
377 template <> OCTAVE_API float octave_read_value (std::istream& is)
378 {
379  return octave_read_fp_value<float> (is);
380 }
381 
382 template <> OCTAVE_API FloatComplex octave_read_value (std::istream& is)
383 {
384  return octave_read_cx_fp_value<float> (is);
385 }
386 
387 void
388 octave_write_double (std::ostream& os, double d)
389 {
390  if (lo_ieee_is_NA (d))
391  os << "NA";
392  else if (lo_ieee_isnan (d))
393  os << "NaN";
394  else if (lo_ieee_isinf (d))
395  os << (d < 0 ? "-Inf" : "Inf");
396  else
397  os << d;
398 }
399 
400 void
401 octave_write_complex (std::ostream& os, const Complex& c)
402 {
403  os << "(";
404  octave_write_double (os, real (c));
405  os << ",";
406  octave_write_double (os, imag (c));
407  os << ")";
408 }
409 
410 void
411 octave_write_float (std::ostream& os, float d)
412 {
413  if (lo_ieee_is_NA (d))
414  os << "NA";
415  else if (lo_ieee_isnan (d))
416  os << "NaN";
417  else if (lo_ieee_isinf (d))
418  os << (d < 0 ? "-Inf" : "Inf");
419  else
420  os << d;
421 }
422 
423 void
424 octave_write_float_complex (std::ostream& os, const FloatComplex& c)
425 {
426  os << "(";
427  octave_write_float (os, real (c));
428  os << ",";
429  octave_write_float (os, imag (c));
430  os << ")";
431 }
void octave_write_double(std::ostream &os, double d)
Definition: lo-utils.cc:388
std::complex< T > octave_read_cx_fp_value(std::istream &is)
Definition: lo-utils.cc:326
#define lo_ieee_is_NA(x)
Definition: lo-ieee.h:115
void octave_putenv(const std::string &name, const std::string &value)
Definition: lo-utils.cc:95
std::string octave_fgets(FILE *f)
Definition: lo-utils.cc:114
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE * f
OCTAVE_NORETURN liboctave_error_handler current_liboctave_error_handler
Definition: lo-error.c:38
bool isnan(double x)
Definition: lo-mappers.cc:347
void octave_write_complex(std::ostream &os, const Complex &c)
Definition: lo-utils.cc:401
bool xis_zero(double x)
Definition: lo-utils.cc:51
#define lo_ieee_isinf(x)
Definition: lo-ieee.h:111
int octave_putenv_wrapper(char *str)
s
Definition: file-io.cc:2682
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
#define lo_ieee_isnan(x)
Definition: lo-ieee.h:103
OCTAVE_API double octave_read_value(std::istream &is)
Definition: lo-utils.cc:367
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable name
Definition: input.cc:871
char * strsave(const char *s)
Definition: lo-utils.cc:78
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the special constant used to designate missing values Note that NA always compares not equal to NA(NA!=NA).To find NA values
double tmp
Definition: data.cc:6300
octave_value retval
Definition: data.cc:6294
T read_inf_nan_na(std::istream &is, char c0)
Definition: lo-utils.cc:211
bool finite(double x)
Definition: lo-mappers.cc:367
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
Definition: lu.cc:138
T::size_type strlen(const typename T::value_type *str)
Definition: oct-string.cc:75
double octave_read_fp_value(std::istream &is)
Definition: lo-utils.cc:264
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:228
void octave_write_float(std::ostream &os, float d)
Definition: lo-utils.cc:411
void free(void *)
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the IEEE symbol zero divided by nd tex zero divided by nd ifnottex and any operation involving another NaN value(5+NaN).Note that NaN always compares not equal to NaN(NaN!
bool xtoo_large_for_float(double x)
Definition: lo-utils.cc:54
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:142
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
void * malloc(size_t)
std::complex< double > Complex
Definition: oct-cmplx.h:31
void octave_write_float_complex(std::ostream &os, const FloatComplex &c)
Definition: lo-utils.cc:424
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:136
write the output to stdout if nargout is
Definition: load-save.cc:1576
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:854
bool xis_one_or_zero(double x)
Definition: lo-utils.cc:48
T x_nint(T x)
Definition: lo-mappers.h:299
F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T F77_DBLE &F77_RET_T F77_REAL &F77_RET_T F77_REAL &F77_RET_T F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T F77_REAL F77_REAL &F77_RET_T F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE * x
bool xis_int_or_inf_or_nan(double x)
Definition: lo-utils.cc:45
std::string octave_fgetl(FILE *f)
Definition: lo-utils.cc:188