1/* Packed decimal conversion module for the decNumber C Library.
2   Copyright (C) 2007-2015 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 3, 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
17Under Section 7 of GPL version 3, you are granted additional
18permissions described in the GCC Runtime Library Exception, version
193.1, as published by the Free Software Foundation.
20
21You should have received a copy of the GNU General Public License and
22a copy of the GCC Runtime Library Exception along with this program;
23see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24<http://www.gnu.org/licenses/>.  */
25
26/* ------------------------------------------------------------------ */
27/* Packed Decimal conversion module				      */
28/* ------------------------------------------------------------------ */
29/* This module comprises the routines for Packed Decimal format       */
30/* numbers.  Conversions are supplied to and from decNumber, which in */
31/* turn supports:						      */
32/*   conversions to and from string				      */
33/*   arithmetic routines					      */
34/*   utilities. 						      */
35/* Conversions from decNumber to and from densely packed decimal      */
36/* formats are provided by the decimal32 through decimal128 modules.  */
37/* ------------------------------------------------------------------ */
38
39#include <string.h>	      /* for NULL */
40#include "decNumber.h"	      /* base number library */
41#include "decPacked.h"	      /* packed decimal */
42#include "decNumberLocal.h"   /* decNumber local types, etc. */
43
44/* ------------------------------------------------------------------ */
45/* decPackedFromNumber -- convert decNumber to BCD Packed Decimal     */
46/*								      */
47/*   bcd    is the BCD bytes					      */
48/*   length is the length of the BCD array			      */
49/*   scale  is the scale result 				      */
50/*   dn     is the decNumber					      */
51/*   returns bcd, or NULL if error				      */
52/*								      */
53/* The number is converted to a BCD packed decimal byte array,	      */
54/* right aligned in the bcd array, whose length is indicated by the   */
55/* second parameter.  The final 4-bit nibble in the array will be a   */
56/* sign nibble, C (1100) for + and D (1101) for -.  Unused bytes and  */
57/* nibbles to the left of the number are set to 0.		      */
58/*								      */
59/* scale is set to the scale of the number (this is the exponent,     */
60/* negated).  To force the number to a specified scale, first use the */
61/* decNumberRescale routine, which will round and change the exponent */
62/* as necessary.						      */
63/*								      */
64/* If there is an error (that is, the decNumber has too many digits   */
65/* to fit in length bytes, or it is a NaN or Infinity), NULL is       */
66/* returned and the bcd and scale results are unchanged.  Otherwise   */
67/* bcd is returned.						      */
68/* ------------------------------------------------------------------ */
69uByte * decPackedFromNumber(uByte *bcd, Int length, Int *scale,
70			    const decNumber *dn) {
71  const Unit *up=dn->lsu;     /* Unit array pointer */
72  uByte obyte, *out;	      /* current output byte, and where it goes */
73  Int indigs=dn->digits;      /* digits processed */
74  uInt cut=DECDPUN;	      /* downcounter per Unit */
75  uInt u=*up;		      /* work */
76  uInt nib;		      /* .. */
77  #if DECDPUN<=4
78  uInt temp;		      /* .. */
79  #endif
80
81  if (dn->digits>length*2-1		     /* too long .. */
82   ||(dn->bits & DECSPECIAL)) return NULL;   /* .. or special -- hopeless */
83
84  if (dn->bits&DECNEG) obyte=DECPMINUS;      /* set the sign .. */
85   else 	       obyte=DECPPLUS;
86  *scale=-dn->exponent; 		     /* .. and scale */
87
88  /* loop from lowest (rightmost) byte */
89  out=bcd+length-1;			     /* -> final byte */
90  for (; out>=bcd; out--) {
91    if (indigs>0) {
92      if (cut==0) {
93	up++;
94	u=*up;
95	cut=DECDPUN;
96	}
97      #if DECDPUN<=4
98	temp=(u*6554)>>16;	   /* fast /10 */
99	nib=u-X10(temp);
100	u=temp;
101      #else
102	nib=u%10;		   /* cannot use *6554 trick :-( */
103	u=u/10;
104      #endif
105      obyte|=(nib<<4);
106      indigs--;
107      cut--;
108      }
109    *out=obyte;
110    obyte=0;			   /* assume 0 */
111    if (indigs>0) {
112      if (cut==0) {
113	up++;
114	u=*up;
115	cut=DECDPUN;
116	}
117      #if DECDPUN<=4
118	temp=(u*6554)>>16;	   /* as above */
119	obyte=(uByte)(u-X10(temp));
120	u=temp;
121      #else
122	obyte=(uByte)(u%10);
123	u=u/10;
124      #endif
125      indigs--;
126      cut--;
127      }
128    } /* loop */
129
130  return bcd;
131  } /* decPackedFromNumber */
132
133/* ------------------------------------------------------------------ */
134/* decPackedToNumber -- convert BCD Packed Decimal to a decNumber     */
135/*								      */
136/*   bcd    is the BCD bytes					      */
137/*   length is the length of the BCD array			      */
138/*   scale  is the scale associated with the BCD integer	      */
139/*   dn     is the decNumber [with space for length*2 digits]	      */
140/*   returns dn, or NULL if error				      */
141/*								      */
142/* The BCD packed decimal byte array, together with an associated     */
143/* scale, is converted to a decNumber.	The BCD array is assumed full */
144/* of digits, and must be ended by a 4-bit sign nibble in the least   */
145/* significant four bits of the final byte.			      */
146/*								      */
147/* The scale is used (negated) as the exponent of the decNumber.      */
148/* Note that zeros may have a sign and/or a scale.		      */
149/*								      */
150/* The decNumber structure is assumed to have sufficient space to     */
151/* hold the converted number (that is, up to length*2-1 digits), so   */
152/* no error is possible unless the adjusted exponent is out of range, */
153/* no sign nibble was found, or a sign nibble was found before the    */
154/* final nibble.  In these error cases, NULL is returned and the      */
155/* decNumber will be 0. 					      */
156/* ------------------------------------------------------------------ */
157decNumber * decPackedToNumber(const uByte *bcd, Int length,
158			      const Int *scale, decNumber *dn) {
159  const uByte *last=bcd+length-1;  /* -> last byte */
160  const uByte *first;		   /* -> first non-zero byte */
161  uInt	nib;			   /* work nibble */
162  Unit	*up=dn->lsu;		   /* output pointer */
163  Int	digits; 		   /* digits count */
164  Int	cut=0;			   /* phase of output */
165
166  decNumberZero(dn);		   /* default result */
167  last=&bcd[length-1];
168  nib=*last & 0x0f;		   /* get the sign */
169  if (nib==DECPMINUS || nib==DECPMINUSALT) dn->bits=DECNEG;
170   else if (nib<=9) return NULL;   /* not a sign nibble */
171
172  /* skip leading zero bytes [final byte is always non-zero, due to sign] */
173  for (first=bcd; *first==0;) first++;
174  digits=(last-first)*2+1;		/* calculate digits .. */
175  if ((*first & 0xf0)==0) digits--;	/* adjust for leading zero nibble */
176  if (digits!=0) dn->digits=digits;	/* count of actual digits [if 0, */
177					/* leave as 1] */
178
179  /* check the adjusted exponent; note that scale could be unbounded */
180  dn->exponent=-*scale; 		/* set the exponent */
181  if (*scale>=0) {			/* usual case */
182    if ((dn->digits-*scale-1)<-DECNUMMAXE) {	  /* underflow */
183      decNumberZero(dn);
184      return NULL;}
185    }
186   else { /* -ve scale; +ve exponent */
187    /* need to be careful to avoid wrap, here, also BADINT case */
188    if ((*scale<-DECNUMMAXE)		/* overflow even without digits */
189	 || ((dn->digits-*scale-1)>DECNUMMAXE)) { /* overflow */
190      decNumberZero(dn);
191      return NULL;}
192    }
193  if (digits==0) return dn;		/* result was zero */
194
195  /* copy the digits to the number's units, starting at the lsu */
196  /* [unrolled] */
197  for (;;) {				/* forever */
198    /* left nibble first */
199    nib=(unsigned)(*last & 0xf0)>>4;
200    /* got a digit, in nib */
201    if (nib>9) {decNumberZero(dn); return NULL;}
202
203    if (cut==0) *up=(Unit)nib;
204     else *up=(Unit)(*up+nib*DECPOWERS[cut]);
205    digits--;
206    if (digits==0) break;		/* got them all */
207    cut++;
208    if (cut==DECDPUN) {
209      up++;
210      cut=0;
211      }
212    last--;				/* ready for next */
213    nib=*last & 0x0f;			/* get right nibble */
214    if (nib>9) {decNumberZero(dn); return NULL;}
215
216    /* got a digit, in nib */
217    if (cut==0) *up=(Unit)nib;
218     else *up=(Unit)(*up+nib*DECPOWERS[cut]);
219    digits--;
220    if (digits==0) break;		/* got them all */
221    cut++;
222    if (cut==DECDPUN) {
223      up++;
224      cut=0;
225      }
226    } /* forever */
227
228  return dn;
229  } /* decPackedToNumber */
230
231