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   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.)
20
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.
25
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.  */
30
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 */
35
36/* ================================================================== */
37/* Shared utility routines                                            */
38/* ================================================================== */
39
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 */
48
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)
56
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/* ------------------------------------------------------------------ */
75void
76decDensePackCoeff (const decNumber * dn, uByte * bytes, Int len, Int shift)
77{
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
89
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 */
98
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 */
102
103      cut = (DECDPUN - shift % DECDPUN) % DECDPUN;
104      for (; source >= dn->lsu; source--, target--)
105	{
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 */
112	}
113      /* propagate remainder to one below and clear the rest */
114      for (; target >= uar; target--)
115	{
116	  *target = (Unit) next;
117	  next = 0;
118	}
119      digits += shift;		/* add count (shift) of zeros added */
120      inu = uar;		/* use units in working array */
121    }
122
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 */
126
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
132
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 */
139
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++)
144	{
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
153
154	  if (j == 0)
155	    bin = dig;
156	  else if (j == 1)
157	    bin += X10 (dig);
158	  else			/* j==2 */
159	    bin += X100 (dig);
160
161	  digits--;
162	  if (digits == 0)
163	    break;		/* [also protects *inu below] */
164	  cut++;
165	  if (cut == DECDPUN)
166	    {
167	      inu++;
168	      in = *inu;
169	      cut = 0;
170	    }
171	}
172#endif
173      /* here we have 3 digits in bin, or have used all input digits */
174
175      dpd = BIN2DPD[bin];
176
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;
204}
205
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/* ------------------------------------------------------------------ */
223void
224decDenseUnpackCoeff (const uByte * bytes, Int len, decNumber * dn,
225		     Int bunches, Int odd)
226{
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
238
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 */
268
269#if DECDPUN==3
270      if (dpd == 0)
271	*uout = 0;
272      else
273	{
274	  *uout = DPD2BIN[dpd];	/* convert 10 bits to binary 0-999 */
275	  last = uout;		/* record most significant unit */
276	}
277      uout++;
278
279#else /* DECDPUN!=3 */
280      if (dpd == 0)
281	{			/* fastpath [e.g., leading zeros] */
282	  cut += 3;
283	  for (; cut >= DECDPUN;)
284	    {
285	      cut -= DECDPUN;
286	      *uout = out;
287	      uout++;
288	      out = 0;
289	    }
290	  continue;
291	}
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)
298	{
299	  last = uout;
300	  out = (Unit) (out + nibble * powers[cut]);
301	}
302      cut++;
303      if (cut == DECDPUN)
304	{
305	  *uout = out;
306	  uout++;
307	  cut = 0;
308	  out = 0;
309	}
310      if (n < bunches)
311	{
312	  nibble = bcd & 0x00f0;
313	  if (nibble)
314	    {
315	      nibble >>= 4;
316	      last = uout;
317	      out = (Unit) (out + nibble * powers[cut]);
318	    }
319	  cut++;
320	  if (cut == DECDPUN)
321	    {
322	      *uout = out;
323	      uout++;
324	      cut = 0;
325	      out = 0;
326	    }
327	  nibble = bcd & 0x0f00;
328	  if (nibble)
329	    {
330	      nibble >>= 8;
331	      last = uout;
332	      out = (Unit) (out + nibble * powers[cut]);
333	    }
334	  cut++;
335	  if (cut == DECDPUN)
336	    {
337	      *uout = out;
338	      uout++;
339	      cut = 0;
340	      out = 0;
341	    }
342	}
343#endif
344    }				/* n */
345  if (cut != 0)
346    *uout = out;		/* write out final unit */
347
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++)
352    {
353      if (*last < powers[cut])
354	break;
355      dn->digits++;
356    }
357  if (dn->digits == 0)
358    dn->digits++;		/* zero has one digit */
359  return;
360}
361