File: | build/libdecnumber/dpd/decimal64.c |
Warning: | line 677, column 10 Assigned value is garbage or undefined |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Copyright (C) 2007-2023 Free Software Foundation, Inc. | |||
2 | ||||
3 | This file is part of GCC. | |||
4 | ||||
5 | GCC is free software; you can redistribute it and/or modify it under | |||
6 | the terms of the GNU General Public License as published by the Free | |||
7 | Software Foundation; either version 3, or (at your option) any later | |||
8 | version. | |||
9 | ||||
10 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |||
11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or | |||
12 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |||
13 | for more details. | |||
14 | ||||
15 | Under Section 7 of GPL version 3, you are granted additional | |||
16 | permissions described in the GCC Runtime Library Exception, version | |||
17 | 3.1, as published by the Free Software Foundation. | |||
18 | ||||
19 | You should have received a copy of the GNU General Public License and | |||
20 | a copy of the GCC Runtime Library Exception along with this program; | |||
21 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |||
22 | <http://www.gnu.org/licenses/>. */ | |||
23 | ||||
24 | #define decimal64FromString __dpd64FromString | |||
25 | #define decimal64ToString __dpd64ToString | |||
26 | #define decimal64ToEngString __dpd64ToEngString | |||
27 | #define decimal64FromNumber __dpd64FromNumber | |||
28 | #define decimal64ToNumber __dpd64ToNumber | |||
29 | ||||
30 | #include "dpd/decimal64.c" | |||
31 | ||||
32 | #undef decimal64FromString | |||
33 | #undef decimal64ToString | |||
34 | #undef decimal64ToEngString | |||
35 | #undef decimal64FromNumber | |||
36 | #undef decimal64ToNumber | |||
37 | ||||
38 | #include "bid-dpd.h" | |||
39 | ||||
40 | #ifdef IN_LIBGCC2 | |||
41 | #define decimal64FromString __decimal64FromString | |||
42 | #define decimal64ToString __decimal64ToString | |||
43 | #define decimal64ToEngString __decimal64ToEngString | |||
44 | #define decimal64FromNumber __decimal64FromNumber | |||
45 | #define decimal64ToNumber __decimal64ToNumber | |||
46 | #endif | |||
47 | ||||
48 | decimal64 *decimal64FromString (decimal64 *, const char *, decContext *); | |||
49 | char *decimal64ToString (const decimal64 *, char *); | |||
50 | char *decimal64ToEngString (const decimal64 *, char *); | |||
51 | decimal64 *decimal64FromNumber (decimal64 *, const decNumber *, decContext *); | |||
52 | decNumber *decimal64ToNumber (const decimal64 *, decNumber *); | |||
53 | ||||
54 | void __host_to_ieee_64 (_Decimal64UINT64 in, decimal64 *out); | |||
55 | void __ieee_to_host_64 (decimal64 in, _Decimal64UINT64 *out); | |||
56 | ||||
57 | decimal64 * | |||
58 | decimal64FromNumber (decimal64 *d64, const decNumber *dn, | |||
59 | decContext *set) | |||
60 | { | |||
61 | /* decimal64 and _Decimal64 are different types. */ | |||
62 | union | |||
63 | { | |||
64 | _Decimal64UINT64 _Dec; | |||
65 | decimal64 dec; | |||
66 | } u; | |||
67 | ||||
68 | __dpd64FromNumber (d64, dn, set); | |||
69 | ||||
70 | /* __dpd64FromNumber returns in big endian. But _dpd_to_bid64 takes | |||
71 | host endian. */ | |||
72 | __ieee_to_host_64 (*d64, &u._Dec); | |||
73 | ||||
74 | /* Convert DPD to BID. */ | |||
75 | _dpd_to_bid64 (&u._Dec, &u._Dec); | |||
76 | ||||
77 | /* dfp.c is in bid endian. */ | |||
78 | __host_to_ieee_64 (u._Dec, &u.dec); | |||
79 | ||||
80 | /* d64 is returned as a pointer to _Decimal64 here. */ | |||
81 | *d64 = u.dec; | |||
82 | ||||
83 | return d64; | |||
84 | } | |||
85 | ||||
86 | decNumber * | |||
87 | decimal64ToNumber (const decimal64 *bid64, decNumber *dn) | |||
88 | { | |||
89 | /* decimal64 and _Decimal64 are different types. */ | |||
90 | union | |||
91 | { | |||
92 | _Decimal64UINT64 _Dec; | |||
93 | decimal64 dec; | |||
94 | } u; | |||
95 | ||||
96 | /* bid64 is a pointer to _Decimal64 in bid endian. But _bid_to_dpd64 | |||
97 | takes host endian. */ | |||
98 | __ieee_to_host_64 (*bid64, &u._Dec); | |||
99 | ||||
100 | /* Convert BID to DPD. */ | |||
101 | _bid_to_dpd64 (&u._Dec, &u._Dec); | |||
102 | ||||
103 | /* __dpd64ToNumber is in bid endian. */ | |||
104 | __host_to_ieee_64 (u._Dec, &u.dec); | |||
105 | ||||
106 | return __dpd64ToNumber (&u.dec, dn); | |||
107 | } | |||
108 | ||||
109 | char * | |||
110 | decimal64ToString (const decimal64 *d64, char *string) | |||
111 | { | |||
112 | decNumber dn; /* work */ | |||
113 | decimal64ToNumber (d64, &dn); | |||
114 | decNumberToString (&dn, string); | |||
115 | return string; | |||
116 | } | |||
117 | ||||
118 | char * | |||
119 | decimal64ToEngString (const decimal64 *d64, char *string) | |||
120 | { | |||
121 | decNumber dn; /* work */ | |||
122 | decimal64ToNumber (d64, &dn); | |||
123 | decNumberToEngString (&dn, string); | |||
124 | return string; | |||
125 | } | |||
126 | ||||
127 | decimal64 * | |||
128 | decimal64FromString (decimal64 *result, const char *string, | |||
129 | decContext *set) | |||
130 | { | |||
131 | decContext dc; /* work */ | |||
132 | decNumber dn; /* .. */ | |||
133 | ||||
134 | decContextDefault (&dc, DEC_INIT_DECIMAL6464); /* no traps, please */ | |||
135 | dc.round = set->round; /* use supplied rounding */ | |||
136 | ||||
137 | decNumberFromString (&dn, string, &dc); /* will round if needed */ | |||
138 | decimal64FromNumber (result, &dn, &dc); | |||
| ||||
139 | if (dc.status != 0) | |||
140 | { /* something happened */ | |||
141 | decContextSetStatus (set, dc.status); /* .. pass it on */ | |||
142 | } | |||
143 | return result; | |||
144 | } |
1 | /* Decimal 64-bit format module for the decNumber C Library. | ||||
2 | Copyright (C) 2005-2023 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 | |||||
17 | Under Section 7 of GPL version 3, you are granted additional | ||||
18 | permissions described in the GCC Runtime Library Exception, version | ||||
19 | 3.1, as published by the Free Software Foundation. | ||||
20 | |||||
21 | You should have received a copy of the GNU General Public License and | ||||
22 | a copy of the GCC Runtime Library Exception along with this program; | ||||
23 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | ||||
24 | <http://www.gnu.org/licenses/>. */ | ||||
25 | |||||
26 | /* ------------------------------------------------------------------ */ | ||||
27 | /* Decimal 64-bit format module */ | ||||
28 | /* ------------------------------------------------------------------ */ | ||||
29 | /* This module comprises the routines for decimal64 format numbers. */ | ||||
30 | /* Conversions are supplied to and from decNumber and String. */ | ||||
31 | /* */ | ||||
32 | /* This is used when decNumber provides operations, either for all */ | ||||
33 | /* operations or as a proxy between decNumber and decSingle. */ | ||||
34 | /* */ | ||||
35 | /* Error handling is the same as decNumber (qv.). */ | ||||
36 | /* ------------------------------------------------------------------ */ | ||||
37 | #include <string.h> /* [for memset/memcpy] */ | ||||
38 | #include <stdio.h> /* [for printf] */ | ||||
39 | |||||
40 | #include "dconfig.h" /* GCC definitions */ | ||||
41 | #define DECNUMDIGITS16 16 /* make decNumbers with space for 16 */ | ||||
42 | #include "decNumber.h" /* base number library */ | ||||
43 | #include "decNumberLocal.h" /* decNumber local types, etc. */ | ||||
44 | #include "decimal64.h" /* our primary include */ | ||||
45 | |||||
46 | /* Utility routines and tables [in decimal64.c]; externs for C++ */ | ||||
47 | extern const uIntuint32_t COMBEXP[32], COMBMSD[32]; | ||||
48 | extern const uShortuint16_t DPD2BIN[1024]; | ||||
49 | extern const uShortuint16_t BIN2DPD[1000]; | ||||
50 | extern const uByteuint8_t BIN2CHAR[4001]; | ||||
51 | |||||
52 | extern void decDigitsFromDPD(decNumber *, const uIntuint32_t *, Intint32_t); | ||||
53 | extern void decDigitsToDPD(const decNumber *, uIntuint32_t *, Intint32_t); | ||||
54 | |||||
55 | #if DECTRACE0 || DECCHECK0 | ||||
56 | void decimal64Show(const decimal64 *); /* for debug */ | ||||
57 | extern void decNumberShow(const decNumber *); /* .. */ | ||||
58 | #endif | ||||
59 | |||||
60 | /* Useful macro */ | ||||
61 | /* Clear a structure (e.g., a decNumber) */ | ||||
62 | #define DEC_clear(d)memset(d, 0, sizeof(*d)) memset(d, 0, sizeof(*d)) | ||||
63 | |||||
64 | /* define and include the tables to use for conversions */ | ||||
65 | #define DEC_BIN2CHAR1 1 | ||||
66 | #define DEC_DPD2BIN1 1 | ||||
67 | #define DEC_BIN2DPD1 1 /* used for all sizes */ | ||||
68 | #include "decDPD.h" /* lookup tables */ | ||||
69 | |||||
70 | /* ------------------------------------------------------------------ */ | ||||
71 | /* decimal64FromNumber -- convert decNumber to decimal64 */ | ||||
72 | /* */ | ||||
73 | /* ds is the target decimal64 */ | ||||
74 | /* dn is the source number (assumed valid) */ | ||||
75 | /* set is the context, used only for reporting errors */ | ||||
76 | /* */ | ||||
77 | /* The set argument is used only for status reporting and for the */ | ||||
78 | /* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */ | ||||
79 | /* digits or an overflow is detected). If the exponent is out of the */ | ||||
80 | /* valid range then Overflow or Underflow will be raised. */ | ||||
81 | /* After Underflow a subnormal result is possible. */ | ||||
82 | /* */ | ||||
83 | /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ | ||||
84 | /* by reducing its exponent and multiplying the coefficient by a */ | ||||
85 | /* power of ten, or if the exponent on a zero had to be clamped. */ | ||||
86 | /* ------------------------------------------------------------------ */ | ||||
87 | decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, | ||||
88 | decContext *set) { | ||||
89 | uIntuint32_t status=0; /* status accumulator */ | ||||
90 | Intint32_t ae; /* adjusted exponent */ | ||||
91 | decNumber dw; /* work */ | ||||
92 | decContext dc; /* .. */ | ||||
93 | uIntuint32_t comb, exp; /* .. */ | ||||
94 | uIntuint32_t uiwork; /* for macros */ | ||||
95 | uIntuint32_t targar[2]={0, 0}; /* target 64-bit */ | ||||
96 | #define targhitargar[1] targar[1] /* name the word with the sign */ | ||||
97 | #define targlotargar[0] targar[0] /* and the other */ | ||||
98 | |||||
99 | /* If the number has too many digits, or the exponent could be */ | ||||
100 | /* out of range then reduce the number under the appropriate */ | ||||
101 | /* constraints. This could push the number to Infinity or zero, */ | ||||
102 | /* so this check and rounding must be done before generating the */ | ||||
103 | /* decimal64] */ | ||||
104 | ae=dn->exponent+dn->digits-1; /* [0 if special] */ | ||||
105 | if (dn->digits>DECIMAL64_Pmax16 /* too many digits */ | ||||
106 | || ae>DECIMAL64_Emax384 /* likely overflow */ | ||||
107 | || ae<DECIMAL64_Emin-383) { /* likely underflow */ | ||||
108 | decContextDefault(&dc, DEC_INIT_DECIMAL6464); /* [no traps] */ | ||||
109 | dc.round=set->round; /* use supplied rounding */ | ||||
110 | decNumberPlus(&dw, dn, &dc); /* (round and check) */ | ||||
111 | /* [this changes -0 to 0, so enforce the sign...] */ | ||||
112 | dw.bits|=dn->bits&DECNEG0x80; | ||||
113 | status=dc.status; /* save status */ | ||||
114 | dn=&dw; /* use the work number */ | ||||
115 | } /* maybe out of range */ | ||||
116 | |||||
117 | if (dn->bits&DECSPECIAL(0x40|0x20|0x10)) { /* a special value */ | ||||
118 | if (dn->bits&DECINF0x40) targhitargar[1]=DECIMAL_Inf0x78<<24; | ||||
119 | else { /* sNaN or qNaN */ | ||||
120 | if ((*dn->lsu!=0 || dn->digits>1) /* non-zero coefficient */ | ||||
121 | && (dn->digits<DECIMAL64_Pmax16)) { /* coefficient fits */ | ||||
122 | decDigitsToDPD(dn, targar, 0); | ||||
123 | } | ||||
124 | if (dn->bits&DECNAN0x20) targhitargar[1]|=DECIMAL_NaN0x7c<<24; | ||||
125 | else targhitargar[1]|=DECIMAL_sNaN0x7e<<24; | ||||
126 | } /* a NaN */ | ||||
127 | } /* special */ | ||||
128 | |||||
129 | else { /* is finite */ | ||||
130 | if (decNumberIsZero(dn)(*(dn)->lsu==0 && (dn)->digits==1 && (( (dn)->bits&(0x40|0x20|0x10))==0))) { /* is a zero */ | ||||
131 | /* set and clamp exponent */ | ||||
132 | if (dn->exponent<-DECIMAL64_Bias398) { | ||||
133 | exp=0; /* low clamp */ | ||||
134 | status|=DEC_Clamped0x00000400; | ||||
135 | } | ||||
136 | else { | ||||
137 | exp=dn->exponent+DECIMAL64_Bias398; /* bias exponent */ | ||||
138 | if (exp>DECIMAL64_Ehigh(384 +398 -16 +1)) { /* top clamp */ | ||||
139 | exp=DECIMAL64_Ehigh(384 +398 -16 +1); | ||||
140 | status|=DEC_Clamped0x00000400; | ||||
141 | } | ||||
142 | } | ||||
143 | comb=(exp>>5) & 0x18; /* msd=0, exp top 2 bits .. */ | ||||
144 | } | ||||
145 | else { /* non-zero finite number */ | ||||
146 | uIntuint32_t msd; /* work */ | ||||
147 | Intint32_t pad=0; /* coefficient pad digits */ | ||||
148 | |||||
149 | /* the dn is known to fit, but it may need to be padded */ | ||||
150 | exp=(uIntuint32_t)(dn->exponent+DECIMAL64_Bias398); /* bias exponent */ | ||||
151 | if (exp>DECIMAL64_Ehigh(384 +398 -16 +1)) { /* fold-down case */ | ||||
152 | pad=exp-DECIMAL64_Ehigh(384 +398 -16 +1); | ||||
153 | exp=DECIMAL64_Ehigh(384 +398 -16 +1); /* [to maximum] */ | ||||
154 | status|=DEC_Clamped0x00000400; | ||||
155 | } | ||||
156 | |||||
157 | /* fastpath common case */ | ||||
158 | if (DECDPUN3==3 && pad
| ||||
159 | uIntuint32_t dpd[6]={0,0,0,0,0,0}; | ||||
160 | uIntuint32_t i; | ||||
161 | Intint32_t d=dn->digits; | ||||
162 | for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]]; | ||||
163 | targlotargar[0] =dpd[0]; | ||||
164 | targlotargar[0]|=dpd[1]<<10; | ||||
165 | targlotargar[0]|=dpd[2]<<20; | ||||
166 | if (dn->digits>6) { | ||||
167 | targlotargar[0]|=dpd[3]<<30; | ||||
168 | targhitargar[1] =dpd[3]>>2; | ||||
169 | targhitargar[1]|=dpd[4]<<8; | ||||
170 | } | ||||
171 | msd=dpd[5]; /* [did not really need conversion] */ | ||||
172 | } | ||||
173 | else { /* general case */ | ||||
174 | decDigitsToDPD(dn, targar, pad); | ||||
175 | /* save and clear the top digit */ | ||||
176 | msd=targhitargar[1]>>18; | ||||
177 | targhitargar[1]&=0x0003ffff; | ||||
178 | } | ||||
179 | |||||
180 | /* create the combination field */ | ||||
181 | if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01); | ||||
182 | else comb=((exp>>5) & 0x18) | msd; | ||||
183 | } | ||||
184 | targhitargar[1]|=comb<<26; /* add combination field .. */ | ||||
185 | targhitargar[1]|=(exp&0xff)<<18; /* .. and exponent continuation */ | ||||
186 | } /* finite */ | ||||
187 | |||||
188 | if (dn->bits&DECNEG0x80) targhitargar[1]|=0x80000000; /* add sign bit */ | ||||
189 | |||||
190 | /* now write to storage; this is now always endian */ | ||||
191 | if (DECLITEND1) { | ||||
192 | /* lo int then hi */ | ||||
193 | UBFROMUI(d64->bytes, targar[0])(uiwork=(targar[0]), memcpy(d64->bytes, (void *)&uiwork , 4)); | ||||
194 | UBFROMUI(d64->bytes+4, targar[1])(uiwork=(targar[1]), memcpy(d64->bytes+4, (void *)&uiwork , 4)); | ||||
195 | } | ||||
196 | else { | ||||
197 | /* hi int then lo */ | ||||
198 | UBFROMUI(d64->bytes, targar[1])(uiwork=(targar[1]), memcpy(d64->bytes, (void *)&uiwork , 4)); | ||||
199 | UBFROMUI(d64->bytes+4, targar[0])(uiwork=(targar[0]), memcpy(d64->bytes+4, (void *)&uiwork , 4)); | ||||
200 | } | ||||
201 | |||||
202 | if (status!=0) decContextSetStatus(set, status); /* pass on status */ | ||||
203 | /* decimal64Show(d64); */ | ||||
204 | return d64; | ||||
205 | } /* decimal64FromNumber */ | ||||
206 | |||||
207 | /* ------------------------------------------------------------------ */ | ||||
208 | /* decimal64ToNumber -- convert decimal64 to decNumber */ | ||||
209 | /* d64 is the source decimal64 */ | ||||
210 | /* dn is the target number, with appropriate space */ | ||||
211 | /* No error is possible. */ | ||||
212 | /* ------------------------------------------------------------------ */ | ||||
213 | decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { | ||||
214 | uIntuint32_t msd; /* coefficient MSD */ | ||||
215 | uIntuint32_t exp; /* exponent top two bits */ | ||||
216 | uIntuint32_t comb; /* combination field */ | ||||
217 | Intint32_t need; /* work */ | ||||
218 | uIntuint32_t uiwork; /* for macros */ | ||||
219 | uIntuint32_t sourar[2]; /* source 64-bit */ | ||||
220 | #define sourhisourar[1] sourar[1] /* name the word with the sign */ | ||||
221 | #define sourlosourar[0] sourar[0] /* and the lower word */ | ||||
222 | |||||
223 | /* load source from storage; this is endian */ | ||||
224 | if (DECLITEND1) { | ||||
225 | sourlosourar[0]=UBTOUI(d64->bytes )(memcpy((void *)&uiwork, d64->bytes, 4), uiwork); /* directly load the low int */ | ||||
226 | sourhisourar[1]=UBTOUI(d64->bytes+4)(memcpy((void *)&uiwork, d64->bytes+4, 4), uiwork); /* then the high int */ | ||||
227 | } | ||||
228 | else { | ||||
229 | sourhisourar[1]=UBTOUI(d64->bytes )(memcpy((void *)&uiwork, d64->bytes, 4), uiwork); /* directly load the high int */ | ||||
230 | sourlosourar[0]=UBTOUI(d64->bytes+4)(memcpy((void *)&uiwork, d64->bytes+4, 4), uiwork); /* then the low int */ | ||||
231 | } | ||||
232 | |||||
233 | comb=(sourhisourar[1]>>26)&0x1f; /* combination field */ | ||||
234 | |||||
235 | decNumberZero(dn); /* clean number */ | ||||
236 | if (sourhisourar[1]&0x80000000) dn->bits=DECNEG0x80; /* set sign if negative */ | ||||
237 | |||||
238 | msd=COMBMSD[comb]; /* decode the combination field */ | ||||
239 | exp=COMBEXP[comb]; /* .. */ | ||||
240 | |||||
241 | if (exp==3) { /* is a special */ | ||||
242 | if (msd==0) { | ||||
243 | dn->bits|=DECINF0x40; | ||||
244 | return dn; /* no coefficient needed */ | ||||
245 | } | ||||
246 | else if (sourhisourar[1]&0x02000000) dn->bits|=DECSNAN0x10; | ||||
247 | else dn->bits|=DECNAN0x20; | ||||
248 | msd=0; /* no top digit */ | ||||
249 | } | ||||
250 | else { /* is a finite number */ | ||||
251 | dn->exponent=(exp<<8)+((sourhisourar[1]>>18)&0xff)-DECIMAL64_Bias398; /* unbiased */ | ||||
252 | } | ||||
253 | |||||
254 | /* get the coefficient */ | ||||
255 | sourhisourar[1]&=0x0003ffff; /* clean coefficient continuation */ | ||||
256 | if (msd) { /* non-zero msd */ | ||||
257 | sourhisourar[1]|=msd<<18; /* prefix to coefficient */ | ||||
258 | need=6; /* process 6 declets */ | ||||
259 | } | ||||
260 | else { /* msd=0 */ | ||||
261 | if (!sourhisourar[1]) { /* top word 0 */ | ||||
262 | if (!sourlosourar[0]) return dn; /* easy: coefficient is 0 */ | ||||
263 | need=3; /* process at least 3 declets */ | ||||
264 | if (sourlosourar[0]&0xc0000000) need++; /* process 4 declets */ | ||||
265 | /* [could reduce some more, here] */ | ||||
266 | } | ||||
267 | else { /* some bits in top word, msd=0 */ | ||||
268 | need=4; /* process at least 4 declets */ | ||||
269 | if (sourhisourar[1]&0x0003ff00) need++; /* top declet!=0, process 5 */ | ||||
270 | } | ||||
271 | } /*msd=0 */ | ||||
272 | |||||
273 | decDigitsFromDPD(dn, sourar, need); /* process declets */ | ||||
274 | return dn; | ||||
275 | } /* decimal64ToNumber */ | ||||
276 | |||||
277 | |||||
278 | /* ------------------------------------------------------------------ */ | ||||
279 | /* to-scientific-string -- conversion to numeric string */ | ||||
280 | /* to-engineering-string -- conversion to numeric string */ | ||||
281 | /* */ | ||||
282 | /* decimal64ToString(d64, string); */ | ||||
283 | /* decimal64ToEngString(d64, string); */ | ||||
284 | /* */ | ||||
285 | /* d64 is the decimal64 format number to convert */ | ||||
286 | /* string is the string where the result will be laid out */ | ||||
287 | /* */ | ||||
288 | /* string must be at least 24 characters */ | ||||
289 | /* */ | ||||
290 | /* No error is possible, and no status can be set. */ | ||||
291 | /* ------------------------------------------------------------------ */ | ||||
292 | char * decimal64ToEngString(const decimal64 *d64, char *string){ | ||||
293 | decNumber dn; /* work */ | ||||
294 | decimal64ToNumber(d64, &dn); | ||||
295 | decNumberToEngString(&dn, string); | ||||
296 | return string; | ||||
297 | } /* decimal64ToEngString */ | ||||
298 | |||||
299 | char * decimal64ToString(const decimal64 *d64, char *string){ | ||||
300 | uIntuint32_t msd; /* coefficient MSD */ | ||||
301 | Intint32_t exp; /* exponent top two bits or full */ | ||||
302 | uIntuint32_t comb; /* combination field */ | ||||
303 | char *cstart; /* coefficient start */ | ||||
304 | char *c; /* output pointer in string */ | ||||
305 | const uByteuint8_t *u; /* work */ | ||||
306 | char *s, *t; /* .. (source, target) */ | ||||
307 | Intint32_t dpd; /* .. */ | ||||
308 | Intint32_t pre, e; /* .. */ | ||||
309 | uIntuint32_t uiwork; /* for macros */ | ||||
310 | |||||
311 | uIntuint32_t sourar[2]; /* source 64-bit */ | ||||
312 | #define sourhisourar[1] sourar[1] /* name the word with the sign */ | ||||
313 | #define sourlosourar[0] sourar[0] /* and the lower word */ | ||||
314 | |||||
315 | /* load source from storage; this is endian */ | ||||
316 | if (DECLITEND1) { | ||||
317 | sourlosourar[0]=UBTOUI(d64->bytes )(memcpy((void *)&uiwork, d64->bytes, 4), uiwork); /* directly load the low int */ | ||||
318 | sourhisourar[1]=UBTOUI(d64->bytes+4)(memcpy((void *)&uiwork, d64->bytes+4, 4), uiwork); /* then the high int */ | ||||
319 | } | ||||
320 | else { | ||||
321 | sourhisourar[1]=UBTOUI(d64->bytes )(memcpy((void *)&uiwork, d64->bytes, 4), uiwork); /* directly load the high int */ | ||||
322 | sourlosourar[0]=UBTOUI(d64->bytes+4)(memcpy((void *)&uiwork, d64->bytes+4, 4), uiwork); /* then the low int */ | ||||
323 | } | ||||
324 | |||||
325 | c=string; /* where result will go */ | ||||
326 | if (((Intint32_t)sourhisourar[1])<0) *c++='-'; /* handle sign */ | ||||
327 | |||||
328 | comb=(sourhisourar[1]>>26)&0x1f; /* combination field */ | ||||
329 | msd=COMBMSD[comb]; /* decode the combination field */ | ||||
330 | exp=COMBEXP[comb]; /* .. */ | ||||
331 | |||||
332 | if (exp==3) { | ||||
333 | if (msd==0) { /* infinity */ | ||||
334 | strcpy(c, "Inf"); | ||||
335 | strcpy(c+3, "inity"); | ||||
336 | return string; /* easy */ | ||||
337 | } | ||||
338 | if (sourhisourar[1]&0x02000000) *c++='s'; /* sNaN */ | ||||
339 | strcpy(c, "NaN"); /* complete word */ | ||||
340 | c+=3; /* step past */ | ||||
341 | if (sourlosourar[0]==0 && (sourhisourar[1]&0x0003ffff)==0) return string; /* zero payload */ | ||||
342 | /* otherwise drop through to add integer; set correct exp */ | ||||
343 | exp=0; msd=0; /* setup for following code */ | ||||
344 | } | ||||
345 | else exp=(exp<<8)+((sourhisourar[1]>>18)&0xff)-DECIMAL64_Bias398; | ||||
346 | |||||
347 | /* convert 16 digits of significand to characters */ | ||||
348 | cstart=c; /* save start of coefficient */ | ||||
349 | if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ | ||||
350 | |||||
351 | /* Now decode the declets. After extracting each one, it is */ | ||||
352 | /* decoded to binary and then to a 4-char sequence by table lookup; */ | ||||
353 | /* the 4-chars are a 1-char length (significant digits, except 000 */ | ||||
354 | /* has length 0). This allows us to left-align the first declet */ | ||||
355 | /* with non-zero content, then remaining ones are full 3-char */ | ||||
356 | /* length. We use fixed-length memcpys because variable-length */ | ||||
357 | /* causes a subroutine call in GCC. (These are length 4 for speed */ | ||||
358 | /* and are safe because the array has an extra terminator byte.) */ | ||||
359 | #define dpd2charu=&BIN2CHAR[DPD2BIN[dpd]*4]; if (c!=cstart) {memcpy(c, u+ 1, 4); c+=3;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ | ||||
360 | if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ | ||||
361 | else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} | ||||
362 | |||||
363 | dpd=(sourhisourar[1]>>8)&0x3ff; /* declet 1 */ | ||||
364 | dpd2charu=&BIN2CHAR[DPD2BIN[dpd]*4]; if (c!=cstart) {memcpy(c, u+ 1, 4); c+=3;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}; | ||||
365 | dpd=((sourhisourar[1]&0xff)<<2) | (sourlosourar[0]>>30); /* declet 2 */ | ||||
366 | dpd2charu=&BIN2CHAR[DPD2BIN[dpd]*4]; if (c!=cstart) {memcpy(c, u+ 1, 4); c+=3;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}; | ||||
367 | dpd=(sourlosourar[0]>>20)&0x3ff; /* declet 3 */ | ||||
368 | dpd2charu=&BIN2CHAR[DPD2BIN[dpd]*4]; if (c!=cstart) {memcpy(c, u+ 1, 4); c+=3;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}; | ||||
369 | dpd=(sourlosourar[0]>>10)&0x3ff; /* declet 4 */ | ||||
370 | dpd2charu=&BIN2CHAR[DPD2BIN[dpd]*4]; if (c!=cstart) {memcpy(c, u+ 1, 4); c+=3;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}; | ||||
371 | dpd=(sourlosourar[0])&0x3ff; /* declet 5 */ | ||||
372 | dpd2charu=&BIN2CHAR[DPD2BIN[dpd]*4]; if (c!=cstart) {memcpy(c, u+ 1, 4); c+=3;} else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;}; | ||||
373 | |||||
374 | if (c==cstart) *c++='0'; /* all zeros -- make 0 */ | ||||
375 | |||||
376 | if (exp==0) { /* integer or NaN case -- easy */ | ||||
377 | *c='\0'; /* terminate */ | ||||
378 | return string; | ||||
379 | } | ||||
380 | |||||
381 | /* non-0 exponent */ | ||||
382 | e=0; /* assume no E */ | ||||
383 | pre=c-cstart+exp; | ||||
384 | /* [here, pre-exp is the digits count (==1 for zero)] */ | ||||
385 | if (exp>0 || pre<-5) { /* need exponential form */ | ||||
386 | e=pre-1; /* calculate E value */ | ||||
387 | pre=1; /* assume one digit before '.' */ | ||||
388 | } /* exponential form */ | ||||
389 | |||||
390 | /* modify the coefficient, adding 0s, '.', and E+nn as needed */ | ||||
391 | s=c-1; /* source (LSD) */ | ||||
392 | if (pre>0) { /* ddd.ddd (plain), perhaps with E */ | ||||
393 | char *dotat=cstart+pre; | ||||
394 | if (dotat<c) { /* if embedded dot needed... */ | ||||
395 | t=c; /* target */ | ||||
396 | for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ | ||||
397 | *t='.'; /* insert the dot */ | ||||
398 | c++; /* length increased by one */ | ||||
399 | } | ||||
400 | |||||
401 | /* finally add the E-part, if needed; it will never be 0, and has */ | ||||
402 | /* a maximum length of 3 digits */ | ||||
403 | if (e!=0) { | ||||
404 | *c++='E'; /* starts with E */ | ||||
405 | *c++='+'; /* assume positive */ | ||||
406 | if (e<0) { | ||||
407 | *(c-1)='-'; /* oops, need '-' */ | ||||
408 | e=-e; /* uInt, please */ | ||||
409 | } | ||||
410 | u=&BIN2CHAR[e*4]; /* -> length byte */ | ||||
411 | memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ | ||||
412 | c+=*u; /* bump pointer appropriately */ | ||||
413 | } | ||||
414 | *c='\0'; /* add terminator */ | ||||
415 | /*printf("res %s\n", string); */ | ||||
416 | return string; | ||||
417 | } /* pre>0 */ | ||||
418 | |||||
419 | /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ | ||||
420 | t=c+1-pre; | ||||
421 | *(t+1)='\0'; /* can add terminator now */ | ||||
422 | for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ | ||||
423 | c=cstart; | ||||
424 | *c++='0'; /* always starts with 0. */ | ||||
425 | *c++='.'; | ||||
426 | for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ | ||||
427 | /*printf("res %s\n", string); */ | ||||
428 | return string; | ||||
429 | } /* decimal64ToString */ | ||||
430 | |||||
431 | /* ------------------------------------------------------------------ */ | ||||
432 | /* to-number -- conversion from numeric string */ | ||||
433 | /* */ | ||||
434 | /* decimal64FromString(result, string, set); */ | ||||
435 | /* */ | ||||
436 | /* result is the decimal64 format number which gets the result of */ | ||||
437 | /* the conversion */ | ||||
438 | /* *string is the character string which should contain a valid */ | ||||
439 | /* number (which may be a special value) */ | ||||
440 | /* set is the context */ | ||||
441 | /* */ | ||||
442 | /* The context is supplied to this routine is used for error handling */ | ||||
443 | /* (setting of status and traps) and for the rounding mode, only. */ | ||||
444 | /* If an error occurs, the result will be a valid decimal64 NaN. */ | ||||
445 | /* ------------------------------------------------------------------ */ | ||||
446 | decimal64 * decimal64FromString(decimal64 *result, const char *string, | ||||
447 | decContext *set) { | ||||
448 | decContext dc; /* work */ | ||||
449 | decNumber dn; /* .. */ | ||||
450 | |||||
451 | decContextDefault(&dc, DEC_INIT_DECIMAL6464); /* no traps, please */ | ||||
452 | dc.round=set->round; /* use supplied rounding */ | ||||
453 | |||||
454 | decNumberFromString(&dn, string, &dc); /* will round if needed */ | ||||
455 | |||||
456 | decimal64FromNumber(result, &dn, &dc); | ||||
457 | if (dc.status!=0) { /* something happened */ | ||||
458 | decContextSetStatus(set, dc.status); /* .. pass it on */ | ||||
459 | } | ||||
460 | return result; | ||||
461 | } /* decimal64FromString */ | ||||
462 | |||||
463 | /* ------------------------------------------------------------------ */ | ||||
464 | /* decimal64IsCanonical -- test whether encoding is canonical */ | ||||
465 | /* d64 is the source decimal64 */ | ||||
466 | /* returns 1 if the encoding of d64 is canonical, 0 otherwise */ | ||||
467 | /* No error is possible. */ | ||||
468 | /* ------------------------------------------------------------------ */ | ||||
469 | uIntuint32_t decimal64IsCanonical(const decimal64 *d64) { | ||||
470 | decNumber dn; /* work */ | ||||
471 | decimal64 canon; /* .. */ | ||||
472 | decContext dc; /* .. */ | ||||
473 | decContextDefault(&dc, DEC_INIT_DECIMAL6464); | ||||
474 | decimal64ToNumber(d64, &dn); | ||||
475 | decimal64FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ | ||||
476 | return memcmp(d64, &canon, DECIMAL64_Bytes8)==0; | ||||
477 | } /* decimal64IsCanonical */ | ||||
478 | |||||
479 | /* ------------------------------------------------------------------ */ | ||||
480 | /* decimal64Canonical -- copy an encoding, ensuring it is canonical */ | ||||
481 | /* d64 is the source decimal64 */ | ||||
482 | /* result is the target (may be the same decimal64) */ | ||||
483 | /* returns result */ | ||||
484 | /* No error is possible. */ | ||||
485 | /* ------------------------------------------------------------------ */ | ||||
486 | decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { | ||||
487 | decNumber dn; /* work */ | ||||
488 | decContext dc; /* .. */ | ||||
489 | decContextDefault(&dc, DEC_INIT_DECIMAL6464); | ||||
490 | decimal64ToNumber(d64, &dn); | ||||
491 | decimal64FromNumber(result, &dn, &dc);/* result will now be canonical */ | ||||
492 | return result; | ||||
493 | } /* decimal64Canonical */ | ||||
494 | |||||
495 | #if DECTRACE0 || DECCHECK0 | ||||
496 | /* Macros for accessing decimal64 fields. These assume the | ||||
497 | argument is a reference (pointer) to the decimal64 structure, | ||||
498 | and the decimal64 is in network byte order (big-endian) */ | ||||
499 | /* Get sign */ | ||||
500 | #define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7) | ||||
501 | |||||
502 | /* Get combination field */ | ||||
503 | #define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2) | ||||
504 | |||||
505 | /* Get exponent continuation [does not remove bias] */ | ||||
506 | #define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \ | ||||
507 | | ((unsigned)(d)->bytes[1]>>2)) | ||||
508 | |||||
509 | /* Set sign [this assumes sign previously 0] */ | ||||
510 | #define decimal64SetSign(d, b) { \ | ||||
511 | (d)->bytes[0]|=((unsigned)(b)<<7);} | ||||
512 | |||||
513 | /* Set exponent continuation [does not apply bias] */ | ||||
514 | /* This assumes range has been checked and exponent previously 0; */ | ||||
515 | /* type of exponent must be unsigned */ | ||||
516 | #define decimal64SetExpCon(d, e) { \ | ||||
517 | (d)->bytes[0]|=(uByteuint8_t)((e)>>6); \ | ||||
518 | (d)->bytes[1]|=(uByteuint8_t)(((e)&0x3F)<<2);} | ||||
519 | |||||
520 | /* ------------------------------------------------------------------ */ | ||||
521 | /* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ | ||||
522 | /* d64 -- the number to show */ | ||||
523 | /* ------------------------------------------------------------------ */ | ||||
524 | /* Also shows sign/cob/expconfields extracted */ | ||||
525 | void decimal64Show(const decimal64 *d64) { | ||||
526 | char buf[DECIMAL64_Bytes8*2+1]; | ||||
527 | Intint32_t i, j=0; | ||||
528 | |||||
529 | if (DECLITEND1) { | ||||
530 | for (i=0; i<DECIMAL64_Bytes8; i++, j+=2) { | ||||
531 | sprintf(&buf[j], "%02x", d64->bytes[7-i]); | ||||
532 | } | ||||
533 | printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, | ||||
534 | d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f, | ||||
535 | ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2)); | ||||
536 | } | ||||
537 | else { /* big-endian */ | ||||
538 | for (i=0; i<DECIMAL64_Bytes8; i++, j+=2) { | ||||
539 | sprintf(&buf[j], "%02x", d64->bytes[i]); | ||||
540 | } | ||||
541 | printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, | ||||
542 | decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64)); | ||||
543 | } | ||||
544 | } /* decimal64Show */ | ||||
545 | #endif | ||||
546 | |||||
547 | /* ================================================================== */ | ||||
548 | /* Shared utility routines and tables */ | ||||
549 | /* ================================================================== */ | ||||
550 | /* define and include the conversion tables to use for shared code */ | ||||
551 | #if DECDPUN3==3 | ||||
552 | #define DEC_DPD2BIN1 1 | ||||
553 | #else | ||||
554 | #define DEC_DPD2BCD 1 | ||||
555 | #endif | ||||
556 | #include "decDPD.h" /* lookup tables */ | ||||
557 | |||||
558 | /* The maximum number of decNumberUnits needed for a working copy of */ | ||||
559 | /* the units array is the ceiling of digits/DECDPUN, where digits is */ | ||||
560 | /* the maximum number of digits in any of the formats for which this */ | ||||
561 | /* is used. decimal128.h must not be included in this module, so, as */ | ||||
562 | /* a very special case, that number is defined as a literal here. */ | ||||
563 | #define DECMAX75434 34 | ||||
564 | #define DECMAXUNITS((34 +3 -1)/3) ((DECMAX75434+DECDPUN3-1)/DECDPUN3) | ||||
565 | |||||
566 | /* ------------------------------------------------------------------ */ | ||||
567 | /* Combination field lookup tables (uInts to save measurable work) */ | ||||
568 | /* */ | ||||
569 | /* COMBEXP - 2-bit most-significant-bits of exponent */ | ||||
570 | /* [11 if an Infinity or NaN] */ | ||||
571 | /* COMBMSD - 4-bit most-significant-digit */ | ||||
572 | /* [0=Infinity, 1=NaN if COMBEXP=11] */ | ||||
573 | /* */ | ||||
574 | /* Both are indexed by the 5-bit combination field (0-31) */ | ||||
575 | /* ------------------------------------------------------------------ */ | ||||
576 | const uIntuint32_t COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0, | ||||
577 | 1, 1, 1, 1, 1, 1, 1, 1, | ||||
578 | 2, 2, 2, 2, 2, 2, 2, 2, | ||||
579 | 0, 0, 1, 1, 2, 2, 3, 3}; | ||||
580 | const uIntuint32_t COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, | ||||
581 | 0, 1, 2, 3, 4, 5, 6, 7, | ||||
582 | 0, 1, 2, 3, 4, 5, 6, 7, | ||||
583 | 8, 9, 8, 9, 8, 9, 0, 1}; | ||||
584 | |||||
585 | /* ------------------------------------------------------------------ */ | ||||
586 | /* decDigitsToDPD -- pack coefficient into DPD form */ | ||||
587 | /* */ | ||||
588 | /* dn is the source number (assumed valid, max DECMAX754 digits) */ | ||||
589 | /* targ is 1, 2, or 4-element uInt array, which the caller must */ | ||||
590 | /* have cleared to zeros */ | ||||
591 | /* shift is the number of 0 digits to add on the right (normally 0) */ | ||||
592 | /* */ | ||||
593 | /* The coefficient must be known small enough to fit. The full */ | ||||
594 | /* coefficient is copied, including the leading 'odd' digit. This */ | ||||
595 | /* digit is retrieved and packed into the combination field by the */ | ||||
596 | /* caller. */ | ||||
597 | /* */ | ||||
598 | /* The target uInts are altered only as necessary to receive the */ | ||||
599 | /* digits of the decNumber. When more than one uInt is needed, they */ | ||||
600 | /* are filled from left to right (that is, the uInt at offset 0 will */ | ||||
601 | /* end up with the least-significant digits). */ | ||||
602 | /* */ | ||||
603 | /* shift is used for 'fold-down' padding. */ | ||||
604 | /* */ | ||||
605 | /* No error is possible. */ | ||||
606 | /* ------------------------------------------------------------------ */ | ||||
607 | #if DECDPUN3<=4 | ||||
608 | /* Constant multipliers for divide-by-power-of five using reciprocal */ | ||||
609 | /* multiply, after removing powers of 2 by shifting, and final shift */ | ||||
610 | /* of 17 [we only need up to **4] */ | ||||
611 | static const uIntuint32_t multies[]={131073, 26215, 5243, 1049, 210}; | ||||
612 | /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */ | ||||
613 | #define QUOT10(u, n)((((uint32_t)(u)>>(n))*multies[n])>>17) ((((uIntuint32_t)(u)>>(n))*multies[n])>>17) | ||||
614 | #endif | ||||
615 | void decDigitsToDPD(const decNumber *dn, uIntuint32_t *targ, Intint32_t shift) { | ||||
616 | Intint32_t cut; /* work */ | ||||
617 | Intint32_t digits=dn->digits; /* digit countdown */ | ||||
618 | uIntuint32_t dpd; /* densely packed decimal value */ | ||||
619 | uIntuint32_t bin; /* binary value 0-999 */ | ||||
620 | uIntuint32_t *uout=targ; /* -> current output uInt */ | ||||
621 | uIntuint32_t uoff=0; /* -> current output offset [from right] */ | ||||
622 | const Unituint16_t *inu=dn->lsu; /* -> current input unit */ | ||||
623 | Unituint16_t uar[DECMAXUNITS((34 +3 -1)/3)]; /* working copy of units, iff shifted */ | ||||
624 | #if DECDPUN3!=3 /* not fast path */ | ||||
625 | Unituint16_t in; /* current unit */ | ||||
626 | #endif | ||||
627 | |||||
628 | if (shift
| ||||
629 | /* shift the units array to the left by pad digits and copy */ | ||||
630 | /* [this code is a special case of decShiftToMost, which could */ | ||||
631 | /* be used instead if exposed and the array were copied first] */ | ||||
632 | const Unituint16_t *source; /* .. */ | ||||
633 | Unituint16_t *target, *first; /* .. */ | ||||
634 | uIntuint32_t next=0; /* work */ | ||||
635 | |||||
636 | source=dn->lsu+D2U(digits)((digits)<=49?d2utable[digits]:((digits)+3 -1)/3)-1; /* where msu comes from */ | ||||
637 | target=uar+D2U(digits)((digits)<=49?d2utable[digits]:((digits)+3 -1)/3)-1+D2U(shift)((shift)<=49?d2utable[shift]:((shift)+3 -1)/3);/* where upper part of first cut goes */ | ||||
638 | cut=DECDPUN3-MSUDIGITS(shift)((shift)-(((shift)<=49?d2utable[shift]:((shift)+3 -1)/3)-1 )*3); /* where to slice */ | ||||
639 | if (cut==0) { /* unit-boundary case */ | ||||
640 | for (; source>=dn->lsu; source--, target--) *target=*source; | ||||
641 | } | ||||
642 | else { | ||||
643 | first=uar+D2U(digits+shift)((digits+shift)<=49?d2utable[digits+shift]:((digits+shift) +3 -1)/3)-1; /* where msu will end up */ | ||||
644 | for (; source>=dn->lsu; source--, target--) { | ||||
645 | /* split the source Unit and accumulate remainder for next */ | ||||
646 | #if DECDPUN3<=4 | ||||
647 | uIntuint32_t quot=QUOT10(*source, cut)((((uint32_t)(*source)>>(cut))*multies[cut])>>17); | ||||
648 | uIntuint32_t rem=*source-quot*DECPOWERS[cut]; | ||||
649 | next+=quot; | ||||
650 | #else | ||||
651 | uIntuint32_t rem=*source%DECPOWERS[cut]; | ||||
652 | next+=*source/DECPOWERS[cut]; | ||||
653 | #endif | ||||
654 | if (target<=first) *target=(Unituint16_t)next; /* write to target iff valid */ | ||||
655 | next=rem*DECPOWERS[DECDPUN3-cut]; /* save remainder for next Unit */ | ||||
656 | } | ||||
657 | } /* shift-move */ | ||||
658 | /* propagate remainder to one below and clear the rest */ | ||||
659 | for (; target>=uar; target--) { | ||||
660 | *target=(Unituint16_t)next; | ||||
661 | next=0; | ||||
662 | } | ||||
663 | digits+=shift; /* add count (shift) of zeros added */ | ||||
664 | inu=uar; /* use units in working array */ | ||||
665 | } | ||||
666 | |||||
667 | /* now densely pack the coefficient into DPD declets */ | ||||
668 | |||||
669 | #if DECDPUN3!=3 /* not fast path */ | ||||
670 | in=*inu; /* current unit */ | ||||
671 | cut=0; /* at lowest digit */ | ||||
672 | bin=0; /* [keep compiler quiet] */ | ||||
673 | #endif | ||||
674 | |||||
675 | for(; digits>0;) { /* each output bunch */ | ||||
676 | #if DECDPUN3==3 /* fast path, 3-at-a-time */ | ||||
677 | bin=*inu; /* 3 digits ready for convert */ | ||||
| |||||
678 | digits-=3; /* [may go negative] */ | ||||
679 | inu++; /* may need another */ | ||||
680 | |||||
681 | #else /* must collect digit-by-digit */ | ||||
682 | Unituint16_t dig; /* current digit */ | ||||
683 | Intint32_t j; /* digit-in-declet count */ | ||||
684 | for (j=0; j<3; j++) { | ||||
685 | #if DECDPUN3<=4 | ||||
686 | Unituint16_t temp=(Unituint16_t)((uIntuint32_t)(in*6554)>>16); | ||||
687 | dig=(Unituint16_t)(in-X10(temp)(((temp)<<1)+((temp)<<3))); | ||||
688 | in=temp; | ||||
689 | #else | ||||
690 | dig=in%10; | ||||
691 | in=in/10; | ||||
692 | #endif | ||||
693 | if (j==0) bin=dig; | ||||
694 | else if (j==1) bin+=X10(dig)(((dig)<<1)+((dig)<<3)); | ||||
695 | else /* j==2 */ bin+=X100(dig)(((dig)<<2)+((dig)<<5)+((dig)<<6)); | ||||
696 | digits--; | ||||
697 | if (digits==0) break; /* [also protects *inu below] */ | ||||
698 | cut++; | ||||
699 | if (cut==DECDPUN3) {inu++; in=*inu; cut=0;} | ||||
700 | } | ||||
701 | #endif | ||||
702 | /* here there are 3 digits in bin, or have used all input digits */ | ||||
703 | |||||
704 | dpd=BIN2DPD[bin]; | ||||
705 | |||||
706 | /* write declet to uInt array */ | ||||
707 | *uout|=dpd<<uoff; | ||||
708 | uoff+=10; | ||||
709 | if (uoff<32) continue; /* no uInt boundary cross */ | ||||
710 | uout++; | ||||
711 | uoff-=32; | ||||
712 | *uout|=dpd>>(10-uoff); /* collect top bits */ | ||||
713 | } /* n declets */ | ||||
714 | return; | ||||
715 | } /* decDigitsToDPD */ | ||||
716 | |||||
717 | /* ------------------------------------------------------------------ */ | ||||
718 | /* decDigitsFromDPD -- unpack a format's coefficient */ | ||||
719 | /* */ | ||||
720 | /* dn is the target number, with 7, 16, or 34-digit space. */ | ||||
721 | /* sour is a 1, 2, or 4-element uInt array containing only declets */ | ||||
722 | /* declets is the number of (right-aligned) declets in sour to */ | ||||
723 | /* be processed. This may be 1 more than the obvious number in */ | ||||
724 | /* a format, as any top digit is prefixed to the coefficient */ | ||||
725 | /* continuation field. It also may be as small as 1, as the */ | ||||
726 | /* caller may pre-process leading zero declets. */ | ||||
727 | /* */ | ||||
728 | /* When doing the 'extra declet' case care is taken to avoid writing */ | ||||
729 | /* extra digits when there are leading zeros, as these could overflow */ | ||||
730 | /* the units array when DECDPUN is not 3. */ | ||||
731 | /* */ | ||||
732 | /* The target uInts are used only as necessary to process declets */ | ||||
733 | /* declets into the decNumber. When more than one uInt is needed, */ | ||||
734 | /* they are used from left to right (that is, the uInt at offset 0 */ | ||||
735 | /* provides the least-significant digits). */ | ||||
736 | /* */ | ||||
737 | /* dn->digits is set, but not the sign or exponent. */ | ||||
738 | /* No error is possible [the redundant 888 codes are allowed]. */ | ||||
739 | /* ------------------------------------------------------------------ */ | ||||
740 | void decDigitsFromDPD(decNumber *dn, const uIntuint32_t *sour, Intint32_t declets) { | ||||
741 | |||||
742 | uIntuint32_t dpd; /* collector for 10 bits */ | ||||
743 | Intint32_t n; /* counter */ | ||||
744 | Unituint16_t *uout=dn->lsu; /* -> current output unit */ | ||||
745 | Unituint16_t *last=uout; /* will be unit containing msd */ | ||||
746 | const uIntuint32_t *uin=sour; /* -> current input uInt */ | ||||
747 | uIntuint32_t uoff=0; /* -> current input offset [from right] */ | ||||
748 | |||||
749 | #if DECDPUN3!=3 | ||||
750 | uIntuint32_t bcd; /* BCD result */ | ||||
751 | uIntuint32_t nibble; /* work */ | ||||
752 | Unituint16_t out=0; /* accumulator */ | ||||
753 | Intint32_t cut=0; /* power of ten in current unit */ | ||||
754 | #endif | ||||
755 | #if DECDPUN3>4 | ||||
756 | uIntuint32_t const *pow; /* work */ | ||||
757 | #endif | ||||
758 | |||||
759 | /* Expand the densely-packed integer, right to left */ | ||||
760 | for (n=declets-1; n>=0; n--) { /* count down declets of 10 bits */ | ||||
761 | dpd=*uin>>uoff; | ||||
762 | uoff+=10; | ||||
763 | if (uoff>32) { /* crossed uInt boundary */ | ||||
764 | uin++; | ||||
765 | uoff-=32; | ||||
766 | dpd|=*uin<<(10-uoff); /* get waiting bits */ | ||||
767 | } | ||||
768 | dpd&=0x3ff; /* clear uninteresting bits */ | ||||
769 | |||||
770 | #if DECDPUN3==3 | ||||
771 | if (dpd==0) *uout=0; | ||||
772 | else { | ||||
773 | *uout=DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */ | ||||
774 | last=uout; /* record most significant unit */ | ||||
775 | } | ||||
776 | uout++; | ||||
777 | } /* n */ | ||||
778 | |||||
779 | #else /* DECDPUN!=3 */ | ||||
780 | if (dpd==0) { /* fastpath [e.g., leading zeros] */ | ||||
781 | /* write out three 0 digits (nibbles); out may have digit(s) */ | ||||
782 | cut++; | ||||
783 | if (cut==DECDPUN3) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | ||||
784 | if (n==0) break; /* [as below, works even if MSD=0] */ | ||||
785 | cut++; | ||||
786 | if (cut==DECDPUN3) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | ||||
787 | cut++; | ||||
788 | if (cut==DECDPUN3) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | ||||
789 | continue; | ||||
790 | } | ||||
791 | |||||
792 | bcd=DPD2BCD[dpd]; /* convert 10 bits to 12 bits BCD */ | ||||
793 | |||||
794 | /* now accumulate the 3 BCD nibbles into units */ | ||||
795 | nibble=bcd & 0x00f; | ||||
796 | if (nibble) out=(Unituint16_t)(out+nibble*DECPOWERS[cut]); | ||||
797 | cut++; | ||||
798 | if (cut==DECDPUN3) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | ||||
799 | bcd>>=4; | ||||
800 | |||||
801 | /* if this is the last declet and the remaining nibbles in bcd */ | ||||
802 | /* are 00 then process no more nibbles, because this could be */ | ||||
803 | /* the 'odd' MSD declet and writing any more Units would then */ | ||||
804 | /* overflow the unit array */ | ||||
805 | if (n==0 && !bcd) break; | ||||
806 | |||||
807 | nibble=bcd & 0x00f; | ||||
808 | if (nibble) out=(Unituint16_t)(out+nibble*DECPOWERS[cut]); | ||||
809 | cut++; | ||||
810 | if (cut==DECDPUN3) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | ||||
811 | bcd>>=4; | ||||
812 | |||||
813 | nibble=bcd & 0x00f; | ||||
814 | if (nibble) out=(Unituint16_t)(out+nibble*DECPOWERS[cut]); | ||||
815 | cut++; | ||||
816 | if (cut==DECDPUN3) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | ||||
817 | } /* n */ | ||||
818 | if (cut!=0) { /* some more left over */ | ||||
819 | *uout=out; /* write out final unit */ | ||||
820 | if (out) last=uout; /* and note if non-zero */ | ||||
821 | } | ||||
822 | #endif | ||||
823 | |||||
824 | /* here, last points to the most significant unit with digits; */ | ||||
825 | /* inspect it to get the final digits count -- this is essentially */ | ||||
826 | /* the same code as decGetDigits in decNumber.c */ | ||||
827 | dn->digits=(last-dn->lsu)*DECDPUN3+1; /* floor of digits, plus */ | ||||
828 | /* must be at least 1 digit */ | ||||
829 | #if DECDPUN3>1 | ||||
830 | if (*last<10) return; /* common odd digit or 0 */ | ||||
831 | dn->digits++; /* must be 2 at least */ | ||||
832 | #if DECDPUN3>2 | ||||
833 | if (*last<100) return; /* 10-99 */ | ||||
834 | dn->digits++; /* must be 3 at least */ | ||||
835 | #if DECDPUN3>3 | ||||
836 | if (*last<1000) return; /* 100-999 */ | ||||
837 | dn->digits++; /* must be 4 at least */ | ||||
838 | #if DECDPUN3>4 | ||||
839 | for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++; | ||||
840 | #endif | ||||
841 | #endif | ||||
842 | #endif | ||||
843 | #endif | ||||
844 | return; | ||||
845 | } /*decDigitsFromDPD */ |