Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027
00028 #include <string>
00029 #include <cctype>
00030 #include <sstream>
00031 #include <algorithm>
00032
00033 #include "lo-ieee.h"
00034
00035 #include "Cell.h"
00036 #include "ov.h"
00037 #include "defun-dld.h"
00038 #include "gripes.h"
00039 #include "utils.h"
00040
00041 static inline bool
00042 is_imag_unit (int c)
00043 { return c == 'i' || c == 'j'; }
00044
00045 static std::istringstream&
00046 single_num (std::istringstream& is, double& num)
00047 {
00048 char c = is.peek ();
00049
00050
00051 while (isspace (c))
00052 {
00053 is.get ();
00054 c = is.peek ();
00055 }
00056
00057 if (c == 'I')
00058 {
00059
00060 is.get ();
00061 char c1 = is.get (), c2 = is.get ();
00062 if (c1 == 'n' && c2 == 'f')
00063 {
00064 num = octave_Inf;
00065 is.peek ();
00066 }
00067 else
00068 is.setstate (std::ios::failbit);
00069 }
00070 else if (c == 'N')
00071 {
00072
00073 is.get ();
00074 char c1 = is.get ();
00075 if (c1 == 'A')
00076 {
00077 num = octave_NA;
00078 is.peek ();
00079 }
00080 else
00081 {
00082 char c2 = is.get ();
00083 if (c1 == 'a' && c2 == 'N')
00084 {
00085 num = octave_NaN;
00086 is.peek ();
00087 }
00088 else
00089 is.setstate (std::ios::failbit);
00090 }
00091 }
00092 else
00093 is >> num;
00094
00095 return is;
00096 }
00097
00098 static std::istringstream&
00099 extract_num (std::istringstream& is, double& num, bool& imag, bool& have_sign)
00100 {
00101 have_sign = imag = false;
00102
00103 char c = is.peek ();
00104
00105
00106 while (isspace (c))
00107 {
00108 is.get ();
00109 c = is.peek ();
00110 }
00111
00112 bool negative = false;
00113
00114
00115 if (c == '+' || c == '-')
00116 {
00117 negative = c == '-';
00118 is.get ();
00119 c = is.peek ();
00120 have_sign = true;
00121 }
00122
00123
00124 while (isspace (c))
00125 {
00126 is.get ();
00127 c = is.peek ();
00128 }
00129
00130
00131 if (is_imag_unit (c))
00132 {
00133 imag = true;
00134 is.get ();
00135 c = is.peek ();
00136
00137
00138 while (isspace (c))
00139 {
00140 is.get ();
00141 c = is.peek ();
00142 }
00143
00144 if (c == '*')
00145 {
00146
00147 is.get ();
00148 single_num (is, num);
00149 if (is.good ())
00150 c = is.peek ();
00151 }
00152 else
00153 num = 1.0;
00154 }
00155 else
00156 {
00157
00158 single_num (is, num);
00159 if (is.good ())
00160 {
00161 c = is.peek ();
00162
00163
00164 while (isspace (c))
00165 {
00166 is.get ();
00167 c = is.peek ();
00168 }
00169
00170 if (c == '*')
00171 {
00172 is.get ();
00173 c = is.peek ();
00174
00175
00176 while (isspace (c))
00177 {
00178 is.get ();
00179 c = is.peek ();
00180 }
00181
00182 if (is_imag_unit (c))
00183 {
00184 imag = true;
00185 is.get ();
00186 c = is.peek ();
00187 }
00188 else
00189 is.setstate (std::ios::failbit);
00190 }
00191 else if (is_imag_unit (c))
00192 {
00193 imag = true;
00194 is.get ();
00195 c = is.peek ();
00196 }
00197 }
00198 }
00199
00200 if (is.good ())
00201 {
00202
00203 while (isspace (c))
00204 {
00205 is.get ();
00206 c = is.peek ();
00207 }
00208 }
00209
00210 if (negative)
00211 num = -num;
00212
00213 return is;
00214 }
00215
00216 static inline void
00217 set_component (Complex& c, double num, bool imag)
00218 {
00219 #if defined (HAVE_CXX_COMPLEX_SETTERS)
00220 if (imag)
00221 c.imag (num);
00222 else
00223 c.real (num);
00224 #elif defined (HAVE_CXX_COMPLEX_REFERENCE_ACCESSORS)
00225 if (imag)
00226 c.imag () = num;
00227 else
00228 c.real () = num;
00229 #else
00230 if (imag)
00231 c = Complex (c.real (), num);
00232 else
00233 c = Complex (num, c.imag ());
00234 #endif
00235 }
00236
00237 static Complex
00238 str2double1 (const std::string& str_arg)
00239 {
00240 Complex val (0.0, 0.0);
00241
00242 std::string str = str_arg;
00243
00244
00245 std::string::iterator se = str.end ();
00246 se = std::remove (str.begin (), se, ',');
00247 str.erase (se, str.end ());
00248 std::istringstream is (str);
00249
00250 double num;
00251 bool i1, i2, s1, s2;
00252
00253 if (is.eof ())
00254 val = octave_NaN;
00255 else if (! extract_num (is, num, i1, s1))
00256 val = octave_NaN;
00257 else
00258 {
00259 set_component (val, num, i1);
00260
00261 if (! is.eof ())
00262 {
00263 if (! extract_num (is, num, i2, s2) || i1 == i2 || ! s2)
00264 val = octave_NaN;
00265 else
00266 set_component (val, num, i2);
00267 }
00268 }
00269
00270 return val;
00271 }
00272
00273 DEFUN_DLD (str2double, args, ,
00274 "-*- texinfo -*-\n\
00275 @deftypefn {Built-in Function} {} str2double (@var{s})\n\
00276 Convert a string to a real or complex number.\n\
00277 \n\
00278 The string must be in one of the following formats where\n\
00279 a and b are real numbers and the complex unit is 'i' or 'j':\n\
00280 \n\
00281 @itemize\n\
00282 @item a + bi\n\
00283 \n\
00284 @item a + b*i\n\
00285 \n\
00286 @item a + i*b\n\
00287 \n\
00288 @item bi + a\n\
00289 \n\
00290 @item b*i + a\n\
00291 \n\
00292 @item i*b + a\n\
00293 @end itemize\n\
00294 \n\
00295 If present, a and/or b are of the form @nospell{[+-]d[,.]d[[eE][+-]d]} where\n\
00296 the brackets indicate optional arguments and 'd' indicates zero or more\n\
00297 digits. The special input values @code{Inf}, @code{NaN}, and @code{NA} are\n\
00298 also accepted.\n\
00299 \n\
00300 @var{s} may also be a character matrix, in which case the conversion is\n\
00301 repeated for each row. Or @var{s} may be a cell array of strings, in which\n\
00302 case each element is converted and an array of the same dimensions is\n\
00303 returned.\n\
00304 \n\
00305 @code{str2double} returns NaN for elements of @var{s} which cannot be\n\
00306 converted.\n\
00307 \n\
00308 @code{str2double} can replace @code{str2num}, and it avoids the security\n\
00309 risk of using @code{eval} on unknown data.\n\
00310 @seealso{str2num}\n\
00311 @end deftypefn")
00312 {
00313 octave_value retval;
00314
00315 if (args.length () != 1)
00316 print_usage ();
00317 else if (args(0).is_string ())
00318 {
00319 if (args(0).rows () == 1 && args(0).ndims () == 2)
00320 {
00321 retval = str2double1 (args(0).string_value ());
00322 }
00323 else
00324 {
00325 const string_vector sv = args(0).all_strings ();
00326 if (! error_state)
00327 retval = sv.map<Complex> (str2double1);
00328 }
00329 }
00330 else if (args(0).is_cell ())
00331 {
00332 const Cell cell = args(0).cell_value ();
00333
00334 if (! error_state)
00335 {
00336 ComplexNDArray output (cell.dims (), octave_NaN);
00337 for (octave_idx_type i = 0; i < cell.numel (); i++)
00338 {
00339 if (cell(i).is_string ())
00340 output(i) = str2double1 (cell(i).string_value ());
00341 }
00342 retval = output;
00343 }
00344 }
00345 else
00346 retval = NDArray (args(0).dims (), octave_NaN);
00347
00348
00349 return retval;
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382