GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
lo-utils.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2018 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 #if defined (HAVE_CONFIG_H)
24 # include "config.h"
25 #endif
26 
27 #include <cstdlib>
28 #include <cstring>
29 
30 #include <complex>
31 #include <limits>
32 #include <string>
33 
34 #include "quit.h"
35 
36 #include "lo-error.h"
37 #include "lo-ieee.h"
38 #include "lo-mappers.h"
39 #include "lo-utils.h"
40 #include "putenv-wrapper.h"
41 
42 bool xis_int_or_inf_or_nan (double x)
43 { return octave::math::isnan (x) || octave::math::x_nint (x) == x; }
44 
45 bool xis_one_or_zero (double x)
46 { return x == 0 || x == 1; }
47 
48 bool xis_zero (double x)
49 { return x == 0; }
50 
51 bool xtoo_large_for_float (double x)
52 {
53  return (octave::math::isfinite (x)
54  && fabs (x) > std::numeric_limits<float>::max ());
55 }
56 
58 {
59  return (xtoo_large_for_float (x.real ())
60  || xtoo_large_for_float (x.imag ()));
61 }
62 
64 { return octave::math::isnan (x) || octave::math::x_nint (x) == x; }
65 
66 bool xis_one_or_zero (float x)
67 { return x == 0 || x == 1; }
68 
69 bool xis_zero (float x)
70 { return x == 0; }
71 
72 // Save a string.
73 
74 char *
75 strsave (const char *s)
76 {
77  if (! s)
78  return nullptr;
79 
80  int len = strlen (s);
81  char *tmp = new char [len+1];
82  tmp = strcpy (tmp, s);
83  return tmp;
84 }
85 
86 // This function was adapted from xputenv from Karl Berry's kpathsearch
87 // library.
88 
89 // FIXME: make this do the right thing if we don't have a SMART_PUTENV.
90 
91 void
93 {
94  int new_len = name.length () + value.length () + 2;
95 
96  // FIXME: This leaks memory, but so would a call to setenv.
97  // Short of extreme measures to track memory, altering the environment
98  // always leaks memory, but the saving grace is that the leaks are small.
99  char *new_item = static_cast<char *> (std::malloc (new_len));
100 
101  sprintf (new_item, "%s=%s", name.c_str (), value.c_str ());
102 
103  // As far as I can see there's no way to distinguish between the
104  // various errors; putenv doesn't have errno values.
105 
106  if (octave_putenv_wrapper (new_item) < 0)
107  (*current_liboctave_error_handler) ("putenv (%s) failed", new_item);
108 }
109 
112 {
113  bool eof;
114  return octave_fgets (f, eof);
115 }
116 
118 octave_fgets (FILE *f, bool& eof)
119 {
120  eof = false;
121 
123 
124  int grow_size = 1024;
125  int max_size = grow_size;
126 
127  char *buf = static_cast<char *> (std::malloc (max_size));
128  char *bufptr = buf;
129  int len = 0;
130 
131  do
132  {
133  if (std::fgets (bufptr, grow_size, f))
134  {
135  len = strlen (bufptr);
136 
137  if (len == grow_size - 1)
138  {
139  int tmp = bufptr - buf + grow_size - 1;
140  grow_size *= 2;
141  max_size += grow_size;
142  buf = static_cast<char *> (std::realloc (buf, max_size));
143  bufptr = buf + tmp;
144 
145  if (*(bufptr-1) == '\n')
146  {
147  *bufptr = '\0';
148  retval = buf;
149  }
150  }
151  else if (bufptr[len-1] != '\n')
152  {
153  bufptr[len++] = '\n';
154  bufptr[len] = '\0';
155  retval = buf;
156  }
157  else
158  retval = buf;
159  }
160  else
161  {
162  if (len == 0)
163  {
164  eof = true;
165 
166  free (buf);
167 
168  buf = nullptr;
169  }
170 
171  break;
172  }
173  }
174  while (retval.empty ());
175 
176  free (buf);
177 
178  octave_quit ();
179 
180  return retval;
181 }
182 
185 {
186  bool eof;
187  return octave_fgetl (f, eof);
188 }
189 
191 octave_fgetl (FILE *f, bool& eof)
192 {
193  std::string retval = octave_fgets (f, eof);
194 
195  if (! retval.empty () && retval.back () == '\n')
196  retval.pop_back ();
197 
198  return retval;
199 }
200 
201 // Note that the caller is responsible for repositioning the stream on failure.
202 
203 template <typename T>
204 T
205 read_inf_nan_na (std::istream& is, char c0)
206 {
207  T val = 0.0;
208 
209  switch (c0)
210  {
211  case 'i': case 'I':
212  {
213  char c1 = is.get ();
214  if (c1 == 'n' || c1 == 'N')
215  {
216  char c2 = is.get ();
217  if (c2 == 'f' || c2 == 'F')
218  val = std::numeric_limits<T>::infinity ();
219  else
220  is.setstate (std::ios::failbit);
221  }
222  else
223  is.setstate (std::ios::failbit);
224  }
225  break;
226 
227  case 'n': case 'N':
228  {
229  char c1 = is.get ();
230  if (c1 == 'a' || c1 == 'A')
231  {
232  char c2 = is.get ();
233  if (c2 == 'n' || c2 == 'N')
234  val = std::numeric_limits<T>::quiet_NaN ();
235  else
236  {
238  if (c2 != std::istream::traits_type::eof ())
239  is.putback (c2);
240  }
241  }
242  else
243  is.setstate (std::ios::failbit);
244  }
245  break;
246 
247  default:
248  (*current_liboctave_error_handler) ("read_inf_nan_na: invalid character '%c'");
249  }
250 
251  return val;
252 }
253 
254 // Read a double value. Discard any sign on NaN and NA.
255 
256 template <typename T>
257 double
258 octave_read_fp_value (std::istream& is)
259 {
260  T val = 0.0;
261 
262  // FIXME: resetting stream position is likely to fail unless we are
263  // reading from a file.
264  std::ios::streampos pos = is.tellg ();
265 
266  char c1 = ' ';
267 
268  while (isspace (c1))
269  c1 = is.get ();
270 
271  bool neg = false;
272 
273  switch (c1)
274  {
275  case '-':
276  neg = true;
277  OCTAVE_FALLTHROUGH;
278 
279  case '+':
280  {
281  char c2 = 0;
282  c2 = is.get ();
283  if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
284  val = read_inf_nan_na<T> (is, c2);
285  else
286  {
287  is.putback (c2);
288  is >> val;
289  }
290 
291  if (neg && ! is.fail ())
292  val = -val;
293  }
294  break;
295 
296  case 'i': case 'I':
297  case 'n': case 'N':
298  val = read_inf_nan_na<T> (is, c1);
299  break;
300 
301  default:
302  is.putback (c1);
303  is >> val;
304  break;
305  }
306 
307  std::ios::iostate status = is.rdstate ();
308  if (status & std::ios::failbit)
309  {
310  // Convert MAX_VAL returned by C++ streams for very large numbers to Inf
312  {
313  if (neg)
314  val = -std::numeric_limits<T>::infinity ();
315  else
316  val = std::numeric_limits<T>::infinity ();
317  is.clear (status & ~std::ios::failbit);
318  }
319  else
320  {
321  // True error. Reset stream to original position and pass status on.
322  is.clear ();
323  is.seekg (pos);
324  is.setstate (status);
325  }
326  }
327 
328  return val;
329 }
330 
331 template <typename T>
332 std::complex<T>
334 {
335  T re = 0.0;
336  T im = 0.0;
337 
338  std::complex<T> cx = 0.0;
339 
340  char ch = ' ';
341 
342  while (isspace (ch))
343  ch = is.get ();
344 
345  if (ch == '(')
346  {
347  re = octave_read_value<T> (is);
348  ch = is.get ();
349 
350  if (ch == ',')
351  {
352  im = octave_read_value<T> (is);
353  ch = is.get ();
354 
355  if (ch == ')')
356  cx = std::complex<T> (re, im);
357  else
358  is.setstate (std::ios::failbit);
359  }
360  else if (ch == ')')
361  cx = re;
362  else
363  is.setstate (std::ios::failbit);
364  }
365  else
366  {
367  is.putback (ch);
368  cx = octave_read_value<double> (is);
369  }
370 
371  return cx;
372 }
373 
374 template <> OCTAVE_API double octave_read_value (std::istream& is)
375 {
376  return octave_read_fp_value<double> (is);
377 }
378 
379 template <> OCTAVE_API Complex octave_read_value (std::istream& is)
380 {
381  return octave_read_cx_fp_value<double> (is);
382 }
383 
384 template <> OCTAVE_API float octave_read_value (std::istream& is)
385 {
386  return octave_read_fp_value<float> (is);
387 }
388 
389 template <> OCTAVE_API FloatComplex octave_read_value (std::istream& is)
390 {
391  return octave_read_cx_fp_value<float> (is);
392 }
393 
394 void
395 octave_write_double (std::ostream& os, double d)
396 {
397  if (lo_ieee_is_NA (d))
398  os << "NA";
399  else if (lo_ieee_isnan (d))
400  os << "NaN";
401  else if (lo_ieee_isinf (d))
402  os << (d < 0 ? "-Inf" : "Inf");
403  else
404  os << d;
405 }
406 
407 void
408 octave_write_complex (std::ostream& os, const Complex& c)
409 {
410  os << '(';
412  os << ',';
414  os << ')';
415 }
416 
417 void
418 octave_write_float (std::ostream& os, float d)
419 {
420  if (lo_ieee_is_NA (d))
421  os << "NA";
422  else if (lo_ieee_isnan (d))
423  os << "NaN";
424  else if (lo_ieee_isinf (d))
425  os << (d < 0 ? "-Inf" : "Inf");
426  else
427  os << d;
428 }
429 
430 void
432 {
433  os << '(';
435  os << ',';
437  os << ')';
438 }
void octave_write_double(std::ostream &os, double d)
Definition: lo-utils.cc:395
std::complex< T > octave_read_cx_fp_value(std::istream &is)
Definition: lo-utils.cc:333
#define lo_ieee_is_NA(x)
Definition: lo-ieee.h:117
void octave_putenv(const std::string &name, const std::string &value)
Definition: lo-utils.cc:92
std::string octave_fgets(FILE *f)
Definition: lo-utils.cc:111
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
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 const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &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(bool)
Definition: lo-mappers.h:187
void octave_write_complex(std::ostream &os, const Complex &c)
Definition: lo-utils.cc:408
bool xis_zero(double x)
Definition: lo-utils.cc:48
#define lo_ieee_isinf(x)
Definition: lo-ieee.h:113
int octave_putenv_wrapper(char *str)
nd example oindent opens the file binary numeric values will be read assuming they are stored in IEEE format with the least significant bit and then converted to the native representation Opening a file that is already open simply opens it again and returns a separate file id It is not an error to open a file several though writing to the same file through several different file ids may produce unexpected results The possible values of text mode reading and writing automatically converts linefeeds to the appropriate line end character for the you may append a you must also open the file in binary mode The parameter conversions are currently only supported for and permissions will be set to and then everything is written in a single operation This is very efficient and improves performance c
Definition: file-io.cc:587
s
Definition: file-io.cc:2729
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 const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
#define lo_ieee_isnan(x)
Definition: lo-ieee.h:105
OCTAVE_API double octave_read_value(std::istream &is)
Definition: lo-utils.cc:374
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
nd deftypefn *std::string name
Definition: sysdep.cc:647
char * strsave(const char *s)
Definition: lo-utils.cc:75
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
T read_inf_nan_na(std::istream &is, char c0)
Definition: lo-utils.cc:205
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:258
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:227
void octave_write_float(std::ostream &os, float d)
Definition: lo-utils.cc:418
bool isfinite(double x)
Definition: lo-mappers.h:201
bool xtoo_large_for_float(double x)
Definition: lo-utils.cc:51
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:141
std::complex< float > FloatComplex
Definition: oct-cmplx.h:32
std::complex< double > Complex
Definition: oct-cmplx.h:31
void octave_write_float_complex(std::ostream &os, const FloatComplex &c)
Definition: lo-utils.cc:431
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:135
write the output to stdout if nargout is
Definition: load-save.cc:1612
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:888
nd group nd example For each display the value
Definition: sysdep.cc:866
bool xis_one_or_zero(double x)
Definition: lo-utils.cc:45
octave::stream os
Definition: file-io.cc:627
T x_nint(T x)
Definition: lo-mappers.h:284
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 const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
bool xis_int_or_inf_or_nan(double x)
Definition: lo-utils.cc:42
std::string octave_fgetl(FILE *f)
Definition: lo-utils.cc:184