1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include "lint.h"
28 #include "base_conversion.h"
29 #include <string.h>
30 #include <sys/types.h>
31 #include "libc.h"
32
33 /*
34 * Copies the appropriate string for a datum of class cl into *buf,
35 * choosing "Inf" or "Infinity" according to ndigits, the desired
36 * output string length.
37 */
38 void
__infnanstring(enum fp_class_type cl,int ndigits,char * buf)39 __infnanstring(enum fp_class_type cl, int ndigits, char *buf)
40 {
41 if (cl == fp_infinity) {
42 if (ndigits < 8)
43 (void) memcpy(buf, "Inf", 4);
44 else
45 (void) memcpy(buf, "Infinity", 9);
46 __inf_written = 1;
47 } else {
48 (void) memcpy(buf, "NaN", 4);
49 __nan_written = 1;
50 }
51 }
52
53 char *
econvert(double arg,int ndigits,int * decpt,int * sign,char * buf)54 econvert(double arg, int ndigits, int *decpt, int *sign, char *buf)
55 {
56 decimal_mode dm;
57 decimal_record dr;
58 fp_exception_field_type ef;
59 int i;
60
61 #if defined(__sparc)
62 dm.rd = _QgetRD();
63 #elif defined(__i386) || defined(__amd64)
64 dm.rd = __xgetRD();
65 #else
66 #error Unknown architecture
67 #endif
68 dm.df = floating_form; /* E format. */
69 if (ndigits <= 0)
70 ndigits = 1;
71 else if (ndigits >= DECIMAL_STRING_LENGTH)
72 ndigits = DECIMAL_STRING_LENGTH - 1;
73 dm.ndigits = ndigits; /* Number of significant digits. */
74 double_to_decimal(&arg, &dm, &dr, &ef);
75 *sign = dr.sign;
76 switch (dr.fpclass) {
77 case fp_normal:
78 case fp_subnormal:
79 *decpt = dr.exponent + ndigits;
80 for (i = 0; i < ndigits; i++)
81 buf[i] = dr.ds[i];
82 buf[ndigits] = 0;
83 break;
84 case fp_zero:
85 *decpt = 1;
86 for (i = 0; i < ndigits; i++)
87 buf[i] = '0';
88 buf[ndigits] = 0;
89 break;
90 default:
91 *decpt = 0;
92 __infnanstring(dr.fpclass, ndigits, buf);
93 break;
94 }
95 return (buf);
96 }
97
98 char *
seconvert(single * arg,int ndigits,int * decpt,int * sign,char * buf)99 seconvert(single *arg, int ndigits, int *decpt, int *sign, char *buf)
100 {
101 decimal_mode dm;
102 decimal_record dr;
103 fp_exception_field_type ef;
104 int i;
105
106 #if defined(__sparc)
107 dm.rd = _QgetRD();
108 #elif defined(__i386) || defined(__amd64)
109 dm.rd = __xgetRD();
110 #else
111 #error Unknown architecture
112 #endif
113 dm.df = floating_form; /* E format. */
114 if (ndigits <= 0)
115 ndigits = 1;
116 else if (ndigits >= DECIMAL_STRING_LENGTH)
117 ndigits = DECIMAL_STRING_LENGTH - 1;
118 dm.ndigits = ndigits; /* Number of significant digits. */
119 single_to_decimal(arg, &dm, &dr, &ef);
120 *sign = dr.sign;
121 switch (dr.fpclass) {
122 case fp_normal:
123 case fp_subnormal:
124 *decpt = dr.exponent + ndigits;
125 for (i = 0; i < ndigits; i++)
126 buf[i] = dr.ds[i];
127 buf[ndigits] = 0;
128 break;
129 case fp_zero:
130 *decpt = 1;
131 for (i = 0; i < ndigits; i++)
132 buf[i] = '0';
133 buf[ndigits] = 0;
134 break;
135 default:
136 *decpt = 0;
137 __infnanstring(dr.fpclass, ndigits, buf);
138 break;
139 }
140 return (buf);
141 }
142
143 char *
qeconvert(quadruple * arg,int ndigits,int * decpt,int * sign,char * buf)144 qeconvert(quadruple *arg, int ndigits, int *decpt, int *sign, char *buf)
145 {
146 decimal_mode dm;
147 decimal_record dr;
148 fp_exception_field_type ef;
149 int i;
150
151 #if defined(__sparc)
152 dm.rd = _QgetRD();
153 #elif defined(__i386) || defined(__amd64)
154 dm.rd = __xgetRD();
155 #else
156 #error Unknown architecture
157 #endif
158 dm.df = floating_form; /* E format. */
159 if (ndigits <= 0)
160 ndigits = 1;
161 else if (ndigits >= DECIMAL_STRING_LENGTH)
162 ndigits = DECIMAL_STRING_LENGTH - 1;
163 dm.ndigits = ndigits; /* Number of significant digits. */
164 #if defined(__sparc)
165 quadruple_to_decimal(arg, &dm, &dr, &ef);
166 #elif defined(__i386) || defined(__amd64)
167 extended_to_decimal((extended *)arg, &dm, &dr, &ef);
168 #else
169 #error Unknown architecture
170 #endif
171 *sign = dr.sign;
172 switch (dr.fpclass) {
173 case fp_normal:
174 case fp_subnormal:
175 *decpt = dr.exponent + ndigits;
176 for (i = 0; i < ndigits; i++)
177 buf[i] = dr.ds[i];
178 buf[ndigits] = 0;
179 break;
180 case fp_zero:
181 *decpt = 1;
182 for (i = 0; i < ndigits; i++)
183 buf[i] = '0';
184 buf[ndigits] = 0;
185 break;
186 default:
187 *decpt = 0;
188 __infnanstring(dr.fpclass, ndigits, buf);
189 break;
190 }
191 return (buf);
192 }
193