Mercurial > octave
comparison liboctave/util/lo-utils.cc @ 31607:aac27ad79be6 stable
maint: Re-indent code after switch to using namespace macros.
* build-env.h, build-env.in.cc, Cell.h, __betainc__.cc, __eigs__.cc,
__ftp__.cc, __ichol__.cc, __ilu__.cc, __isprimelarge__.cc, __magick_read__.cc,
__pchip_deriv__.cc, amd.cc, base-text-renderer.cc, base-text-renderer.h,
besselj.cc, bitfcns.cc, bsxfun.cc, c-file-ptr-stream.h, call-stack.cc,
call-stack.h, ccolamd.cc, cellfun.cc, chol.cc, colamd.cc, dasrt.cc, data.cc,
debug.cc, defaults.cc, defaults.h, det.cc, display.cc, display.h, dlmread.cc,
dynamic-ld.cc, dynamic-ld.h, ellipj.cc, environment.cc, environment.h,
error.cc, error.h, errwarn.h, event-manager.cc, event-manager.h,
event-queue.cc, event-queue.h, fcn-info.cc, fcn-info.h, fft.cc, fft2.cc,
file-io.cc, filter.cc, find.cc, ft-text-renderer.cc, ft-text-renderer.h,
gcd.cc, gl-render.cc, gl-render.h, gl2ps-print.cc, gl2ps-print.h,
graphics-toolkit.cc, graphics-toolkit.h, graphics.cc, gsvd.cc, gtk-manager.cc,
gtk-manager.h, help.cc, help.h, hook-fcn.cc, hook-fcn.h, input.cc, input.h,
interpreter-private.cc, interpreter-private.h, interpreter.cc, interpreter.h,
inv.cc, jsondecode.cc, jsonencode.cc, latex-text-renderer.cc,
latex-text-renderer.h, load-path.cc, load-path.h, load-save.cc, load-save.h,
lookup.cc, ls-hdf5.cc, ls-mat4.cc, ls-mat5.cc, lsode.cc, lu.cc, mappers.cc,
matrix_type.cc, max.cc, mex.cc, mexproto.h, mxarray.h, mxtypes.in.h,
oct-errno.in.cc, oct-hdf5-types.cc, oct-hist.cc, oct-hist.h, oct-map.cc,
oct-map.h, oct-opengl.h, oct-prcstrm.h, oct-process.cc, oct-process.h,
oct-stdstrm.h, oct-stream.cc, oct-stream.h, oct-strstrm.h,
octave-default-image.h, ordqz.cc, ordschur.cc, pager.cc, pager.h, pinv.cc,
pow2.cc, pr-output.cc, psi.cc, qr.cc, quadcc.cc, rand.cc, regexp.cc,
settings.cc, settings.h, sighandlers.cc, sighandlers.h, sparse-xpow.cc,
sqrtm.cc, stack-frame.cc, stack-frame.h, stream-euler.cc, strfns.cc, svd.cc,
syminfo.cc, syminfo.h, symrcm.cc, symrec.cc, symrec.h, symscope.cc, symscope.h,
symtab.cc, symtab.h, sysdep.cc, sysdep.h, text-engine.cc, text-engine.h,
text-renderer.cc, text-renderer.h, time.cc, toplev.cc, typecast.cc,
url-handle-manager.cc, url-handle-manager.h, urlwrite.cc, utils.cc, utils.h,
variables.cc, variables.h, xdiv.cc, __delaunayn__.cc, __init_fltk__.cc,
__init_gnuplot__.cc, __ode15__.cc, __voronoi__.cc, audioread.cc, convhulln.cc,
gzip.cc, cdef-class.cc, cdef-class.h, cdef-fwd.h, cdef-manager.cc,
cdef-manager.h, cdef-method.cc, cdef-method.h, cdef-object.cc, cdef-object.h,
cdef-package.cc, cdef-package.h, cdef-property.cc, cdef-property.h,
cdef-utils.cc, cdef-utils.h, ov-base-diag.cc, ov-base-int.cc, ov-base-mat.cc,
ov-base-mat.h, ov-base-scalar.cc, ov-base.cc, ov-base.h, ov-bool-mat.cc,
ov-bool-mat.h, ov-bool-sparse.cc, ov-bool.cc, ov-builtin.h, ov-cell.cc,
ov-ch-mat.cc, ov-class.cc, ov-class.h, ov-classdef.cc, ov-classdef.h,
ov-complex.cc, ov-cx-diag.cc, ov-cx-mat.cc, ov-cx-sparse.cc, ov-dld-fcn.cc,
ov-dld-fcn.h, ov-fcn-handle.cc, ov-fcn-handle.h, ov-fcn.h, ov-float.cc,
ov-flt-complex.cc, ov-flt-cx-diag.cc, ov-flt-cx-mat.cc, ov-flt-re-diag.cc,
ov-flt-re-mat.cc, ov-flt-re-mat.h, ov-intx.h, ov-java.cc, ov-lazy-idx.cc,
ov-legacy-range.cc, ov-magic-int.cc, ov-mex-fcn.cc, ov-mex-fcn.h,
ov-null-mat.cc, ov-perm.cc, ov-range.cc, ov-re-diag.cc, ov-re-mat.cc,
ov-re-mat.h, ov-re-sparse.cc, ov-scalar.cc, ov-str-mat.cc, ov-struct.cc,
ov-typeinfo.cc, ov-typeinfo.h, ov-usr-fcn.cc, ov-usr-fcn.h, ov.cc, ov.h, ovl.h,
octave.cc, octave.h, op-b-sbm.cc, op-bm-sbm.cc, op-cs-scm.cc, op-fm-fcm.cc,
op-fs-fcm.cc, op-s-scm.cc, op-scm-cs.cc, op-scm-s.cc, op-sm-cs.cc, ops.h,
anon-fcn-validator.cc, anon-fcn-validator.h, bp-table.cc, bp-table.h,
comment-list.cc, comment-list.h, filepos.h, lex.h, oct-lvalue.cc, oct-lvalue.h,
parse.h, profiler.cc, profiler.h, pt-anon-scopes.cc, pt-anon-scopes.h,
pt-arg-list.cc, pt-arg-list.h, pt-args-block.cc, pt-args-block.h,
pt-array-list.cc, pt-array-list.h, pt-assign.cc, pt-assign.h, pt-binop.cc,
pt-binop.h, pt-bp.cc, pt-bp.h, pt-cbinop.cc, pt-cbinop.h, pt-cell.cc,
pt-cell.h, pt-check.cc, pt-check.h, pt-classdef.cc, pt-classdef.h, pt-cmd.h,
pt-colon.cc, pt-colon.h, pt-const.cc, pt-const.h, pt-decl.cc, pt-decl.h,
pt-eval.cc, pt-eval.h, pt-except.cc, pt-except.h, pt-exp.cc, pt-exp.h,
pt-fcn-handle.cc, pt-fcn-handle.h, pt-id.cc, pt-id.h, pt-idx.cc, pt-idx.h,
pt-jump.h, pt-loop.cc, pt-loop.h, pt-mat.cc, pt-mat.h, pt-misc.cc, pt-misc.h,
pt-pr-code.cc, pt-pr-code.h, pt-select.cc, pt-select.h, pt-spmd.cc, pt-spmd.h,
pt-stmt.cc, pt-stmt.h, pt-tm-const.cc, pt-tm-const.h, pt-unop.cc, pt-unop.h,
pt-walk.cc, pt-walk.h, pt.cc, pt.h, token.cc, token.h, Range.cc, Range.h,
idx-vector.cc, idx-vector.h, range-fwd.h, CollocWt.cc, CollocWt.h,
aepbalance.cc, aepbalance.h, chol.cc, chol.h, gepbalance.cc, gepbalance.h,
gsvd.cc, gsvd.h, hess.cc, hess.h, lo-mappers.cc, lo-mappers.h, lo-specfun.cc,
lo-specfun.h, lu.cc, lu.h, oct-convn.cc, oct-convn.h, oct-fftw.cc, oct-fftw.h,
oct-norm.cc, oct-norm.h, oct-rand.cc, oct-rand.h, oct-spparms.cc,
oct-spparms.h, qr.cc, qr.h, qrp.cc, qrp.h, randgamma.cc, randgamma.h,
randmtzig.cc, randmtzig.h, randpoisson.cc, randpoisson.h, schur.cc, schur.h,
sparse-chol.cc, sparse-chol.h, sparse-lu.cc, sparse-lu.h, sparse-qr.cc,
sparse-qr.h, svd.cc, svd.h, child-list.cc, child-list.h, dir-ops.cc, dir-ops.h,
file-ops.cc, file-ops.h, file-stat.cc, file-stat.h, lo-sysdep.cc, lo-sysdep.h,
lo-sysinfo.cc, lo-sysinfo.h, mach-info.cc, mach-info.h, oct-env.cc, oct-env.h,
oct-group.cc, oct-group.h, oct-password.cc, oct-password.h, oct-syscalls.cc,
oct-syscalls.h, oct-time.cc, oct-time.h, oct-uname.cc, oct-uname.h,
action-container.cc, action-container.h, base-list.h, cmd-edit.cc, cmd-edit.h,
cmd-hist.cc, cmd-hist.h, f77-fcn.h, file-info.cc, file-info.h,
lo-array-errwarn.cc, lo-array-errwarn.h, lo-hash.cc, lo-hash.h, lo-ieee.h,
lo-regexp.cc, lo-regexp.h, lo-utils.cc, lo-utils.h, oct-base64.cc,
oct-base64.h, oct-glob.cc, oct-glob.h, oct-inttypes.h, oct-mutex.cc,
oct-mutex.h, oct-refcount.h, oct-shlib.cc, oct-shlib.h, oct-sparse.cc,
oct-sparse.h, oct-string.h, octave-preserve-stream-state.h, pathsearch.cc,
pathsearch.h, quit.cc, quit.h, unwind-prot.cc, unwind-prot.h, url-transfer.cc,
url-transfer.h:
Re-indent code after switch to using namespace macros.
author | Rik <rik@octave.org> |
---|---|
date | Thu, 01 Dec 2022 18:02:15 -0800 |
parents | e88a07dec498 |
children | 23664317f0d3 597f3ee61a48 |
comparison
equal
deleted
inserted
replaced
31605:e88a07dec498 | 31607:aac27ad79be6 |
---|---|
45 #include "lo-utils.h" | 45 #include "lo-utils.h" |
46 #include "oct-inttypes.h" | 46 #include "oct-inttypes.h" |
47 | 47 |
48 OCTAVE_BEGIN_NAMESPACE(octave) | 48 OCTAVE_BEGIN_NAMESPACE(octave) |
49 | 49 |
50 bool is_int_or_inf_or_nan (double x) | 50 bool is_int_or_inf_or_nan (double x) |
51 { | 51 { |
52 return math::isnan (x) || math::x_nint (x) == x; | 52 return math::isnan (x) || math::x_nint (x) == x; |
53 } | 53 } |
54 | 54 |
55 bool too_large_for_float (double x) | 55 bool too_large_for_float (double x) |
56 { | 56 { |
57 return (math::isfinite (x) | 57 return (math::isfinite (x) |
58 && fabs (x) > std::numeric_limits<float>::max ()); | 58 && fabs (x) > std::numeric_limits<float>::max ()); |
59 } | 59 } |
60 | 60 |
61 bool too_large_for_float (const Complex& x) | 61 bool too_large_for_float (const Complex& x) |
62 { | 62 { |
63 return (too_large_for_float (x.real ()) | 63 return (too_large_for_float (x.real ()) |
64 || too_large_for_float (x.imag ())); | 64 || too_large_for_float (x.imag ())); |
65 } | 65 } |
66 | 66 |
67 bool is_int_or_inf_or_nan (float x) | 67 bool is_int_or_inf_or_nan (float x) |
68 { | 68 { |
69 return math::isnan (x) || math::x_nint (x) == x; | 69 return math::isnan (x) || math::x_nint (x) == x; |
70 } | 70 } |
71 | 71 |
72 // Save a string. | 72 // Save a string. |
73 | 73 |
74 char * strsave (const char *s) | 74 char * strsave (const char *s) |
75 { | 75 { |
76 if (! s) | 76 if (! s) |
77 return nullptr; | 77 return nullptr; |
78 | 78 |
79 int len = strlen (s); | 79 int len = strlen (s); |
80 char *tmp = new char [len+1]; | 80 char *tmp = new char [len+1]; |
81 tmp = strcpy (tmp, s); | 81 tmp = strcpy (tmp, s); |
82 return tmp; | 82 return tmp; |
83 } | 83 } |
84 | 84 |
85 std::string fgets (FILE *f) | 85 std::string fgets (FILE *f) |
86 { | 86 { |
87 bool eof; | 87 bool eof; |
88 return fgets (f, eof); | 88 return fgets (f, eof); |
89 } | 89 } |
90 | 90 |
91 std::string fgets (FILE *f, bool& eof) | 91 std::string fgets (FILE *f, bool& eof) |
92 { | 92 { |
93 eof = false; | 93 eof = false; |
94 | 94 |
95 std::string retval; | 95 std::string retval; |
96 | 96 |
97 int grow_size = 1024; | 97 int grow_size = 1024; |
98 int max_size = grow_size; | 98 int max_size = grow_size; |
99 | 99 |
100 char *buf = static_cast<char *> (std::malloc (max_size)); | 100 char *buf = static_cast<char *> (std::malloc (max_size)); |
101 if (! buf) | 101 if (! buf) |
102 (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size); | 102 (*current_liboctave_error_handler) ("octave_fgets: unable to malloc %d bytes", max_size); |
103 | 103 |
104 char *bufptr = buf; | 104 char *bufptr = buf; |
105 int len = 0; | 105 int len = 0; |
106 | 106 |
107 do | 107 do |
108 { | |
109 if (std::fgets (bufptr, grow_size, f)) | |
110 { | |
111 len = strlen (bufptr); | |
112 | |
113 if (len == grow_size - 1) | |
114 { | |
115 int tmp = bufptr - buf + grow_size - 1; | |
116 grow_size *= 2; | |
117 max_size += grow_size; | |
118 auto tmpbuf = static_cast<char *> (std::realloc (buf, max_size)); | |
119 if (! tmpbuf) | |
120 { | |
121 free (buf); | |
122 (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size); | |
123 } | |
124 buf = tmpbuf; | |
125 bufptr = buf + tmp; | |
126 | |
127 if (*(bufptr-1) == '\n') | |
128 { | |
129 *bufptr = '\0'; | |
130 retval = buf; | |
131 } | |
132 } | |
133 else if (bufptr[len-1] != '\n') | |
134 { | |
135 bufptr[len++] = '\n'; | |
136 bufptr[len] = '\0'; | |
137 retval = buf; | |
138 } | |
139 else | |
140 retval = buf; | |
141 } | |
142 else | |
143 { | |
144 if (len == 0) | |
145 { | |
146 eof = true; | |
147 | |
148 free (buf); | |
149 | |
150 buf = nullptr; | |
151 } | |
152 | |
153 break; | |
154 } | |
155 } | |
156 while (retval.empty ()); | |
157 | |
158 free (buf); | |
159 | |
160 octave_quit (); | |
161 | |
162 return retval; | |
163 } | |
164 | |
165 std::string fgetl (FILE *f) | |
166 { | |
167 bool eof; | |
168 return fgetl (f, eof); | |
169 } | |
170 | |
171 std::string fgetl (FILE *f, bool& eof) | |
172 { | |
173 std::string retval = fgets (f, eof); | |
174 | |
175 if (! retval.empty () && retval.back () == '\n') | |
176 retval.pop_back (); | |
177 | |
178 return retval; | |
179 } | |
180 | |
181 template <typename T> | |
182 T | |
183 read_value (std::istream& is) | |
184 { | |
185 T retval; | |
186 is >> retval; | |
187 return retval; | |
188 } | |
189 | |
190 template OCTAVE_API bool read_value<bool> (std::istream& is); | |
191 template OCTAVE_API octave_int8 read_value<octave_int8> (std::istream& is); | |
192 template OCTAVE_API octave_int16 read_value<octave_int16> (std::istream& is); | |
193 template OCTAVE_API octave_int32 read_value<octave_int32> (std::istream& is); | |
194 template OCTAVE_API octave_int64 read_value<octave_int64> (std::istream& is); | |
195 template OCTAVE_API octave_uint8 read_value<octave_uint8> (std::istream& is); | |
196 template OCTAVE_API octave_uint16 read_value<octave_uint16> (std::istream& is); | |
197 template OCTAVE_API octave_uint32 read_value<octave_uint32> (std::istream& is); | |
198 template OCTAVE_API octave_uint64 read_value<octave_uint64> (std::istream& is); | |
199 | |
200 // Note that the caller is responsible for repositioning the stream on | |
201 // 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': | |
108 { | 212 { |
109 if (std::fgets (bufptr, grow_size, f)) | 213 char c1 = is.get (); |
214 if (c1 == 'n' || c1 == 'N') | |
110 { | 215 { |
111 len = strlen (bufptr); | 216 char c2 = is.get (); |
112 | 217 if (c2 == 'f' || c2 == 'F') |
113 if (len == grow_size - 1) | 218 val = std::numeric_limits<T>::infinity (); |
114 { | |
115 int tmp = bufptr - buf + grow_size - 1; | |
116 grow_size *= 2; | |
117 max_size += grow_size; | |
118 auto tmpbuf = static_cast<char *> (std::realloc (buf, max_size)); | |
119 if (! tmpbuf) | |
120 { | |
121 free (buf); | |
122 (*current_liboctave_error_handler) ("octave_fgets: unable to realloc %d bytes", max_size); | |
123 } | |
124 buf = tmpbuf; | |
125 bufptr = buf + tmp; | |
126 | |
127 if (*(bufptr-1) == '\n') | |
128 { | |
129 *bufptr = '\0'; | |
130 retval = buf; | |
131 } | |
132 } | |
133 else if (bufptr[len-1] != '\n') | |
134 { | |
135 bufptr[len++] = '\n'; | |
136 bufptr[len] = '\0'; | |
137 retval = buf; | |
138 } | |
139 else | 219 else |
140 retval = buf; | 220 is.setstate (std::ios::failbit); |
141 } | 221 } |
142 else | 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') | |
143 { | 231 { |
144 if (len == 0) | 232 char c2 = is.get (); |
233 if (c2 == 'n' || c2 == 'N') | |
234 val = std::numeric_limits<T>::quiet_NaN (); | |
235 else | |
145 { | 236 { |
146 eof = true; | 237 val = numeric_limits<T>::NA (); |
147 | 238 if (c2 != std::istream::traits_type::eof ()) |
148 free (buf); | 239 is.putback (c2); |
149 | 240 else |
150 buf = nullptr; | 241 is.clear (is.rdstate () & ~std::ios::failbit); |
151 } | 242 } |
152 | |
153 break; | |
154 } | 243 } |
244 else | |
245 is.setstate (std::ios::failbit); | |
155 } | 246 } |
156 while (retval.empty ()); | 247 break; |
157 | 248 |
158 free (buf); | 249 default: |
159 | 250 (*current_liboctave_error_handler) |
160 octave_quit (); | 251 ("read_inf_nan_na: invalid character '%c'", c0); |
161 | 252 } |
162 return retval; | 253 |
163 } | 254 return val; |
164 | 255 } |
165 std::string fgetl (FILE *f) | 256 |
166 { | 257 // Read a double value. Discard any sign on NaN and NA. |
167 bool eof; | 258 |
168 return fgetl (f, eof); | 259 template <typename T> |
169 } | 260 double |
170 | 261 read_fp_value (std::istream& is) |
171 std::string fgetl (FILE *f, bool& eof) | 262 { |
172 { | 263 T val = 0.0; |
173 std::string retval = fgets (f, eof); | 264 |
174 | 265 // FIXME: resetting stream position is likely to fail unless we are |
175 if (! retval.empty () && retval.back () == '\n') | 266 // reading from a file. |
176 retval.pop_back (); | 267 std::streampos pos = is.tellg (); |
177 | 268 |
178 return retval; | 269 char c1 = ' '; |
179 } | 270 |
180 | 271 while (isspace (c1)) |
181 template <typename T> | 272 c1 = is.get (); |
182 T | 273 |
183 read_value (std::istream& is) | 274 bool neg = false; |
184 { | 275 |
185 T retval; | 276 switch (c1) |
186 is >> retval; | 277 { |
187 return retval; | 278 case '-': |
188 } | 279 neg = true; |
189 | 280 OCTAVE_FALLTHROUGH; |
190 template OCTAVE_API bool read_value<bool> (std::istream& is); | 281 |
191 template OCTAVE_API octave_int8 read_value<octave_int8> (std::istream& is); | 282 case '+': |
192 template OCTAVE_API octave_int16 read_value<octave_int16> (std::istream& is); | |
193 template OCTAVE_API octave_int32 read_value<octave_int32> (std::istream& is); | |
194 template OCTAVE_API octave_int64 read_value<octave_int64> (std::istream& is); | |
195 template OCTAVE_API octave_uint8 read_value<octave_uint8> (std::istream& is); | |
196 template OCTAVE_API octave_uint16 read_value<octave_uint16> (std::istream& is); | |
197 template OCTAVE_API octave_uint32 read_value<octave_uint32> (std::istream& is); | |
198 template OCTAVE_API octave_uint64 read_value<octave_uint64> (std::istream& is); | |
199 | |
200 // Note that the caller is responsible for repositioning the stream on | |
201 // 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 { | 283 { |
211 case 'i': case 'I': | 284 char c2 = 0; |
285 c2 = is.get (); | |
286 if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') | |
287 val = read_inf_nan_na<T> (is, c2); | |
288 else | |
289 { | |
290 is.putback (c2); | |
291 is >> val; | |
292 } | |
293 | |
294 if (neg && ! is.fail ()) | |
295 val = -val; | |
296 } | |
297 break; | |
298 | |
299 case 'i': case 'I': | |
300 case 'n': case 'N': | |
301 val = read_inf_nan_na<T> (is, c1); | |
302 break; | |
303 | |
304 default: | |
305 is.putback (c1); | |
306 is >> val; | |
307 break; | |
308 } | |
309 | |
310 std::ios::iostate status = is.rdstate (); | |
311 if (status & std::ios::failbit) | |
312 { | |
313 // Convert MAX_VAL returned by C++ streams for very large numbers to Inf | |
314 if (val == std::numeric_limits<T>::max ()) | |
212 { | 315 { |
213 char c1 = is.get (); | 316 if (neg) |
214 if (c1 == 'n' || c1 == 'N') | 317 val = -std::numeric_limits<T>::infinity (); |
215 { | 318 else |
216 char c2 = is.get (); | 319 val = std::numeric_limits<T>::infinity (); |
217 if (c2 == 'f' || c2 == 'F') | 320 is.clear (status & ~std::ios::failbit); |
218 val = std::numeric_limits<T>::infinity (); | 321 } |
219 else | 322 else |
220 is.setstate (std::ios::failbit); | 323 { |
221 } | 324 // True error. Reset stream to original position and pass status on. |
325 is.clear (); | |
326 is.seekg (pos); | |
327 is.setstate (status); | |
328 } | |
329 } | |
330 | |
331 return val; | |
332 } | |
333 | |
334 template <typename T> | |
335 std::complex<T> | |
336 read_cx_fp_value (std::istream& is) | |
337 { | |
338 T re = 0.0; | |
339 T im = 0.0; | |
340 | |
341 std::complex<T> cx = 0.0; | |
342 | |
343 char ch = ' '; | |
344 | |
345 while (isspace (ch)) | |
346 ch = is.get (); | |
347 | |
348 if (ch == '(') | |
349 { | |
350 re = read_value<T> (is); | |
351 ch = is.get (); | |
352 | |
353 if (ch == ',') | |
354 { | |
355 im = read_value<T> (is); | |
356 ch = is.get (); | |
357 | |
358 if (ch == ')') | |
359 cx = std::complex<T> (re, im); | |
222 else | 360 else |
223 is.setstate (std::ios::failbit); | 361 is.setstate (std::ios::failbit); |
224 } | 362 } |
225 break; | 363 else if (ch == ')') |
226 | 364 cx = re; |
227 case 'n': case 'N': | 365 else |
228 { | 366 is.setstate (std::ios::failbit); |
229 char c1 = is.get (); | 367 } |
230 if (c1 == 'a' || c1 == 'A') | 368 else |
231 { | 369 { |
232 char c2 = is.get (); | 370 is.putback (ch); |
233 if (c2 == 'n' || c2 == 'N') | 371 cx = read_value<T> (is); |
234 val = std::numeric_limits<T>::quiet_NaN (); | 372 } |
235 else | 373 |
236 { | 374 return cx; |
237 val = numeric_limits<T>::NA (); | 375 } |
238 if (c2 != std::istream::traits_type::eof ()) | 376 |
239 is.putback (c2); | 377 // FIXME: Could we use traits and enable_if to avoid duplication in the |
240 else | 378 // following specializations? |
241 is.clear (is.rdstate () & ~std::ios::failbit); | 379 |
242 } | 380 template <> OCTAVE_API double read_value (std::istream& is) |
243 } | 381 { |
244 else | 382 return read_fp_value<double> (is); |
245 is.setstate (std::ios::failbit); | 383 } |
246 } | 384 |
247 break; | 385 template <> OCTAVE_API Complex read_value (std::istream& is) |
248 | 386 { |
249 default: | 387 return read_cx_fp_value<double> (is); |
250 (*current_liboctave_error_handler) | 388 } |
251 ("read_inf_nan_na: invalid character '%c'", c0); | 389 |
252 } | 390 template <> OCTAVE_API float read_value (std::istream& is) |
253 | 391 { |
254 return val; | 392 return read_fp_value<float> (is); |
255 } | 393 } |
256 | 394 |
257 // Read a double value. Discard any sign on NaN and NA. | 395 template <> OCTAVE_API FloatComplex read_value (std::istream& is) |
258 | 396 { |
259 template <typename T> | 397 return read_cx_fp_value<float> (is); |
260 double | 398 } |
261 read_fp_value (std::istream& is) | 399 |
262 { | 400 template <typename T> |
263 T val = 0.0; | 401 void |
264 | 402 write_value (std::ostream& os, const T& value) |
265 // FIXME: resetting stream position is likely to fail unless we are | 403 { |
266 // reading from a file. | 404 os << value; |
267 std::streampos pos = is.tellg (); | 405 } |
268 | 406 |
269 char c1 = ' '; | 407 template OCTAVE_API void |
270 | 408 write_value<bool> (std::ostream& os, const bool& value); |
271 while (isspace (c1)) | 409 template OCTAVE_API void |
272 c1 = is.get (); | 410 write_value<octave_int8> (std::ostream& os, const octave_int8& value); |
273 | 411 template OCTAVE_API void |
274 bool neg = false; | 412 write_value<octave_int16> (std::ostream& os, const octave_int16& value); |
275 | 413 template OCTAVE_API void |
276 switch (c1) | 414 write_value<octave_int32> (std::ostream& os, const octave_int32& value); |
277 { | 415 template OCTAVE_API void |
278 case '-': | 416 write_value<octave_int64> (std::ostream& os, const octave_int64& value); |
279 neg = true; | 417 template OCTAVE_API void |
280 OCTAVE_FALLTHROUGH; | 418 write_value<octave_uint8> (std::ostream& os, const octave_uint8& value); |
281 | 419 template OCTAVE_API void |
282 case '+': | 420 write_value<octave_uint16> (std::ostream& os, const octave_uint16& value); |
283 { | 421 template OCTAVE_API void |
284 char c2 = 0; | 422 write_value<octave_uint32> (std::ostream& os, const octave_uint32& value); |
285 c2 = is.get (); | 423 template OCTAVE_API void |
286 if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') | 424 write_value<octave_uint64> (std::ostream& os, const octave_uint64& value); |
287 val = read_inf_nan_na<T> (is, c2); | 425 |
288 else | 426 // Note: precision is supposed to be managed outside of this function by |
289 { | 427 // setting stream parameters. |
290 is.putback (c2); | 428 |
291 is >> val; | 429 template <> OCTAVE_API void |
292 } | 430 write_value (std::ostream& os, const double& value) |
293 | 431 { |
294 if (neg && ! is.fail ()) | 432 if (lo_ieee_is_NA (value)) |
295 val = -val; | 433 os << "NA"; |
296 } | 434 else if (lo_ieee_isnan (value)) |
297 break; | 435 os << "NaN"; |
298 | 436 else if (lo_ieee_isinf (value)) |
299 case 'i': case 'I': | 437 os << (value < 0 ? "-Inf" : "Inf"); |
300 case 'n': case 'N': | 438 else |
301 val = read_inf_nan_na<T> (is, c1); | |
302 break; | |
303 | |
304 default: | |
305 is.putback (c1); | |
306 is >> val; | |
307 break; | |
308 } | |
309 | |
310 std::ios::iostate status = is.rdstate (); | |
311 if (status & std::ios::failbit) | |
312 { | |
313 // Convert MAX_VAL returned by C++ streams for very large numbers to Inf | |
314 if (val == std::numeric_limits<T>::max ()) | |
315 { | |
316 if (neg) | |
317 val = -std::numeric_limits<T>::infinity (); | |
318 else | |
319 val = std::numeric_limits<T>::infinity (); | |
320 is.clear (status & ~std::ios::failbit); | |
321 } | |
322 else | |
323 { | |
324 // True error. Reset stream to original position and pass status on. | |
325 is.clear (); | |
326 is.seekg (pos); | |
327 is.setstate (status); | |
328 } | |
329 } | |
330 | |
331 return val; | |
332 } | |
333 | |
334 template <typename T> | |
335 std::complex<T> | |
336 read_cx_fp_value (std::istream& is) | |
337 { | |
338 T re = 0.0; | |
339 T im = 0.0; | |
340 | |
341 std::complex<T> cx = 0.0; | |
342 | |
343 char ch = ' '; | |
344 | |
345 while (isspace (ch)) | |
346 ch = is.get (); | |
347 | |
348 if (ch == '(') | |
349 { | |
350 re = read_value<T> (is); | |
351 ch = is.get (); | |
352 | |
353 if (ch == ',') | |
354 { | |
355 im = read_value<T> (is); | |
356 ch = is.get (); | |
357 | |
358 if (ch == ')') | |
359 cx = std::complex<T> (re, im); | |
360 else | |
361 is.setstate (std::ios::failbit); | |
362 } | |
363 else if (ch == ')') | |
364 cx = re; | |
365 else | |
366 is.setstate (std::ios::failbit); | |
367 } | |
368 else | |
369 { | |
370 is.putback (ch); | |
371 cx = read_value<T> (is); | |
372 } | |
373 | |
374 return cx; | |
375 } | |
376 | |
377 // FIXME: Could we use traits and enable_if to avoid duplication in the | |
378 // following specializations? | |
379 | |
380 template <> OCTAVE_API double read_value (std::istream& is) | |
381 { | |
382 return read_fp_value<double> (is); | |
383 } | |
384 | |
385 template <> OCTAVE_API Complex read_value (std::istream& is) | |
386 { | |
387 return read_cx_fp_value<double> (is); | |
388 } | |
389 | |
390 template <> OCTAVE_API float read_value (std::istream& is) | |
391 { | |
392 return read_fp_value<float> (is); | |
393 } | |
394 | |
395 template <> OCTAVE_API FloatComplex read_value (std::istream& is) | |
396 { | |
397 return read_cx_fp_value<float> (is); | |
398 } | |
399 | |
400 template <typename T> | |
401 void | |
402 write_value (std::ostream& os, const T& value) | |
403 { | |
404 os << value; | 439 os << value; |
405 } | 440 } |
406 | 441 |
407 template OCTAVE_API void | 442 template <> OCTAVE_API void |
408 write_value<bool> (std::ostream& os, const bool& value); | 443 write_value (std::ostream& os, const Complex& value) |
409 template OCTAVE_API void | 444 { |
410 write_value<octave_int8> (std::ostream& os, const octave_int8& value); | 445 os << '('; |
411 template OCTAVE_API void | 446 write_value<double> (os, real (value)); |
412 write_value<octave_int16> (std::ostream& os, const octave_int16& value); | 447 os << ','; |
413 template OCTAVE_API void | 448 write_value<double> (os, imag (value)); |
414 write_value<octave_int32> (std::ostream& os, const octave_int32& value); | 449 os << ')'; |
415 template OCTAVE_API void | 450 } |
416 write_value<octave_int64> (std::ostream& os, const octave_int64& value); | 451 |
417 template OCTAVE_API void | 452 // Note: precision is supposed to be managed outside of this function by |
418 write_value<octave_uint8> (std::ostream& os, const octave_uint8& value); | 453 // setting stream parameters. |
419 template OCTAVE_API void | 454 |
420 write_value<octave_uint16> (std::ostream& os, const octave_uint16& value); | 455 template <> OCTAVE_API void |
421 template OCTAVE_API void | 456 write_value (std::ostream& os, const float& value) |
422 write_value<octave_uint32> (std::ostream& os, const octave_uint32& value); | 457 { |
423 template OCTAVE_API void | 458 if (lo_ieee_is_NA (value)) |
424 write_value<octave_uint64> (std::ostream& os, const octave_uint64& value); | 459 os << "NA"; |
425 | 460 else if (lo_ieee_isnan (value)) |
426 // Note: precision is supposed to be managed outside of this function by | 461 os << "NaN"; |
427 // setting stream parameters. | 462 else if (lo_ieee_isinf (value)) |
428 | 463 os << (value < 0 ? "-Inf" : "Inf"); |
429 template <> OCTAVE_API void | 464 else |
430 write_value (std::ostream& os, const double& value) | 465 os << value; |
431 { | 466 } |
432 if (lo_ieee_is_NA (value)) | 467 |
433 os << "NA"; | 468 template <> OCTAVE_API void |
434 else if (lo_ieee_isnan (value)) | 469 write_value (std::ostream& os, const FloatComplex& value) |
435 os << "NaN"; | 470 { |
436 else if (lo_ieee_isinf (value)) | 471 os << '('; |
437 os << (value < 0 ? "-Inf" : "Inf"); | 472 write_value<float> (os, real (value)); |
438 else | 473 os << ','; |
439 os << value; | 474 write_value<float> (os, imag (value)); |
440 } | 475 os << ')'; |
441 | 476 } |
442 template <> OCTAVE_API void | |
443 write_value (std::ostream& os, const Complex& value) | |
444 { | |
445 os << '('; | |
446 write_value<double> (os, real (value)); | |
447 os << ','; | |
448 write_value<double> (os, imag (value)); | |
449 os << ')'; | |
450 } | |
451 | |
452 // Note: precision is supposed to be managed outside of this function by | |
453 // setting stream parameters. | |
454 | |
455 template <> OCTAVE_API void | |
456 write_value (std::ostream& os, const float& value) | |
457 { | |
458 if (lo_ieee_is_NA (value)) | |
459 os << "NA"; | |
460 else if (lo_ieee_isnan (value)) | |
461 os << "NaN"; | |
462 else if (lo_ieee_isinf (value)) | |
463 os << (value < 0 ? "-Inf" : "Inf"); | |
464 else | |
465 os << value; | |
466 } | |
467 | |
468 template <> OCTAVE_API void | |
469 write_value (std::ostream& os, const FloatComplex& value) | |
470 { | |
471 os << '('; | |
472 write_value<float> (os, real (value)); | |
473 os << ','; | |
474 write_value<float> (os, imag (value)); | |
475 os << ')'; | |
476 } | |
477 | 477 |
478 OCTAVE_BEGIN_NAMESPACE(math) | 478 OCTAVE_BEGIN_NAMESPACE(math) |
479 | 479 |
480 bool int_multiply_overflow (int a, int b, int *r) | 480 bool int_multiply_overflow (int a, int b, int *r) |
481 { | 481 { |
482 return octave_i_multiply_overflow_wrapper (a, b, r); | 482 return octave_i_multiply_overflow_wrapper (a, b, r); |
483 } | 483 } |
484 | 484 |
485 bool int_multiply_overflow (long int a, long int b, long int *r) | 485 bool int_multiply_overflow (long int a, long int b, long int *r) |
486 { | 486 { |
487 return octave_li_multiply_overflow_wrapper (a, b, r); | 487 return octave_li_multiply_overflow_wrapper (a, b, r); |
488 } | 488 } |
489 | 489 |
490 #if defined (OCTAVE_HAVE_LONG_LONG_INT) | 490 #if defined (OCTAVE_HAVE_LONG_LONG_INT) |
491 bool int_multiply_overflow (long long int a, long long int b, | 491 bool int_multiply_overflow (long long int a, long long int b, |
492 long long int *r) | 492 long long int *r) |
493 { | 493 { |
494 return octave_lli_multiply_overflow_wrapper (a, b, r); | 494 return octave_lli_multiply_overflow_wrapper (a, b, r); |
495 } | 495 } |
496 #endif | 496 #endif |
497 | 497 |
498 bool int_multiply_overflow (unsigned int a, unsigned int b, | 498 bool int_multiply_overflow (unsigned int a, unsigned int b, |
499 unsigned int *r) | 499 unsigned int *r) |
500 { | 500 { |
501 return octave_ui_multiply_overflow_wrapper (a, b, r); | 501 return octave_ui_multiply_overflow_wrapper (a, b, r); |
502 } | 502 } |
503 | 503 |
504 bool int_multiply_overflow (unsigned long int a, unsigned long int b, | 504 bool int_multiply_overflow (unsigned long int a, unsigned long int b, |
505 unsigned long int *r) | 505 unsigned long int *r) |
506 { | 506 { |
507 return octave_uli_multiply_overflow_wrapper (a, b, r); | 507 return octave_uli_multiply_overflow_wrapper (a, b, r); |
508 } | 508 } |
509 | 509 |
510 #if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT) | 510 #if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT) |
511 bool int_multiply_overflow (unsigned long long int a, | 511 bool int_multiply_overflow (unsigned long long int a, |
512 unsigned long long int b, | 512 unsigned long long int b, |
513 unsigned long long int *r) | 513 unsigned long long int *r) |
514 { | 514 { |
515 return octave_ulli_multiply_overflow_wrapper (a, b, r); | 515 return octave_ulli_multiply_overflow_wrapper (a, b, r); |
516 } | 516 } |
517 #endif | 517 #endif |
518 | 518 |
519 OCTAVE_END_NAMESPACE(math) | 519 OCTAVE_END_NAMESPACE(math) |
520 OCTAVE_END_NAMESPACE(octave) | 520 OCTAVE_END_NAMESPACE(octave) |