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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 1988 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 "base_conversion.h" 30 31 #ifdef DEBUG 32 33 void 34 _display_big_float(_big_float *pbf, unsigned base) 35 { 36 int i; 37 38 for (i = 0; i < pbf->blength; i++) { 39 switch (base) { 40 case 2: 41 printf(" + %d * 2** %d", pbf->bsignificand[i], (16 * i + pbf->bexponent)); 42 break; 43 case 10: 44 printf(" + %d * 10** %d", pbf->bsignificand[i], (4 * i + pbf->bexponent)); 45 break; 46 } 47 if ((i % 4) == 3) 48 printf("\n"); 49 } 50 printf("\n"); 51 } 52 53 #endif 54 55 void 56 _integerstring_to_big_decimal(char ds[], unsigned ndigs, unsigned nzin, 57 unsigned *pnzout, _big_float *pd) 58 { 59 /* 60 * Convert ndigs decimal digits from ds, and up to 3 trailing zeros, 61 * into a decimal big_float in *pd. nzin tells how many implicit 62 * trailing zeros may be used, while *pnzout tells how many were 63 * actually absorbed. Up to 3 are used if available so that 64 * (ndigs+*pnzout) % 4 = 0. 65 */ 66 67 int extras, taken, id, ids; 68 69 #ifdef DEBUG 70 printf(" _integerstring_to_big_decimal: ndigs %d nzin %d ds %s \n", ndigs, nzin, ds); 71 #endif 72 73 /* Compute how many trailing zeros we're going to put in *pd. */ 74 75 extras = ndigs % 4; 76 if ((extras > 0) && (nzin != 0)) { 77 taken = 4 - extras; 78 if (taken > nzin) 79 taken = nzin; 80 } else 81 taken = 0; 82 83 *pnzout = nzin - taken; 84 85 #define IDIGIT(i) ((i < 0) ? 0 : ((i < ndigs) ? (ds[i] - '0') : 0)) 86 87 pd->bexponent = 0; 88 pd->blength = (ndigs + taken + 3) / 4; 89 90 ids = (ndigs + taken) - 4 * pd->blength; 91 id = pd->blength - 1; 92 93 #ifdef DEBUG 94 printf(" _integerstring_to_big_decimal exponent %d ids %d id %d \n", pd->bexponent, ids, id); 95 #endif 96 97 pd->bsignificand[id] = 1000 * IDIGIT(ids) + 100 * IDIGIT(ids + 1) + 10 * IDIGIT(ids + 2) + IDIGIT(ids + 3); 98 ids += 4; 99 100 for (; ids < (int) (ndigs + taken - 4); ids += 4) { /* Additional digits to 101 * be found. Main loop. */ 102 id--; 103 pd->bsignificand[id] = 1000 * ds[ids] + 100 * ds[ids + 1] + 10 * ds[ids + 2] + ds[ids + 3] - 1111 * '0'; 104 } 105 106 #ifdef DEBUG 107 assert((id == 1) || (id == 0)); 108 #endif 109 if (id != 0) 110 pd->bsignificand[0] = 1000 * IDIGIT(ids) + 100 * IDIGIT(ids + 1) + 10 * IDIGIT(ids + 2) + IDIGIT(ids + 3); 111 112 #ifdef DEBUG 113 printf(" _integerstring_to_big_decimal: "); 114 _display_big_float(pd, 10); 115 #endif 116 } 117 118 void 119 _fractionstring_to_big_decimal(char ds[], unsigned ndigs, unsigned nzin, 120 _big_float *pbf) 121 { 122 /* 123 * Converts a decimal string containing an implicit point, nzin 124 * leading implicit zeros, and ndigs explicit digits, into a big 125 * float. 126 */ 127 128 int ids, ibf; 129 130 #ifdef DEBUG 131 printf(" _fractionstring_to_big_decimal ndigs %d nzin %d s %s \n", ndigs, nzin, ds); 132 #endif 133 134 pbf->bexponent = -(int) (nzin + ndigs); 135 pbf->blength = (ndigs + 3) / 4; 136 137 ids = nzin + ndigs - 4 * pbf->blength; 138 ibf = pbf->blength - 1; 139 140 #ifdef DEBUG 141 printf(" _fractionstring_to_big_decimal exponent %d ids %d ibf %d \n", pbf->bexponent, ids, ibf); 142 #endif 143 144 #define FDIGIT(i) ((i < nzin) ? 0 : ((i < (nzin+ndigs)) ? (ds[i-nzin] - '0') : 0)) 145 146 pbf->bsignificand[ibf] = 1000 * FDIGIT(ids) + 100 * FDIGIT(ids + 1) + 10 * FDIGIT(ids + 2) + FDIGIT(ids + 3); 147 ids += 4; 148 149 for (; ids < (int) (nzin + ndigs - 4); ids += 4) { /* Additional digits to 150 * be found. Main loop. */ 151 ibf--; 152 pbf->bsignificand[ibf] = 1000 * ds[ids - nzin] + 100 * ds[ids + 1 - nzin] + 10 * ds[ids + 2 - nzin] + ds[ids + 3 - nzin] - 1111 * '0'; 153 } 154 155 if (ibf > 0) { 156 #ifdef DEBUG 157 assert(ibf == 1); 158 #endif 159 pbf->bsignificand[0] = 1000 * FDIGIT(ids) + 100 * FDIGIT(ids + 1) + 10 * FDIGIT(ids + 2) + FDIGIT(ids + 3); 160 } else { 161 #ifdef DEBUG 162 assert(ibf == 0); 163 #endif 164 } 165 166 #ifdef DEBUG 167 printf(" _fractionstring_to_big_decimal: "); 168 _display_big_float(pbf, 10); 169 #endif 170 } 171 172 void 173 _mul_10000short(_big_float *pbf, long unsigned carry) 174 { 175 int j; 176 long unsigned p; 177 178 for (j = 0; j < pbf->blength; j++) { 179 p = _prod_10000_b65536(pbf->bsignificand[j], carry); 180 pbf->bsignificand[j] = (_BIG_FLOAT_DIGIT) (p & 0xffff); 181 carry = p >> 16; 182 } 183 while (carry != 0) { 184 p = _carry_out_b10000(carry); 185 pbf->bsignificand[j++] = (_BIG_FLOAT_DIGIT) (p & 0xffff); 186 carry = p >> 16; 187 } 188 pbf->blength = j; 189 } 190 191 void 192 _big_decimal_to_big_binary(_big_float *pd, _big_float *pb) 193 { 194 /* Convert _big_float from decimal form to binary form. */ 195 196 int id, idbound; 197 _BIG_FLOAT_DIGIT sticky, carry; 198 _BIG_FLOAT_DIGIT multiplier; 199 200 #ifdef DEBUG 201 assert(pd->bexponent >= -3); 202 assert(pd->bexponent <= 3); 203 #endif 204 pb->bexponent = 0; 205 pb->blength = 1; 206 id = pd->blength - 1; 207 if ((id == 0) && (pd->bexponent < 0)) { 208 pb->bsignificand[0] = 0; 209 } else { 210 pb->bsignificand[0] = pd->bsignificand[id--]; 211 idbound = (pd->bexponent < 0) ? 1 : 0; /* How far to carry next 212 * for loop depends on 213 * whether last digit 214 * requires special 215 * treatment. */ 216 for (; id >= idbound; id--) { 217 _mul_10000short(pb, (long unsigned) pd->bsignificand[id]); 218 } 219 } 220 if (pd->bexponent < 0) {/* Have to save some integer bits, discard 221 * and stick some fraction bits at the end. */ 222 #ifdef DEBUG 223 assert(id == 0); 224 #endif 225 sticky = 0; 226 carry = pd->bsignificand[0]; 227 multiplier = 10000; 228 switch (pd->bexponent) { 229 case -1: 230 sticky = carry % 10; 231 carry /= 10; 232 multiplier = 1000; 233 break; 234 case -2: 235 sticky = carry % 100; 236 carry /= 100; 237 multiplier = 100; 238 break; 239 case -3: 240 sticky = carry % 1000; 241 carry /= 1000; 242 multiplier = 10; 243 break; 244 } 245 _multiply_base_two(pb, multiplier, (long unsigned) carry); 246 if (sticky != 0) 247 pb->bsignificand[0] |= 1; /* Save lost bits. */ 248 } else if (pd->bexponent > 0) { /* Have to append some zeros. */ 249 switch (pd->bexponent) { 250 case 1: 251 multiplier = 10; 252 break; 253 case 2: 254 multiplier = 100; 255 break; 256 case 3: 257 multiplier = 1000; 258 break; 259 } 260 carry = 0; 261 _multiply_base_two(pb, multiplier, (long unsigned) carry); 262 } 263 #ifdef DEBUG 264 printf(" _big_decimal_to_big_binary "); 265 _display_big_float(pb, 2); 266 #endif 267 } 268 269 void 270 _big_binary_to_unpacked(_big_float *pb, unpacked *pu) 271 { 272 /* Convert a binary big_float to a binary_unpacked. */ 273 274 int ib, iu; 275 276 #ifdef DEBUG 277 assert(pb->bsignificand[pb->blength - 1] != 0); /* Assert pb is 278 * normalized. */ 279 #endif 280 281 iu = 0; 282 for (ib = pb->blength - 1; ((ib - 1) >= 0) && (iu < UNPACKED_SIZE); ib -= 2) { 283 pu->significand[iu++] = pb->bsignificand[ib] << 16 | pb->bsignificand[ib - 1]; 284 } 285 if (iu < UNPACKED_SIZE) { /* The big float fits in the unpacked 286 * with no rounding. */ 287 if (ib == 0) 288 pu->significand[iu++] = pb->bsignificand[ib] << 16; 289 for (; iu < UNPACKED_SIZE; iu++) 290 pu->significand[iu] = 0; 291 } else { /* The big float is too big; chop, stick, and 292 * normalize. */ 293 while (pb->bsignificand[ib] == 0) 294 ib--; 295 if (ib >= 0) 296 pu->significand[UNPACKED_SIZE - 1] |= 1; /* Stick lsb if nonzero 297 * found. */ 298 } 299 300 pu->exponent = 16 * pb->blength + pb->bexponent - 1; 301 _fp_normalize(pu); 302 303 #ifdef DEBUG 304 printf(" _big_binary_to_unpacked \n"); 305 _display_unpacked(pu); 306 #endif 307 } 308