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