* flow.c (elim_reg_cond): Handle a comparison of a subreg.
[official-gcc.git] / libdecnumber / decUtility.c
blob2cbed947ba78d032326254b5e038e1b4e2d836ee
1 /* Utility functions for decimal floating point support via decNumber.
2 Copyright (C) 2005 Free Software Foundation, Inc.
3 Contributed by IBM Corporation. Author Mike Cowlishaw.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 In addition to the permissions in the GNU General Public License,
13 the Free Software Foundation gives you unlimited permission to link
14 the compiled version of this file into combinations with other
15 programs, and to distribute those combinations without any
16 restriction coming from the use of this file. (The General Public
17 License restrictions do apply in other respects; for example, they
18 cover modification of the file, and distribution when not linked
19 into a combine executable.)
21 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
22 WARRANTY; without even the implied warranty of MERCHANTABILITY or
23 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 for more details.
26 You should have received a copy of the GNU General Public License
27 along with GCC; see the file COPYING. If not, write to the Free
28 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
29 02110-1301, USA. */
31 #include "config.h"
32 #include "decNumber.h" /* base number library */
33 #include "decNumberLocal.h" /* decNumber local types, etc. */
34 #include "decUtility.h" /* utility routines */
36 /* ================================================================== */
37 /* Shared utility routines */
38 /* ================================================================== */
40 /* define and include the conversion tables to use */
41 #define DEC_BIN2DPD 1 /* used for all sizes */
42 #if DECDPUN==3
43 #define DEC_DPD2BIN 1
44 #else
45 #define DEC_DPD2BCD 1
46 #endif
47 #include "decDPD.h" /* lookup tables */
49 /* The maximum number of decNumberUnits we need for a working copy of */
50 /* the units array is the ceiling of digits/DECDPUN, where digits is */
51 /* the maximum number of digits in any of the formats for which this */
52 /* is used. We do not want to include decimal128.h, so, as a very */
53 /* special case, that number is defined here. */
54 #define DECMAX754 34
55 #define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN)
57 /* ------------------------------------------------------------------ */
58 /* decDensePackCoeff -- densely pack coefficient into DPD form */
59 /* */
60 /* dn is the source number (assumed valid, max DECMAX754 digits) */
61 /* bytes is the target's byte array */
62 /* len is length of target format's byte array */
63 /* shift is the number of 0 digits to add on the right (normally 0) */
64 /* */
65 /* The coefficient must be known small enough to fit, and is filled */
66 /* in from the right (least significant first). Note that the full */
67 /* coefficient is copied, including the leading 'odd' digit. This */
68 /* digit is retrieved and packed into the combination field by the */
69 /* caller. */
70 /* */
71 /* shift is used for 'fold-down' padding. */
72 /* */
73 /* No error is possible. */
74 /* ------------------------------------------------------------------ */
75 void
76 decDensePackCoeff (const decNumber * dn, uByte * bytes, Int len, Int shift)
78 Int cut; /* work */
79 Int n; /* output bunch counter */
80 Int digits = dn->digits; /* digit countdown */
81 uInt dpd; /* densely packed decimal value */
82 uInt bin; /* binary value 0-999 */
83 uByte *bout; /* -> current output byte */
84 const Unit *inu = dn->lsu; /* -> current input unit */
85 Unit uar[DECMAXUNITS]; /* working copy of units, iff shifted */
86 #if DECDPUN!=3 /* not fast path */
87 Unit in; /* current input unit */
88 #endif
90 if (shift != 0)
91 { /* shift towards most significant required */
92 /* shift the units array to the left by pad digits and copy */
93 /* [this code is a special case of decShiftToMost, which could */
94 /* be used instead if exposed and the array were copied first] */
95 Unit *target, *first; /* work */
96 const Unit *source; /* work */
97 uInt next = 0; /* work */
99 source = dn->lsu + D2U (digits) - 1; /* where msu comes from */
100 first = uar + D2U (digits + shift) - 1; /* where msu will end up */
101 target = uar + D2U (digits) - 1 + D2U (shift); /* where upper part of first cut goes */
103 cut = (DECDPUN - shift % DECDPUN) % DECDPUN;
104 for (; source >= dn->lsu; source--, target--)
106 /* split the source Unit and accumulate remainder for next */
107 uInt rem = *source % powers[cut];
108 next += *source / powers[cut];
109 if (target <= first)
110 *target = (Unit) next; /* write to target iff valid */
111 next = rem * powers[DECDPUN - cut]; /* save remainder for next Unit */
113 /* propagate remainder to one below and clear the rest */
114 for (; target >= uar; target--)
116 *target = (Unit) next;
117 next = 0;
119 digits += shift; /* add count (shift) of zeros added */
120 inu = uar; /* use units in working array */
123 /* densely pack the coefficient into the byte array, starting from
124 the right (optionally padded) */
125 bout = &bytes[len - 1]; /* rightmost result byte for phase */
127 #if DECDPUN!=3 /* not fast path */
128 in = *inu; /* prime */
129 cut = 0; /* at lowest digit */
130 bin = 0; /* [keep compiler quiet] */
131 #endif
133 for (n = 0; digits > 0; n++)
134 { /* each output bunch */
135 #if DECDPUN==3 /* fast path, 3-at-a-time */
136 bin = *inu; /* 3 ready for convert */
137 digits -= 3; /* [may go negative] */
138 inu++; /* may need another */
140 #else /* must collect digit-by-digit */
141 Unit dig; /* current digit */
142 Int j; /* digit-in-bunch count */
143 for (j = 0; j < 3; j++)
145 #if DECDPUN<=4
146 Unit temp = (Unit) ((uInt) (in * 6554) >> 16);
147 dig = (Unit) (in - X10 (temp));
148 in = temp;
149 #else
150 dig = in % 10;
151 in = in / 10;
152 #endif
154 if (j == 0)
155 bin = dig;
156 else if (j == 1)
157 bin += X10 (dig);
158 else /* j==2 */
159 bin += X100 (dig);
161 digits--;
162 if (digits == 0)
163 break; /* [also protects *inu below] */
164 cut++;
165 if (cut == DECDPUN)
167 inu++;
168 in = *inu;
169 cut = 0;
172 #endif
173 /* here we have 3 digits in bin, or have used all input digits */
175 dpd = BIN2DPD[bin];
177 /* write bunch (bcd) to byte array */
178 switch (n & 0x03)
179 { /* phase 0-3 */
180 case 0:
181 *bout = (uByte) dpd; /* [top 2 bits truncated] */
182 bout--;
183 *bout = (uByte) (dpd >> 8);
184 break;
185 case 1:
186 *bout |= (uByte) (dpd << 2);
187 bout--;
188 *bout = (uByte) (dpd >> 6);
189 break;
190 case 2:
191 *bout |= (uByte) (dpd << 4);
192 bout--;
193 *bout = (uByte) (dpd >> 4);
194 break;
195 case 3:
196 *bout |= (uByte) (dpd << 6);
197 bout--;
198 *bout = (uByte) (dpd >> 2);
199 bout--;
200 break;
201 } /* switch */
202 } /* n bunches */
203 return;
206 /* ------------------------------------------------------------------ */
207 /* decDenseUnpackCoeff -- unpack a format's coefficient */
208 /* */
209 /* byte is the source's byte array */
210 /* len is length of the source's byte array */
211 /* dn is the target number, with 7, 16, or 34-digit space. */
212 /* bunches is the count of DPD groups in the decNumber (2, 5, or 11)*/
213 /* odd is 1 if there is a non-zero leading 10-bit group containing */
214 /* a single digit, 0 otherwise */
215 /* */
216 /* (This routine works on a copy of the number, if necessary, where */
217 /* an extra 10-bit group is prefixed to the coefficient continuation */
218 /* to hold the most significant digit if the latter is non-0.) */
219 /* */
220 /* dn->digits is set, but not the sign or exponent. */
221 /* No error is possible [the redundant 888 codes are allowed]. */
222 /* ------------------------------------------------------------------ */
223 void
224 decDenseUnpackCoeff (const uByte * bytes, Int len, decNumber * dn,
225 Int bunches, Int odd)
227 uInt dpd = 0; /* collector for 10 bits */
228 Int n; /* counter */
229 const uByte *bin; /* -> current input byte */
230 Unit *uout = dn->lsu; /* -> current output unit */
231 Unit out = 0; /* accumulator */
232 Int cut = 0; /* power of ten in current unit */
233 Unit *last = uout; /* will be unit containing msd */
234 #if DECDPUN!=3
235 uInt bcd; /* BCD result */
236 uInt nibble; /* work */
237 #endif
239 /* Expand the densely-packed integer, right to left */
240 bin = &bytes[len - 1]; /* next input byte to use */
241 for (n = 0; n < bunches + odd; n++)
242 { /* N bunches of 10 bits */
243 /* assemble the 10 bits */
244 switch (n & 0x03)
245 { /* phase 0-3 */
246 case 0:
247 dpd = *bin;
248 bin--;
249 dpd |= (*bin & 0x03) << 8;
250 break;
251 case 1:
252 dpd = (unsigned) *bin >> 2;
253 bin--;
254 dpd |= (*bin & 0x0F) << 6;
255 break;
256 case 2:
257 dpd = (unsigned) *bin >> 4;
258 bin--;
259 dpd |= (*bin & 0x3F) << 4;
260 break;
261 case 3:
262 dpd = (unsigned) *bin >> 6;
263 bin--;
264 dpd |= (*bin) << 2;
265 bin--;
266 break;
267 } /*switch */
269 #if DECDPUN==3
270 if (dpd == 0)
271 *uout = 0;
272 else
274 *uout = DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */
275 last = uout; /* record most significant unit */
277 uout++;
279 #else /* DECDPUN!=3 */
280 if (dpd == 0)
281 { /* fastpath [e.g., leading zeros] */
282 cut += 3;
283 for (; cut >= DECDPUN;)
285 cut -= DECDPUN;
286 *uout = out;
287 uout++;
288 out = 0;
290 continue;
292 bcd = DPD2BCD[dpd]; /* convert 10 bits to 12 bits BCD */
293 /* now split the 3 BCD nibbles into bytes, and accumulate into units */
294 /* If this is the last bunch and it is an odd one, we only have one */
295 /* nibble to handle [extras could overflow a Unit] */
296 nibble = bcd & 0x000f;
297 if (nibble)
299 last = uout;
300 out = (Unit) (out + nibble * powers[cut]);
302 cut++;
303 if (cut == DECDPUN)
305 *uout = out;
306 uout++;
307 cut = 0;
308 out = 0;
310 if (n < bunches)
312 nibble = bcd & 0x00f0;
313 if (nibble)
315 nibble >>= 4;
316 last = uout;
317 out = (Unit) (out + nibble * powers[cut]);
319 cut++;
320 if (cut == DECDPUN)
322 *uout = out;
323 uout++;
324 cut = 0;
325 out = 0;
327 nibble = bcd & 0x0f00;
328 if (nibble)
330 nibble >>= 8;
331 last = uout;
332 out = (Unit) (out + nibble * powers[cut]);
334 cut++;
335 if (cut == DECDPUN)
337 *uout = out;
338 uout++;
339 cut = 0;
340 out = 0;
343 #endif
344 } /* n */
345 if (cut != 0)
346 *uout = out; /* write out final unit */
348 /* here, last points to the most significant unit with digits */
349 /* we need to inspect it to get final digits count */
350 dn->digits = (last - dn->lsu) * DECDPUN; /* floor of digits */
351 for (cut = 0; cut < DECDPUN; cut++)
353 if (*last < powers[cut])
354 break;
355 dn->digits++;
357 if (dn->digits == 0)
358 dn->digits++; /* zero has one digit */
359 return;