00001 /* Utility functions for decimal floating point support via decNumber. 00002 Copyright (C) 2005 Free Software Foundation, Inc. 00003 Contributed by IBM Corporation. Author Mike Cowlishaw. 00004 00005 This file is part of GCC. 00006 00007 GCC is free software; you can redistribute it and/or modify it under 00008 the terms of the GNU General Public License as published by the Free 00009 Software Foundation; either version 2, or (at your option) any later 00010 version. 00011 00012 In addition to the permissions in the GNU General Public License, 00013 the Free Software Foundation gives you unlimited permission to link 00014 the compiled version of this file into combinations with other 00015 programs, and to distribute those combinations without any 00016 restriction coming from the use of this file. (The General Public 00017 License restrictions do apply in other respects; for example, they 00018 cover modification of the file, and distribution when not linked 00019 into a combine executable.) 00020 00021 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 00022 WARRANTY; without even the implied warranty of MERCHANTABILITY or 00023 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00024 for more details. 00025 00026 You should have received a copy of the GNU General Public License 00027 along with GCC; see the file COPYING. If not, write to the Free 00028 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 00029 02110-1301, USA. */ 00030 00031 #include "config.h" 00032 #include "decNumber.h" /* base number library */ 00033 #include "decNumberLocal.h" /* decNumber local types, etc. */ 00034 #include "decUtility.h" /* utility routines */ 00035 00036 /* ================================================================== */ 00037 /* Shared utility routines */ 00038 /* ================================================================== */ 00039 00040 /* define and include the conversion tables to use */ 00041 #define DEC_BIN2DPD 1 /* used for all sizes */ 00042 #if DECDPUN==3 00043 #define DEC_DPD2BIN 1 00044 #else 00045 #define DEC_DPD2BCD 1 00046 #endif 00047 #include "decDPD.h" /* lookup tables */ 00048 00049 /* The maximum number of decNumberUnits we need for a working copy of */ 00050 /* the units array is the ceiling of digits/DECDPUN, where digits is */ 00051 /* the maximum number of digits in any of the formats for which this */ 00052 /* is used. We do not want to include decimal128.h, so, as a very */ 00053 /* special case, that number is defined here. */ 00054 #define DECMAX754 34 00055 #define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN) 00056 00057 /* ------------------------------------------------------------------ */ 00058 /* decDensePackCoeff -- densely pack coefficient into DPD form */ 00059 /* */ 00060 /* dn is the source number (assumed valid, max DECMAX754 digits) */ 00061 /* bytes is the target's byte array */ 00062 /* len is length of target format's byte array */ 00063 /* shift is the number of 0 digits to add on the right (normally 0) */ 00064 /* */ 00065 /* The coefficient must be known small enough to fit, and is filled */ 00066 /* in from the right (least significant first). Note that the full */ 00067 /* coefficient is copied, including the leading 'odd' digit. This */ 00068 /* digit is retrieved and packed into the combination field by the */ 00069 /* caller. */ 00070 /* */ 00071 /* shift is used for 'fold-down' padding. */ 00072 /* */ 00073 /* No error is possible. */ 00074 /* ------------------------------------------------------------------ */ 00075 void 00076 decDensePackCoeff (const decNumber * dn, uByte * bytes, Int len, Int shift) 00077 { 00078 Int cut; /* work */ 00079 Int n; /* output bunch counter */ 00080 Int digits = dn->digits; /* digit countdown */ 00081 uInt dpd; /* densely packed decimal value */ 00082 uInt bin; /* binary value 0-999 */ 00083 uByte *bout; /* -> current output byte */ 00084 const Unit *inu = dn->lsu; /* -> current input unit */ 00085 Unit uar[DECMAXUNITS]; /* working copy of units, iff shifted */ 00086 #if DECDPUN!=3 /* not fast path */ 00087 Unit in; /* current input unit */ 00088 #endif 00089 00090 if (shift != 0) 00091 { /* shift towards most significant required */ 00092 /* shift the units array to the left by pad digits and copy */ 00093 /* [this code is a special case of decShiftToMost, which could */ 00094 /* be used instead if exposed and the array were copied first] */ 00095 Unit *target, *first; /* work */ 00096 const Unit *source; /* work */ 00097 uInt next = 0; /* work */ 00098 00099 source = dn->lsu + D2U (digits) - 1; /* where msu comes from */ 00100 first = uar + D2U (digits + shift) - 1; /* where msu will end up */ 00101 target = uar + D2U (digits) - 1 + D2U (shift); /* where upper part of first cut goes */ 00102 00103 cut = (DECDPUN - shift % DECDPUN) % DECDPUN; 00104 for (; source >= dn->lsu; source--, target--) 00105 { 00106 /* split the source Unit and accumulate remainder for next */ 00107 uInt rem = *source % powers[cut]; 00108 next += *source / powers[cut]; 00109 if (target <= first) 00110 *target = (Unit) next; /* write to target iff valid */ 00111 next = rem * powers[DECDPUN - cut]; /* save remainder for next Unit */ 00112 } 00113 /* propagate remainder to one below and clear the rest */ 00114 for (; target >= uar; target--) 00115 { 00116 *target = (Unit) next; 00117 next = 0; 00118 } 00119 digits += shift; /* add count (shift) of zeros added */ 00120 inu = uar; /* use units in working array */ 00121 } 00122 00123 /* densely pack the coefficient into the byte array, starting from 00124 the right (optionally padded) */ 00125 bout = &bytes[len - 1]; /* rightmost result byte for phase */ 00126 00127 #if DECDPUN!=3 /* not fast path */ 00128 in = *inu; /* prime */ 00129 cut = 0; /* at lowest digit */ 00130 bin = 0; /* [keep compiler quiet] */ 00131 #endif 00132 00133 for (n = 0; digits > 0; n++) 00134 { /* each output bunch */ 00135 #if DECDPUN==3 /* fast path, 3-at-a-time */ 00136 bin = *inu; /* 3 ready for convert */ 00137 digits -= 3; /* [may go negative] */ 00138 inu++; /* may need another */ 00139 00140 #else /* must collect digit-by-digit */ 00141 Unit dig; /* current digit */ 00142 Int j; /* digit-in-bunch count */ 00143 for (j = 0; j < 3; j++) 00144 { 00145 #if DECDPUN<=4 00146 Unit temp = (Unit) ((uInt) (in * 6554) >> 16); 00147 dig = (Unit) (in - X10 (temp)); 00148 in = temp; 00149 #else 00150 dig = in % 10; 00151 in = in / 10; 00152 #endif 00153 00154 if (j == 0) 00155 bin = dig; 00156 else if (j == 1) 00157 bin += X10 (dig); 00158 else /* j==2 */ 00159 bin += X100 (dig); 00160 00161 digits--; 00162 if (digits == 0) 00163 break; /* [also protects *inu below] */ 00164 cut++; 00165 if (cut == DECDPUN) 00166 { 00167 inu++; 00168 in = *inu; 00169 cut = 0; 00170 } 00171 } 00172 #endif 00173 /* here we have 3 digits in bin, or have used all input digits */ 00174 00175 dpd = BIN2DPD[bin]; 00176 00177 /* write bunch (bcd) to byte array */ 00178 switch (n & 0x03) 00179 { /* phase 0-3 */ 00180 case 0: 00181 *bout = (uByte) dpd; /* [top 2 bits truncated] */ 00182 bout--; 00183 *bout = (uByte) (dpd >> 8); 00184 break; 00185 case 1: 00186 *bout |= (uByte) (dpd << 2); 00187 bout--; 00188 *bout = (uByte) (dpd >> 6); 00189 break; 00190 case 2: 00191 *bout |= (uByte) (dpd << 4); 00192 bout--; 00193 *bout = (uByte) (dpd >> 4); 00194 break; 00195 case 3: 00196 *bout |= (uByte) (dpd << 6); 00197 bout--; 00198 *bout = (uByte) (dpd >> 2); 00199 bout--; 00200 break; 00201 } /* switch */ 00202 } /* n bunches */ 00203 return; 00204 } 00205 00206 /* ------------------------------------------------------------------ */ 00207 /* decDenseUnpackCoeff -- unpack a format's coefficient */ 00208 /* */ 00209 /* byte is the source's byte array */ 00210 /* len is length of the source's byte array */ 00211 /* dn is the target number, with 7, 16, or 34-digit space. */ 00212 /* bunches is the count of DPD groups in the decNumber (2, 5, or 11)*/ 00213 /* odd is 1 if there is a non-zero leading 10-bit group containing */ 00214 /* a single digit, 0 otherwise */ 00215 /* */ 00216 /* (This routine works on a copy of the number, if necessary, where */ 00217 /* an extra 10-bit group is prefixed to the coefficient continuation */ 00218 /* to hold the most significant digit if the latter is non-0.) */ 00219 /* */ 00220 /* dn->digits is set, but not the sign or exponent. */ 00221 /* No error is possible [the redundant 888 codes are allowed]. */ 00222 /* ------------------------------------------------------------------ */ 00223 void 00224 decDenseUnpackCoeff (const uByte * bytes, Int len, decNumber * dn, 00225 Int bunches, Int odd) 00226 { 00227 uInt dpd = 0; /* collector for 10 bits */ 00228 Int n; /* counter */ 00229 const uByte *bin; /* -> current input byte */ 00230 Unit *uout = dn->lsu; /* -> current output unit */ 00231 Unit out = 0; /* accumulator */ 00232 Int cut = 0; /* power of ten in current unit */ 00233 Unit *last = uout; /* will be unit containing msd */ 00234 #if DECDPUN!=3 00235 uInt bcd; /* BCD result */ 00236 uInt nibble; /* work */ 00237 #endif 00238 00239 /* Expand the densely-packed integer, right to left */ 00240 bin = &bytes[len - 1]; /* next input byte to use */ 00241 for (n = 0; n < bunches + odd; n++) 00242 { /* N bunches of 10 bits */ 00243 /* assemble the 10 bits */ 00244 switch (n & 0x03) 00245 { /* phase 0-3 */ 00246 case 0: 00247 dpd = *bin; 00248 bin--; 00249 dpd |= (*bin & 0x03) << 8; 00250 break; 00251 case 1: 00252 dpd = (unsigned) *bin >> 2; 00253 bin--; 00254 dpd |= (*bin & 0x0F) << 6; 00255 break; 00256 case 2: 00257 dpd = (unsigned) *bin >> 4; 00258 bin--; 00259 dpd |= (*bin & 0x3F) << 4; 00260 break; 00261 case 3: 00262 dpd = (unsigned) *bin >> 6; 00263 bin--; 00264 dpd |= (*bin) << 2; 00265 bin--; 00266 break; 00267 } /*switch */ 00268 00269 #if DECDPUN==3 00270 if (dpd == 0) 00271 *uout = 0; 00272 else 00273 { 00274 *uout = DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */ 00275 last = uout; /* record most significant unit */ 00276 } 00277 uout++; 00278 00279 #else /* DECDPUN!=3 */ 00280 if (dpd == 0) 00281 { /* fastpath [e.g., leading zeros] */ 00282 cut += 3; 00283 for (; cut >= DECDPUN;) 00284 { 00285 cut -= DECDPUN; 00286 *uout = out; 00287 uout++; 00288 out = 0; 00289 } 00290 continue; 00291 } 00292 bcd = DPD2BCD[dpd]; /* convert 10 bits to 12 bits BCD */ 00293 /* now split the 3 BCD nibbles into bytes, and accumulate into units */ 00294 /* If this is the last bunch and it is an odd one, we only have one */ 00295 /* nibble to handle [extras could overflow a Unit] */ 00296 nibble = bcd & 0x000f; 00297 if (nibble) 00298 { 00299 last = uout; 00300 out = (Unit) (out + nibble * powers[cut]); 00301 } 00302 cut++; 00303 if (cut == DECDPUN) 00304 { 00305 *uout = out; 00306 uout++; 00307 cut = 0; 00308 out = 0; 00309 } 00310 if (n < bunches) 00311 { 00312 nibble = bcd & 0x00f0; 00313 if (nibble) 00314 { 00315 nibble >>= 4; 00316 last = uout; 00317 out = (Unit) (out + nibble * powers[cut]); 00318 } 00319 cut++; 00320 if (cut == DECDPUN) 00321 { 00322 *uout = out; 00323 uout++; 00324 cut = 0; 00325 out = 0; 00326 } 00327 nibble = bcd & 0x0f00; 00328 if (nibble) 00329 { 00330 nibble >>= 8; 00331 last = uout; 00332 out = (Unit) (out + nibble * powers[cut]); 00333 } 00334 cut++; 00335 if (cut == DECDPUN) 00336 { 00337 *uout = out; 00338 uout++; 00339 cut = 0; 00340 out = 0; 00341 } 00342 } 00343 #endif 00344 } /* n */ 00345 if (cut != 0) 00346 *uout = out; /* write out final unit */ 00347 00348 /* here, last points to the most significant unit with digits */ 00349 /* we need to inspect it to get final digits count */ 00350 dn->digits = (last - dn->lsu) * DECDPUN; /* floor of digits */ 00351 for (cut = 0; cut < DECDPUN; cut++) 00352 { 00353 if (*last < powers[cut]) 00354 break; 00355 dn->digits++; 00356 } 00357 if (dn->digits == 0) 00358 dn->digits++; /* zero has one digit */ 00359 return; 00360 }
1.5.6