GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
dlmread.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 2008-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// Adapted from previous version of dlmread.occ as authored by Kai
27// Habel, but core code has been completely re-written.
28
29#if defined (HAVE_CONFIG_H)
30# include "config.h"
31#endif
32
33#include <clocale>
34#include <cmath>
35#include <cctype>
36#include <fstream>
37#include <limits>
38
39#include "file-ops.h"
40#include "lo-ieee.h"
41#include "lo-sysdep.h"
42
43#include "defun.h"
44#include "interpreter.h"
45#include "oct-stream.h"
46#include "error.h"
47#include "ovl.h"
48#include "utils.h"
49
50static constexpr octave_idx_type idx_max
51 = std::numeric_limits<octave_idx_type>::max () - 1;
52
53static constexpr double idx_max_dbl = double (idx_max);
54
55static bool
56read_cell_spec (std::istream& is, octave_idx_type& row, octave_idx_type& col)
57{
58 bool stat = false;
59
60 if (is.peek () == std::istream::traits_type::eof ())
61 stat = true;
62 else
63 {
64 if (::isalpha (is.peek ()))
65 {
66 col = 0;
67 while (is && ::isalpha (is.peek ()))
68 {
69 char ch = is.get ();
70 col *= 26;
71 if (ch >= 'a')
72 col += ch - 'a' + 1;
73 else
74 col += ch - 'A' + 1;
75 }
76 col--;
77
78 if (is)
79 {
80 is >> row;
81 row--;
82 if (is)
83 stat = true;
84 }
85 }
86 }
87
88 return stat;
89}
90
91static bool
92parse_range_spec (const octave_value& range_spec,
95{
96 bool stat = true;
97
98 if (range_spec.is_string ())
99 {
100 std::istringstream is (range_spec.string_value ());
101 char ch = is.peek ();
102
103 if (ch == '.' || ch == ':')
104 {
105 rlo = 0;
106 clo = 0;
107 ch = is.get ();
108 if (ch == '.')
109 {
110 ch = is.get ();
111 if (ch != '.')
112 stat = false;
113 }
114 }
115 else
116 {
117 stat = read_cell_spec (is, rlo, clo);
118
119 if (stat)
120 {
121 ch = is.peek ();
122
123 if (ch == '.' || ch == ':')
124 {
125 ch = is.get ();
126 if (ch == '.')
127 {
128 ch = is.get ();
129 if (! is || ch != '.')
130 stat = false;
131 }
132
133 rup = idx_max;
134 cup = idx_max;
135 }
136 else
137 {
138 rup = rlo;
139 cup = clo;
140 if (! is || ! is.eof ())
141 stat = false;
142 }
143 }
144 }
145
146 if (stat && is && ! is.eof ())
147 stat = read_cell_spec (is, rup, cup);
148
149 if (! is || ! is.eof ())
150 stat = false;
151 }
152 else if (range_spec.is_real_matrix () && range_spec.numel () == 4)
153 {
154 NDArray range (range_spec.array_value ());
155 if (range.any_element_is_nan ())
156 error ("dlmread: NaN is not a valid row or column specifier");
157
158 // double --> unsigned int avoiding any overflow
159 rlo = static_cast<octave_idx_type> (std::min (range(0), idx_max_dbl));
160 clo = static_cast<octave_idx_type> (std::min (range(1), idx_max_dbl));
161 rup = static_cast<octave_idx_type> (std::min (range(2), idx_max_dbl));
162 cup = static_cast<octave_idx_type> (std::min (range(3), idx_max_dbl));
163 }
164 else
165 stat = false;
166
167 return stat;
168}
169
171
172DEFMETHOD (dlmread, interp, args, ,
173 doc: /* -*- texinfo -*-
174@deftypefn {} {@var{data} =} dlmread (@var{file})
175@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep})
176@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep}, @var{r0}, @var{c0})
177@deftypefnx {} {@var{data} =} dlmread (@var{file}, @var{sep}, @var{range})
178@deftypefnx {} {@var{data} =} dlmread (@dots{}, "emptyvalue", @var{EMPTYVAL})
179Read numeric data from the text file @var{file} which uses the delimiter
180@var{sep} between data values.
181
182If @var{sep} is not defined the separator between fields is determined from
183the file itself.
184
185The optional scalar arguments @var{r0} and @var{c0} define the starting row
186and column of the data to be read. These values are indexed from zero,
187i.e., the first data row corresponds to an index of zero.
188
189The @var{range} parameter specifies exactly which data elements are read.
190The first form of the parameter is a 4-element vector containing the upper
191left and lower right corners @code{[@var{R0},@var{C0},@var{R1},@var{C1}]}
192where the indices are zero-based. To specify the last column---the equivalent
193of @code{end} when indexing---use the specifier @code{Inf}. Alternatively, a
194spreadsheet style form such as @qcode{"A2..Q15"} or @qcode{"T1:AA5"} can be
195used. The lowest alphabetical index @qcode{'A'} refers to the first column.
196The lowest row index is 1.
197
198@var{file} should be a filename or a file id given by @code{fopen}. In the
199latter case, the file is read until end of file is reached.
200
201The @qcode{"emptyvalue"} option may be used to specify the value used to
202fill empty fields. The default is zero. Note that any non-numeric values,
203such as text, are also replaced by the @qcode{"emptyvalue"}.
204@seealso{csvread, textscan, dlmwrite}
205@end deftypefn */)
206{
207 int nargin = args.length ();
208
209 double empty_value = 0.0;
210
211 if (nargin > 2 && args(nargin-2).is_string ()
212 && args(nargin-2).string_value () == "emptyvalue")
213 {
214 empty_value = args(nargin-1).double_value ();
215
216 nargin -= 2;
217 }
218
219 if (nargin < 1 || nargin > 4)
220 print_usage ();
221
222 std::istream *input = nullptr;
223 std::ifstream input_file;
224
225 if (args(0).is_string ())
226 {
227 // Filename.
228 std::string fname (args(0).string_value ());
229
230 std::string tname = sys::file_ops::tilde_expand (fname);
231
232 tname = find_data_file_in_load_path ("dlmread", tname);
233
234#if defined (OCTAVE_USE_WINDOWS_API)
235 std::wstring wname = sys::u8_to_wstring (tname);
236 input_file.open (wname.c_str (), std::ios::in);
237#else
238 input_file.open (tname.c_str (), std::ios::in);
239#endif
240
241 if (! input_file)
242 error ("dlmread: unable to open file '%s'", fname.c_str ());
243
244 input = &input_file;
245 }
246 else if (args(0).is_scalar_type ())
247 {
248 stream_list& streams = interp.get_stream_list ();
249
250 stream is = streams.lookup (args(0), "dlmread");
251
252 input = is.input_stream ();
253
254 if (! input)
255 error ("dlmread: stream FILE not open for input");
256 }
257 else
258 error ("dlmread: FILE argument must be a string or file id");
259
260 // Set default separator.
261 std::string sep;
262 if (nargin > 1)
263 {
264 if (args(1).is_sq_string ())
265 sep = do_string_escapes (args(1).string_value ());
266 else
267 sep = args(1).string_value ();
268 }
269
270 // Take a subset if a range was given.
271 octave_idx_type r0 = 0;
272 octave_idx_type c0 = 0;
273 octave_idx_type r1 = idx_max;
274 octave_idx_type c1 = idx_max;
275 if (nargin > 2)
276 {
277 if (nargin == 3)
278 {
279 if (! parse_range_spec (args(2), r0, c0, r1, c1))
280 error ("dlmread: error parsing RANGE");
281 }
282 else if (nargin == 4)
283 {
284 r0 = args(2).idx_type_value ();
285 c0 = args(3).idx_type_value ();
286 }
287
288 if (r0 < 0 || c0 < 0)
289 error ("dlmread: left (R0) and top (C0) must be positive");
290
291 // Short-circuit and return if range is empty
292 if (r1 < r0 || c1 < c0)
293 return ovl (Matrix (0, 0));
294 }
295
296 octave_idx_type i = 0;
297 octave_idx_type j = 0;
298 octave_idx_type r = 1;
299 octave_idx_type c = 1;
300 // Start with a reasonable size to avoid constant resizing of matrix.
301 octave_idx_type rmax = 32;
302 octave_idx_type cmax = 0;
303
304 Matrix rdata (rmax, cmax, empty_value);
305 ComplexMatrix cdata;
306
307 bool iscmplx = false;
308 bool sep_is_wspace = (sep.find_first_of (" \t") != std::string::npos);
309 bool auto_sep_is_wspace = false;
310
311 if (r0 == 0)
312 {
313 // Peek into stream and potentially strip Byte Order Mark (BOM)
314 const char BOM[3] = {'\xEF', '\xBB', '\xBF'};
315 char buf[3];
316 int i_bom;
317 bool found_bom = true;
318 for (i_bom = 0; i_bom < 3; i_bom++)
319 {
320 char ch_p = input->peek ();
321 if (ch_p == BOM[i_bom])
322 buf[i_bom] = input->get ();
323 else
324 {
325 found_bom = false;
326 break;
327 }
328 }
329 // Put back read characters if it wasn't a BOM
330 if (! found_bom)
331 {
332 for (int i_ret = i_bom-1; i_ret >= 0; i_ret--)
333 input->putback (buf[i_ret]);
334 }
335 }
336
337 // Set "C" locale for the remainder of this function to avoid the performance
338 // panelty of frequently switching the locale when reading floating point
339 // values from the stream.
340 char *prev_locale = std::setlocale (LC_ALL, nullptr);
341 std::string old_locale (prev_locale ? prev_locale : "");
342 std::setlocale (LC_ALL, "C");
343 unwind_action act
344 ([old_locale] () { std::setlocale (LC_ALL, old_locale.c_str ()); });
345
346 std::string line;
347
348 // Skip the r0 leading lines
349 octave_idx_type rcnt = r0;
350 while (rcnt > 0 && getline (*input, line))
351 rcnt--;
352
353 if (rcnt > 0)
354 return ovl (Matrix (0, 0)); // Not enough lines in file to satisfy RANGE
355 else
356 r1 -= r0;
357
358 std::istringstream tmp_stream;
359
360 // Read the data one field at a time, growing the data matrix as needed.
361 while (getline (*input, line))
362 {
363 // Skip blank lines for compatibility.
364 if ((! sep_is_wspace || auto_sep_is_wspace)
365 && line.find_first_not_of (" \t") == std::string::npos)
366 continue;
367
368 // Infer separator from file if delimiter is blank.
369 if (sep.empty ())
370 {
371 // Skip leading whitespace.
372 std::size_t pos1 = line.find_first_not_of (" \t");
373
374 // For Matlab compatibility, blank delimiter should
375 // correspond to whitespace (space and tab).
376 std::size_t n = line.find_first_of (",:; \t", pos1);
377 if (n == std::string::npos)
378 {
379 sep = " \t";
380 auto_sep_is_wspace = true;
381 }
382 else
383 {
384 char ch = line.at (n);
385
386 switch (line.at (n))
387 {
388 case ' ':
389 case '\t':
390 sep = " \t";
391 auto_sep_is_wspace = true;
392 break;
393
394 default:
395 sep = ch;
396 break;
397 }
398 }
399 }
400
401 // Estimate the number of columns from first line of data.
402 if (cmax == 0)
403 {
404 std::size_t pos1, pos2;
405 if (auto_sep_is_wspace)
406 pos1 = line.find_first_not_of (" \t");
407 else
408 pos1 = 0;
409
410 do
411 {
412 pos2 = line.find_first_of (sep, pos1);
413
414 if (auto_sep_is_wspace && pos2 != std::string::npos)
415 {
416 // Treat consecutive separators as one.
417 pos2 = line.find_first_not_of (sep, pos2);
418 if (pos2 != std::string::npos)
419 pos2 -= 1;
420 }
421
422 // Separator followed by EOL doesn't generate extra column
423 if (pos2 != std::string::npos)
424 cmax++;
425
426 pos1 = pos2 + 1;
427 }
428 while (pos2 != std::string::npos);
429
430 // FIXME: Should always be the case that iscmplx == false.
431 // Flag is initialized that way and no data has been read.
432 if (iscmplx)
433 cdata.resize (rmax, cmax, empty_value);
434 else
435 rdata.resize (rmax, cmax, empty_value);
436 }
437
438 r = (r > i + 1 ? r : i + 1);
439 j = 0;
440
441 std::size_t pos1, pos2;
442 if (auto_sep_is_wspace)
443 pos1 = line.find_first_not_of (" \t"); // Skip leading whitespace.
444 else
445 pos1 = 0;
446
447 do
448 {
449 octave_quit ();
450
451 pos2 = line.find_first_of (sep, pos1);
452 std::string str = line.substr (pos1, pos2 - pos1);
453
454 if (auto_sep_is_wspace && pos2 != std::string::npos)
455 {
456 // Treat consecutive separators as one.
457 pos2 = line.find_first_not_of (sep, pos2);
458 if (pos2 != std::string::npos)
459 pos2 -= 1;
460 else
461 pos2 = line.length () - 1;
462 }
463
464 // Separator followed by EOL doesn't generate extra column
465 if (pos2 == std::string::npos && str.empty ())
466 break;
467
468 c = (c > j + 1 ? c : j + 1);
469 if (r > rmax || c > cmax)
470 {
471 // Use resize_and_fill for the case of unequal length rows.
472 // Keep rmax a power of 2.
473 rmax = std::max (2*(r-1), rmax);
474 cmax = std::max (c, cmax);
475 if (iscmplx)
476 cdata.resize (rmax, cmax, empty_value);
477 else
478 rdata.resize (rmax, cmax, empty_value);
479 }
480
481 tmp_stream.str (str);
482 tmp_stream.clear ();
483
484 double x = read_value<double> (tmp_stream);
485 if (tmp_stream)
486 {
487 if (tmp_stream.eof ())
488 {
489 if (iscmplx)
490 cdata(i, j++) = x;
491 else
492 rdata(i, j++) = x;
493 }
494 else
495 {
496 int next_char = tmp_stream.peek ();
497 if (next_char == 'i' || next_char == 'j'
498 || next_char == 'I' || next_char == 'J')
499 {
500 // Process pure imaginary numbers.
501 tmp_stream.get ();
502 next_char = tmp_stream.peek ();
503 if (next_char == std::istringstream::traits_type::eof ())
504 {
505 if (! iscmplx)
506 {
507 iscmplx = true;
508 cdata = ComplexMatrix (rdata);
509 }
510
511 cdata(i, j++) = Complex (0, x);
512 }
513 else
514 {
515 // Parsing failed, <number>i|j<extra text>
516 j++; // Leave data initialized to empty_value
517 }
518 }
519 else if (std::isalpha (next_char) && ! std::isfinite (x))
520 {
521 // Parsing failed, <Inf|NA|NaN><extra text>
522 j++; // Leave data initialized to empty_value
523 }
524 else
525 {
526 double y = read_value<double> (tmp_stream);
527
528 if (! iscmplx && y != 0.0)
529 {
530 iscmplx = true;
531 cdata = ComplexMatrix (rdata);
532 }
533
534 if (iscmplx)
535 cdata(i, j++) = Complex (x, y);
536 else
537 rdata(i, j++) = x;
538 }
539 }
540 }
541 else
542 {
543 // read_value<double>() parsing failed
544 j++; // Leave data initialized to empty_value
545 }
546
547 pos1 = pos2 + 1;
548 }
549 while (pos2 != std::string::npos);
550
551 if (i == r1)
552 break; // Stop early if the desired range has been read.
553
554 i++;
555 }
556
557 // Clip selection indices to actual size of data
558 if (r1 >= r)
559 r1 = r - 1;
560 if (c1 >= c)
561 c1 = c - 1;
562
563 if (iscmplx)
564 {
565 if ((i == 0 && j == 0) || (c0 > c1))
566 return ovl (ComplexMatrix (0, 0));
567
568 cdata = cdata.extract (0, c0, r1, c1);
569 return ovl (cdata);
570 }
571 else
572 {
573 if ((i == 0 && j == 0) || (c0 > c1))
574 return ovl (Matrix (0, 0));
575
576 rdata = rdata.extract (0, c0, r1, c1);
577 return ovl (rdata);
578 }
579}
580
581/*
582%!test
583%! file = tempname ();
584%! unwind_protect
585%! fid = fopen (file, "wt");
586%! fwrite (fid, "1, 2, 3\n4, 5, 6\n7, 8, 9\n10, 11, 12");
587%! fclose (fid);
588%!
589%! assert (dlmread (file), [1, 2, 3; 4, 5, 6; 7, 8, 9;10, 11, 12]);
590%! assert (dlmread (file, ","), [1, 2, 3; 4, 5, 6; 7, 8, 9; 10, 11, 12]);
591%! assert (dlmread (file, ",", [1, 0, 2, 1]), [4, 5; 7, 8]);
592%! assert (dlmread (file, ",", "B1..C2"), [2, 3; 5, 6]);
593%! assert (dlmread (file, ",", "B1:C2"), [2, 3; 5, 6]);
594%! assert (dlmread (file, ",", "..C2"), [1, 2, 3; 4, 5, 6]);
595%! assert (dlmread (file, ",", 0, 1), [2, 3; 5, 6; 8, 9; 11, 12]);
596%! assert (dlmread (file, ",", "B1.."), [2, 3; 5, 6; 8, 9; 11, 12]);
597%! assert (dlmread (file, ",", 10, 0), []);
598%! assert (dlmread (file, ",", 0, 10), []);
599%! fail ('dlmread (file, ",", [0 1])', "error parsing RANGE");
600%! unwind_protect_cleanup
601%! unlink (file);
602%! end_unwind_protect
603
604%!testif ; ! __have_feature__ ("LLVM_LIBCXX")
605%! file = tempname ();
606%! unwind_protect
607%! fid = fopen (file, "wt");
608%! fwrite (fid, "1, 2, 3\n4+4i, 5, 6\n7, 8, 9\n10, 11, 12");
609%! fclose (fid);
610%!
611%! assert (dlmread (file), [1, 2, 3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
612%! assert (dlmread (file, ","), [1,2,3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
613%! assert (dlmread (file, ",", [1, 0, 2, 1]), [4 + 4i, 5; 7, 8]);
614%! assert (dlmread (file, ",", "A2..B3"), [4 + 4i, 5; 7, 8]);
615%! assert (dlmread (file, ",", "A2:B3"), [4 + 4i, 5; 7, 8]);
616%! assert (dlmread (file, ",", "..B3"), [1, 2; 4 + 4i, 5; 7, 8]);
617%! assert (dlmread (file, ",", 1, 0), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
618%! assert (dlmread (file, ",", "A2.."), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
619%! assert (dlmread (file, ",", 10, 0), []);
620%! assert (dlmread (file, ",", 0, 10), []);
621%! unwind_protect_cleanup
622%! unlink (file);
623%! end_unwind_protect
624
625%!testif HAVE_LLVM_LIBCXX <47413>
626%! ## Same test code as above, intended only for test statistics with libc++.
627%! file = tempname ();
628%! unwind_protect
629%! fid = fopen (file, "wt");
630%! fwrite (fid, "1, 2, 3\n4+4i, 5, 6\n7, 8, 9\n10, 11, 12");
631%! fclose (fid);
632%!
633%! assert (dlmread (file), [1, 2, 3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
634%! assert (dlmread (file, ","), [1,2,3; 4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
635%! assert (dlmread (file, ",", [1, 0, 2, 1]), [4 + 4i, 5; 7, 8]);
636%! assert (dlmread (file, ",", "A2..B3"), [4 + 4i, 5; 7, 8]);
637%! assert (dlmread (file, ",", "A2:B3"), [4 + 4i, 5; 7, 8]);
638%! assert (dlmread (file, ",", "..B3"), [1, 2; 4 + 4i, 5; 7, 8]);
639%! assert (dlmread (file, ",", 1, 0), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
640%! assert (dlmread (file, ",", "A2.."), [4 + 4i, 5, 6; 7, 8, 9; 10, 11, 12]);
641%! assert (dlmread (file, ",", 10, 0), []);
642%! assert (dlmread (file, ",", 0, 10), []);
643%! unwind_protect_cleanup
644%! unlink (file);
645%! end_unwind_protect
646
647%!test <*42025>
648%! file = tempname ();
649%! unwind_protect
650%! fid = fopen (file, "wt");
651%! fwrite (fid, " \n 1 2\n11 22\n ");
652%! fclose (fid);
653%!
654%! assert (dlmread (file), [1, 2; 11, 22]);
655%! assert (dlmread (file, " "), [ 0, 0, 0, 0
656%! 0, 1, 2, 0
657%! 11, 22, 0, 0
658%! 0, 0, 0, 0]);
659%! unwind_protect_cleanup
660%! unlink (file);
661%! end_unwind_protect
662
663%!testif ; ! __have_feature__ ("LLVM_LIBCXX") <*50589>
664%! file = tempname ();
665%! unwind_protect
666%! fid = fopen (file, "wt");
667%! fwrite (fid, "1;2;3\n");
668%! fwrite (fid, "1i;2I;3j;4J\n");
669%! fwrite (fid, "4;5;6\n");
670%! fwrite (fid, "-4i;+5I;-6j;+7J\n");
671%! fclose (fid);
672%!
673%! assert (dlmread (file), [1, 2, 3, 0; 1i, 2i, 3i, 4i;
674%! 4, 5, 6, 0; -4i, 5i, -6i, 7i]);
675%! assert (dlmread (file, "", [0 0 0 3]), [1, 2, 3]);
676%! assert (dlmread (file, "", [1 0 1 3]), [1i, 2i, 3i, 4i]);
677%! unwind_protect_cleanup
678%! unlink (file);
679%! end_unwind_protect
680
681%!testif HAVE_LLVM_LIBCXX <47413>
682%! ## Same test code as above, intended only for test statistics with libc++.
683%! file = tempname ();
684%! unwind_protect
685%! fid = fopen (file, "wt");
686%! fwrite (fid, "1;2;3\n");
687%! fwrite (fid, "1i;2I;3j;4J\n");
688%! fwrite (fid, "4;5;6\n");
689%! fwrite (fid, "-4i;+5I;-6j;+7J\n");
690%! fclose (fid);
691%!
692%! assert (dlmread (file), [1, 2, 3, 0; 1i, 2i, 3i, 4i;
693%! 4, 5, 6, 0; -4i, 5i, -6i, 7i]);
694%! assert (dlmread (file, "", [0 0 0 3]), [1, 2, 3]);
695%! assert (dlmread (file, "", [1 0 1 3]), [1i, 2i, 3i, 4i]);
696%! unwind_protect_cleanup
697%! unlink (file);
698%! end_unwind_protect
699
700## NA was not properly read from a file
701%!test
702%! file = tempname ();
703%! unwind_protect
704%! fid = fopen (file, "wt");
705%! fwrite (fid, "1,NA,3");
706%! fclose (fid);
707%!
708%! assert (dlmread (file), [1, NA, 3]);
709%! unwind_protect_cleanup
710%! unlink (file);
711%! end_unwind_protect
712
713## "Name" was read as NA rather than parse error
714%!test <*54029>
715%! file = tempname ();
716%! unwind_protect
717%! fid = fopen (file, "wt");
718%! fwrite (fid, "NaNe,bNa,Name,c\n1,NaN,3,Inftest\n-Inf,6,NA,8");
719%! fclose (fid);
720%!
721%! assert (dlmread (file), [0, 0, 0, 0; 1, NaN, 3, 0; -Inf, 6, NA, 8]);
722%! unwind_protect_cleanup
723%! unlink (file);
724%! end_unwind_protect
725
726## Infinity incorrectly changed matrix to complex, rather than parse error
727%!test
728%! file = tempname ();
729%! unwind_protect
730%! fid = fopen (file, "wt");
731%! fwrite (fid, "1,Infinity,3");
732%! fclose (fid);
733%!
734%! assert (dlmread (file), [1, 0, 3]);
735%! unwind_protect_cleanup
736%! unlink (file);
737%! end_unwind_protect
738
739## Purely complex numbers with trailing garbage produced complex matrix
740%!test
741%! file = tempname ();
742%! unwind_protect
743%! fid = fopen (file, "wt");
744%! fwrite (fid, "1,2jack,3");
745%! fclose (fid);
746%!
747%! assert (dlmread (file), [1, 0, 3]);
748%! unwind_protect_cleanup
749%! unlink (file);
750%! end_unwind_protect
751
752## Verify UTF-8 Byte Order Mark does not cause problems with reading
753%!test <*58813>
754%! file = tempname ();
755%! unwind_protect
756%! fid = fopen (file, "wt");
757%! fwrite (fid, char ([0xEF, 0xBB, 0xBF])); # UTF-8 BOM
758%! fwrite (fid, "1,2\n3,4");
759%! fclose (fid);
760%!
761%! assert (dlmread (file), [1, 2; 3, 4]);
762%! unwind_protect_cleanup
763%! unlink (file);
764%! end_unwind_protect
765
766*/
767
768OCTAVE_END_NAMESPACE(octave)
ComplexMatrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
Definition CMatrix.cc:684
void resize(octave_idx_type nr, octave_idx_type nc, const Complex &rfv=Complex(0))
Definition CMatrix.h:191
Matrix extract(octave_idx_type r1, octave_idx_type c1, octave_idx_type r2, octave_idx_type c2) const
Definition dMatrix.cc:398
void resize(octave_idx_type nr, octave_idx_type nc, double rfv=0)
Definition dMatrix.h:156
bool is_string() const
Definition ov.h:637
octave_idx_type numel() const
Definition ov.h:559
bool is_real_matrix() const
Definition ov.h:613
std::string string_value(bool force=false) const
Definition ov.h:983
NDArray array_value(bool frc_str_conv=false) const
Definition ov.h:865
stream lookup(int fid, const std::string &who="") const
std::istream * input_stream()
Definition oct-stream.h:444
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
Definition defun-int.h:72
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
Definition defun.h:111
void error(const char *fmt,...)
Definition error.cc:1003
F77_RET_T const F77_DBLE * x
std::complex< double > Complex
Definition oct-cmplx.h:33
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition ovl.h:217
subroutine stat(x, n, av, var, xmin, xmax)
Definition tstgmn.for:112
std::string do_string_escapes(const std::string &s)
Definition utils.cc:838
std::string find_data_file_in_load_path(const std::string &fcn, const std::string &file, bool require_regular_file)
Definition utils.cc:711