OLD | NEW |
1 /* Decimal 64-bit format module for the decNumber C Library. | 1 /* Decimal 64-bit format module for the decNumber C Library. |
2 Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc. | 2 Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc. |
3 Contributed by IBM Corporation. Author Mike Cowlishaw. | 3 Contributed by IBM Corporation. Author Mike Cowlishaw. |
4 | 4 |
5 This file is part of GCC. | 5 This file is part of GCC. |
6 | 6 |
7 GCC is free software; you can redistribute it and/or modify it under | 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 | 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 | 9 Software Foundation; either version 3, or (at your option) any later |
10 version. | 10 version. |
11 | 11 |
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | 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 | 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 for more details. | 15 for more details. |
16 | 16 |
17 Under Section 7 of GPL version 3, you are granted additional | 17 Under Section 7 of GPL version 3, you are granted additional |
18 permissions described in the GCC Runtime Library Exception, version | 18 permissions described in the GCC Runtime Library Exception, version |
19 3.1, as published by the Free Software Foundation. | 19 3.1, as published by the Free Software Foundation. |
20 | 20 |
21 You should have received a copy of the GNU General Public License and | 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; | 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 | 23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
24 <http://www.gnu.org/licenses/>. */ | 24 <http://www.gnu.org/licenses/>. */ |
25 | 25 |
26 /* ------------------------------------------------------------------ */ | 26 /* ------------------------------------------------------------------ */ |
27 /* Decimal 64-bit format module»» » » » */ | 27 /* Decimal 64-bit format module » » » » */ |
28 /* ------------------------------------------------------------------ */ | 28 /* ------------------------------------------------------------------ */ |
29 /* This module comprises the routines for decimal64 format numbers. */ | 29 /* This module comprises the routines for decimal64 format numbers. */ |
30 /* Conversions are supplied to and from decNumber and String. */ | 30 /* Conversions are supplied to and from decNumber and String. */ |
31 /* */ | 31 /* */ |
32 /* This is used when decNumber provides operations, either for all */ | 32 /* This is used when decNumber provides operations, either for all */ |
33 /* operations or as a proxy between decNumber and decSingle. */ | 33 /* operations or as a proxy between decNumber and decSingle. */ |
34 /* */ | 34 /* */ |
35 /* Error handling is the same as decNumber (qv.). */ | 35 /* Error handling is the same as decNumber (qv.). */ |
36 /* ------------------------------------------------------------------ */ | 36 /* ------------------------------------------------------------------ */ |
37 #include <string.h> /* [for memset/memcpy] */ | 37 #include <string.h> /* [for memset/memcpy] */ |
38 #include <stdio.h> /* [for printf] */ | 38 #include <stdio.h> /* [for printf] */ |
39 | 39 |
40 #include "dconfig.h"» /* GCC definitions */ | 40 #include "dconfig.h" /* GCC definitions */ |
41 #define» DECNUMDIGITS 16 /* make decNumbers with space for 16 */ | 41 #define DECNUMDIGITS 16 /* make decNumbers with space for 16 */ |
42 #include "decNumber.h" /* base number library */ | 42 #include "decNumber.h" /* base number library */ |
43 #include "decNumberLocal.h" /* decNumber local types, etc. */ | 43 #include "decNumberLocal.h" /* decNumber local types, etc. */ |
44 #include "decimal64.h" /* our primary include */ | 44 #include "decimal64.h" /* our primary include */ |
45 | 45 |
46 /* Utility routines and tables [in decimal64.c]; externs for C++ */ | 46 /* Utility routines and tables [in decimal64.c]; externs for C++ */ |
47 extern const uInt COMBEXP[32], COMBMSD[32]; | 47 extern const uInt COMBEXP[32], COMBMSD[32]; |
48 extern const uShort DPD2BIN[1024]; | 48 extern const uShort DPD2BIN[1024]; |
49 extern const uShort BIN2DPD[1000]; | 49 extern const uShort BIN2DPD[1000]; |
50 extern const uByte BIN2CHAR[4001]; | 50 extern const uByte BIN2CHAR[4001]; |
51 | 51 |
(...skipping 11 matching lines...) Expand all Loading... |
63 | 63 |
64 /* define and include the tables to use for conversions */ | 64 /* define and include the tables to use for conversions */ |
65 #define DEC_BIN2CHAR 1 | 65 #define DEC_BIN2CHAR 1 |
66 #define DEC_DPD2BIN 1 | 66 #define DEC_DPD2BIN 1 |
67 #define DEC_BIN2DPD 1 /* used for all sizes */ | 67 #define DEC_BIN2DPD 1 /* used for all sizes */ |
68 #include "decDPD.h" /* lookup tables */ | 68 #include "decDPD.h" /* lookup tables */ |
69 | 69 |
70 /* ------------------------------------------------------------------ */ | 70 /* ------------------------------------------------------------------ */ |
71 /* decimal64FromNumber -- convert decNumber to decimal64 */ | 71 /* decimal64FromNumber -- convert decNumber to decimal64 */ |
72 /* */ | 72 /* */ |
73 /* ds is the target decimal64»» » » » */ | 73 /* ds is the target decimal64 » » » » */ |
74 /* dn is the source number (assumed valid) */ | 74 /* dn is the source number (assumed valid) */ |
75 /* set is the context, used only for reporting errors»» */ | 75 /* set is the context, used only for reporting errors » */ |
76 /* */ | 76 /* */ |
77 /* The set argument is used only for status reporting and for the */ | 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 */ | 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 */ | 79 /* digits or an overflow is detected). If the exponent is out of the */ |
80 /* valid range then Overflow or Underflow will be raised. */ | 80 /* valid range then Overflow or Underflow will be raised. */ |
81 /* After Underflow a subnormal result is possible. */ | 81 /* After Underflow a subnormal result is possible. */ |
82 /* */ | 82 /* */ |
83 /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ | 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 */ | 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. */ | 85 /* power of ten, or if the exponent on a zero had to be clamped. */ |
86 /* ------------------------------------------------------------------ */ | 86 /* ------------------------------------------------------------------ */ |
87 decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, | 87 decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, |
88 decContext *set) { | 88 decContext *set) { |
89 uInt status=0; /* status accumulator */ | 89 uInt status=0; /* status accumulator */ |
90 Int ae; /* adjusted exponent */ | 90 Int ae; /* adjusted exponent */ |
91 decNumber dw; /* work */ | 91 decNumber dw; /* work */ |
92 decContext dc; /* .. */ | 92 decContext dc; /* .. */ |
93 uInt *pu; /* .. */ | |
94 uInt comb, exp; /* .. */ | 93 uInt comb, exp; /* .. */ |
| 94 uInt uiwork; /* for macros */ |
95 uInt targar[2]={0, 0}; /* target 64-bit */ | 95 uInt targar[2]={0, 0}; /* target 64-bit */ |
96 #define targhi targar[1] /* name the word with the sign */ | 96 #define targhi targar[1] /* name the word with the sign */ |
97 #define targlo targar[0] /* and the other */ | 97 #define targlo targar[0] /* and the other */ |
98 | 98 |
99 /* If the number has too many digits, or the exponent could be */ | 99 /* If the number has too many digits, or the exponent could be */ |
100 /* out of range then reduce the number under the appropriate */ | 100 /* out of range then reduce the number under the appropriate */ |
101 /* constraints. This could push the number to Infinity or zero, */ | 101 /* constraints. This could push the number to Infinity or zero, */ |
102 /* so this check and rounding must be done before generating the */ | 102 /* so this check and rounding must be done before generating the */ |
103 /* decimal64] */ | 103 /* decimal64] */ |
104 ae=dn->exponent+dn->digits-1;»» /* [0 if special] */ | 104 ae=dn->exponent+dn->digits-1; » /* [0 if special] */ |
105 if (dn->digits>DECIMAL64_Pmax»» /* too many digits */ | 105 if (dn->digits>DECIMAL64_Pmax » /* too many digits */ |
106 || ae>DECIMAL64_Emax»» » /* likely overflow */ | 106 || ae>DECIMAL64_Emax » » /* likely overflow */ |
107 || ae<DECIMAL64_Emin) { /* likely underflow */ | 107 || ae<DECIMAL64_Emin) { /* likely underflow */ |
108 decContextDefault(&dc, DEC_INIT_DECIMAL64); /* [no traps] */ | 108 decContextDefault(&dc, DEC_INIT_DECIMAL64); /* [no traps] */ |
109 dc.round=set->round; /* use supplied rounding */ | 109 dc.round=set->round; /* use supplied rounding */ |
110 decNumberPlus(&dw, dn, &dc); /* (round and check) */ | 110 decNumberPlus(&dw, dn, &dc); /* (round and check) */ |
111 /* [this changes -0 to 0, so enforce the sign...] */ | 111 /* [this changes -0 to 0, so enforce the sign...] */ |
112 dw.bits|=dn->bits&DECNEG; | 112 dw.bits|=dn->bits&DECNEG; |
113 status=dc.status; /* save status */ | 113 status=dc.status; /* save status */ |
114 dn=&dw; /* use the work number */ | 114 dn=&dw; /* use the work number */ |
115 } /* maybe out of range */ | 115 } /* maybe out of range */ |
116 | 116 |
117 if (dn->bits&DECSPECIAL) { /* a special value */ | 117 if (dn->bits&DECSPECIAL) { /* a special value */ |
118 if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; | 118 if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; |
119 else { /* sNaN or qNaN */ | 119 else { /* sNaN or qNaN */ |
120 if ((*dn->lsu!=0 || dn->digits>1)»» /* non-zero coefficient */ | 120 if ((*dn->lsu!=0 || dn->digits>1) » /* non-zero coefficient */ |
121 && (dn->digits<DECIMAL64_Pmax)) { /* coefficient fits */ | 121 && (dn->digits<DECIMAL64_Pmax)) { /* coefficient fits */ |
122 decDigitsToDPD(dn, targar, 0); | 122 decDigitsToDPD(dn, targar, 0); |
123 } | 123 } |
124 if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24; | 124 if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24; |
125 else targhi|=DECIMAL_sNaN<<24; | 125 else targhi|=DECIMAL_sNaN<<24; |
126 } /* a NaN */ | 126 } /* a NaN */ |
127 } /* special */ | 127 } /* special */ |
128 | 128 |
129 else { /* is finite */ | 129 else { /* is finite */ |
130 if (decNumberIsZero(dn)) { /* is a zero */ | 130 if (decNumberIsZero(dn)) { /* is a zero */ |
131 /* set and clamp exponent */ | 131 /* set and clamp exponent */ |
132 if (dn->exponent<-DECIMAL64_Bias) { | 132 if (dn->exponent<-DECIMAL64_Bias) { |
133 exp=0; /* low clamp */ | 133 exp=0; /* low clamp */ |
134 status|=DEC_Clamped; | 134 status|=DEC_Clamped; |
135 } | 135 } |
136 else { | 136 else { |
137 exp=dn->exponent+DECIMAL64_Bias; /* bias exponent */ | 137 exp=dn->exponent+DECIMAL64_Bias; /* bias exponent */ |
138 if (exp>DECIMAL64_Ehigh) { /* top clamp */ | 138 if (exp>DECIMAL64_Ehigh) { /* top clamp */ |
139 exp=DECIMAL64_Ehigh; | 139 exp=DECIMAL64_Ehigh; |
140 status|=DEC_Clamped; | 140 status|=DEC_Clamped; |
141 } | 141 } |
142 } | 142 } |
143 comb=(exp>>5) & 0x18; /* msd=0, exp top 2 bits .. */ | 143 comb=(exp>>5) & 0x18; /* msd=0, exp top 2 bits .. */ |
144 } | 144 } |
145 else { /* non-zero finite number */ | 145 else { /* non-zero finite number */ |
146 uInt msd;»» » » /* work */ | 146 uInt msd; » » » /* work */ |
147 Int pad=0; /* coefficient pad digits */ | 147 Int pad=0; /* coefficient pad digits */ |
148 | 148 |
149 /* the dn is known to fit, but it may need to be padded */ | 149 /* the dn is known to fit, but it may need to be padded */ |
150 exp=(uInt)(dn->exponent+DECIMAL64_Bias); /* bias exponent */ | 150 exp=(uInt)(dn->exponent+DECIMAL64_Bias); /* bias exponent */ |
151 if (exp>DECIMAL64_Ehigh) { /* fold-down case */ | 151 if (exp>DECIMAL64_Ehigh) { /* fold-down case */ |
152 pad=exp-DECIMAL64_Ehigh; | 152 pad=exp-DECIMAL64_Ehigh; |
153 exp=DECIMAL64_Ehigh; /* [to maximum] */ | 153 exp=DECIMAL64_Ehigh; /* [to maximum] */ |
154 status|=DEC_Clamped; | 154 status|=DEC_Clamped; |
155 } | 155 } |
156 | 156 |
(...skipping 24 matching lines...) Expand all Loading... |
181 if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01); | 181 if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01); |
182 else comb=((exp>>5) & 0x18) | msd; | 182 else comb=((exp>>5) & 0x18) | msd; |
183 } | 183 } |
184 targhi|=comb<<26; /* add combination field .. */ | 184 targhi|=comb<<26; /* add combination field .. */ |
185 targhi|=(exp&0xff)<<18; /* .. and exponent continuation */ | 185 targhi|=(exp&0xff)<<18; /* .. and exponent continuation */ |
186 } /* finite */ | 186 } /* finite */ |
187 | 187 |
188 if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */ | 188 if (dn->bits&DECNEG) targhi|=0x80000000; /* add sign bit */ |
189 | 189 |
190 /* now write to storage; this is now always endian */ | 190 /* now write to storage; this is now always endian */ |
191 pu=(uInt *)d64->bytes; /* overlay */ | |
192 if (DECLITEND) { | 191 if (DECLITEND) { |
193 pu[0]=targar[0];» » /* directly store the low int */ | 192 /* lo int then hi */ |
194 pu[1]=targar[1];» » /* then the high int */ | 193 UBFROMUI(d64->bytes, targar[0]); |
| 194 UBFROMUI(d64->bytes+4, targar[1]); |
195 } | 195 } |
196 else { | 196 else { |
197 pu[0]=targar[1];» » /* directly store the high int */ | 197 /* hi int then lo */ |
198 pu[1]=targar[0];» » /* then the low int */ | 198 UBFROMUI(d64->bytes, targar[1]); |
| 199 UBFROMUI(d64->bytes+4, targar[0]); |
199 } | 200 } |
200 | 201 |
201 if (status!=0) decContextSetStatus(set, status); /* pass on status */ | 202 if (status!=0) decContextSetStatus(set, status); /* pass on status */ |
202 /* decimal64Show(d64); */ | 203 /* decimal64Show(d64); */ |
203 return d64; | 204 return d64; |
204 } /* decimal64FromNumber */ | 205 } /* decimal64FromNumber */ |
205 | 206 |
206 /* ------------------------------------------------------------------ */ | 207 /* ------------------------------------------------------------------ */ |
207 /* decimal64ToNumber -- convert decimal64 to decNumber */ | 208 /* decimal64ToNumber -- convert decimal64 to decNumber */ |
208 /* d64 is the source decimal64 */ | 209 /* d64 is the source decimal64 */ |
209 /* dn is the target number, with appropriate space */ | 210 /* dn is the target number, with appropriate space */ |
210 /* No error is possible. */ | 211 /* No error is possible. */ |
211 /* ------------------------------------------------------------------ */ | 212 /* ------------------------------------------------------------------ */ |
212 decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { | 213 decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { |
213 uInt msd; /* coefficient MSD */ | 214 uInt msd; /* coefficient MSD */ |
214 uInt exp; /* exponent top two bits */ | 215 uInt exp; /* exponent top two bits */ |
215 uInt comb; /* combination field */ | 216 uInt comb; /* combination field */ |
216 const uInt *pu;» » /* work */ | 217 Int need;» » » /* work */ |
217 Int need;» » » /* .. */ | 218 uInt uiwork;» » » /* for macros */ |
218 uInt sourar[2]; /* source 64-bit */ | 219 uInt sourar[2]; /* source 64-bit */ |
219 #define sourhi sourar[1] /* name the word with the sign */ | 220 #define sourhi sourar[1] /* name the word with the sign */ |
220 #define sourlo sourar[0] /* and the lower word */ | 221 #define sourlo sourar[0] /* and the lower word */ |
221 | 222 |
222 /* load source from storage; this is endian */ | 223 /* load source from storage; this is endian */ |
223 pu=(const uInt *)d64->bytes; /* overlay */ | |
224 if (DECLITEND) { | 224 if (DECLITEND) { |
225 sourlo=pu[0];» » /* directly load the low int */ | 225 sourlo=UBTOUI(d64->bytes ); /* directly load the low int */ |
226 sourhi=pu[1];» » /* then the high int */ | 226 sourhi=UBTOUI(d64->bytes+4); /* then the high int */ |
227 } | 227 } |
228 else { | 228 else { |
229 sourhi=pu[0];» » /* directly load the high int */ | 229 sourhi=UBTOUI(d64->bytes ); /* directly load the high int */ |
230 sourlo=pu[1];» » /* then the low int */ | 230 sourlo=UBTOUI(d64->bytes+4); /* then the low int */ |
231 } | 231 } |
232 | 232 |
233 comb=(sourhi>>26)&0x1f; /* combination field */ | 233 comb=(sourhi>>26)&0x1f; /* combination field */ |
234 | 234 |
235 decNumberZero(dn); /* clean number */ | 235 decNumberZero(dn); /* clean number */ |
236 if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */ | 236 if (sourhi&0x80000000) dn->bits=DECNEG; /* set sign if negative */ |
237 | 237 |
238 msd=COMBMSD[comb]; /* decode the combination field */ | 238 msd=COMBMSD[comb]; /* decode the combination field */ |
239 exp=COMBEXP[comb]; /* .. */ | 239 exp=COMBEXP[comb]; /* .. */ |
240 | 240 |
241 if (exp==3) {»» » /* is a special */ | 241 if (exp==3) { » » /* is a special */ |
242 if (msd==0) { | 242 if (msd==0) { |
243 dn->bits|=DECINF; | 243 dn->bits|=DECINF; |
244 return dn; /* no coefficient needed */ | 244 return dn; /* no coefficient needed */ |
245 } | 245 } |
246 else if (sourhi&0x02000000) dn->bits|=DECSNAN; | 246 else if (sourhi&0x02000000) dn->bits|=DECSNAN; |
247 else dn->bits|=DECNAN; | 247 else dn->bits|=DECNAN; |
248 msd=0; /* no top digit */ | 248 msd=0; /* no top digit */ |
249 } | 249 } |
250 else { /* is a finite number */ | 250 else { /* is a finite number */ |
251 dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; /* unbiased */ | 251 dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; /* unbiased */ |
(...skipping 17 matching lines...) Expand all Loading... |
269 if (sourhi&0x0003ff00) need++; /* top declet!=0, process 5 */ | 269 if (sourhi&0x0003ff00) need++; /* top declet!=0, process 5 */ |
270 } | 270 } |
271 } /*msd=0 */ | 271 } /*msd=0 */ |
272 | 272 |
273 decDigitsFromDPD(dn, sourar, need); /* process declets */ | 273 decDigitsFromDPD(dn, sourar, need); /* process declets */ |
274 return dn; | 274 return dn; |
275 } /* decimal64ToNumber */ | 275 } /* decimal64ToNumber */ |
276 | 276 |
277 | 277 |
278 /* ------------------------------------------------------------------ */ | 278 /* ------------------------------------------------------------------ */ |
279 /* to-scientific-string -- conversion to numeric string»» */ | 279 /* to-scientific-string -- conversion to numeric string » */ |
280 /* to-engineering-string -- conversion to numeric string */ | 280 /* to-engineering-string -- conversion to numeric string */ |
281 /* */ | 281 /* */ |
282 /* decimal64ToString(d64, string); */ | 282 /* decimal64ToString(d64, string); */ |
283 /* decimal64ToEngString(d64, string);»» » » */ | 283 /* decimal64ToEngString(d64, string); » » » */ |
284 /* */ | 284 /* */ |
285 /* d64 is the decimal64 format number to convert */ | 285 /* d64 is the decimal64 format number to convert */ |
286 /* string is the string where the result will be laid out */ | 286 /* string is the string where the result will be laid out */ |
287 /* */ | 287 /* */ |
288 /* string must be at least 24 characters */ | 288 /* string must be at least 24 characters */ |
289 /* */ | 289 /* */ |
290 /* No error is possible, and no status can be set. */ | 290 /* No error is possible, and no status can be set. */ |
291 /* ------------------------------------------------------------------ */ | 291 /* ------------------------------------------------------------------ */ |
292 char * decimal64ToEngString(const decimal64 *d64, char *string){ | 292 char * decimal64ToEngString(const decimal64 *d64, char *string){ |
293 decNumber dn;»» » » /* work */ | 293 decNumber dn; » » » /* work */ |
294 decimal64ToNumber(d64, &dn); | 294 decimal64ToNumber(d64, &dn); |
295 decNumberToEngString(&dn, string); | 295 decNumberToEngString(&dn, string); |
296 return string; | 296 return string; |
297 } /* decimal64ToEngString */ | 297 } /* decimal64ToEngString */ |
298 | 298 |
299 char * decimal64ToString(const decimal64 *d64, char *string){ | 299 char * decimal64ToString(const decimal64 *d64, char *string){ |
300 uInt msd; /* coefficient MSD */ | 300 uInt msd; /* coefficient MSD */ |
301 Int exp; /* exponent top two bits or full */ | 301 Int exp; /* exponent top two bits or full */ |
302 uInt comb; /* combination field */ | 302 uInt comb; /* combination field */ |
303 char *cstart;»» » /* coefficient start */ | 303 char *cstart; » » /* coefficient start */ |
304 char *c; /* output pointer in string */ | 304 char *c; /* output pointer in string */ |
305 const uInt *pu;» » /* work */ | 305 const uByte *u;» » /* work */ |
306 char *s, *t; /* .. (source, target) */ | 306 char *s, *t; /* .. (source, target) */ |
307 Int dpd; /* .. */ | 307 Int dpd; /* .. */ |
308 Int pre, e; /* .. */ | 308 Int pre, e; /* .. */ |
309 const uByte *u;» » /* .. */ | 309 uInt uiwork;» » » /* for macros */ |
310 | 310 |
311 uInt sourar[2]; /* source 64-bit */ | 311 uInt sourar[2]; /* source 64-bit */ |
312 #define sourhi sourar[1] /* name the word with the sign */ | 312 #define sourhi sourar[1] /* name the word with the sign */ |
313 #define sourlo sourar[0] /* and the lower word */ | 313 #define sourlo sourar[0] /* and the lower word */ |
314 | 314 |
315 /* load source from storage; this is endian */ | 315 /* load source from storage; this is endian */ |
316 pu=(const uInt *)d64->bytes; /* overlay */ | |
317 if (DECLITEND) { | 316 if (DECLITEND) { |
318 sourlo=pu[0];» » /* directly load the low int */ | 317 sourlo=UBTOUI(d64->bytes ); /* directly load the low int */ |
319 sourhi=pu[1];» » /* then the high int */ | 318 sourhi=UBTOUI(d64->bytes+4); /* then the high int */ |
320 } | 319 } |
321 else { | 320 else { |
322 sourhi=pu[0];» » /* directly load the high int */ | 321 sourhi=UBTOUI(d64->bytes ); /* directly load the high int */ |
323 sourlo=pu[1];» » /* then the low int */ | 322 sourlo=UBTOUI(d64->bytes+4); /* then the low int */ |
324 } | 323 } |
325 | 324 |
326 c=string; /* where result will go */ | 325 c=string; /* where result will go */ |
327 if (((Int)sourhi)<0) *c++='-'; /* handle sign */ | 326 if (((Int)sourhi)<0) *c++='-'; /* handle sign */ |
328 | 327 |
329 comb=(sourhi>>26)&0x1f; /* combination field */ | 328 comb=(sourhi>>26)&0x1f; /* combination field */ |
330 msd=COMBMSD[comb]; /* decode the combination field */ | 329 msd=COMBMSD[comb]; /* decode the combination field */ |
331 exp=COMBEXP[comb]; /* .. */ | 330 exp=COMBEXP[comb]; /* .. */ |
332 | 331 |
333 if (exp==3) { | 332 if (exp==3) { |
334 if (msd==0) { /* infinity */ | 333 if (msd==0) { /* infinity */ |
335 strcpy(c,» "Inf"); | 334 strcpy(c, "Inf"); |
336 strcpy(c+3, "inity"); | 335 strcpy(c+3, "inity"); |
337 return string; /* easy */ | 336 return string; /* easy */ |
338 } | 337 } |
339 if (sourhi&0x02000000) *c++='s'; /* sNaN */ | 338 if (sourhi&0x02000000) *c++='s'; /* sNaN */ |
340 strcpy(c, "NaN"); /* complete word */ | 339 strcpy(c, "NaN"); /* complete word */ |
341 c+=3; /* step past */ | 340 c+=3; /* step past */ |
342 if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; /* zero payload */ | 341 if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; /* zero payload */ |
343 /* otherwise drop through to add integer; set correct exp */ | 342 /* otherwise drop through to add integer; set correct exp */ |
344 exp=0; msd=0; /* setup for following code */ | 343 exp=0; msd=0; /* setup for following code */ |
345 } | 344 } |
346 else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; | 345 else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; |
347 | 346 |
348 /* convert 16 digits of significand to characters */ | 347 /* convert 16 digits of significand to characters */ |
349 cstart=c; /* save start of coefficient */ | 348 cstart=c; /* save start of coefficient */ |
350 if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ | 349 if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ |
351 | 350 |
352 /* Now decode the declets. After extracting each one, it is */ | 351 /* Now decode the declets. After extracting each one, it is */ |
353 /* decoded to binary and then to a 4-char sequence by table lookup; */ | 352 /* decoded to binary and then to a 4-char sequence by table lookup; */ |
354 /* the 4-chars are a 1-char length (significant digits, except 000 */ | 353 /* the 4-chars are a 1-char length (significant digits, except 000 */ |
355 /* has length 0). This allows us to left-align the first declet */ | 354 /* has length 0). This allows us to left-align the first declet */ |
356 /* with non-zero content, then remaining ones are full 3-char */ | 355 /* with non-zero content, then remaining ones are full 3-char */ |
357 /* length. We use fixed-length memcpys because variable-length */ | 356 /* length. We use fixed-length memcpys because variable-length */ |
358 /* causes a subroutine call in GCC. (These are length 4 for speed */ | 357 /* causes a subroutine call in GCC. (These are length 4 for speed */ |
359 /* and are safe because the array has an extra terminator byte.) */ | 358 /* and are safe because the array has an extra terminator byte.) */ |
360 #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];»» » \ | 359 #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; » » \ |
361 if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ | 360 if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ |
362 else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} | 361 else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} |
363 | 362 |
364 dpd=(sourhi>>8)&0x3ff; /* declet 1 */ | 363 dpd=(sourhi>>8)&0x3ff; /* declet 1 */ |
365 dpd2char; | 364 dpd2char; |
366 dpd=((sourhi&0xff)<<2) | (sourlo>>30); /* declet 2 */ | 365 dpd=((sourhi&0xff)<<2) | (sourlo>>30); /* declet 2 */ |
367 dpd2char; | 366 dpd2char; |
368 dpd=(sourlo>>20)&0x3ff; /* declet 3 */ | 367 dpd=(sourlo>>20)&0x3ff; /* declet 3 */ |
369 dpd2char; | 368 dpd2char; |
370 dpd=(sourlo>>10)&0x3ff; /* declet 4 */ | 369 dpd=(sourlo>>10)&0x3ff; /* declet 4 */ |
371 dpd2char; | 370 dpd2char; |
372 dpd=(sourlo)&0x3ff; /* declet 5 */ | 371 dpd=(sourlo)&0x3ff; /* declet 5 */ |
373 dpd2char; | 372 dpd2char; |
374 | 373 |
375 if (c==cstart) *c++='0'; /* all zeros -- make 0 */ | 374 if (c==cstart) *c++='0'; /* all zeros -- make 0 */ |
376 | 375 |
377 if (exp==0) {»» » /* integer or NaN case -- easy */ | 376 if (exp==0) { » » /* integer or NaN case -- easy */ |
378 *c='\0'; /* terminate */ | 377 *c='\0'; /* terminate */ |
379 return string; | 378 return string; |
380 } | 379 } |
381 | 380 |
382 /* non-0 exponent */ | 381 /* non-0 exponent */ |
383 e=0; /* assume no E */ | 382 e=0; /* assume no E */ |
384 pre=c-cstart+exp; | 383 pre=c-cstart+exp; |
385 /* [here, pre-exp is the digits count (==1 for zero)] */ | 384 /* [here, pre-exp is the digits count (==1 for zero)] */ |
386 if (exp>0 || pre<-5) { /* need exponential form */ | 385 if (exp>0 || pre<-5) { /* need exponential form */ |
387 e=pre-1; /* calculate E value */ | 386 e=pre-1; /* calculate E value */ |
388 pre=1; /* assume one digit before '.' */ | 387 pre=1; /* assume one digit before '.' */ |
389 } /* exponential form */ | 388 } /* exponential form */ |
390 | 389 |
391 /* modify the coefficient, adding 0s, '.', and E+nn as needed */ | 390 /* modify the coefficient, adding 0s, '.', and E+nn as needed */ |
392 s=c-1; /* source (LSD) */ | 391 s=c-1; /* source (LSD) */ |
393 if (pre>0) { /* ddd.ddd (plain), perhaps with E */ | 392 if (pre>0) { /* ddd.ddd (plain), perhaps with E */ |
394 char *dotat=cstart+pre; | 393 char *dotat=cstart+pre; |
395 if (dotat<c) { /* if embedded dot needed... */ | 394 if (dotat<c) { /* if embedded dot needed... */ |
396 t=c; /* target */ | 395 t=c; /* target */ |
397 for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ | 396 for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ |
398 *t='.'; /* insert the dot */ | 397 *t='.'; /* insert the dot */ |
399 c++; /* length increased by one */ | 398 c++; /* length increased by one */ |
400 } | 399 } |
401 | 400 |
402 /* finally add the E-part, if needed; it will never be 0, and has */ | 401 /* finally add the E-part, if needed; it will never be 0, and has */ |
403 /* a maximum length of 3 digits */ | 402 /* a maximum length of 3 digits */ |
404 if (e!=0) { | 403 if (e!=0) { |
405 *c++='E';»» » /* starts with E */ | 404 *c++='E'; » » /* starts with E */ |
406 *c++='+';»» » /* assume positive */ | 405 *c++='+'; » » /* assume positive */ |
407 if (e<0) { | 406 if (e<0) { |
408 *(c-1)='-'; /* oops, need '-' */ | 407 *(c-1)='-'; /* oops, need '-' */ |
409 e=-e; /* uInt, please */ | 408 e=-e; /* uInt, please */ |
410 } | 409 } |
411 u=&BIN2CHAR[e*4];»» /* -> length byte */ | 410 u=&BIN2CHAR[e*4]; » /* -> length byte */ |
412 memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ | 411 memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ |
413 c+=*u; /* bump pointer appropriately */ | 412 c+=*u; /* bump pointer appropriately */ |
414 } | 413 } |
415 *c='\0'; /* add terminator */ | 414 *c='\0'; /* add terminator */ |
416 /*printf("res %s\n", string); */ | 415 /*printf("res %s\n", string); */ |
417 return string; | 416 return string; |
418 } /* pre>0 */ | 417 } /* pre>0 */ |
419 | 418 |
420 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ | 419 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ |
421 t=c+1-pre; | 420 t=c+1-pre; |
422 *(t+1)='\0'; /* can add terminator now */ | 421 *(t+1)='\0'; /* can add terminator now */ |
423 for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ | 422 for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ |
424 c=cstart; | 423 c=cstart; |
425 *c++='0'; /* always starts with 0. */ | 424 *c++='0'; /* always starts with 0. */ |
426 *c++='.'; | 425 *c++='.'; |
427 for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ | 426 for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ |
428 /*printf("res %s\n", string); */ | 427 /*printf("res %s\n", string); */ |
429 return string; | 428 return string; |
430 } /* decimal64ToString */ | 429 } /* decimal64ToString */ |
431 | 430 |
432 /* ------------------------------------------------------------------ */ | 431 /* ------------------------------------------------------------------ */ |
433 /* to-number -- conversion from numeric string */ | 432 /* to-number -- conversion from numeric string */ |
434 /* */ | 433 /* */ |
435 /* decimal64FromString(result, string, set); */ | 434 /* decimal64FromString(result, string, set); */ |
436 /* */ | 435 /* */ |
437 /* result is the decimal64 format number which gets the result of */ | 436 /* result is the decimal64 format number which gets the result of */ |
438 /* the conversion */ | 437 /* the conversion */ |
439 /* *string is the character string which should contain a valid */ | 438 /* *string is the character string which should contain a valid */ |
440 /* number (which may be a special value) */ | 439 /* number (which may be a special value) */ |
441 /* set» is the context» » » » » */ | 440 /* set is the context» » » » » */ |
442 /* */ | 441 /* */ |
443 /* The context is supplied to this routine is used for error handling */ | 442 /* The context is supplied to this routine is used for error handling */ |
444 /* (setting of status and traps) and for the rounding mode, only. */ | 443 /* (setting of status and traps) and for the rounding mode, only. */ |
445 /* If an error occurs, the result will be a valid decimal64 NaN. */ | 444 /* If an error occurs, the result will be a valid decimal64 NaN. */ |
446 /* ------------------------------------------------------------------ */ | 445 /* ------------------------------------------------------------------ */ |
447 decimal64 * decimal64FromString(decimal64 *result, const char *string, | 446 decimal64 * decimal64FromString(decimal64 *result, const char *string, |
448 decContext *set) { | 447 decContext *set) { |
449 decContext dc; /* work */ | 448 decContext dc; /* work */ |
450 decNumber dn;»» » » /* .. */ | 449 decNumber dn; » » » /* .. */ |
451 | 450 |
452 decContextDefault(&dc, DEC_INIT_DECIMAL64); /* no traps, please */ | 451 decContextDefault(&dc, DEC_INIT_DECIMAL64); /* no traps, please */ |
453 dc.round=set->round; /* use supplied rounding */ | 452 dc.round=set->round; /* use supplied rounding */ |
454 | 453 |
455 decNumberFromString(&dn, string, &dc); /* will round if needed */ | 454 decNumberFromString(&dn, string, &dc); /* will round if needed */ |
456 | 455 |
457 decimal64FromNumber(result, &dn, &dc); | 456 decimal64FromNumber(result, &dn, &dc); |
458 if (dc.status!=0) { /* something happened */ | 457 if (dc.status!=0) { /* something happened */ |
459 decContextSetStatus(set, dc.status); /* .. pass it on */ | 458 decContextSetStatus(set, dc.status); /* .. pass it on */ |
460 } | 459 } |
461 return result; | 460 return result; |
462 } /* decimal64FromString */ | 461 } /* decimal64FromString */ |
463 | 462 |
464 /* ------------------------------------------------------------------ */ | 463 /* ------------------------------------------------------------------ */ |
465 /* decimal64IsCanonical -- test whether encoding is canonical */ | 464 /* decimal64IsCanonical -- test whether encoding is canonical */ |
466 /* d64 is the source decimal64 */ | 465 /* d64 is the source decimal64 */ |
467 /* returns 1 if the encoding of d64 is canonical, 0 otherwise» */ | 466 /* returns 1 if the encoding of d64 is canonical, 0 otherwise */ |
468 /* No error is possible. */ | 467 /* No error is possible. */ |
469 /* ------------------------------------------------------------------ */ | 468 /* ------------------------------------------------------------------ */ |
470 uint32_t decimal64IsCanonical(const decimal64 *d64) { | 469 uInt decimal64IsCanonical(const decimal64 *d64) { |
471 decNumber dn;»» » » /* work */ | 470 decNumber dn; » » » /* work */ |
472 decimal64 canon; /* .. */ | 471 decimal64 canon; /* .. */ |
473 decContext dc; /* .. */ | 472 decContext dc; /* .. */ |
474 decContextDefault(&dc, DEC_INIT_DECIMAL64); | 473 decContextDefault(&dc, DEC_INIT_DECIMAL64); |
475 decimal64ToNumber(d64, &dn); | 474 decimal64ToNumber(d64, &dn); |
476 decimal64FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ | 475 decimal64FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ |
477 return memcmp(d64, &canon, DECIMAL64_Bytes)==0; | 476 return memcmp(d64, &canon, DECIMAL64_Bytes)==0; |
478 } /* decimal64IsCanonical */ | 477 } /* decimal64IsCanonical */ |
479 | 478 |
480 /* ------------------------------------------------------------------ */ | 479 /* ------------------------------------------------------------------ */ |
481 /* decimal64Canonical -- copy an encoding, ensuring it is canonical */ | 480 /* decimal64Canonical -- copy an encoding, ensuring it is canonical */ |
482 /* d64 is the source decimal64 */ | 481 /* d64 is the source decimal64 */ |
483 /* result is the target (may be the same decimal64) */ | 482 /* result is the target (may be the same decimal64) */ |
484 /* returns result */ | 483 /* returns result */ |
485 /* No error is possible. */ | 484 /* No error is possible. */ |
486 /* ------------------------------------------------------------------ */ | 485 /* ------------------------------------------------------------------ */ |
487 decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { | 486 decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { |
488 decNumber dn;»» » » /* work */ | 487 decNumber dn; » » » /* work */ |
489 decContext dc; /* .. */ | 488 decContext dc; /* .. */ |
490 decContextDefault(&dc, DEC_INIT_DECIMAL64); | 489 decContextDefault(&dc, DEC_INIT_DECIMAL64); |
491 decimal64ToNumber(d64, &dn); | 490 decimal64ToNumber(d64, &dn); |
492 decimal64FromNumber(result, &dn, &dc);/* result will now be canonical */ | 491 decimal64FromNumber(result, &dn, &dc);/* result will now be canonical */ |
493 return result; | 492 return result; |
494 } /* decimal64Canonical */ | 493 } /* decimal64Canonical */ |
495 | 494 |
496 #if DECTRACE || DECCHECK | 495 #if DECTRACE || DECCHECK |
497 /* Macros for accessing decimal64 fields. These assume the | 496 /* Macros for accessing decimal64 fields. These assume the |
498 argument is a reference (pointer) to the decimal64 structure, | 497 argument is a reference (pointer) to the decimal64 structure, |
499 and the decimal64 is in network byte order (big-endian) */ | 498 and the decimal64 is in network byte order (big-endian) */ |
500 /* Get sign */ | 499 /* Get sign */ |
501 #define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7) | 500 #define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7) |
502 | 501 |
503 /* Get combination field */ | 502 /* Get combination field */ |
504 #define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2) | 503 #define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2) |
505 | 504 |
506 /* Get exponent continuation [does not remove bias] */ | 505 /* Get exponent continuation [does not remove bias] */ |
507 #define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \ | 506 #define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \ |
508 | ((unsigned)(d)->bytes[1]>>2)) | 507 | ((unsigned)(d)->bytes[1]>>2)) |
509 | 508 |
510 /* Set sign [this assumes sign previously 0] */ | 509 /* Set sign [this assumes sign previously 0] */ |
511 #define decimal64SetSign(d, b) { \ | 510 #define decimal64SetSign(d, b) { \ |
512 (d)->bytes[0]|=((unsigned)(b)<<7);} | 511 (d)->bytes[0]|=((unsigned)(b)<<7);} |
513 | 512 |
514 /* Set exponent continuation [does not apply bias] */ | 513 /* Set exponent continuation [does not apply bias] */ |
515 /* This assumes range has been checked and exponent previously 0; */ | 514 /* This assumes range has been checked and exponent previously 0; */ |
516 /* type of exponent must be unsigned */ | 515 /* type of exponent must be unsigned */ |
517 #define decimal64SetExpCon(d, e) { \ | 516 #define decimal64SetExpCon(d, e) { \ |
518 (d)->bytes[0]|=(uint8_t)((e)>>6);» » » » \ | 517 (d)->bytes[0]|=(uByte)((e)>>6);» » » » \ |
519 (d)->bytes[1]|=(uint8_t)(((e)&0x3F)<<2);} | 518 (d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);} |
520 | 519 |
521 /* ------------------------------------------------------------------ */ | 520 /* ------------------------------------------------------------------ */ |
522 /* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ | 521 /* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ |
523 /* d64 -- the number to show */ | 522 /* d64 -- the number to show */ |
524 /* ------------------------------------------------------------------ */ | 523 /* ------------------------------------------------------------------ */ |
525 /* Also shows sign/cob/expconfields extracted */ | 524 /* Also shows sign/cob/expconfields extracted */ |
526 void decimal64Show(const decimal64 *d64) { | 525 void decimal64Show(const decimal64 *d64) { |
527 char buf[DECIMAL64_Bytes*2+1]; | 526 char buf[DECIMAL64_Bytes*2+1]; |
528 Int i, j=0; | 527 Int i, j=0; |
529 | 528 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 2, 2, 2, 2, 2, 2, 2, 2, | 578 2, 2, 2, 2, 2, 2, 2, 2, |
580 0, 0, 1, 1, 2, 2, 3, 3}; | 579 0, 0, 1, 1, 2, 2, 3, 3}; |
581 const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, | 580 const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, |
582 0, 1, 2, 3, 4, 5, 6, 7, | 581 0, 1, 2, 3, 4, 5, 6, 7, |
583 0, 1, 2, 3, 4, 5, 6, 7, | 582 0, 1, 2, 3, 4, 5, 6, 7, |
584 8, 9, 8, 9, 8, 9, 0, 1}; | 583 8, 9, 8, 9, 8, 9, 0, 1}; |
585 | 584 |
586 /* ------------------------------------------------------------------ */ | 585 /* ------------------------------------------------------------------ */ |
587 /* decDigitsToDPD -- pack coefficient into DPD form */ | 586 /* decDigitsToDPD -- pack coefficient into DPD form */ |
588 /* */ | 587 /* */ |
589 /* dn» is the source number (assumed valid, max DECMAX754 digits) */ | 588 /* dn is the source number (assumed valid, max DECMAX754 digits) */ |
590 /* targ is 1, 2, or 4-element uInt array, which the caller must */ | 589 /* targ is 1, 2, or 4-element uInt array, which the caller must */ |
591 /*» have cleared to zeros»» » » » */ | 590 /*» have cleared to zeros » » » » */ |
592 /* shift is the number of 0 digits to add on the right (normally 0) */ | 591 /* shift is the number of 0 digits to add on the right (normally 0) */ |
593 /* */ | 592 /* */ |
594 /* The coefficient must be known small enough to fit. The full» */ | 593 /* The coefficient must be known small enough to fit. The full */ |
595 /* coefficient is copied, including the leading 'odd' digit. This */ | 594 /* coefficient is copied, including the leading 'odd' digit. This */ |
596 /* digit is retrieved and packed into the combination field by the */ | 595 /* digit is retrieved and packed into the combination field by the */ |
597 /* caller. */ | 596 /* caller. */ |
598 /* */ | 597 /* */ |
599 /* The target uInts are altered only as necessary to receive the */ | 598 /* The target uInts are altered only as necessary to receive the */ |
600 /* digits of the decNumber. When more than one uInt is needed, they */ | 599 /* digits of the decNumber. When more than one uInt is needed, they */ |
601 /* are filled from left to right (that is, the uInt at offset 0 will */ | 600 /* are filled from left to right (that is, the uInt at offset 0 will */ |
602 /* end up with the least-significant digits). */ | 601 /* end up with the least-significant digits). */ |
603 /* */ | 602 /* */ |
604 /* shift is used for 'fold-down' padding. */ | 603 /* shift is used for 'fold-down' padding. */ |
605 /* */ | 604 /* */ |
606 /* No error is possible. */ | 605 /* No error is possible. */ |
607 /* ------------------------------------------------------------------ */ | 606 /* ------------------------------------------------------------------ */ |
608 #if DECDPUN<=4 | 607 #if DECDPUN<=4 |
609 /* Constant multipliers for divide-by-power-of five using reciprocal */ | 608 /* Constant multipliers for divide-by-power-of five using reciprocal */ |
610 /* multiply, after removing powers of 2 by shifting, and final shift */ | 609 /* multiply, after removing powers of 2 by shifting, and final shift */ |
611 /* of 17 [we only need up to **4] */ | 610 /* of 17 [we only need up to **4] */ |
612 static const uInt multies[]={131073, 26215, 5243, 1049, 210}; | 611 static const uInt multies[]={131073, 26215, 5243, 1049, 210}; |
613 /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */ | 612 /* QUOT10 -- macro to return the quotient of unit u divided by 10**n */ |
614 #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) | 613 #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) |
615 #endif | 614 #endif |
616 void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { | 615 void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { |
617 Int cut; /* work */ | 616 Int cut; /* work */ |
618 Int n; /* output bunch counter */ | 617 Int n; /* output bunch counter */ |
619 Int digits=dn->digits; /* digit countdown */ | 618 Int digits=dn->digits; /* digit countdown */ |
620 uInt dpd; /* densely packed decimal value */ | 619 uInt dpd; /* densely packed decimal value */ |
621 uInt bin; /* binary value 0-999 */ | 620 uInt bin; /* binary value 0-999 */ |
622 uInt *uout=targ; /* -> current output uInt */ | 621 uInt *uout=targ; /* -> current output uInt */ |
623 uInt» uoff=0;»» /* -> current output offset [from right] */ | 622 uInt» uoff=0; » /* -> current output offset [from right] */ |
624 const Unit *inu=dn->lsu; /* -> current input unit */ | 623 const Unit *inu=dn->lsu; /* -> current input unit */ |
625 Unit uar[DECMAXUNITS]; /* working copy of units, iff shifted */ | 624 Unit uar[DECMAXUNITS]; /* working copy of units, iff shifted */ |
626 #if DECDPUN!=3 /* not fast path */ | 625 #if DECDPUN!=3 /* not fast path */ |
627 Unit in; /* current unit */ | 626 Unit in; /* current unit */ |
628 #endif | 627 #endif |
629 | 628 |
630 if (shift!=0) { /* shift towards most significant required */ | 629 if (shift!=0) { /* shift towards most significant required */ |
631 /* shift the units array to the left by pad digits and copy */ | 630 /* shift the units array to the left by pad digits and copy */ |
632 /* [this code is a special case of decShiftToMost, which could */ | 631 /* [this code is a special case of decShiftToMost, which could */ |
633 /* be used instead if exposed and the array were copied first] */ | 632 /* be used instead if exposed and the array were copied first] */ |
634 const Unit *source;»» » /* .. */ | 633 const Unit *source; » » /* .. */ |
635 Unit *target, *first; /* .. */ | 634 Unit *target, *first; /* .. */ |
636 uInt next=0; /* work */ | 635 uInt next=0; /* work */ |
637 | 636 |
638 source=dn->lsu+D2U(digits)-1; /* where msu comes from */ | 637 source=dn->lsu+D2U(digits)-1; /* where msu comes from */ |
639 target=uar+D2U(digits)-1+D2U(shift);/* where upper part of first cut goes */ | 638 target=uar+D2U(digits)-1+D2U(shift);/* where upper part of first cut goes */ |
640 cut=DECDPUN-MSUDIGITS(shift); /* where to slice */ | 639 cut=DECDPUN-MSUDIGITS(shift); /* where to slice */ |
641 if (cut==0) { /* unit-boundary case */ | 640 if (cut==0) { /* unit-boundary case */ |
642 for (; source>=dn->lsu; source--, target--) *target=*source; | 641 for (; source>=dn->lsu; source--, target--) *target=*source; |
643 } | 642 } |
644 else { | 643 else { |
(...skipping 24 matching lines...) Expand all Loading... |
669 /* now densely pack the coefficient into DPD declets */ | 668 /* now densely pack the coefficient into DPD declets */ |
670 | 669 |
671 #if DECDPUN!=3 /* not fast path */ | 670 #if DECDPUN!=3 /* not fast path */ |
672 in=*inu; /* current unit */ | 671 in=*inu; /* current unit */ |
673 cut=0; /* at lowest digit */ | 672 cut=0; /* at lowest digit */ |
674 bin=0; /* [keep compiler quiet] */ | 673 bin=0; /* [keep compiler quiet] */ |
675 #endif | 674 #endif |
676 | 675 |
677 for(n=0; digits>0; n++) { /* each output bunch */ | 676 for(n=0; digits>0; n++) { /* each output bunch */ |
678 #if DECDPUN==3 /* fast path, 3-at-a-time */ | 677 #if DECDPUN==3 /* fast path, 3-at-a-time */ |
679 bin=*inu;»» » /* 3 digits ready for convert */ | 678 bin=*inu; » » /* 3 digits ready for convert */ |
680 digits-=3; /* [may go negative] */ | 679 digits-=3; /* [may go negative] */ |
681 inu++; /* may need another */ | 680 inu++; /* may need another */ |
682 | 681 |
683 #else /* must collect digit-by-digit */ | 682 #else /* must collect digit-by-digit */ |
684 Unit dig;»» » /* current digit */ | 683 Unit dig; » » /* current digit */ |
685 Int j; /* digit-in-declet count */ | 684 Int j; /* digit-in-declet count */ |
686 for (j=0; j<3; j++) { | 685 for (j=0; j<3; j++) { |
687 #if DECDPUN<=4 | 686 #if DECDPUN<=4 |
688 Unit temp=(Unit)((uInt)(in*6554)>>16); | 687 Unit temp=(Unit)((uInt)(in*6554)>>16); |
689 dig=(Unit)(in-X10(temp)); | 688 dig=(Unit)(in-X10(temp)); |
690 in=temp; | 689 in=temp; |
691 #else | 690 #else |
692 dig=in%10; | 691 dig=in%10; |
693 in=in/10; | 692 in=in/10; |
694 #endif | 693 #endif |
695 if (j==0) bin=dig; | 694 if (j==0) bin=dig; |
696 » else if (j==1)» bin+=X10(dig); | 695 » else if (j==1) bin+=X10(dig); |
697 else /* j==2 */ bin+=X100(dig); | 696 else /* j==2 */ bin+=X100(dig); |
698 digits--; | 697 digits--; |
699 if (digits==0) break; /* [also protects *inu below] */ | 698 if (digits==0) break; /* [also protects *inu below] */ |
700 cut++; | 699 cut++; |
701 if (cut==DECDPUN) {inu++; in=*inu; cut=0;} | 700 if (cut==DECDPUN) {inu++; in=*inu; cut=0;} |
702 } | 701 } |
703 #endif | 702 #endif |
704 /* here there are 3 digits in bin, or have used all input digits */ | 703 /* here there are 3 digits in bin, or have used all input digits */ |
705 | 704 |
706 dpd=BIN2DPD[bin]; | 705 dpd=BIN2DPD[bin]; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
738 /* */ | 737 /* */ |
739 /* dn->digits is set, but not the sign or exponent. */ | 738 /* dn->digits is set, but not the sign or exponent. */ |
740 /* No error is possible [the redundant 888 codes are allowed]. */ | 739 /* No error is possible [the redundant 888 codes are allowed]. */ |
741 /* ------------------------------------------------------------------ */ | 740 /* ------------------------------------------------------------------ */ |
742 void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { | 741 void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { |
743 | 742 |
744 uInt dpd; /* collector for 10 bits */ | 743 uInt dpd; /* collector for 10 bits */ |
745 Int n; /* counter */ | 744 Int n; /* counter */ |
746 Unit *uout=dn->lsu; /* -> current output unit */ | 745 Unit *uout=dn->lsu; /* -> current output unit */ |
747 Unit *last=uout; /* will be unit containing msd */ | 746 Unit *last=uout; /* will be unit containing msd */ |
748 const uInt *uin=sour;»» /* -> current input uInt */ | 747 const uInt *uin=sour; » /* -> current input uInt */ |
749 uInt» uoff=0;»» » /* -> current input offset [from right] */ | 748 uInt» uoff=0; » » /* -> current input offset [from right] */ |
750 | 749 |
751 #if DECDPUN!=3 | 750 #if DECDPUN!=3 |
752 uInt bcd; /* BCD result */ | 751 uInt bcd; /* BCD result */ |
753 uInt» nibble;»» » /* work */ | 752 uInt» nibble; » » /* work */ |
754 Unit out=0; /* accumulator */ | 753 Unit out=0; /* accumulator */ |
755 Int cut=0; /* power of ten in current unit */ | 754 Int cut=0; /* power of ten in current unit */ |
756 #endif | 755 #endif |
757 #if DECDPUN>4 | 756 #if DECDPUN>4 |
758 uInt const *pow; /* work */ | 757 uInt const *pow; /* work */ |
759 #endif | 758 #endif |
760 | 759 |
761 /* Expand the densely-packed integer, right to left */ | 760 /* Expand the densely-packed integer, right to left */ |
762 for (n=declets-1; n>=0; n--) { /* count down declets of 10 bits */ | 761 for (n=declets-1; n>=0; n--) { /* count down declets of 10 bits */ |
763 dpd=*uin>>uoff; | 762 dpd=*uin>>uoff; |
764 uoff+=10; | 763 uoff+=10; |
765 if (uoff>32) { /* crossed uInt boundary */ | 764 if (uoff>32) { /* crossed uInt boundary */ |
766 uin++; | 765 uin++; |
767 uoff-=32; | 766 uoff-=32; |
768 dpd|=*uin<<(10-uoff); /* get waiting bits */ | 767 dpd|=*uin<<(10-uoff); /* get waiting bits */ |
769 } | 768 } |
770 dpd&=0x3ff;»» » /* clear uninteresting bits */ | 769 dpd&=0x3ff; » » /* clear uninteresting bits */ |
771 | 770 |
772 #if DECDPUN==3 | 771 #if DECDPUN==3 |
773 if (dpd==0) *uout=0; | 772 if (dpd==0) *uout=0; |
774 else { | 773 else { |
775 *uout=DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */ | 774 *uout=DPD2BIN[dpd]; /* convert 10 bits to binary 0-999 */ |
776 last=uout; /* record most significant unit */ | 775 last=uout; /* record most significant unit */ |
777 } | 776 } |
778 uout++; | 777 uout++; |
779 } /* n */ | 778 } /* n */ |
780 | 779 |
(...skipping 29 matching lines...) Expand all Loading... |
810 if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); | 809 if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); |
811 cut++; | 810 cut++; |
812 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | 811 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} |
813 bcd>>=4; | 812 bcd>>=4; |
814 | 813 |
815 nibble=bcd & 0x00f; | 814 nibble=bcd & 0x00f; |
816 if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); | 815 if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); |
817 cut++; | 816 cut++; |
818 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} | 817 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} |
819 } /* n */ | 818 } /* n */ |
820 if (cut!=0) {»» » » /* some more left over */ | 819 if (cut!=0) { » » » /* some more left over */ |
821 *uout=out; /* write out final unit */ | 820 *uout=out; /* write out final unit */ |
822 if (out) last=uout;»» » /* and note if non-zero */ | 821 if (out) last=uout; » » /* and note if non-zero */ |
823 } | 822 } |
824 #endif | 823 #endif |
825 | 824 |
826 /* here, last points to the most significant unit with digits; */ | 825 /* here, last points to the most significant unit with digits; */ |
827 /* inspect it to get the final digits count -- this is essentially */ | 826 /* inspect it to get the final digits count -- this is essentially */ |
828 /* the same code as decGetDigits in decNumber.c */ | 827 /* the same code as decGetDigits in decNumber.c */ |
829 dn->digits=(last-dn->lsu)*DECDPUN+1; /* floor of digits, plus */ | 828 dn->digits=(last-dn->lsu)*DECDPUN+1; /* floor of digits, plus */ |
830 /* must be at least 1 digit */ | 829 /* must be at least 1 digit */ |
831 #if DECDPUN>1 | 830 #if DECDPUN>1 |
832 if (*last<10) return;»» » /* common odd digit or 0 */ | 831 if (*last<10) return; » » /* common odd digit or 0 */ |
833 dn->digits++;»» » » /* must be 2 at least */ | 832 dn->digits++; » » » /* must be 2 at least */ |
834 #if DECDPUN>2 | 833 #if DECDPUN>2 |
835 if (*last<100) return; /* 10-99 */ | 834 if (*last<100) return; /* 10-99 */ |
836 dn->digits++;»» » » /* must be 3 at least */ | 835 dn->digits++; » » » /* must be 3 at least */ |
837 #if DECDPUN>3 | 836 #if DECDPUN>3 |
838 if (*last<1000) return; /* 100-999 */ | 837 if (*last<1000) return; /* 100-999 */ |
839 dn->digits++;»» » » /* must be 4 at least */ | 838 dn->digits++; » » » /* must be 4 at least */ |
840 #if DECDPUN>4 | 839 #if DECDPUN>4 |
841 for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++; | 840 for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++; |
842 #endif | 841 #endif |
843 #endif | 842 #endif |
844 #endif | 843 #endif |
845 #endif | 844 #endif |
846 return; | 845 return; |
847 } /*decDigitsFromDPD */ | 846 } /*decDigitsFromDPD */ |
OLD | NEW |