Mercurial > hg > octave-lojdl
changeset 14811:52cb71787cd1
use templates to avoid code duplication in octave_read_value functions
* lo-utils.cc (octave_read_fp_value, octave_read_cx_fp_value):
New template functions.
(octave_read_value<double>, octave_read_value<float>,
octave_read_value<Complex>, octave_read_value<FloatComplex>):
Call new template functions to do the work.
(read_inf_nan_na): Use templates to avoid duplicate code.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 26 Jun 2012 16:57:32 -0400 |
parents | d40349493d87 |
children | 95b93a728603 |
files | liboctave/lo-utils.cc |
diffstat | 1 files changed, 34 insertions(+), 170 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/lo-utils.cc +++ b/liboctave/lo-utils.cc @@ -198,10 +198,11 @@ // Note that the caller is responsible for repositioning the stream on // failure. -static inline double +template <typename T> +T read_inf_nan_na (std::istream& is, char c0) { - double d = 0.0; + T val = 0.0; switch (c0) { @@ -212,7 +213,7 @@ { char c2 = is.get (); if (c2 == 'f' || c2 == 'F') - d = octave_Inf; + val = std::numeric_limits<T>::infinity (); else is.setstate (std::ios::failbit); } @@ -228,9 +229,9 @@ { char c2 = is.get (); if (c2 == 'n' || c2 == 'N') - d = octave_NaN; + val = std::numeric_limits<T>::quiet_NaN (); else - d = octave_NA; + val = octave_numeric_limits<T>::NA (); } else is.setstate (std::ios::failbit); @@ -241,16 +242,16 @@ abort (); } - return d; + return val; } // Read a double value. Discard any sign on NaN and NA. -template <> +template <typename T> double -octave_read_value (std::istream& is) +octave_read_fp_value (std::istream& is) { - double d = 0.0; + T val = 0.0; // FIXME -- resetting stream position is likely to fail unless we are // reading from a file. @@ -274,26 +275,26 @@ char c2 = 0; c2 = is.get (); if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') - d = read_inf_nan_na (is, c2); + val = read_inf_nan_na<T> (is, c2); else { is.putback (c2); - is >> d; + is >> val; } if (neg && ! is.fail ()) - d = -d; + val = -val; } break; case 'i': case 'I': case 'n': case 'N': - d = read_inf_nan_na (is, c1); + val = read_inf_nan_na<T> (is, c1); break; default: is.putback (c1); - is >> d; + is >> val; break; } @@ -305,16 +306,16 @@ is.setstate (status); } - return d; + return val; } -template <> -Complex -octave_read_value (std::istream& is) +template <typename T> +std::complex<T> +octave_read_cx_fp_value (std::istream& is) { - double re = 0.0, im = 0.0; + T re = 0.0, im = 0.0; - Complex cx = 0.0; + std::complex<T> cx = 0.0; char ch = ' '; @@ -323,16 +324,16 @@ if (ch == '(') { - re = octave_read_value<double> (is); + re = octave_read_value<T> (is); ch = is.get (); if (ch == ',') { - im = octave_read_value<double> (is); + im = octave_read_value<T> (is); ch = is.get (); if (ch == ')') - cx = Complex (re, im); + cx = std::complex<T> (re, im); else is.setstate (std::ios::failbit); } @@ -348,163 +349,26 @@ } return cx; - } -// Note that the caller is responsible for repositioning the stream on -// failure. - -static inline float -read_float_inf_nan_na (std::istream& is, char c0, char sign = '+') +template <> OCTAVE_API double octave_read_value (std::istream& is) { - float d = 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') - d = octave_Float_Inf; - 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') - d = octave_Float_NaN; - else - d = octave_Float_NA; - } - else - is.setstate (std::ios::failbit); - } - break; - - default: - abort (); - } - - return d; + return octave_read_fp_value<double> (is); } -// Read a float value. Discard any sign on NaN and NA. - -template <> -float -octave_read_value (std::istream& is) +template <> OCTAVE_API Complex octave_read_value (std::istream& is) { - float d = 0.0; - - // FIXME -- resetting stream position is likely to fail unless we are - // reading from a file. - std::ios::streampos pos = is.tellg (); - - char c1 = ' '; - - while (isspace (c1)) - c1 = is.get (); - - bool neg = false; - - switch (c1) - { - case '-': - neg = true; - // fall through... - - case '+': - { - char c2 = 0; - c2 = is.get (); - if (c2 == 'i' || c2 == 'I' || c2 == 'n' || c2 == 'N') - d = read_float_inf_nan_na (is, c2); - else - { - is.putback (c2); - is >> d; - } - - if (neg && ! is.fail ()) - d = -d; - } - break; - - case 'i': case 'I': - case 'n': case 'N': - d = read_float_inf_nan_na (is, c1); - break; - - default: - is.putback (c1); - is >> d; - break; - } - - std::ios::iostate status = is.rdstate (); - if (status & std::ios::failbit) - { - is.clear (); - is.seekg (pos); - is.setstate (status); - } - - return d; + return octave_read_cx_fp_value<double> (is); } -template <> -FloatComplex -octave_read_value (std::istream& is) +template <> OCTAVE_API float octave_read_value (std::istream& is) { - float re = 0.0, im = 0.0; - - FloatComplex cx = 0.0; - - char ch = ' '; - - while (isspace (ch)) - ch = is.get (); - - if (ch == '(') - { - re = octave_read_value<float> (is); - ch = is.get (); + return octave_read_fp_value<float> (is); +} - if (ch == ',') - { - im = octave_read_value<float> (is); - ch = is.get (); - - if (ch == ')') - cx = FloatComplex (re, im); - else - is.setstate (std::ios::failbit); - } - else if (ch == ')') - cx = re; - else - is.setstate (std::ios::failbit); - } - else - { - is.putback (ch); - cx = octave_read_value<float> (is); - } - - return cx; - +template <> OCTAVE_API FloatComplex octave_read_value (std::istream& is) +{ + return octave_read_cx_fp_value<float> (is); } void