/* Extract from stream the longest string made up of alphanumeric char and '_' (i.e. n-char-sequence). The user must free the returned string. */ static char * extract_suffix (FILE *stream) { int c; size_t nread = 0; size_t strsize = 100; char *str = mpc_alloc_str (strsize); c = getc (stream); while (isalnum ((unsigned char) c) || c == '_') { str [nread] = (char) c; nread++; if (nread == strsize) { str = mpc_realloc_str (str, strsize, 2 * strsize); strsize *= 2; } c = getc (stream); } str = mpc_realloc_str (str, strsize, nread + 1); strsize = nread + 1; str [nread] = '\0'; if (c != EOF) ungetc (c, stream); return str; }
char * mpc_get_str (int base, size_t n, mpc_srcptr op, mpc_rnd_t rnd) { size_t needed_size; char *real_str; char *imag_str; char *complex_str = NULL; if (base < 2 || base > 36) return NULL; real_str = get_pretty_str (base, n, MPC_RE (op), MPC_RND_RE (rnd)); imag_str = get_pretty_str (base, n, MPC_IM (op), MPC_RND_IM (rnd)); needed_size = strlen (real_str) + strlen (imag_str) + 4; complex_str = mpc_alloc_str (needed_size); MPC_ASSERT (complex_str != NULL); strcpy (complex_str, "("); strcat (complex_str, real_str); strcat (complex_str, " "); strcat (complex_str, imag_str); strcat (complex_str, ")"); mpc_free_str (real_str); mpc_free_str (imag_str); return complex_str; }
static char * pretty_zero (mpfr_srcptr zero) { char *pretty; pretty = mpc_alloc_str (3); pretty[0] = mpfr_signbit (zero) ? '-' : '+'; pretty[1] = '0'; pretty[2] = '\0'; return pretty; }
/* Extract from the stream the longest string of characters which are neither whitespace nor brackets (except for an optional bracketed n-char_sequence directly following nan or @nan@ independently of case). The user must free the returned string. */ static char * extract_string (FILE *stream) { int c; size_t nread = 0; size_t strsize = 100; char *str = mpc_alloc_str (strsize); size_t lenstr; c = getc (stream); while (c != EOF && c != '\n' && !isspace ((unsigned char) c) && c != '(' && c != ')') { str [nread] = (char) c; nread++; if (nread == strsize) { str = mpc_realloc_str (str, strsize, 2 * strsize); strsize *= 2; } c = getc (stream); } str = mpc_realloc_str (str, strsize, nread + 1); strsize = nread + 1; str [nread] = '\0'; if (nread == 0) return str; lenstr = nread; if (c == '(') { size_t n; char *suffix; int ret; /* (n-char-sequence) only after a NaN */ if ((nread != 3 || tolower ((unsigned char) (str[0])) != 'n' || tolower ((unsigned char) (str[1])) != 'a' || tolower ((unsigned char) (str[2])) != 'n') && (nread != 5 || str[0] != '@' || tolower ((unsigned char) (str[1])) != 'n' || tolower ((unsigned char) (str[2])) != 'a' || tolower ((unsigned char) (str[3])) != 'n' || str[4] != '@')) { ungetc (c, stream); return str; } suffix = extract_suffix (stream); nread += strlen (suffix) + 1; if (nread >= strsize) { str = mpc_realloc_str (str, strsize, nread + 1); strsize = nread + 1; } /* Warning: the sprintf does not allow overlap between arguments. */ ret = sprintf (str + lenstr, "(%s", suffix); MPC_ASSERT (ret >= 0); n = lenstr + (size_t) ret; MPC_ASSERT (n == nread); c = getc (stream); if (c == ')') { str = mpc_realloc_str (str, strsize, nread + 2); strsize = nread + 2; str [nread] = (char) c; str [nread+1] = '\0'; nread++; } else if (c != EOF) ungetc (c, stream); mpc_free_str (suffix); } else if (c != EOF) ungetc (c, stream); return str; }
int mpc_inp_str (mpc_ptr rop, FILE *stream, size_t *read, int base, mpc_rnd_t rnd_mode) { size_t white, nread = 0; int inex = -1; int c; char *str; if (stream == NULL) stream = stdin; white = skip_whitespace (stream); c = getc (stream); if (c != EOF) { if (c == '(') { char *real_str; char *imag_str; size_t n; int ret; nread++; /* the opening parenthesis */ white = skip_whitespace (stream); real_str = extract_string (stream); nread += strlen(real_str); c = getc (stream); if (!isspace ((unsigned int) c)) { if (c != EOF) ungetc (c, stream); mpc_free_str (real_str); goto error; } else ungetc (c, stream); white += skip_whitespace (stream); imag_str = extract_string (stream); nread += strlen (imag_str); str = mpc_alloc_str (nread + 2); ret = sprintf (str, "(%s %s", real_str, imag_str); MPC_ASSERT (ret >= 0); n = (size_t) ret; MPC_ASSERT (n == nread + 1); mpc_free_str (real_str); mpc_free_str (imag_str); white += skip_whitespace (stream); c = getc (stream); if (c == ')') { str = mpc_realloc_str (str, nread +2, nread + 3); str [nread+1] = (char) c; str [nread+2] = '\0'; nread++; } else if (c != EOF) ungetc (c, stream); } else { if (c != EOF) ungetc (c, stream); str = extract_string (stream); nread += strlen (str); } inex = mpc_set_str (rop, str, base, rnd_mode); mpc_free_str (str); } error: if (inex == -1) { mpfr_set_nan (MPC_RE(rop)); mpfr_set_nan (MPC_IM(rop)); } if (read != NULL) *read = white + nread; return inex; }
static char * prettify (const char *str, const mp_exp_t expo, int base, int special) { size_t sz; char *pretty; char *p; const char *s; mp_exp_t x; int sign; sz = strlen (str) + 1; /* + terminal '\0' */ if (special) { /* special number: nan or inf */ pretty = mpc_alloc_str (sz); strcpy (pretty, str); return pretty; } /* regular number */ sign = (str[0] == '-' || str[0] == '+'); x = expo - 1; /* expo is the exponent value with decimal point BEFORE the first digit, we wants decimal point AFTER the first digit */ if (base == 16) x <<= 2; /* the output exponent is a binary exponent */ ++sz; /* + decimal point */ if (x != 0) { /* augment sz with the size needed for an exponent written in base ten */ mp_exp_t xx; sz += 3; /* + exponent char + sign + 1 digit */ if (x < 0) { /* avoid overflow when changing sign (assuming that, for the mp_exp_t type, (max value) is greater than (- min value / 10)) */ if (x < -10) { xx = - (x / 10); sz++; } else xx = -x; } else xx = x; /* compute sz += floor(log(expo)/log(10)) without using libm functions */ while (xx > 9) { sz++; xx /= 10; } } pretty = mpc_alloc_str (sz); p = pretty; /* 1. optional sign plus first digit */ s = str; *p++ = *s++; if (sign) *p++ = *s++; /* 2. decimal point */ #ifdef HAVE_LOCALECONV *p++ = *localeconv ()->decimal_point; #else *p++ = '.'; #endif *p = '\0'; /* 3. other significant digits */ strcat (pretty, s); /* 4. exponent (in base ten) */ if (x == 0) return pretty; p = pretty + strlen (str) + 1; switch (base) { case 10: *p++ = 'e'; break; case 2: case 16: *p++ = 'p'; break; default: *p++ = '@'; } *p = '\0'; sprintf (p, "%+"MPC_EXP_FORMAT_SPEC, x); return pretty; }