|
jwe@4634
|
1 |
/*
|
|
jwe@4634
|
2 |
|
|
jwe@7017
|
3 |
Copyright (C) 1996, 1997, 2003, 2004, 2005, 2006, 2007 John W. Eaton
|
|
jwe@4634
|
4 |
|
|
jwe@4634
|
5 |
This file is part of Octave.
|
|
jwe@4634
|
6 |
|
|
jwe@4634
|
7 |
Octave is free software; you can redistribute it and/or modify it
|
|
jwe@4634
|
8 |
under the terms of the GNU General Public License as published by the
|
|
jwe@7016
|
9 |
Free Software Foundation; either version 3 of the License, or (at your
|
|
jwe@7016
|
10 |
option) any later version.
|
|
jwe@4634
|
11 |
|
|
jwe@4634
|
12 |
Octave is distributed in the hope that it will be useful, but WITHOUT
|
|
jwe@4634
|
13 |
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
jwe@4634
|
14 |
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
jwe@4634
|
15 |
for more details.
|
|
jwe@4634
|
16 |
|
|
jwe@4634
|
17 |
You should have received a copy of the GNU General Public License
|
|
jwe@7016
|
18 |
along with Octave; see the file COPYING. If not, see
|
|
jwe@7016
|
19 |
<http://www.gnu.org/licenses/>.
|
|
jwe@4634
|
20 |
|
|
jwe@4634
|
21 |
*/
|
|
jwe@4634
|
22 |
|
|
jwe@4634
|
23 |
// Author: John W. Eaton.
|
|
jwe@4634
|
24 |
|
|
jwe@4634
|
25 |
#ifdef HAVE_CONFIG_H
|
|
jwe@4634
|
26 |
#include <config.h>
|
|
jwe@4634
|
27 |
#endif
|
|
jwe@4634
|
28 |
|
|
jwe@4634
|
29 |
#include <cstring>
|
|
jwe@4634
|
30 |
#include <cctype>
|
|
jwe@4634
|
31 |
|
|
jwe@4634
|
32 |
#include <fstream>
|
|
jwe@4634
|
33 |
#include <iomanip>
|
|
jwe@4634
|
34 |
#include <iostream>
|
|
jwe@5765
|
35 |
#include <sstream>
|
|
jwe@4634
|
36 |
#include <string>
|
|
jwe@4634
|
37 |
|
|
jwe@4634
|
38 |
#include "byte-swap.h"
|
|
jwe@4634
|
39 |
#include "data-conv.h"
|
|
jwe@4634
|
40 |
#include "file-ops.h"
|
|
jwe@4634
|
41 |
#include "glob-match.h"
|
|
jwe@4634
|
42 |
#include "lo-mappers.h"
|
|
jwe@4634
|
43 |
#include "mach-info.h"
|
|
jwe@4634
|
44 |
#include "oct-env.h"
|
|
jwe@4634
|
45 |
#include "oct-time.h"
|
|
jwe@4634
|
46 |
#include "quit.h"
|
|
jwe@4634
|
47 |
#include "str-vec.h"
|
|
jwe@4634
|
48 |
|
|
jwe@4634
|
49 |
#include "Cell.h"
|
|
jwe@4634
|
50 |
#include "defun.h"
|
|
jwe@4634
|
51 |
#include "error.h"
|
|
jwe@4634
|
52 |
#include "gripes.h"
|
|
jwe@4634
|
53 |
#include "load-save.h"
|
|
jwe@4634
|
54 |
#include "oct-obj.h"
|
|
jwe@4634
|
55 |
#include "oct-map.h"
|
|
jwe@4634
|
56 |
#include "ov-cell.h"
|
|
jwe@4634
|
57 |
#include "pager.h"
|
|
jwe@4634
|
58 |
#include "pt-exp.h"
|
|
jwe@4634
|
59 |
#include "symtab.h"
|
|
jwe@4634
|
60 |
#include "sysdep.h"
|
|
jwe@4634
|
61 |
#include "unwind-prot.h"
|
|
jwe@4634
|
62 |
#include "utils.h"
|
|
jwe@4634
|
63 |
#include "variables.h"
|
|
jwe@4634
|
64 |
#include "version.h"
|
|
jwe@4634
|
65 |
#include "dMatrix.h"
|
|
jwe@4634
|
66 |
|
|
jwe@4634
|
67 |
#include "ls-oct-ascii.h"
|
|
jwe@4634
|
68 |
|
|
jwe@4634
|
69 |
// The number of decimal digits to use when writing ascii data.
|
|
jwe@5951
|
70 |
static int Vsave_precision = 16;
|
|
jwe@4634
|
71 |
|
|
jwe@4634
|
72 |
// Functions for reading ascii data.
|
|
jwe@4634
|
73 |
|
|
jwe@4634
|
74 |
// Extract a KEYWORD and its value from stream IS, returning the
|
|
jwe@4634
|
75 |
// associated value in a new string.
|
|
jwe@4634
|
76 |
//
|
|
jwe@4634
|
77 |
// Input should look something like:
|
|
jwe@4634
|
78 |
//
|
|
jwe@4634
|
79 |
// [%#][ \t]*keyword[ \t]*:[ \t]*string-value[ \t]*\n
|
|
jwe@4634
|
80 |
|
|
jwe@4634
|
81 |
std::string
|
|
jwe@4687
|
82 |
extract_keyword (std::istream& is, const char *keyword, const bool next_only)
|
|
jwe@4634
|
83 |
{
|
|
jwe@4634
|
84 |
std::string retval;
|
|
jwe@4634
|
85 |
|
|
jwe@4634
|
86 |
char c;
|
|
jwe@4634
|
87 |
while (is.get (c))
|
|
jwe@4634
|
88 |
{
|
|
jwe@4634
|
89 |
if (c == '%' || c == '#')
|
|
jwe@4634
|
90 |
{
|
|
jwe@5765
|
91 |
std::ostringstream buf;
|
|
jwe@4634
|
92 |
|
|
jwe@4634
|
93 |
while (is.get (c) && (c == ' ' || c == '\t' || c == '%' || c == '#'))
|
|
jwe@4634
|
94 |
; // Skip whitespace and comment characters.
|
|
jwe@4634
|
95 |
|
|
jwe@4634
|
96 |
if (isalpha (c))
|
|
jwe@4634
|
97 |
buf << c;
|
|
jwe@4634
|
98 |
|
|
jwe@4634
|
99 |
while (is.get (c) && isalpha (c))
|
|
jwe@4634
|
100 |
buf << c;
|
|
jwe@4634
|
101 |
|
|
jwe@5765
|
102 |
std::string tmp = buf.str ();
|
|
jwe@5679
|
103 |
bool match = (tmp.compare (0, strlen (keyword), keyword) == 0);
|
|
jwe@4634
|
104 |
|
|
jwe@4634
|
105 |
if (match)
|
|
jwe@4634
|
106 |
{
|
|
jwe@5765
|
107 |
std::ostringstream value;
|
|
jwe@4634
|
108 |
while (is.get (c) && (c == ' ' || c == '\t' || c == ':'))
|
|
jwe@4634
|
109 |
; // Skip whitespace and the colon.
|
|
jwe@4634
|
110 |
|
|
lindnerb@7685
|
111 |
is.putback(c);
|
|
lindnerb@7685
|
112 |
retval = read_until_newline (is, false);
|
|
jwe@4634
|
113 |
break;
|
|
jwe@4634
|
114 |
}
|
|
jwe@4687
|
115 |
else if (next_only)
|
|
jwe@4687
|
116 |
break;
|
|
jwe@6202
|
117 |
else
|
|
jwe@6202
|
118 |
{
|
|
jwe@7566
|
119 |
while (is.get (c) && c != '\n' && c != '\r')
|
|
jwe@6202
|
120 |
; // Skip to end of line.
|
|
jwe@6202
|
121 |
}
|
|
jwe@4634
|
122 |
}
|
|
jwe@4634
|
123 |
}
|
|
jwe@4634
|
124 |
|
|
jwe@4634
|
125 |
int len = retval.length ();
|
|
jwe@4634
|
126 |
|
|
jwe@4634
|
127 |
if (len > 0)
|
|
jwe@4634
|
128 |
{
|
|
jwe@4634
|
129 |
while (len)
|
|
jwe@4634
|
130 |
{
|
|
jwe@4634
|
131 |
c = retval[len-1];
|
|
jwe@4634
|
132 |
|
|
jwe@4634
|
133 |
if (c == ' ' || c == '\t')
|
|
jwe@4634
|
134 |
len--;
|
|
jwe@4634
|
135 |
else
|
|
jwe@4634
|
136 |
{
|
|
jwe@4634
|
137 |
retval.resize (len);
|
|
jwe@4634
|
138 |
break;
|
|
jwe@4634
|
139 |
}
|
|
jwe@4634
|
140 |
}
|
|
jwe@4634
|
141 |
}
|
|
jwe@4634
|
142 |
|
|
jwe@4634
|
143 |
return retval;
|
|
jwe@4634
|
144 |
}
|
|
jwe@4634
|
145 |
|
|
jwe@4634
|
146 |
// Extract one value (scalar, matrix, string, etc.) from stream IS and
|
|
jwe@4634
|
147 |
// place it in TC, returning the name of the variable. If the value
|
|
jwe@4634
|
148 |
// is tagged as global in the file, return TRUE in GLOBAL.
|
|
jwe@4634
|
149 |
//
|
|
jwe@4687
|
150 |
// Each type supplies its own function to load the data, and so this
|
|
jwe@4687
|
151 |
// function is extensible.
|
|
jwe@4687
|
152 |
//
|
|
jwe@4634
|
153 |
// FILENAME is used for error messages.
|
|
jwe@4634
|
154 |
//
|
|
jwe@4634
|
155 |
// The data is expected to be in the following format:
|
|
jwe@4634
|
156 |
//
|
|
jwe@4634
|
157 |
// The input file must have a header followed by some data.
|
|
jwe@4634
|
158 |
//
|
|
jwe@4634
|
159 |
// All lines in the header must begin with a `#' character.
|
|
jwe@4634
|
160 |
//
|
|
jwe@4634
|
161 |
// The header must contain a list of keyword and value pairs with the
|
|
jwe@4634
|
162 |
// keyword and value separated by a colon.
|
|
jwe@4634
|
163 |
//
|
|
jwe@4634
|
164 |
// Keywords must appear in the following order:
|
|
jwe@4634
|
165 |
//
|
|
jwe@4634
|
166 |
// # name: <name>
|
|
jwe@4634
|
167 |
// # type: <type>
|
|
jwe@4634
|
168 |
// # <info>
|
|
jwe@4634
|
169 |
//
|
|
jwe@4687
|
170 |
// Where, for the built in types are:
|
|
jwe@4634
|
171 |
//
|
|
jwe@4634
|
172 |
// <name> : a valid identifier
|
|
jwe@4634
|
173 |
//
|
|
jwe@4634
|
174 |
// <type> : <typename>
|
|
jwe@4634
|
175 |
// | global <typename>
|
|
jwe@4634
|
176 |
//
|
|
jwe@4634
|
177 |
// <typename> : scalar
|
|
jwe@4634
|
178 |
// | complex scalar
|
|
jwe@4634
|
179 |
// | matrix
|
|
jwe@4634
|
180 |
// | complex matrix
|
|
jwe@4687
|
181 |
// | bool
|
|
jwe@4687
|
182 |
// | bool matrix
|
|
jwe@4634
|
183 |
// | string
|
|
jwe@4634
|
184 |
// | range
|
|
jwe@4634
|
185 |
//
|
|
jwe@4634
|
186 |
// <info> : <matrix info>
|
|
jwe@4634
|
187 |
// | <string info>
|
|
jwe@4634
|
188 |
//
|
|
jwe@4634
|
189 |
// <matrix info> : # rows: <integer>
|
|
jwe@4634
|
190 |
// : # columns: <integer>
|
|
jwe@4634
|
191 |
//
|
|
jwe@4687
|
192 |
// <string info> : # elements: <integer>
|
|
jwe@4687
|
193 |
// : # length: <integer> (once before each string)
|
|
jwe@4687
|
194 |
//
|
|
jwe@4687
|
195 |
// For backward compatibility the type "string array" is treated as a
|
|
jwe@4687
|
196 |
// "string" type. Also "string" can have a single element with no elements
|
|
jwe@4687
|
197 |
// line such that
|
|
jwe@4687
|
198 |
//
|
|
jwe@4634
|
199 |
// <string info> : # length: <integer>
|
|
jwe@4634
|
200 |
//
|
|
jwe@4634
|
201 |
// Formatted ASCII data follows the header.
|
|
jwe@4634
|
202 |
//
|
|
jwe@4634
|
203 |
// Example:
|
|
jwe@4634
|
204 |
//
|
|
jwe@4634
|
205 |
// # name: foo
|
|
jwe@4634
|
206 |
// # type: matrix
|
|
jwe@4634
|
207 |
// # rows: 2
|
|
jwe@4634
|
208 |
// # columns: 2
|
|
jwe@4634
|
209 |
// 2 4
|
|
jwe@4634
|
210 |
// 1 3
|
|
jwe@4634
|
211 |
//
|
|
jwe@4634
|
212 |
// Example:
|
|
jwe@4634
|
213 |
//
|
|
jwe@4634
|
214 |
// # name: foo
|
|
jwe@4687
|
215 |
// # type: string
|
|
jwe@4634
|
216 |
// # elements: 5
|
|
jwe@4634
|
217 |
// # length: 4
|
|
jwe@4634
|
218 |
// this
|
|
jwe@4634
|
219 |
// # length: 2
|
|
jwe@4634
|
220 |
// is
|
|
jwe@4634
|
221 |
// # length: 1
|
|
jwe@4634
|
222 |
// a
|
|
jwe@4634
|
223 |
// # length: 6
|
|
jwe@4634
|
224 |
// string
|
|
jwe@4634
|
225 |
// # length: 5
|
|
jwe@4634
|
226 |
// array
|
|
jwe@4634
|
227 |
//
|
|
jwe@5775
|
228 |
// FIXME -- this format is fairly rigid, and doesn't allow for
|
|
jwe@4687
|
229 |
// arbitrary comments. Someone should fix that. It does allow arbitrary
|
|
jwe@4687
|
230 |
// types however.
|
|
jwe@4634
|
231 |
|
|
jwe@4634
|
232 |
// Ugh. The signature of the compare method is not standard in older
|
|
jwe@4634
|
233 |
// versions of the GNU libstdc++. Do this instead:
|
|
jwe@4634
|
234 |
|
|
jwe@4634
|
235 |
#define SUBSTRING_COMPARE_EQ(s, pos, n, t) (s.substr (pos, n) == t)
|
|
jwe@4634
|
236 |
|
|
jwe@4634
|
237 |
std::string
|
|
jwe@4634
|
238 |
read_ascii_data (std::istream& is, const std::string& filename, bool& global,
|
|
jwe@5754
|
239 |
octave_value& tc, octave_idx_type count)
|
|
jwe@4634
|
240 |
{
|
|
jwe@4634
|
241 |
// Read name for this entry or break on EOF.
|
|
jwe@4634
|
242 |
|
|
jwe@4634
|
243 |
std::string name = extract_keyword (is, "name");
|
|
jwe@4634
|
244 |
|
|
jwe@4634
|
245 |
if (name.empty ())
|
|
jwe@4634
|
246 |
{
|
|
jwe@4634
|
247 |
if (count == 0)
|
|
jwe@4634
|
248 |
error ("load: empty name keyword or no data found in file `%s'",
|
|
jwe@4634
|
249 |
filename.c_str ());
|
|
jwe@4634
|
250 |
|
|
jwe@4634
|
251 |
return std::string ();
|
|
jwe@4634
|
252 |
}
|
|
jwe@4634
|
253 |
|
|
jwe@4634
|
254 |
if (name == CELL_ELT_TAG)
|
|
jwe@4634
|
255 |
{
|
|
jwe@4634
|
256 |
// This is OK -- name won't be used.
|
|
jwe@4634
|
257 |
}
|
|
jwe@4634
|
258 |
else if (! valid_identifier (name))
|
|
jwe@4634
|
259 |
{
|
|
jwe@4634
|
260 |
error ("load: bogus identifier `%s' found in file `%s'",
|
|
jwe@4634
|
261 |
name.c_str (), filename.c_str ());
|
|
jwe@4634
|
262 |
return std::string ();
|
|
jwe@4634
|
263 |
}
|
|
jwe@4634
|
264 |
|
|
jwe@4634
|
265 |
// Look for type keyword.
|
|
jwe@4634
|
266 |
|
|
jwe@4634
|
267 |
std::string tag = extract_keyword (is, "type");
|
|
jwe@4634
|
268 |
|
|
jwe@4634
|
269 |
if (! tag.empty ())
|
|
jwe@4634
|
270 |
{
|
|
jwe@4634
|
271 |
std::string typ;
|
|
jwe@4634
|
272 |
size_t pos = tag.rfind (' ');
|
|
jwe@4634
|
273 |
|
|
jwe@4634
|
274 |
if (pos != NPOS)
|
|
jwe@4634
|
275 |
{
|
|
jwe@4634
|
276 |
global = SUBSTRING_COMPARE_EQ (tag, 0, 6, "global");
|
|
jwe@4634
|
277 |
|
|
jwe@4634
|
278 |
typ = global ? tag.substr (7) : tag;
|
|
jwe@4634
|
279 |
}
|
|
jwe@4634
|
280 |
else
|
|
jwe@4634
|
281 |
typ = tag;
|
|
jwe@4634
|
282 |
|
|
jwe@4687
|
283 |
// Special case for backward compatiablity. A small bit of cruft
|
|
jwe@4687
|
284 |
if (SUBSTRING_COMPARE_EQ (typ, 0, 12, "string array"))
|
|
jwe@4687
|
285 |
tc = octave_value (charMatrix (), true);
|
|
jwe@4687
|
286 |
else
|
|
jwe@4687
|
287 |
tc = octave_value_typeinfo::lookup_type (typ);
|
|
jwe@4634
|
288 |
|
|
jwe@4988
|
289 |
if (! tc.load_ascii (is))
|
|
jwe@4988
|
290 |
error ("load: trouble reading ascii file `%s'", filename.c_str ());
|
|
jwe@4634
|
291 |
}
|
|
jwe@4634
|
292 |
else
|
|
jwe@4634
|
293 |
error ("load: failed to extract keyword specifying value type");
|
|
jwe@4634
|
294 |
|
|
jwe@4634
|
295 |
if (error_state)
|
|
jwe@4634
|
296 |
{
|
|
jwe@4634
|
297 |
error ("load: reading file %s", filename.c_str ());
|
|
jwe@4634
|
298 |
return std::string ();
|
|
jwe@4634
|
299 |
}
|
|
jwe@4634
|
300 |
|
|
jwe@4634
|
301 |
return name;
|
|
jwe@4634
|
302 |
}
|
|
jwe@4634
|
303 |
|
|
jwe@4634
|
304 |
// Save the data from TC along with the corresponding NAME, and global
|
|
jwe@4634
|
305 |
// flag MARK_AS_GLOBAL on stream OS in the plain text format described
|
|
jwe@4634
|
306 |
// above for load_ascii_data. If NAME is empty, the name: line is not
|
|
jwe@4634
|
307 |
// generated. PRECISION specifies the number of decimal digits to print.
|
|
jwe@4634
|
308 |
//
|
|
jwe@4634
|
309 |
// Assumes ranges and strings cannot contain Inf or NaN values.
|
|
jwe@4634
|
310 |
//
|
|
jwe@4634
|
311 |
// Returns 1 for success and 0 for failure.
|
|
jwe@4634
|
312 |
|
|
jwe@5775
|
313 |
// FIXME -- should probably write the help string here too.
|
|
jwe@4634
|
314 |
|
|
jwe@4634
|
315 |
bool
|
|
jwe@4634
|
316 |
save_ascii_data (std::ostream& os, const octave_value& val_arg,
|
|
jwe@6974
|
317 |
const std::string& name, bool mark_as_global,
|
|
jwe@6974
|
318 |
int precision)
|
|
jwe@4634
|
319 |
{
|
|
jwe@4634
|
320 |
bool success = true;
|
|
jwe@4634
|
321 |
|
|
jwe@4634
|
322 |
if (! name.empty ())
|
|
jwe@4634
|
323 |
os << "# name: " << name << "\n";
|
|
jwe@4634
|
324 |
|
|
jwe@4634
|
325 |
octave_value val = val_arg;
|
|
jwe@4634
|
326 |
|
|
jwe@4687
|
327 |
if (mark_as_global)
|
|
jwe@4687
|
328 |
os << "# type: global " << val.type_name () << "\n";
|
|
jwe@4687
|
329 |
else
|
|
jwe@4687
|
330 |
os << "# type: " << val.type_name() << "\n";
|
|
jwe@4634
|
331 |
|
|
jwe@5951
|
332 |
if (! precision)
|
|
jwe@5951
|
333 |
precision = Vsave_precision;
|
|
jwe@5951
|
334 |
|
|
jwe@5951
|
335 |
long old_precision = os.precision ();
|
|
jwe@5951
|
336 |
os.precision (precision);
|
|
jwe@5951
|
337 |
|
|
jwe@6974
|
338 |
success = val.save_ascii (os);
|
|
jwe@4634
|
339 |
|
|
jwe@4634
|
340 |
os.precision (old_precision);
|
|
jwe@4634
|
341 |
|
|
jwe@4634
|
342 |
return (os && success);
|
|
jwe@4634
|
343 |
}
|
|
jwe@4634
|
344 |
|
|
jwe@4634
|
345 |
bool
|
|
jwe@4634
|
346 |
save_ascii_data_for_plotting (std::ostream& os, const octave_value& t,
|
|
jwe@4634
|
347 |
const std::string& name)
|
|
jwe@4634
|
348 |
{
|
|
jwe@6974
|
349 |
return save_ascii_data (os, t, name, false, 6);
|
|
jwe@4634
|
350 |
}
|
|
jwe@4634
|
351 |
|
|
jwe@4634
|
352 |
// Maybe this should be a static function in tree-plot.cc?
|
|
jwe@4634
|
353 |
|
|
jwe@4634
|
354 |
// If TC is matrix, save it on stream OS in a format useful for
|
|
jwe@4634
|
355 |
// making a 3-dimensional plot with gnuplot. If PARAMETRIC is
|
|
jwe@4634
|
356 |
// TRUE, assume a parametric 3-dimensional plot will be generated.
|
|
jwe@4634
|
357 |
|
|
jwe@4634
|
358 |
bool
|
|
jwe@4634
|
359 |
save_three_d (std::ostream& os, const octave_value& tc, bool parametric)
|
|
jwe@4634
|
360 |
{
|
|
jwe@4634
|
361 |
bool fail = false;
|
|
jwe@4634
|
362 |
|
|
jwe@5275
|
363 |
octave_idx_type nr = tc.rows ();
|
|
jwe@5275
|
364 |
octave_idx_type nc = tc.columns ();
|
|
jwe@4634
|
365 |
|
|
jwe@4634
|
366 |
if (tc.is_real_matrix ())
|
|
jwe@4634
|
367 |
{
|
|
jwe@4634
|
368 |
os << "# 3D data...\n"
|
|
jwe@4634
|
369 |
<< "# type: matrix\n"
|
|
jwe@4634
|
370 |
<< "# total rows: " << nr << "\n"
|
|
jwe@4634
|
371 |
<< "# total columns: " << nc << "\n";
|
|
jwe@4634
|
372 |
|
|
jwe@6171
|
373 |
long old_precision = os.precision ();
|
|
jwe@6257
|
374 |
os.precision (6);
|
|
jwe@6171
|
375 |
|
|
jwe@4634
|
376 |
if (parametric)
|
|
jwe@4634
|
377 |
{
|
|
jwe@5275
|
378 |
octave_idx_type extras = nc % 3;
|
|
jwe@4634
|
379 |
if (extras)
|
|
jwe@4634
|
380 |
warning ("ignoring last %d columns", extras);
|
|
jwe@4634
|
381 |
|
|
jwe@4634
|
382 |
Matrix tmp = tc.matrix_value ();
|
|
jwe@4634
|
383 |
nr = tmp.rows ();
|
|
jwe@4634
|
384 |
|
|
jwe@5275
|
385 |
for (octave_idx_type i = 0; i < nc-extras; i += 3)
|
|
jwe@4634
|
386 |
{
|
|
jwe@4634
|
387 |
os << tmp.extract (0, i, nr-1, i+2);
|
|
jwe@4634
|
388 |
if (i+3 < nc-extras)
|
|
jwe@4634
|
389 |
os << "\n";
|
|
jwe@4634
|
390 |
}
|
|
jwe@4634
|
391 |
}
|
|
jwe@4634
|
392 |
else
|
|
jwe@4634
|
393 |
{
|
|
jwe@4634
|
394 |
Matrix tmp = tc.matrix_value ();
|
|
jwe@4634
|
395 |
nr = tmp.rows ();
|
|
jwe@4634
|
396 |
|
|
jwe@5275
|
397 |
for (octave_idx_type i = 0; i < nc; i++)
|
|
jwe@4634
|
398 |
{
|
|
jwe@4634
|
399 |
os << tmp.extract (0, i, nr-1, i);
|
|
jwe@4634
|
400 |
if (i+1 < nc)
|
|
jwe@4634
|
401 |
os << "\n";
|
|
jwe@4634
|
402 |
}
|
|
jwe@4634
|
403 |
}
|
|
jwe@6171
|
404 |
|
|
jwe@6171
|
405 |
os.precision (old_precision);
|
|
jwe@4634
|
406 |
}
|
|
jwe@4634
|
407 |
else
|
|
jwe@4634
|
408 |
{
|
|
jwe@4634
|
409 |
::error ("for now, I can only save real matrices in 3D format");
|
|
jwe@4634
|
410 |
fail = true;
|
|
jwe@4634
|
411 |
}
|
|
jwe@4634
|
412 |
|
|
jwe@4634
|
413 |
return (os && ! fail);
|
|
jwe@4634
|
414 |
}
|
|
jwe@4634
|
415 |
|
|
jwe@5794
|
416 |
DEFUN (save_precision, args, nargout,
|
|
jwe@5794
|
417 |
"-*- texinfo -*-\n\
|
|
jwe@5794
|
418 |
@deftypefn {Built-in Function} {@var{val} =} save_precision ()\n\
|
|
jwe@5794
|
419 |
@deftypefnx {Built-in Function} {@var{old_val} =} save_precision (@var{new_val})\n\
|
|
jwe@5794
|
420 |
Query or set the internal variable that specifies the number of\n\
|
|
jwe@5794
|
421 |
digits to keep when saving data in text format.\n\
|
|
jwe@5794
|
422 |
@end deftypefn")
|
|
jwe@4634
|
423 |
{
|
|
jwe@5794
|
424 |
return SET_INTERNAL_VARIABLE_WITH_LIMITS (save_precision, -1, INT_MAX);
|
|
jwe@4634
|
425 |
}
|
|
jwe@4634
|
426 |
|
|
jwe@4634
|
427 |
/*
|
|
jwe@4634
|
428 |
;;; Local Variables: ***
|
|
jwe@4634
|
429 |
;;; mode: C++ ***
|
|
jwe@4634
|
430 |
;;; End: ***
|
|
jwe@4634
|
431 |
*/
|
|
jwe@4634
|
432 |
|