| 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 |