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