Mercurial > octave
view liboctave/util/lo-utils.cc @ 30564:796f54d4ddbf stable
update Octave Project Developers copyright for the new year
In files that have the "Octave Project Developers" copyright notice,
update for 2021.
In all .txi and .texi files except gpl.txi and gpl.texi in the
doc/liboctave and doc/interpreter directories, change the copyright
to "Octave Project Developers", the same as used for other source
files. Update copyright notices for 2022 (not done since 2019). For
gpl.txi and gpl.texi, change the copyright notice to be "Free Software
Foundation, Inc." and leave the date at 2007 only because this file
only contains the text of the GPL, not anything created by the Octave
Project Developers.
Add Paul Thomas to contributors.in.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 28 Dec 2021 18:22:40 -0500 |
parents | f3f3e3793fb5 |
children | 6bd338605fd3 e88a07dec498 |
line wrap: on
line source
//////////////////////////////////////////////////////////////////////// // // Copyright (C) 1996-2022 The Octave Project Developers // // See the file COPYRIGHT.md in the top-level directory of this // distribution or <https://octave.org/copyright/>. // // This file is part of Octave. // // Octave is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Octave is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Octave; see the file COPYING. If not, see // <https://www.gnu.org/licenses/>. // //////////////////////////////////////////////////////////////////////// #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <cstdlib> #include <cstring> #include <complex> #include <istream> #include <limits> #include <ostream> #include <string> #include "quit.h" #include "intprops-wrappers.h" #include "lo-error.h" #include "lo-ieee.h" #include "lo-mappers.h" #include "lo-utils.h" #include "oct-inttypes.h" namespace octave { bool is_int_or_inf_or_nan (double x) { return math::isnan (x) || math::x_nint (x) == x; } bool too_large_for_float (double x) { return (math::isfinite (x) && fabs (x) > std::numeric_limits<float>::max ()); } bool too_large_for_float (const Complex& x) { return (too_large_for_float (x.real ()) || too_large_for_float (x.imag ())); } bool is_int_or_inf_or_nan (float x) { return math::isnan (x) || math::x_nint (x) == x; } // Save a string. char * strsave (const char *s) { if (! s) return nullptr; int len = strlen (s); char *tmp = new char [len+1]; tmp = strcpy (tmp, s); return tmp; } std::string fgets (FILE *f) { bool eof; return fgets (f, eof); } std::string fgets (FILE *f, bool& eof) { eof = false; std::string retval; int grow_size = 1024; int max_size = grow_size; char *buf = static_cast<char *> (std::malloc (max_size)); if (! buf) (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size); char *bufptr = buf; int len = 0; do { if (std::fgets (bufptr, grow_size, f)) { len = strlen (bufptr); if (len == grow_size - 1) { int tmp = bufptr - buf + grow_size - 1; grow_size *= 2; max_size += grow_size; auto tmpbuf = static_cast<char *> (std::realloc (buf, max_size)); if (! tmpbuf) { free (buf); (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size); } buf = tmpbuf; bufptr = buf + tmp; if (*(bufptr-1) == '\n') { *bufptr = '\0'; retval = buf; } } else if (bufptr[len-1] != '\n') { bufptr[len++] = '\n'; bufptr[len] = '\0'; retval = buf; } else retval = buf; } else { if (len == 0) { eof = true; free (buf); buf = nullptr; } break; } } while (retval.empty ()); free (buf); octave_quit (); return retval; } std::string fgetl (FILE *f) { bool eof; return fgetl (f, eof); } std::string fgetl (FILE *f, bool& eof) { std::string retval = fgets (f, eof); if (! retval.empty () && retval.back () == '\n') retval.pop_back (); return retval; } template <typename T> T read_value (std::istream& is) { T retval; is >> retval; return retval; } template OCTAVE_API bool read_value<bool> (std::istream& is); template OCTAVE_API octave_int8 read_value<octave_int8> (std::istream& is); template OCTAVE_API octave_int16 read_value<octave_int16> (std::istream& is); template OCTAVE_API octave_int32 read_value<octave_int32> (std::istream& is); template OCTAVE_API octave_int64 read_value<octave_int64> (std::istream& is); template OCTAVE_API octave_uint8 read_value<octave_uint8> (std::istream& is); template OCTAVE_API octave_uint16 read_value<octave_uint16> (std::istream& is); template OCTAVE_API octave_uint32 read_value<octave_uint32> (std::istream& is); template OCTAVE_API octave_uint64 read_value<octave_uint64> (std::istream& is); // Note that the caller is responsible for repositioning the stream on // failure. template <typename T> T read_inf_nan_na (std::istream& is, char c0) { T val = 0.0; switch (c0) { case 'i': case 'I': { char c1 = is.get (); if (c1 == 'n' || c1 == 'N') { char c2 = is.get (); if (c2 == 'f' || c2 == 'F') val = std::numeric_limits<T>::infinity (); else is.setstate (std::ios::failbit); } else is.setstate (std::ios::failbit); } break; case 'n': case 'N': { char c1 = is.get (); if (c1 == 'a' || c1 == 'A') { char c2 = is.get (); if (c2 == 'n' || c2 == 'N') val = std::numeric_limits<T>::quiet_NaN (); else { val = numeric_limits<T>::NA (); if (c2 != std::istream::traits_type::eof ()) is.putback (c2); else is.clear (is.rdstate () & ~std::ios::failbit); } } else is.setstate (std::ios::failbit); } break; default: (*current_liboctave_error_handler) ("read_inf_nan_na: invalid character '%c'", c0); } return val; } // Read a double value. Discard any sign on NaN and NA. template <typename T> double read_fp_value (std::istream& is) { T val = 0.0; // FIXME: resetting stream position is likely to fail unless we are // reading from a file. std::streampos pos = is.tellg (); char c1 = ' '; while (isspace (c1)) c1 = is.get (); bool neg = false; switch (c1) { case '-': neg = true; OCTAVE_FALLTHROUGH; case '+': { char c2 = 0; c2 = is.get (); if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') val = read_inf_nan_na<T> (is, c2); else { is.putback (c2); is >> val; } if (neg && ! is.fail ()) val = -val; } break; case 'i': case 'I': case 'n': case 'N': val = read_inf_nan_na<T> (is, c1); break; default: is.putback (c1); is >> val; break; } std::ios::iostate status = is.rdstate (); if (status & std::ios::failbit) { // Convert MAX_VAL returned by C++ streams for very large numbers to Inf if (val == std::numeric_limits<T>::max ()) { if (neg) val = -std::numeric_limits<T>::infinity (); else val = std::numeric_limits<T>::infinity (); is.clear (status & ~std::ios::failbit); } else { // True error. Reset stream to original position and pass status on. is.clear (); is.seekg (pos); is.setstate (status); } } return val; } template <typename T> std::complex<T> read_cx_fp_value (std::istream& is) { T re = 0.0; T im = 0.0; std::complex<T> cx = 0.0; char ch = ' '; while (isspace (ch)) ch = is.get (); if (ch == '(') { re = read_value<T> (is); ch = is.get (); if (ch == ',') { im = read_value<T> (is); ch = is.get (); if (ch == ')') cx = std::complex<T> (re, im); else is.setstate (std::ios::failbit); } else if (ch == ')') cx = re; else is.setstate (std::ios::failbit); } else { is.putback (ch); cx = read_value<T> (is); } return cx; } // FIXME: Could we use traits and enable_if to avoid duplication in the // following specializations? template <> OCTAVE_API double read_value (std::istream& is) { return read_fp_value<double> (is); } template <> OCTAVE_API Complex read_value (std::istream& is) { return read_cx_fp_value<double> (is); } template <> OCTAVE_API float read_value (std::istream& is) { return read_fp_value<float> (is); } template <> OCTAVE_API FloatComplex read_value (std::istream& is) { return read_cx_fp_value<float> (is); } template <typename T> void write_value (std::ostream& os, const T& value) { os << value; } template OCTAVE_API void write_value<bool> (std::ostream& os, const bool& value); template OCTAVE_API void write_value<octave_int8> (std::ostream& os, const octave_int8& value); template OCTAVE_API void write_value<octave_int16> (std::ostream& os, const octave_int16& value); template OCTAVE_API void write_value<octave_int32> (std::ostream& os, const octave_int32& value); template OCTAVE_API void write_value<octave_int64> (std::ostream& os, const octave_int64& value); template OCTAVE_API void write_value<octave_uint8> (std::ostream& os, const octave_uint8& value); template OCTAVE_API void write_value<octave_uint16> (std::ostream& os, const octave_uint16& value); template OCTAVE_API void write_value<octave_uint32> (std::ostream& os, const octave_uint32& value); template OCTAVE_API void write_value<octave_uint64> (std::ostream& os, const octave_uint64& value); // Note: precision is supposed to be managed outside of this function by // setting stream parameters. template <> OCTAVE_API void write_value (std::ostream& os, const double& value) { if (lo_ieee_is_NA (value)) os << "NA"; else if (lo_ieee_isnan (value)) os << "NaN"; else if (lo_ieee_isinf (value)) os << (value < 0 ? "-Inf" : "Inf"); else os << value; } template <> OCTAVE_API void write_value (std::ostream& os, const Complex& value) { os << '('; write_value<double> (os, real (value)); os << ','; write_value<double> (os, imag (value)); os << ')'; } // Note: precision is supposed to be managed outside of this function by // setting stream parameters. template <> OCTAVE_API void write_value (std::ostream& os, const float& value) { if (lo_ieee_is_NA (value)) os << "NA"; else if (lo_ieee_isnan (value)) os << "NaN"; else if (lo_ieee_isinf (value)) os << (value < 0 ? "-Inf" : "Inf"); else os << value; } template <> OCTAVE_API void write_value (std::ostream& os, const FloatComplex& value) { os << '('; write_value<float> (os, real (value)); os << ','; write_value<float> (os, imag (value)); os << ')'; } namespace math { bool int_multiply_overflow (int a, int b, int *r) { return octave_i_multiply_overflow_wrapper (a, b, r); } bool int_multiply_overflow (long int a, long int b, long int *r) { return octave_li_multiply_overflow_wrapper (a, b, r); } #if defined (OCTAVE_HAVE_LONG_LONG_INT) bool int_multiply_overflow (long long int a, long long int b, long long int *r) { return octave_lli_multiply_overflow_wrapper (a, b, r); } #endif bool int_multiply_overflow (unsigned int a, unsigned int b, unsigned int *r) { return octave_ui_multiply_overflow_wrapper (a, b, r); } bool int_multiply_overflow (unsigned long int a, unsigned long int b, unsigned long int *r) { return octave_uli_multiply_overflow_wrapper (a, b, r); } #if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT) bool int_multiply_overflow (unsigned long long int a, unsigned long long int b, unsigned long long int *r) { return octave_ulli_multiply_overflow_wrapper (a, b, r); } #endif } }