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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include "lint.h"
30 #include "base_conversion.h"
31 #include <string.h>
32 #include <sys/types.h>
33 #include "libc.h"
34
35 /*
36 * Copies the appropriate string for a datum of class cl into *buf,
37 * choosing "Inf" or "Infinity" according to ndigits, the desired
38 * output string length.
39 */
40 void
__infnanstring(enum fp_class_type cl,int ndigits,char * buf)41 __infnanstring(enum fp_class_type cl, int ndigits, char *buf)
42 {
43 if (cl == fp_infinity) {
44 if (ndigits < 8)
45 (void) memcpy(buf, "Inf", 4);
46 else
47 (void) memcpy(buf, "Infinity", 9);
48 __inf_written = 1;
49 } else {
50 (void) memcpy(buf, "NaN", 4);
51 __nan_written = 1;
52 }
53 }
54
55 char *
econvert(double arg,int ndigits,int * decpt,int * sign,char * buf)56 econvert(double arg, int ndigits, int *decpt, int *sign, char *buf)
57 {
58 decimal_mode dm;
59 decimal_record dr;
60 fp_exception_field_type ef;
61 int i;
62
63 #if defined(__sparc)
64 dm.rd = _QgetRD();
65 #elif defined(__i386) || defined(__amd64)
66 dm.rd = __xgetRD();
67 #else
68 #error Unknown architecture
69 #endif
70 dm.df = floating_form; /* E format. */
71 if (ndigits <= 0)
72 ndigits = 1;
73 else if (ndigits >= DECIMAL_STRING_LENGTH)
74 ndigits = DECIMAL_STRING_LENGTH - 1;
75 dm.ndigits = ndigits; /* Number of significant digits. */
76 double_to_decimal(&arg, &dm, &dr, &ef);
77 *sign = dr.sign;
78 switch (dr.fpclass) {
79 case fp_normal:
80 case fp_subnormal:
81 *decpt = dr.exponent + ndigits;
82 for (i = 0; i < ndigits; i++)
83 buf[i] = dr.ds[i];
84 buf[ndigits] = 0;
85 break;
86 case fp_zero:
87 *decpt = 1;
88 for (i = 0; i < ndigits; i++)
89 buf[i] = '0';
90 buf[ndigits] = 0;
91 break;
92 default:
93 *decpt = 0;
94 __infnanstring(dr.fpclass, ndigits, buf);
95 break;
96 }
97 return (buf);
98 }
99
100 char *
seconvert(single * arg,int ndigits,int * decpt,int * sign,char * buf)101 seconvert(single *arg, int ndigits, int *decpt, int *sign, char *buf)
102 {
103 decimal_mode dm;
104 decimal_record dr;
105 fp_exception_field_type ef;
106 int i;
107
108 #if defined(__sparc)
109 dm.rd = _QgetRD();
110 #elif defined(__i386) || defined(__amd64)
111 dm.rd = __xgetRD();
112 #else
113 #error Unknown architecture
114 #endif
115 dm.df = floating_form; /* E format. */
116 if (ndigits <= 0)
117 ndigits = 1;
118 else if (ndigits >= DECIMAL_STRING_LENGTH)
119 ndigits = DECIMAL_STRING_LENGTH - 1;
120 dm.ndigits = ndigits; /* Number of significant digits. */
121 single_to_decimal(arg, &dm, &dr, &ef);
122 *sign = dr.sign;
123 switch (dr.fpclass) {
124 case fp_normal:
125 case fp_subnormal:
126 *decpt = dr.exponent + ndigits;
127 for (i = 0; i < ndigits; i++)
128 buf[i] = dr.ds[i];
129 buf[ndigits] = 0;
130 break;
131 case fp_zero:
132 *decpt = 1;
133 for (i = 0; i < ndigits; i++)
134 buf[i] = '0';
135 buf[ndigits] = 0;
136 break;
137 default:
138 *decpt = 0;
139 __infnanstring(dr.fpclass, ndigits, buf);
140 break;
141 }
142 return (buf);
143 }
144
145 char *
qeconvert(quadruple * arg,int ndigits,int * decpt,int * sign,char * buf)146 qeconvert(quadruple *arg, int ndigits, int *decpt, int *sign, char *buf)
147 {
148 decimal_mode dm;
149 decimal_record dr;
150 fp_exception_field_type ef;
151 int i;
152
153 #if defined(__sparc)
154 dm.rd = _QgetRD();
155 #elif defined(__i386) || defined(__amd64)
156 dm.rd = __xgetRD();
157 #else
158 #error Unknown architecture
159 #endif
160 dm.df = floating_form; /* E format. */
161 if (ndigits <= 0)
162 ndigits = 1;
163 else if (ndigits >= DECIMAL_STRING_LENGTH)
164 ndigits = DECIMAL_STRING_LENGTH - 1;
165 dm.ndigits = ndigits; /* Number of significant digits. */
166 #if defined(__sparc)
167 quadruple_to_decimal(arg, &dm, &dr, &ef);
168 #elif defined(__i386) || defined(__amd64)
169 extended_to_decimal((extended *)arg, &dm, &dr, &ef);
170 #else
171 #error Unknown architecture
172 #endif
173 *sign = dr.sign;
174 switch (dr.fpclass) {
175 case fp_normal:
176 case fp_subnormal:
177 *decpt = dr.exponent + ndigits;
178 for (i = 0; i < ndigits; i++)
179 buf[i] = dr.ds[i];
180 buf[ndigits] = 0;
181 break;
182 case fp_zero:
183 *decpt = 1;
184 for (i = 0; i < ndigits; i++)
185 buf[i] = '0';
186 buf[ndigits] = 0;
187 break;
188 default:
189 *decpt = 0;
190 __infnanstring(dr.fpclass, ndigits, buf);
191 break;
192 }
193 return (buf);
194 }
195