1/* mpfr_out_str -- output a floating-point number to a stream 2 3Copyright 1999, 2001, 2002, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4Contributed by the AriC and Caramel projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23#include "mpfr-impl.h" 24 25/* Warning! S should not contain "%". */ 26#define OUT_STR_RET(S) \ 27 do \ 28 { \ 29 int r; \ 30 r = fprintf (stream, (S)); \ 31 return r < 0 ? 0 : r; \ 32 } \ 33 while (0) 34 35size_t 36mpfr_out_str (FILE *stream, int base, size_t n_digits, mpfr_srcptr op, 37 mpfr_rnd_t rnd_mode) 38{ 39 char *s, *s0; 40 size_t l; 41 mpfr_exp_t e; 42 int err; 43 44 MPFR_ASSERTN (base >= 2 && base <= 62); 45 46 /* when stream=NULL, output to stdout */ 47 if (stream == NULL) 48 stream = stdout; 49 50 if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (op))) 51 { 52 if (MPFR_IS_NAN (op)) 53 OUT_STR_RET ("@NaN@"); 54 else if (MPFR_IS_INF (op)) 55 OUT_STR_RET (MPFR_IS_POS (op) ? "@Inf@" : "-@Inf@"); 56 else 57 { 58 MPFR_ASSERTD (MPFR_IS_ZERO (op)); 59 OUT_STR_RET (MPFR_IS_POS (op) ? "0" : "-0"); 60 } 61 } 62 63 s = mpfr_get_str (NULL, &e, base, n_digits, op, rnd_mode); 64 65 s0 = s; 66 /* for op=3.1416 we have s = "31416" and e = 1 */ 67 68 l = strlen (s) + 1; /* size of allocated block returned by mpfr_get_str 69 - may be incorrect, as only an upper bound? */ 70 71 /* outputs possible sign and significand */ 72 err = (*s == '-' && fputc (*s++, stream) == EOF) 73 || fputc (*s++, stream) == EOF /* leading digit */ 74 || fputc ((unsigned char) MPFR_DECIMAL_POINT, stream) == EOF 75 || fputs (s, stream) == EOF; /* trailing significand */ 76 (*__gmp_free_func) (s0, l); 77 if (MPFR_UNLIKELY (err)) 78 return 0; 79 80 e--; /* due to the leading digit */ 81 82 /* outputs exponent */ 83 if (e) 84 { 85 int r; 86 87 MPFR_ASSERTN(e >= LONG_MIN); 88 MPFR_ASSERTN(e <= LONG_MAX); 89 90 r = fprintf (stream, (base <= 10 ? "e%ld" : "@%ld"), (long) e); 91 if (MPFR_UNLIKELY (r < 0)) 92 return 0; 93 94 l += r; 95 } 96 97 return l; 98} 99