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