Graphviz 12.0.1~dev.20240716.0800
Loading...
Searching...
No Matches
sfcvt.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include <limits.h>
12#include <sfio/sfhdr.h>
13
14/* Convert a floating point value to ASCII
15**
16** Written by Kiem-Phong Vo
17*/
18
19static char *Inf = "Inf", *Zero = "0";
20#define SF_INTPART (SF_IDIGITS/2)
21#define SF_INFINITE ((_Sfi = 3), Inf)
22#define SF_ZERO ((_Sfi = 1), Zero)
23
31char *_sfcvt(void * dv, int n_digit, int *decpt, int *sign, int format)
32{
33 char *sp;
34 long n, v;
35 char *ep, *buf, *endsp;
36 static char Buf[SF_MAXDIGITS];
37
38 *sign = *decpt = 0;
39 {
40 double dval = *(double *)dv;
41
42 if (dval == 0.)
43 return SF_ZERO;
44 else if ((*sign = dval < 0.)) /* assignment = */
45 dval = -dval;
46
47 n = 0;
48 if (dval >= (double)LONG_MAX) { /* scale to a small enough number to fit an int */
49 v = SF_MAXEXP10 - 1;
50 do {
51 if (dval < _Sfpos10[v])
52 v -= 1;
53 else {
54 dval *= _Sfneg10[v];
55 if ((n += 1 << v) >= SF_IDIGITS)
56 return SF_INFINITE;
57 }
58 } while (dval >= (double)LONG_MAX);
59 }
60 *decpt = (int) n;
61
62 buf = sp = Buf + SF_INTPART;
63 if ((v = (int) dval) != 0) { /* translate the integer part */
64 dval -= (double) v;
65
66 sfucvt(v, sp, n, ep, long, ulong);
67
68 n = buf - sp;
69 if ((*decpt += (int) n) >= SF_IDIGITS)
70 return SF_INFINITE;
71 buf = sp;
72 sp = Buf + SF_INTPART;
73 } else
74 n = 0;
75
76 /* remaining number of digits to compute; add 1 for later rounding */
77 n = (((format & SFFMT_EFORMAT)
78 || *decpt <= 0) ? 1 : *decpt + 1) - n;
79 if (n_digit > 0)
80 n += n_digit;
81
82 if ((ep = sp + n) > (endsp = Buf + (SF_MAXDIGITS - 2)))
83 ep = endsp;
84 if (sp > ep)
85 sp = ep;
86 else {
87 if ((format & SFFMT_EFORMAT) && *decpt == 0 && dval > 0.) {
88 double d;
89 while ((int) (d = dval * 10.) == 0) {
90 dval = d;
91 *decpt -= 1;
92 }
93 }
94
95 while (sp < ep) { /* generate fractional digits */
96 if (dval <= 0.) { /* fill with 0's */
97 do {
98 *sp++ = '0';
99 } while (sp < ep);
100 goto done;
101 } else if ((n = (int) (dval *= 10.)) < 10) {
102 *sp++ = (char) ('0' + n);
103 dval -= n;
104 } else { /* n == 10 */
105 do {
106 *sp++ = '9';
107 } while (sp < ep);
108 }
109 }
110 }
111 }
112
113 if (ep <= buf)
114 ep = buf + 1;
115 else if (ep < endsp) { /* round the last digit */
116 *--sp += 5;
117 while (*sp > '9') {
118 *sp = '0';
119 if (sp > buf)
120 *--sp += 1;
121 else { /* next power of 10 */
122 *sp = '1';
123 *decpt += 1;
124 if (!(format & SFFMT_EFORMAT)) { /* add one more 0 for %f precision */
125 ep[-1] = '0';
126 ep += 1;
127 }
128 }
129 }
130 }
131
132 done:
133 *--ep = '\0';
134 _Sfi = ep - buf;
135 return buf;
136}
GVIO_API const char * format
Definition gvio.h:51
static int sign(double v)
Definition legal.c:54
#define SF_INTPART
Definition sfcvt.c:20
#define SF_INFINITE
Definition sfcvt.c:21
#define SF_ZERO
Definition sfcvt.c:22
char * _sfcvt(void *dv, int n_digit, int *decpt, int *sign, int format)
Definition sfcvt.c:31
static char * Zero
Definition sfcvt.c:19
static char * Inf
Definition sfcvt.c:19
ssize_t _Sfi
Definition sfextern.c:21
#define SF_MAXDIGITS
Definition sfhdr.h:125
#define sfucvt(v, s, n, list, type, utype)
Definition sfhdr.h:171
#define SF_IDIGITS
Definition sfhdr.h:124
#define ulong
Definition sfhdr.h:44
#define _Sfpos10
Definition sfhdr.h:128
#define SFFMT_EFORMAT
Definition sfhdr.h:104
#define _Sfneg10
Definition sfhdr.h:129
#define SF_MAXEXP10
Definition sfhdr.h:122