GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
lo-utils.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <cstdlib>
31#include <cstring>
32
33#include <complex>
34#include <istream>
35#include <limits>
36#include <ostream>
37#include <string>
38
39#include "quit.h"
40
41#include "intprops-wrappers.h"
42#include "lo-error.h"
43#include "lo-ieee.h"
44#include "lo-mappers.h"
45#include "lo-utils.h"
46#include "oct-inttypes.h"
47
49
51{
52 return math::isnan (x) || math::x_nint (x) == x;
53}
54
55bool
57{
58 return (math::isfinite (x)
59 && fabs (x) > std::numeric_limits<float>::max ());
60}
61
62bool
64{
65 return (too_large_for_float (x.real ())
66 || too_large_for_float (x.imag ()));
67}
68
69bool
71{
72 return math::isnan (x) || math::x_nint (x) == x;
73}
74
75// Save a string.
76
77char *
78strsave (const char *s)
79{
80 if (! s)
81 return nullptr;
82
83 int len = strlen (s);
84 char *tmp = new char [len+1];
85 tmp = strcpy (tmp, s);
86 return tmp;
87}
88
89std::string
90fgets (FILE *f)
91{
92 bool eof;
93 return fgets (f, eof);
94}
95
96std::string
97fgets (FILE *f, bool& eof)
98{
99 eof = false;
100
101 std::string retval;
102
103 int grow_size = 1024;
104 int max_size = grow_size;
105
106 char *buf = static_cast<char *> (std::malloc (max_size));
107 if (! buf)
108 (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size);
109
110 char *bufptr = buf;
111 int len = 0;
112
113 do
114 {
115 if (std::fgets (bufptr, grow_size, f))
116 {
117 len = strlen (bufptr);
118
119 if (len == grow_size - 1)
120 {
121 int tmp = bufptr - buf + grow_size - 1;
122 grow_size *= 2;
123 max_size += grow_size;
124 auto tmpbuf = static_cast<char *> (std::realloc (buf, max_size));
125 if (! tmpbuf)
126 {
127 free (buf);
128 (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size);
129 }
130 buf = tmpbuf;
131 bufptr = buf + tmp;
132
133 if (*(bufptr-1) == '\n')
134 {
135 *bufptr = '\0';
136 retval = buf;
137 }
138 }
139 else if (bufptr[len-1] != '\n')
140 {
141 bufptr[len++] = '\n';
142 bufptr[len] = '\0';
143 retval = buf;
144 }
145 else
146 retval = buf;
147 }
148 else
149 {
150 if (len == 0)
151 {
152 eof = true;
153
154 free (buf);
155
156 buf = nullptr;
157 }
158
159 break;
160 }
161 }
162 while (retval.empty ());
163
164 free (buf);
165
166 octave_quit ();
167
168 return retval;
169}
170
171std::string
172fgetl (FILE *f)
173{
174 bool eof;
175 return fgetl (f, eof);
176}
177
178std::string
179fgetl (FILE *f, bool& eof)
180{
181 std::string retval = fgets (f, eof);
182
183 if (! retval.empty () && retval.back () == '\n')
184 retval.pop_back ();
185
186 return retval;
187}
188
189template <typename T>
190T
191read_value (std::istream& is)
192{
193 T retval;
194 is >> retval;
195 return retval;
196}
197
198template OCTAVE_API bool read_value<bool> (std::istream& is);
207
208// Note that the caller is responsible for repositioning the stream on
209// failure.
210
211template <typename T>
212T
213read_inf_nan_na (std::istream& is, char c0)
214{
215 T val = 0.0;
216
217 switch (c0)
218 {
219 case 'i': case 'I':
220 {
221 char c1 = is.get ();
222 if (c1 == 'n' || c1 == 'N')
223 {
224 char c2 = is.get ();
225 if (c2 == 'f' || c2 == 'F')
226 {
227 val = std::numeric_limits<T>::infinity ();
228 is.peek (); // Potentially set EOF bit
229 }
230 else
231 is.setstate (std::ios::failbit);
232 }
233 else
234 is.setstate (std::ios::failbit);
235 }
236 break;
237
238 case 'n': case 'N':
239 {
240 char c1 = is.get ();
241 if (c1 == 'a' || c1 == 'A')
242 {
243 char c2 = is.get ();
244 if (c2 == 'n' || c2 == 'N')
245 val = std::numeric_limits<T>::quiet_NaN ();
246 else
247 {
248 val = numeric_limits<T>::NA ();
249 is.putback (c2);
250 is.clear (is.rdstate () & ~std::ios::failbit);
251 }
252 is.peek (); // Potentially set EOF bit
253 }
254 else
255 is.setstate (std::ios::failbit);
256 }
257 break;
258
259 default:
260 (*current_liboctave_error_handler)
261 ("read_inf_nan_na: invalid character '%c'", c0);
262 }
263
264 return val;
265}
266
267// Read a double value. Discard any sign on NaN and NA.
268
269template <typename T>
270double
271read_fp_value (std::istream& is)
272{
273 T val = 0.0;
274
275 // FIXME: resetting stream position is likely to fail unless we are
276 // reading from a file.
277 std::streampos pos = is.tellg ();
278
279 is >> std::ws; // skip through whitespace and advance stream pointer
280
281 bool neg = false;
282 char c1 = is.get ();
283 switch (c1)
284 {
285 case '-':
286 neg = true;
287 OCTAVE_FALLTHROUGH;
288
289 case '+':
290 {
291 char c2 = 0;
292 c2 = is.get ();
293 if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N')
294 val = read_inf_nan_na<T> (is, c2);
295 else if (isspace (c2))
296 is.setstate (std::ios::failbit);
297 else
298 {
299 is.putback (c2);
300 is >> val;
301 }
302
303 if (neg && ! math::isnan (val) && ! is.fail ())
304 val = -val;
305 }
306 break;
307
308 case 'i': case 'I':
309 case 'n': case 'N':
310 val = read_inf_nan_na<T> (is, c1);
311 break;
312
313 default:
314 is.putback (c1);
315 is >> val;
316 break;
317 }
318
319 std::ios::iostate status = is.rdstate ();
320 if (status & std::ios::failbit)
321 {
322 // Convert MAX_VAL returned by C++ streams for very large numbers to Inf
323 if (val == std::numeric_limits<T>::max ())
324 {
325 if (neg)
326 val = -std::numeric_limits<T>::infinity ();
327 else
328 val = std::numeric_limits<T>::infinity ();
329 is.clear (status & ~std::ios::failbit);
330 }
331 else
332 {
333 // True error.
334 // Reset stream to original position, clear eof bit, pass status on.
335 is.clear ();
336 is.seekg (pos);
337 is.setstate (status & ~std::ios_base::eofbit);
338 }
339 }
340
341 return val;
342}
343
344template <typename T>
345std::complex<T>
346read_cx_fp_value (std::istream& is)
347{
348 T re = 0.0;
349 T im = 0.0;
350
351 std::complex<T> cx = 0.0;
352
353 char ch = ' ';
354
355 while (isspace (ch))
356 ch = is.get ();
357
358 if (ch == '(')
359 {
360 re = read_value<T> (is);
361 ch = is.get ();
362
363 if (ch == ',')
364 {
365 im = read_value<T> (is);
366 ch = is.get ();
367
368 if (ch == ')')
369 cx = std::complex<T> (re, im);
370 else
371 is.setstate (std::ios::failbit);
372 }
373 else if (ch == ')')
374 cx = re;
375 else
376 is.setstate (std::ios::failbit);
377 }
378 else
379 {
380 is.putback (ch);
381 cx = read_value<T> (is);
382 }
383
384 return cx;
385}
386
387// FIXME: Could we use traits and enable_if to avoid duplication in the
388// following specializations?
389
390template <> OCTAVE_API double read_value (std::istream& is)
391{
392 return read_fp_value<double> (is);
393}
394
395template <> OCTAVE_API Complex read_value (std::istream& is)
396{
397 return read_cx_fp_value<double> (is);
398}
399
400template <> OCTAVE_API float read_value (std::istream& is)
401{
402 return read_fp_value<float> (is);
403}
404
405template <> OCTAVE_API FloatComplex read_value (std::istream& is)
406{
407 return read_cx_fp_value<float> (is);
408}
409
410template <typename T>
411void
412write_value (std::ostream& os, const T& value)
413{
414 os << value;
415}
416
417template OCTAVE_API void
418write_value<bool> (std::ostream& os, const bool& value);
419template OCTAVE_API void
420write_value<octave_int8> (std::ostream& os, const octave_int8& value);
421template OCTAVE_API void
422write_value<octave_int16> (std::ostream& os, const octave_int16& value);
423template OCTAVE_API void
424write_value<octave_int32> (std::ostream& os, const octave_int32& value);
425template OCTAVE_API void
426write_value<octave_int64> (std::ostream& os, const octave_int64& value);
427template OCTAVE_API void
428write_value<octave_uint8> (std::ostream& os, const octave_uint8& value);
429template OCTAVE_API void
430write_value<octave_uint16> (std::ostream& os, const octave_uint16& value);
431template OCTAVE_API void
432write_value<octave_uint32> (std::ostream& os, const octave_uint32& value);
433template OCTAVE_API void
434write_value<octave_uint64> (std::ostream& os, const octave_uint64& value);
435
436// Note: precision is supposed to be managed outside of this function by
437// setting stream parameters.
438
439template <>
440OCTAVE_API void
441write_value (std::ostream& os, const double& value)
442{
443 if (lo_ieee_is_NA (value))
444 os << "NA";
445 else if (math::isnan (value))
446 os << "NaN";
447 else if (math::isinf (value))
448 os << (value < 0 ? "-Inf" : "Inf");
449 else
450 os << value;
451}
452
453template <>
454OCTAVE_API void
455write_value (std::ostream& os, const Complex& value)
456{
457 os << '(';
458 write_value<double> (os, real (value));
459 os << ',';
460 write_value<double> (os, imag (value));
461 os << ')';
462}
463
464// Note: precision is supposed to be managed outside of this function by
465// setting stream parameters.
466
467template <>
468OCTAVE_API void
469write_value (std::ostream& os, const float& value)
470{
471 if (lo_ieee_is_NA (value))
472 os << "NA";
473 else if (math::isnan (value))
474 os << "NaN";
475 else if (math::isinf (value))
476 os << (value < 0 ? "-Inf" : "Inf");
477 else
478 os << value;
479}
480
481template <>
482OCTAVE_API void
483write_value (std::ostream& os, const FloatComplex& value)
484{
485 os << '(';
486 write_value<float> (os, real (value));
487 os << ',';
488 write_value<float> (os, imag (value));
489 os << ')';
490}
491
493
494bool
495int_multiply_overflow (int a, int b, int *r)
496{
497 return octave_i_multiply_overflow_wrapper (a, b, r);
498}
499
500bool
501int_multiply_overflow (long int a, long int b, long int *r)
502{
504}
505
506#if defined (OCTAVE_HAVE_LONG_LONG_INT)
507bool
508int_multiply_overflow (long long int a, long long int b, long long int *r)
509{
510 return octave_lli_multiply_overflow_wrapper (a, b, r);
511}
512#endif
513
514bool
515int_multiply_overflow (unsigned int a, unsigned int b, unsigned int *r)
516{
518}
519
520bool
521int_multiply_overflow (unsigned long int a, unsigned long int b,
522 unsigned long int *r)
523{
525}
526
527#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
528bool
529int_multiply_overflow (unsigned long long int a, unsigned long long int b,
530 unsigned long long int *r)
531{
532 return octave_ulli_multiply_overflow_wrapper (a, b, r);
533}
534#endif
535
536OCTAVE_END_NAMESPACE(math)
537OCTAVE_END_NAMESPACE(octave)
ColumnVector real(const ComplexColumnVector &a)
ColumnVector imag(const ComplexColumnVector &a)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
int octave_i_multiply_overflow_wrapper(int a, int b, int *r)
int octave_li_multiply_overflow_wrapper(long int a, long int b, long int *r)
int octave_uli_multiply_overflow_wrapper(unsigned long int a, unsigned long int b, unsigned long int *r)
int octave_ui_multiply_overflow_wrapper(unsigned int a, unsigned int b, unsigned int *r)
#define lo_ieee_is_NA(x)
Definition lo-ieee.h:144
F77_RET_T const F77_DBLE * x
F77_RET_T const F77_DBLE const F77_DBLE * f
template void write_value< octave_uint64 >(std::ostream &os, const octave_uint64 &value)
void write_value(std::ostream &os, const T &value)
Definition lo-utils.cc:412
template void write_value< octave_uint8 >(std::ostream &os, const octave_uint8 &value)
bool is_int_or_inf_or_nan(double x)
Definition lo-utils.cc:50
bool int_multiply_overflow(int a, int b, int *r)
Definition lo-utils.cc:495
std::complex< T > read_cx_fp_value(std::istream &is)
Definition lo-utils.cc:346
template void write_value< octave_int16 >(std::ostream &os, const octave_int16 &value)
template void write_value< octave_int32 >(std::ostream &os, const octave_int32 &value)
template void write_value< octave_uint32 >(std::ostream &os, const octave_uint32 &value)
std::string fgetl(FILE *f)
Definition lo-utils.cc:172
template octave_uint8 read_value< octave_uint8 >(std::istream &is)
char * strsave(const char *s)
Definition lo-utils.cc:78
template octave_int64 read_value< octave_int64 >(std::istream &is)
double read_fp_value(std::istream &is)
Definition lo-utils.cc:271
template void write_value< octave_int64 >(std::ostream &os, const octave_int64 &value)
bool too_large_for_float(double x)
Definition lo-utils.cc:56
template void write_value< octave_uint16 >(std::ostream &os, const octave_uint16 &value)
template octave_uint64 read_value< octave_uint64 >(std::istream &is)
template octave_int32 read_value< octave_int32 >(std::istream &is)
std::string fgets(FILE *f)
Definition lo-utils.cc:90
template octave_int8 read_value< octave_int8 >(std::istream &is)
template octave_uint32 read_value< octave_uint32 >(std::istream &is)
template void write_value< octave_int8 >(std::ostream &os, const octave_int8 &value)
template void write_value< bool >(std::ostream &os, const bool &value)
template bool read_value< bool >(std::istream &is)
template octave_uint16 read_value< octave_uint16 >(std::istream &is)
template octave_int16 read_value< octave_int16 >(std::istream &is)
T read_inf_nan_na(std::istream &is, char c0)
Definition lo-utils.cc:213
T read_value(std::istream &is)
Definition lo-utils.cc:191
#define OCTAVE_API
Definition main.in.cc:55
std::complex< double > Complex
Definition oct-cmplx.h:33
std::complex< float > FloatComplex
Definition oct-cmplx.h:34
T::size_type strlen(const typename T::value_type *str)
Definition oct-string.cc:88
void free(void *)
F77_RET_T len
Definition xerbla.cc:61