diff options
author | enge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2009-03-19 17:05:09 +0000 |
---|---|---|
committer | enge <enge@211d60ee-9f03-0410-a15a-8952a2c7a4e4> | 2009-03-19 17:05:09 +0000 |
commit | 4c14321905768e1a782384c38c49a9c66e3c1308 (patch) | |
tree | f27a1e4344bbd162916d9f2eab8f3fb5d8f49569 | |
parent | 2e8fe025b2ac45daec5a2c1b0437b71b7e36c1a6 (diff) | |
download | mpc-4c14321905768e1a782384c38c49a9c66e3c1308.tar.gz |
inp_str, out_str: totally rewritten according to the format of strtoc;
inp_str sets the number to nan+i*nan in case of an error
git-svn-id: svn://scm.gforge.inria.fr/svn/mpc/trunk@483 211d60ee-9f03-0410-a15a-8952a2c7a4e4
-rw-r--r-- | doc/mpc.texi | 40 | ||||
-rw-r--r-- | src/get_str.c | 2 | ||||
-rw-r--r-- | src/inp_str.c | 147 | ||||
-rw-r--r-- | src/out_str.c | 36 | ||||
-rw-r--r-- | tests/inp_str.dat | 14 |
5 files changed, 124 insertions, 115 deletions
diff --git a/doc/mpc.texi b/doc/mpc.texi index ed99f2d..4364964 100644 --- a/doc/mpc.texi +++ b/doc/mpc.texi @@ -913,42 +913,20 @@ When using any of these functions, you need to include @file{stdio.h} @emph{before} @file{mpc.h}. @deftypefun size_t mpc_out_str (FILE *@var{stream}, int @var{base}, size_t @var{n_digits}, mpc_t @var{op}, mpc_rnd_t @var{rnd}) -Output @var{op} on stdio stream @var{stream}, in -base @var{base}, rounded according to @var{rnd}. -First the real part is printed, then @code{+I*} followed by the imaginary part. -The base may vary from 2 to 36. Print at most -@var{n_digits} significant digits for each part, -or if @var{n_digits} is 0, enough digits so that -@var{op} can be read back exactly rounding to nearest. - -In addition to the significant digits, a decimal point at the right of the -first digit and a -trailing exponent, in the form @samp{eNNN}, are printed. If @var{base} -is greater than 10, @samp{@@} will be used instead of @samp{e} as -exponent delimiter. +Output @var{op} on stdio stream @var{stream} in +base @var{base}, rounded according to @var{rnd}, in the same format +as for @code{mpc_strtoc} Return the number of characters written. @end deftypefun @deftypefun size_t mpc_inp_str (mpc_t @var{rop}, FILE *@var{stream}, int @var{base}, mpc_rnd_t @var{rnd}) -Input a string in base @var{base} from stdio stream @var{stream}, -rounded according to @var{rnd}, and put the -read complex in @var{rop}. -Each of the real and imaginary part should be of the form @samp{M@@N} or, -if the base is 10 or less, alternatively @samp{MeN} or @samp{MEN}. -@samp{M} is the mantissa and -@samp{N} is the exponent. The mantissa is always in the specified base. The -exponent is always read in decimal. -This function first reads the real part, then @code{+} or @code{-} followed by -@code{I*} or @code{i*} and the absolute value of the imaginary part. - -The argument @var{base} may be in the range 2 to 36. - -Note: since the real part is read with @code{mpfr_inp_str}, it should be -followed by a whitespace, thus @code{17+I*42} is invalid, but -@code{17 +I*42} is valid. - -Return the number of bytes read, or if an error occurred, return 0. +Input a string in base @var{base} in the same format as for +@code{mpc_strtoc} from stdio stream @var{stream}, +rounded according to @var{rnd}, and put the read complex number into @var{rop}. +Return the number of bytes read. + +If an error occurs, set @var{rop} to @code{NaN + i * NaN} and return 0. @end deftypefun @node Miscellaneous Complex Functions, Advanced Functions, I/O of Complex Numbers, Complex Functions diff --git a/src/get_str.c b/src/get_str.c index 8b065ae..aaa3fff 100644 --- a/src/get_str.c +++ b/src/get_str.c @@ -42,7 +42,7 @@ MA 02111-1307, USA. */ #endif static char * -mpc_alloc_str (int len) { +mpc_alloc_str (size_t len) { void * (*allocfunc) (size_t); mp_get_memory_functions (&allocfunc, NULL, NULL); return (char *) ((*allocfunc) (len * sizeof (char))); diff --git a/src/inp_str.c b/src/inp_str.c index 31565f8..1b25fa0 100644 --- a/src/inp_str.c +++ b/src/inp_str.c @@ -1,6 +1,6 @@ /* mpc_inp_str -- Input a complex number from a given stream. -Copyright (C) 2002, 2009 Andreas Enge, Paul Zimmermann, Philippe Th\'eveny +Copyright (C) 2009 Andreas Enge This file is part of the MPC Library. @@ -21,60 +21,99 @@ MA 02111-1307, USA. */ #include <stdio.h> #include <ctype.h> +#include <string.h> #include "mpc-impl.h" -size_t -mpc_inp_str (mpc_ptr rop, FILE *stream, int base, mpc_rnd_t rnd_mode) -{ - size_t size, size_im; - int c; - int sign; - - if (stream == NULL) - stream = stdin; - - /* input real part */ - size = mpfr_inp_str (MPC_RE(rop), stream, base, MPC_RND_RE(rnd_mode)); - if (size == 0) /* error while reading the real part */ - return 0; - - /* get 'i' or 'I' followed by '*' */ - do - { +static size_t +skip_whitespace (FILE *stream) { + int c = getc (stream); + size_t size = 0; + while (c != EOF && isspace ((unsigned char) c)) { c = getc (stream); - size ++; - } - while (isspace (c)); - - switch (c) - { - case '+': - sign = 0; - break; - case '-': - sign = 1; - break; - default: - /* error */ - return 0; - } - - c = getc (stream); - size ++; - if (c != 'I' && c != 'i') - return 0; /* error */ - - c = getc (stream); - size ++; - if (c != '*') - return 0; /* error */ - - size_im = mpfr_inp_str (MPC_IM(rop), stream, base, MPC_RND_IM(rnd_mode)); - if (size_im == 0) /* error while reading the imaginary part */ - return 0; - - if (sign) - mpfr_setsign (MPC_IM (rop), MPC_IM (rop), sign, GMP_RNDN); - - return size + size_im; + size++; + } + if (c != EOF) + ungetc (c, stream); + return size; +} + + +static char * +mpc_alloc_str (size_t len) { + void * (*allocfunc) (size_t); + mp_get_memory_functions (&allocfunc, NULL, NULL); + return (char *) ((*allocfunc) (len * sizeof (char))); +} + + +static char * +mpc_realloc_str (char * str, size_t oldlen, size_t newlen) { + void * (*reallocfunc) (void *, size_t, size_t); + mp_get_memory_functions (NULL, &reallocfunc, NULL); + return (char *) ((*reallocfunc) (str, oldlen * sizeof (char), + newlen * sizeof (char))); +} + + +static void +mpc_free_str_len (char *str, size_t len) { + void (*freefunc) (void *, size_t); + mp_get_memory_functions (NULL, NULL, &freefunc); + (*freefunc) (str, len * sizeof (char)); +} + + + +size_t +mpc_inp_str (mpc_ptr rop, FILE *stream, int base, mpc_rnd_t rnd_mode) { + size_t size, nread; + int c; + + if (stream == NULL) + stream = stdin; + + size = skip_whitespace (stream); + c = getc (stream); + if (c != EOF) { + if (c != '(') { + /* real number without parentheses */ + ungetc (c, stream); + nread = mpfr_inp_str (MPC_RE(rop), stream, base, MPC_RND_RE(rnd_mode)); + if (nread != 0) { + size += nread; + mpfr_set_ui (MPC_IM(rop), 0ul, GMP_RNDN); + return size; + } + } + else { + /* Complex number in parentheses; read everything from '(' to ')' + into a string and have mpc_setstr do the work */ + size_t strsize = 100; + char *str = mpc_alloc_str (strsize); + nread = 0; + while (c != EOF && c != ')') { + str [nread] = (char) c; + nread++; + if (nread == strsize) { + str = mpc_realloc_str (str, strsize, 2 * strsize); + strsize *= 2; + } + c = getc (stream); + } + if (c != EOF) { + str [nread] = ')'; + nread++; + str = mpc_realloc_str (str, strsize, nread + 1); + str [nread] = '\0'; + size += nread; + if (mpc_set_str (rop, str, base, rnd_mode) != -1) + return size; + } + mpc_free_str_len (str, strsize); + } + } + + mpfr_set_nan (MPC_RE(rop)); + mpfr_set_nan (MPC_IM(rop)); + return 0; } diff --git a/src/out_str.c b/src/out_str.c index f0a724f..080130e 100644 --- a/src/out_str.c +++ b/src/out_str.c @@ -1,6 +1,6 @@ /* mpc_out_str -- Output a complex number on a given stream. -Copyright (C) 2002, 2009 Andreas Enge, Paul Zimmermann, Philippe Th\'eveny +Copyright (C) 2009 Andreas Enge This file is part of the MPC Library. @@ -24,25 +24,17 @@ MA 02111-1307, USA. */ #include "mpc-impl.h" size_t -mpc_out_str (FILE *stream, int base, size_t n, mpc_srcptr op, mpc_rnd_t rnd) -{ - mpfr_t positive_imag; - size_t size; - - if (stream == NULL) - stream = stdout; /* fprintf does not allow NULL as first argument */ - - size = mpfr_out_str (stream, base, n, MPC_RE(op), MPC_RND_RE(rnd)); - - positive_imag[0] = MPC_IM (op)[0]; - if (mpfr_signbit (MPC_IM (op))) - { - size += fprintf (stream, " -I*"); - mpfr_setsign (positive_imag, positive_imag, 0, GMP_RNDN); - } - else - size += fprintf (stream, " +I*"); - size += mpfr_out_str (stream, base, n, positive_imag, MPC_RND_IM(rnd)); - - return size; +mpc_out_str (FILE *stream, int base, size_t n, mpc_srcptr op, mpc_rnd_t rnd) { + size_t size = 3; /* for '(', ' ' and ')' */ + + if (stream == NULL) + stream = stdout; /* fprintf does not allow NULL as first argument */ + + fprintf (stream, "("); + size += mpfr_out_str (stream, base, n, MPC_RE(op), MPC_RND_RE(rnd)); + fprintf (stream, " "); + size += mpfr_out_str (stream, base, n, MPC_IM(op), MPC_RND_RE(rnd)); + fprintf (stream, ")"); + + return size; } diff --git a/tests/inp_str.dat b/tests/inp_str.dat index 418c697..1416581 100644 --- a/tests/inp_str.dat +++ b/tests/inp_str.dat @@ -19,10 +19,10 @@ # the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, # MA 02111-1307, USA. # -1 +I*1 -1 -i*1 -invalid_real_part +I*1 -17 invalid_imaginary_part -17 +unvalid_imaginary_part -17 +Iunvalid_imaginary_part -17 +I*unvalid_imaginary_part +(1 1) +(1 -1) +(invalid_real_part 1) +(17 invalid_imaginary_part) +(17 +unvalid_imaginary_part) +(17 +unvalid_imaginary_part) +(17 +unvalid_imaginary_part) |