OSDN Git Service

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