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