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 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 * 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 * 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 * 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