OLD | NEW |
1 /* Decimal 32-bit format module for the decNumber C Library. | 1 /* Decimal 32-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 32-bit format module»» » » » */ | 27 /* Decimal 32-bit format module » » » » */ |
28 /* ------------------------------------------------------------------ */ | 28 /* ------------------------------------------------------------------ */ |
29 /* This module comprises the routines for decimal32 format numbers. */ | 29 /* This module comprises the routines for decimal32 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 7 /* make decNumbers with space for 7 */ | 41 #define DECNUMDIGITS 7 /* make decNumbers with space for 7 */ |
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 "decimal32.h" /* our primary include */ | 44 #include "decimal32.h" /* our primary include */ |
45 | 45 |
46 /* Utility tables and routines [in decimal64.c] */ | 46 /* Utility tables and routines [in decimal64.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 |
52 extern void decDigitsToDPD(const decNumber *, uInt *, Int); | 52 extern void decDigitsToDPD(const decNumber *, uInt *, Int); |
53 extern void decDigitsFromDPD(decNumber *, const uInt *, Int); | 53 extern void decDigitsFromDPD(decNumber *, const uInt *, Int); |
54 | 54 |
55 #if DECTRACE || DECCHECK | 55 #if DECTRACE || DECCHECK |
56 void decimal32Show(const decimal32 *); /* for debug */ | 56 void decimal32Show(const decimal32 *); /* for debug */ |
57 extern void decNumberShow(const decNumber *); /* .. */ | 57 extern void decNumberShow(const decNumber *); /* .. */ |
58 #endif | 58 #endif |
59 | 59 |
60 /* Useful macro */ | 60 /* Useful macro */ |
61 /* Clear a structure (e.g., a decNumber) */ | 61 /* Clear a structure (e.g., a decNumber) */ |
62 #define DEC_clear(d) memset(d, 0, sizeof(*d)) | 62 #define DEC_clear(d) memset(d, 0, sizeof(*d)) |
63 | 63 |
64 /* ------------------------------------------------------------------ */ | 64 /* ------------------------------------------------------------------ */ |
65 /* decimal32FromNumber -- convert decNumber to decimal32 */ | 65 /* decimal32FromNumber -- convert decNumber to decimal32 */ |
66 /* */ | 66 /* */ |
67 /* ds is the target decimal32»» » » » */ | 67 /* ds is the target decimal32 » » » » */ |
68 /* dn is the source number (assumed valid) */ | 68 /* dn is the source number (assumed valid) */ |
69 /* set is the context, used only for reporting errors»» */ | 69 /* set is the context, used only for reporting errors » */ |
70 /* */ | 70 /* */ |
71 /* The set argument is used only for status reporting and for the */ | 71 /* The set argument is used only for status reporting and for the */ |
72 /* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */ | 72 /* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */ |
73 /* digits or an overflow is detected). If the exponent is out of the */ | 73 /* digits or an overflow is detected). If the exponent is out of the */ |
74 /* valid range then Overflow or Underflow will be raised. */ | 74 /* valid range then Overflow or Underflow will be raised. */ |
75 /* After Underflow a subnormal result is possible. */ | 75 /* After Underflow a subnormal result is possible. */ |
76 /* */ | 76 /* */ |
77 /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ | 77 /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ |
78 /* by reducing its exponent and multiplying the coefficient by a */ | 78 /* by reducing its exponent and multiplying the coefficient by a */ |
79 /* power of ten, or if the exponent on a zero had to be clamped. */ | 79 /* power of ten, or if the exponent on a zero had to be clamped. */ |
80 /* ------------------------------------------------------------------ */ | 80 /* ------------------------------------------------------------------ */ |
81 decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, | 81 decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn, |
82 decContext *set) { | 82 decContext *set) { |
83 uInt status=0; /* status accumulator */ | 83 uInt status=0; /* status accumulator */ |
84 Int ae; /* adjusted exponent */ | 84 Int ae; /* adjusted exponent */ |
85 decNumber dw; /* work */ | 85 decNumber dw; /* work */ |
86 decContext dc; /* .. */ | 86 decContext dc; /* .. */ |
87 uInt *pu; /* .. */ | |
88 uInt comb, exp; /* .. */ | 87 uInt comb, exp; /* .. */ |
| 88 uInt uiwork; /* for macros */ |
89 uInt targ=0; /* target 32-bit */ | 89 uInt targ=0; /* target 32-bit */ |
90 | 90 |
91 /* If the number has too many digits, or the exponent could be */ | 91 /* If the number has too many digits, or the exponent could be */ |
92 /* out of range then reduce the number under the appropriate */ | 92 /* out of range then reduce the number under the appropriate */ |
93 /* constraints. This could push the number to Infinity or zero, */ | 93 /* constraints. This could push the number to Infinity or zero, */ |
94 /* so this check and rounding must be done before generating the */ | 94 /* so this check and rounding must be done before generating the */ |
95 /* decimal32] */ | 95 /* decimal32] */ |
96 ae=dn->exponent+dn->digits-1;»» /* [0 if special] */ | 96 ae=dn->exponent+dn->digits-1; » /* [0 if special] */ |
97 if (dn->digits>DECIMAL32_Pmax»» /* too many digits */ | 97 if (dn->digits>DECIMAL32_Pmax » /* too many digits */ |
98 || ae>DECIMAL32_Emax»» » /* likely overflow */ | 98 || ae>DECIMAL32_Emax » » /* likely overflow */ |
99 || ae<DECIMAL32_Emin) { /* likely underflow */ | 99 || ae<DECIMAL32_Emin) { /* likely underflow */ |
100 decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */ | 100 decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */ |
101 dc.round=set->round; /* use supplied rounding */ | 101 dc.round=set->round; /* use supplied rounding */ |
102 decNumberPlus(&dw, dn, &dc); /* (round and check) */ | 102 decNumberPlus(&dw, dn, &dc); /* (round and check) */ |
103 /* [this changes -0 to 0, so enforce the sign...] */ | 103 /* [this changes -0 to 0, so enforce the sign...] */ |
104 dw.bits|=dn->bits&DECNEG; | 104 dw.bits|=dn->bits&DECNEG; |
105 status=dc.status; /* save status */ | 105 status=dc.status; /* save status */ |
106 dn=&dw; /* use the work number */ | 106 dn=&dw; /* use the work number */ |
107 } /* maybe out of range */ | 107 } /* maybe out of range */ |
108 | 108 |
109 if (dn->bits&DECSPECIAL) { /* a special value */ | 109 if (dn->bits&DECSPECIAL) { /* a special value */ |
110 if (dn->bits&DECINF) targ=DECIMAL_Inf<<24; | 110 if (dn->bits&DECINF) targ=DECIMAL_Inf<<24; |
111 else { /* sNaN or qNaN */ | 111 else { /* sNaN or qNaN */ |
112 if ((*dn->lsu!=0 || dn->digits>1)»» /* non-zero coefficient */ | 112 if ((*dn->lsu!=0 || dn->digits>1) » /* non-zero coefficient */ |
113 && (dn->digits<DECIMAL32_Pmax)) { /* coefficient fits */ | 113 && (dn->digits<DECIMAL32_Pmax)) { /* coefficient fits */ |
114 decDigitsToDPD(dn, &targ, 0); | 114 decDigitsToDPD(dn, &targ, 0); |
115 } | 115 } |
116 if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24; | 116 if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24; |
117 else targ|=DECIMAL_sNaN<<24; | 117 else targ|=DECIMAL_sNaN<<24; |
118 } /* a NaN */ | 118 } /* a NaN */ |
119 } /* special */ | 119 } /* special */ |
120 | 120 |
121 else { /* is finite */ | 121 else { /* is finite */ |
122 if (decNumberIsZero(dn)) { /* is a zero */ | 122 if (decNumberIsZero(dn)) { /* is a zero */ |
123 /* set and clamp exponent */ | 123 /* set and clamp exponent */ |
124 if (dn->exponent<-DECIMAL32_Bias) { | 124 if (dn->exponent<-DECIMAL32_Bias) { |
125 exp=0; /* low clamp */ | 125 exp=0; /* low clamp */ |
126 status|=DEC_Clamped; | 126 status|=DEC_Clamped; |
127 } | 127 } |
128 else { | 128 else { |
129 exp=dn->exponent+DECIMAL32_Bias; /* bias exponent */ | 129 exp=dn->exponent+DECIMAL32_Bias; /* bias exponent */ |
130 if (exp>DECIMAL32_Ehigh) { /* top clamp */ | 130 if (exp>DECIMAL32_Ehigh) { /* top clamp */ |
131 exp=DECIMAL32_Ehigh; | 131 exp=DECIMAL32_Ehigh; |
132 status|=DEC_Clamped; | 132 status|=DEC_Clamped; |
133 } | 133 } |
134 } | 134 } |
135 comb=(exp>>3) & 0x18; /* msd=0, exp top 2 bits .. */ | 135 comb=(exp>>3) & 0x18; /* msd=0, exp top 2 bits .. */ |
136 } | 136 } |
137 else { /* non-zero finite number */ | 137 else { /* non-zero finite number */ |
138 uInt msd;»» » » /* work */ | 138 uInt msd; » » » /* work */ |
139 Int pad=0; /* coefficient pad digits */ | 139 Int pad=0; /* coefficient pad digits */ |
140 | 140 |
141 /* the dn is known to fit, but it may need to be padded */ | 141 /* the dn is known to fit, but it may need to be padded */ |
142 exp=(uInt)(dn->exponent+DECIMAL32_Bias); /* bias exponent */ | 142 exp=(uInt)(dn->exponent+DECIMAL32_Bias); /* bias exponent */ |
143 if (exp>DECIMAL32_Ehigh) { /* fold-down case */ | 143 if (exp>DECIMAL32_Ehigh) { /* fold-down case */ |
144 pad=exp-DECIMAL32_Ehigh; | 144 pad=exp-DECIMAL32_Ehigh; |
145 exp=DECIMAL32_Ehigh; /* [to maximum] */ | 145 exp=DECIMAL32_Ehigh; /* [to maximum] */ |
146 status|=DEC_Clamped; | 146 status|=DEC_Clamped; |
147 } | 147 } |
148 | 148 |
(...skipping 14 matching lines...) Expand all Loading... |
163 if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01); | 163 if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01); |
164 else comb=((exp>>3) & 0x18) | msd; | 164 else comb=((exp>>3) & 0x18) | msd; |
165 } | 165 } |
166 targ|=comb<<26; /* add combination field .. */ | 166 targ|=comb<<26; /* add combination field .. */ |
167 targ|=(exp&0x3f)<<20; /* .. and exponent continuation */ | 167 targ|=(exp&0x3f)<<20; /* .. and exponent continuation */ |
168 } /* finite */ | 168 } /* finite */ |
169 | 169 |
170 if (dn->bits&DECNEG) targ|=0x80000000; /* add sign bit */ | 170 if (dn->bits&DECNEG) targ|=0x80000000; /* add sign bit */ |
171 | 171 |
172 /* now write to storage; this is endian */ | 172 /* now write to storage; this is endian */ |
173 pu=(uInt *)d32->bytes;» /* overlay */ | 173 UBFROMUI(d32->bytes, targ);» /* directly store the int */ |
174 *pu=targ;» » » /* directly store the int */ | |
175 | 174 |
176 if (status!=0) decContextSetStatus(set, status); /* pass on status */ | 175 if (status!=0) decContextSetStatus(set, status); /* pass on status */ |
177 /* decimal32Show(d32); */ | 176 /* decimal32Show(d32); */ |
178 return d32; | 177 return d32; |
179 } /* decimal32FromNumber */ | 178 } /* decimal32FromNumber */ |
180 | 179 |
181 /* ------------------------------------------------------------------ */ | 180 /* ------------------------------------------------------------------ */ |
182 /* decimal32ToNumber -- convert decimal32 to decNumber */ | 181 /* decimal32ToNumber -- convert decimal32 to decNumber */ |
183 /* d32 is the source decimal32 */ | 182 /* d32 is the source decimal32 */ |
184 /* dn is the target number, with appropriate space */ | 183 /* dn is the target number, with appropriate space */ |
185 /* No error is possible. */ | 184 /* No error is possible. */ |
186 /* ------------------------------------------------------------------ */ | 185 /* ------------------------------------------------------------------ */ |
187 decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { | 186 decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) { |
188 uInt msd; /* coefficient MSD */ | 187 uInt msd; /* coefficient MSD */ |
189 uInt exp; /* exponent top two bits */ | 188 uInt exp; /* exponent top two bits */ |
190 uInt comb; /* combination field */ | 189 uInt comb; /* combination field */ |
191 uInt sour; /* source 32-bit */ | 190 uInt sour; /* source 32-bit */ |
192 const uInt *pu;» » /* work */ | 191 uInt uiwork;» » » /* for macros */ |
193 | 192 |
194 /* load source from storage; this is endian */ | 193 /* load source from storage; this is endian */ |
195 pu=(const uInt *)d32->bytes;» /* overlay */ | 194 sour=UBTOUI(d32->bytes);» /* directly load the int */ |
196 sour=*pu;» » » /* directly load the int */ | |
197 | 195 |
198 comb=(sour>>26)&0x1f;»» /* combination field */ | 196 comb=(sour>>26)&0x1f; » /* combination field */ |
199 | 197 |
200 decNumberZero(dn); /* clean number */ | 198 decNumberZero(dn); /* clean number */ |
201 if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */ | 199 if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */ |
202 | 200 |
203 msd=COMBMSD[comb]; /* decode the combination field */ | 201 msd=COMBMSD[comb]; /* decode the combination field */ |
204 exp=COMBEXP[comb]; /* .. */ | 202 exp=COMBEXP[comb]; /* .. */ |
205 | 203 |
206 if (exp==3) {»» » /* is a special */ | 204 if (exp==3) { » » /* is a special */ |
207 if (msd==0) { | 205 if (msd==0) { |
208 dn->bits|=DECINF; | 206 dn->bits|=DECINF; |
209 return dn; /* no coefficient needed */ | 207 return dn; /* no coefficient needed */ |
210 } | 208 } |
211 else if (sour&0x02000000) dn->bits|=DECSNAN; | 209 else if (sour&0x02000000) dn->bits|=DECSNAN; |
212 else dn->bits|=DECNAN; | 210 else dn->bits|=DECNAN; |
213 msd=0; /* no top digit */ | 211 msd=0; /* no top digit */ |
214 } | 212 } |
215 else { /* is a finite number */ | 213 else { /* is a finite number */ |
216 dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */ | 214 dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */ |
217 } | 215 } |
218 | 216 |
219 /* get the coefficient */ | 217 /* get the coefficient */ |
220 sour&=0x000fffff; /* clean coefficient continuation */ | 218 sour&=0x000fffff; /* clean coefficient continuation */ |
221 if (msd) { /* non-zero msd */ | 219 if (msd) { /* non-zero msd */ |
222 sour|=msd<<20; /* prefix to coefficient */ | 220 sour|=msd<<20; /* prefix to coefficient */ |
223 decDigitsFromDPD(dn, &sour, 3); /* process 3 declets */ | 221 decDigitsFromDPD(dn, &sour, 3); /* process 3 declets */ |
224 return dn; | 222 return dn; |
225 } | 223 } |
226 /* msd=0 */ | 224 /* msd=0 */ |
227 if (!sour) return dn;»» /* easy: coefficient is 0 */ | 225 if (!sour) return dn; » /* easy: coefficient is 0 */ |
228 if (sour&0x000ffc00) /* need 2 declets? */ | 226 if (sour&0x000ffc00) /* need 2 declets? */ |
229 decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */ | 227 decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */ |
230 else | 228 else |
231 decDigitsFromDPD(dn, &sour, 1); /* process 1 declet */ | 229 decDigitsFromDPD(dn, &sour, 1); /* process 1 declet */ |
232 return dn; | 230 return dn; |
233 } /* decimal32ToNumber */ | 231 } /* decimal32ToNumber */ |
234 | 232 |
235 /* ------------------------------------------------------------------ */ | 233 /* ------------------------------------------------------------------ */ |
236 /* to-scientific-string -- conversion to numeric string»» */ | 234 /* to-scientific-string -- conversion to numeric string » */ |
237 /* to-engineering-string -- conversion to numeric string */ | 235 /* to-engineering-string -- conversion to numeric string */ |
238 /* */ | 236 /* */ |
239 /* decimal32ToString(d32, string); */ | 237 /* decimal32ToString(d32, string); */ |
240 /* decimal32ToEngString(d32, string);»» » » */ | 238 /* decimal32ToEngString(d32, string); » » » */ |
241 /* */ | 239 /* */ |
242 /* d32 is the decimal32 format number to convert */ | 240 /* d32 is the decimal32 format number to convert */ |
243 /* string is the string where the result will be laid out */ | 241 /* string is the string where the result will be laid out */ |
244 /* */ | 242 /* */ |
245 /* string must be at least 24 characters */ | 243 /* string must be at least 24 characters */ |
246 /* */ | 244 /* */ |
247 /* No error is possible, and no status can be set. */ | 245 /* No error is possible, and no status can be set. */ |
248 /* ------------------------------------------------------------------ */ | 246 /* ------------------------------------------------------------------ */ |
249 char * decimal32ToEngString(const decimal32 *d32, char *string){ | 247 char * decimal32ToEngString(const decimal32 *d32, char *string){ |
250 decNumber dn;»» » » /* work */ | 248 decNumber dn; » » » /* work */ |
251 decimal32ToNumber(d32, &dn); | 249 decimal32ToNumber(d32, &dn); |
252 decNumberToEngString(&dn, string); | 250 decNumberToEngString(&dn, string); |
253 return string; | 251 return string; |
254 } /* decimal32ToEngString */ | 252 } /* decimal32ToEngString */ |
255 | 253 |
256 char * decimal32ToString(const decimal32 *d32, char *string){ | 254 char * decimal32ToString(const decimal32 *d32, char *string){ |
257 uInt msd; /* coefficient MSD */ | 255 uInt msd; /* coefficient MSD */ |
258 Int exp; /* exponent top two bits or full */ | 256 Int exp; /* exponent top two bits or full */ |
259 uInt comb; /* combination field */ | 257 uInt comb; /* combination field */ |
260 char *cstart;»» » /* coefficient start */ | 258 char *cstart; » » /* coefficient start */ |
261 char *c; /* output pointer in string */ | 259 char *c; /* output pointer in string */ |
262 const uInt *pu;» » /* work */ | 260 const uByte *u;» » /* work */ |
263 const uByte *u;» » /* .. */ | |
264 char *s, *t; /* .. (source, target) */ | 261 char *s, *t; /* .. (source, target) */ |
265 Int dpd; /* .. */ | 262 Int dpd; /* .. */ |
266 Int pre, e; /* .. */ | 263 Int pre, e; /* .. */ |
| 264 uInt uiwork; /* for macros */ |
267 uInt sour; /* source 32-bit */ | 265 uInt sour; /* source 32-bit */ |
268 | 266 |
269 /* load source from storage; this is endian */ | 267 /* load source from storage; this is endian */ |
270 pu=(const uInt *)d32->bytes;» /* overlay */ | 268 sour=UBTOUI(d32->bytes);» /* directly load the int */ |
271 sour=*pu;» » » /* directly load the int */ | |
272 | 269 |
273 c=string; /* where result will go */ | 270 c=string; /* where result will go */ |
274 if (((Int)sour)<0) *c++='-'; /* handle sign */ | 271 if (((Int)sour)<0) *c++='-'; /* handle sign */ |
275 | 272 |
276 comb=(sour>>26)&0x1f;»» /* combination field */ | 273 comb=(sour>>26)&0x1f; » /* combination field */ |
277 msd=COMBMSD[comb]; /* decode the combination field */ | 274 msd=COMBMSD[comb]; /* decode the combination field */ |
278 exp=COMBEXP[comb]; /* .. */ | 275 exp=COMBEXP[comb]; /* .. */ |
279 | 276 |
280 if (exp==3) { | 277 if (exp==3) { |
281 if (msd==0) { /* infinity */ | 278 if (msd==0) { /* infinity */ |
282 strcpy(c,» "Inf"); | 279 strcpy(c, "Inf"); |
283 strcpy(c+3, "inity"); | 280 strcpy(c+3, "inity"); |
284 return string; /* easy */ | 281 return string; /* easy */ |
285 } | 282 } |
286 if (sour&0x02000000) *c++='s'; /* sNaN */ | 283 if (sour&0x02000000) *c++='s'; /* sNaN */ |
287 strcpy(c, "NaN"); /* complete word */ | 284 strcpy(c, "NaN"); /* complete word */ |
288 c+=3; /* step past */ | 285 c+=3; /* step past */ |
289 if ((sour&0x000fffff)==0) return string; /* zero payload */ | 286 if ((sour&0x000fffff)==0) return string; /* zero payload */ |
290 /* otherwise drop through to add integer; set correct exp */ | 287 /* otherwise drop through to add integer; set correct exp */ |
291 exp=0; msd=0; /* setup for following code */ | 288 exp=0; msd=0; /* setup for following code */ |
292 } | 289 } |
293 else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */ | 290 else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */ |
294 | 291 |
295 /* convert 7 digits of significand to characters */ | 292 /* convert 7 digits of significand to characters */ |
296 cstart=c; /* save start of coefficient */ | 293 cstart=c; /* save start of coefficient */ |
297 if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ | 294 if (msd) *c++='0'+(char)msd; /* non-zero most significant digit */ |
298 | 295 |
299 /* Now decode the declets. After extracting each one, it is */ | 296 /* Now decode the declets. After extracting each one, it is */ |
300 /* decoded to binary and then to a 4-char sequence by table lookup; */ | 297 /* decoded to binary and then to a 4-char sequence by table lookup; */ |
301 /* the 4-chars are a 1-char length (significant digits, except 000 */ | 298 /* the 4-chars are a 1-char length (significant digits, except 000 */ |
302 /* has length 0). This allows us to left-align the first declet */ | 299 /* has length 0). This allows us to left-align the first declet */ |
303 /* with non-zero content, then remaining ones are full 3-char */ | 300 /* with non-zero content, then remaining ones are full 3-char */ |
304 /* length. We use fixed-length memcpys because variable-length */ | 301 /* length. We use fixed-length memcpys because variable-length */ |
305 /* causes a subroutine call in GCC. (These are length 4 for speed */ | 302 /* causes a subroutine call in GCC. (These are length 4 for speed */ |
306 /* and are safe because the array has an extra terminator byte.) */ | 303 /* and are safe because the array has an extra terminator byte.) */ |
307 #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];»» » \ | 304 #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; » » \ |
308 if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ | 305 if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ |
309 else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} | 306 else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} |
310 | 307 |
311 dpd=(sour>>10)&0x3ff;»» /* declet 1 */ | 308 dpd=(sour>>10)&0x3ff; » /* declet 1 */ |
312 dpd2char; | 309 dpd2char; |
313 dpd=(sour)&0x3ff; /* declet 2 */ | 310 dpd=(sour)&0x3ff; /* declet 2 */ |
314 dpd2char; | 311 dpd2char; |
315 | 312 |
316 if (c==cstart) *c++='0'; /* all zeros -- make 0 */ | 313 if (c==cstart) *c++='0'; /* all zeros -- make 0 */ |
317 | 314 |
318 if (exp==0) {»» » /* integer or NaN case -- easy */ | 315 if (exp==0) { » » /* integer or NaN case -- easy */ |
319 *c='\0'; /* terminate */ | 316 *c='\0'; /* terminate */ |
320 return string; | 317 return string; |
321 } | 318 } |
322 | 319 |
323 /* non-0 exponent */ | 320 /* non-0 exponent */ |
324 e=0; /* assume no E */ | 321 e=0; /* assume no E */ |
325 pre=c-cstart+exp; | 322 pre=c-cstart+exp; |
326 /* [here, pre-exp is the digits count (==1 for zero)] */ | 323 /* [here, pre-exp is the digits count (==1 for zero)] */ |
327 if (exp>0 || pre<-5) { /* need exponential form */ | 324 if (exp>0 || pre<-5) { /* need exponential form */ |
328 e=pre-1; /* calculate E value */ | 325 e=pre-1; /* calculate E value */ |
329 pre=1; /* assume one digit before '.' */ | 326 pre=1; /* assume one digit before '.' */ |
330 } /* exponential form */ | 327 } /* exponential form */ |
331 | 328 |
332 /* modify the coefficient, adding 0s, '.', and E+nn as needed */ | 329 /* modify the coefficient, adding 0s, '.', and E+nn as needed */ |
333 s=c-1; /* source (LSD) */ | 330 s=c-1; /* source (LSD) */ |
334 if (pre>0) { /* ddd.ddd (plain), perhaps with E */ | 331 if (pre>0) { /* ddd.ddd (plain), perhaps with E */ |
335 char *dotat=cstart+pre; | 332 char *dotat=cstart+pre; |
336 if (dotat<c) { /* if embedded dot needed... */ | 333 if (dotat<c) { /* if embedded dot needed... */ |
337 t=c; /* target */ | 334 t=c; /* target */ |
338 for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ | 335 for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */ |
339 *t='.'; /* insert the dot */ | 336 *t='.'; /* insert the dot */ |
340 c++; /* length increased by one */ | 337 c++; /* length increased by one */ |
341 } | 338 } |
342 | 339 |
343 /* finally add the E-part, if needed; it will never be 0, and has */ | 340 /* finally add the E-part, if needed; it will never be 0, and has */ |
344 /* a maximum length of 3 digits (E-101 case) */ | 341 /* a maximum length of 3 digits (E-101 case) */ |
345 if (e!=0) { | 342 if (e!=0) { |
346 *c++='E';»» » /* starts with E */ | 343 *c++='E'; » » /* starts with E */ |
347 *c++='+';»» » /* assume positive */ | 344 *c++='+'; » » /* assume positive */ |
348 if (e<0) { | 345 if (e<0) { |
349 *(c-1)='-'; /* oops, need '-' */ | 346 *(c-1)='-'; /* oops, need '-' */ |
350 e=-e; /* uInt, please */ | 347 e=-e; /* uInt, please */ |
351 } | 348 } |
352 u=&BIN2CHAR[e*4];»» /* -> length byte */ | 349 u=&BIN2CHAR[e*4]; » /* -> length byte */ |
353 memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ | 350 memcpy(c, u+4-*u, 4); /* copy fixed 4 characters [is safe] */ |
354 c+=*u; /* bump pointer appropriately */ | 351 c+=*u; /* bump pointer appropriately */ |
355 } | 352 } |
356 *c='\0'; /* add terminator */ | 353 *c='\0'; /* add terminator */ |
357 /*printf("res %s\n", string); */ | 354 /*printf("res %s\n", string); */ |
358 return string; | 355 return string; |
359 } /* pre>0 */ | 356 } /* pre>0 */ |
360 | 357 |
361 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ | 358 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ |
362 t=c+1-pre; | 359 t=c+1-pre; |
363 *(t+1)='\0'; /* can add terminator now */ | 360 *(t+1)='\0'; /* can add terminator now */ |
364 for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ | 361 for (; s>=cstart; s--, t--) *t=*s; /* shift whole coefficient right */ |
365 c=cstart; | 362 c=cstart; |
366 *c++='0'; /* always starts with 0. */ | 363 *c++='0'; /* always starts with 0. */ |
367 *c++='.'; | 364 *c++='.'; |
368 for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ | 365 for (; pre<0; pre++) *c++='0'; /* add any 0's after '.' */ |
369 /*printf("res %s\n", string); */ | 366 /*printf("res %s\n", string); */ |
370 return string; | 367 return string; |
371 } /* decimal32ToString */ | 368 } /* decimal32ToString */ |
372 | 369 |
373 /* ------------------------------------------------------------------ */ | 370 /* ------------------------------------------------------------------ */ |
374 /* to-number -- conversion from numeric string */ | 371 /* to-number -- conversion from numeric string */ |
375 /* */ | 372 /* */ |
376 /* decimal32FromString(result, string, set); */ | 373 /* decimal32FromString(result, string, set); */ |
377 /* */ | 374 /* */ |
378 /* result is the decimal32 format number which gets the result of */ | 375 /* result is the decimal32 format number which gets the result of */ |
379 /* the conversion */ | 376 /* the conversion */ |
380 /* *string is the character string which should contain a valid */ | 377 /* *string is the character string which should contain a valid */ |
381 /* number (which may be a special value) */ | 378 /* number (which may be a special value) */ |
382 /* set» is the context» » » » » */ | 379 /* set is the context» » » » » */ |
383 /* */ | 380 /* */ |
384 /* The context is supplied to this routine is used for error handling */ | 381 /* The context is supplied to this routine is used for error handling */ |
385 /* (setting of status and traps) and for the rounding mode, only. */ | 382 /* (setting of status and traps) and for the rounding mode, only. */ |
386 /* If an error occurs, the result will be a valid decimal32 NaN. */ | 383 /* If an error occurs, the result will be a valid decimal32 NaN. */ |
387 /* ------------------------------------------------------------------ */ | 384 /* ------------------------------------------------------------------ */ |
388 decimal32 * decimal32FromString(decimal32 *result, const char *string, | 385 decimal32 * decimal32FromString(decimal32 *result, const char *string, |
389 decContext *set) { | 386 decContext *set) { |
390 decContext dc; /* work */ | 387 decContext dc; /* work */ |
391 decNumber dn;»» » » /* .. */ | 388 decNumber dn; » » » /* .. */ |
392 | 389 |
393 decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */ | 390 decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */ |
394 dc.round=set->round; /* use supplied rounding */ | 391 dc.round=set->round; /* use supplied rounding */ |
395 | 392 |
396 decNumberFromString(&dn, string, &dc); /* will round if needed */ | 393 decNumberFromString(&dn, string, &dc); /* will round if needed */ |
397 decimal32FromNumber(result, &dn, &dc); | 394 decimal32FromNumber(result, &dn, &dc); |
398 if (dc.status!=0) { /* something happened */ | 395 if (dc.status!=0) { /* something happened */ |
399 decContextSetStatus(set, dc.status); /* .. pass it on */ | 396 decContextSetStatus(set, dc.status); /* .. pass it on */ |
400 } | 397 } |
401 return result; | 398 return result; |
402 } /* decimal32FromString */ | 399 } /* decimal32FromString */ |
403 | 400 |
404 /* ------------------------------------------------------------------ */ | 401 /* ------------------------------------------------------------------ */ |
405 /* decimal32IsCanonical -- test whether encoding is canonical */ | 402 /* decimal32IsCanonical -- test whether encoding is canonical */ |
406 /* d32 is the source decimal32 */ | 403 /* d32 is the source decimal32 */ |
407 /* returns 1 if the encoding of d32 is canonical, 0 otherwise» */ | 404 /* returns 1 if the encoding of d32 is canonical, 0 otherwise */ |
408 /* No error is possible. */ | 405 /* No error is possible. */ |
409 /* ------------------------------------------------------------------ */ | 406 /* ------------------------------------------------------------------ */ |
410 uint32_t decimal32IsCanonical(const decimal32 *d32) { | 407 uInt decimal32IsCanonical(const decimal32 *d32) { |
411 decNumber dn;»» » » /* work */ | 408 decNumber dn; » » » /* work */ |
412 decimal32 canon; /* .. */ | 409 decimal32 canon; /* .. */ |
413 decContext dc; /* .. */ | 410 decContext dc; /* .. */ |
414 decContextDefault(&dc, DEC_INIT_DECIMAL32); | 411 decContextDefault(&dc, DEC_INIT_DECIMAL32); |
415 decimal32ToNumber(d32, &dn); | 412 decimal32ToNumber(d32, &dn); |
416 decimal32FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ | 413 decimal32FromNumber(&canon, &dn, &dc);/* canon will now be canonical */ |
417 return memcmp(d32, &canon, DECIMAL32_Bytes)==0; | 414 return memcmp(d32, &canon, DECIMAL32_Bytes)==0; |
418 } /* decimal32IsCanonical */ | 415 } /* decimal32IsCanonical */ |
419 | 416 |
420 /* ------------------------------------------------------------------ */ | 417 /* ------------------------------------------------------------------ */ |
421 /* decimal32Canonical -- copy an encoding, ensuring it is canonical */ | 418 /* decimal32Canonical -- copy an encoding, ensuring it is canonical */ |
422 /* d32 is the source decimal32 */ | 419 /* d32 is the source decimal32 */ |
423 /* result is the target (may be the same decimal32) */ | 420 /* result is the target (may be the same decimal32) */ |
424 /* returns result */ | 421 /* returns result */ |
425 /* No error is possible. */ | 422 /* No error is possible. */ |
426 /* ------------------------------------------------------------------ */ | 423 /* ------------------------------------------------------------------ */ |
427 decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) { | 424 decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) { |
428 decNumber dn;»» » » /* work */ | 425 decNumber dn; » » » /* work */ |
429 decContext dc; /* .. */ | 426 decContext dc; /* .. */ |
430 decContextDefault(&dc, DEC_INIT_DECIMAL32); | 427 decContextDefault(&dc, DEC_INIT_DECIMAL32); |
431 decimal32ToNumber(d32, &dn); | 428 decimal32ToNumber(d32, &dn); |
432 decimal32FromNumber(result, &dn, &dc);/* result will now be canonical */ | 429 decimal32FromNumber(result, &dn, &dc);/* result will now be canonical */ |
433 return result; | 430 return result; |
434 } /* decimal32Canonical */ | 431 } /* decimal32Canonical */ |
435 | 432 |
436 #if DECTRACE || DECCHECK | 433 #if DECTRACE || DECCHECK |
437 /* Macros for accessing decimal32 fields. These assume the argument | 434 /* Macros for accessing decimal32 fields. These assume the argument |
438 is a reference (pointer) to the decimal32 structure, and the | 435 is a reference (pointer) to the decimal32 structure, and the |
439 decimal32 is in network byte order (big-endian) */ | 436 decimal32 is in network byte order (big-endian) */ |
440 /* Get sign */ | 437 /* Get sign */ |
441 #define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7) | 438 #define decimal32Sign(d) ((unsigned)(d)->bytes[0]>>7) |
442 | 439 |
443 /* Get combination field */ | 440 /* Get combination field */ |
444 #define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2) | 441 #define decimal32Comb(d) (((d)->bytes[0] & 0x7c)>>2) |
445 | 442 |
446 /* Get exponent continuation [does not remove bias] */ | 443 /* Get exponent continuation [does not remove bias] */ |
447 #define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \ | 444 #define decimal32ExpCon(d) ((((d)->bytes[0] & 0x03)<<4) \ |
448 | ((unsigned)(d)->bytes[1]>>4)) | 445 | ((unsigned)(d)->bytes[1]>>4)) |
449 | 446 |
450 /* Set sign [this assumes sign previously 0] */ | 447 /* Set sign [this assumes sign previously 0] */ |
451 #define decimal32SetSign(d, b) { \ | 448 #define decimal32SetSign(d, b) { \ |
452 (d)->bytes[0]|=((unsigned)(b)<<7);} | 449 (d)->bytes[0]|=((unsigned)(b)<<7);} |
453 | 450 |
454 /* Set exponent continuation [does not apply bias] */ | 451 /* Set exponent continuation [does not apply bias] */ |
455 /* This assumes range has been checked and exponent previously 0; */ | 452 /* This assumes range has been checked and exponent previously 0; */ |
456 /* type of exponent must be unsigned */ | 453 /* type of exponent must be unsigned */ |
457 #define decimal32SetExpCon(d, e) { \ | 454 #define decimal32SetExpCon(d, e) { \ |
458 (d)->bytes[0]|=(uint8_t)((e)>>4);» » » » \ | 455 (d)->bytes[0]|=(uByte)((e)>>4);» » » » \ |
459 (d)->bytes[1]|=(uint8_t)(((e)&0x0F)<<4);} | 456 (d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);} |
460 | 457 |
461 /* ------------------------------------------------------------------ */ | 458 /* ------------------------------------------------------------------ */ |
462 /* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */ | 459 /* decimal32Show -- display a decimal32 in hexadecimal [debug aid] */ |
463 /* d32 -- the number to show */ | 460 /* d32 -- the number to show */ |
464 /* ------------------------------------------------------------------ */ | 461 /* ------------------------------------------------------------------ */ |
465 /* Also shows sign/cob/expconfields extracted - valid bigendian only */ | 462 /* Also shows sign/cob/expconfields extracted - valid bigendian only */ |
466 void decimal32Show(const decimal32 *d32) { | 463 void decimal32Show(const decimal32 *d32) { |
467 char buf[DECIMAL32_Bytes*2+1]; | 464 char buf[DECIMAL32_Bytes*2+1]; |
468 Int i, j=0; | 465 Int i, j=0; |
469 | 466 |
470 if (DECLITEND) { | 467 if (DECLITEND) { |
471 for (i=0; i<DECIMAL32_Bytes; i++, j+=2) { | 468 for (i=0; i<DECIMAL32_Bytes; i++, j+=2) { |
472 sprintf(&buf[j], "%02x", d32->bytes[3-i]); | 469 sprintf(&buf[j], "%02x", d32->bytes[3-i]); |
473 } | 470 } |
474 printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, | 471 printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, |
475 d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f, | 472 d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f, |
476 ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4)); | 473 ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4)); |
477 } | 474 } |
478 else { | 475 else { |
479 for (i=0; i<DECIMAL32_Bytes; i++, j+=2) { | 476 for (i=0; i<DECIMAL32_Bytes; i++, j+=2) { |
480 sprintf(&buf[j], "%02x", d32->bytes[i]); | 477 sprintf(&buf[j], "%02x", d32->bytes[i]); |
481 } | 478 } |
482 printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, | 479 printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, |
483 decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32)); | 480 decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32)); |
484 } | 481 } |
485 } /* decimal32Show */ | 482 } /* decimal32Show */ |
486 #endif | 483 #endif |
OLD | NEW |