github.com/matrixorigin/matrixone@v0.7.0/cgo/external/decNumber/decimal64.c (about) 1 /* ------------------------------------------------------------------ */ 2 /* Decimal 64-bit format module */ 3 /* ------------------------------------------------------------------ */ 4 /* Copyright (c) IBM Corporation, 2000, 2009. All rights reserved. */ 5 /* */ 6 /* This software is made available under the terms of the */ 7 /* ICU License -- ICU 1.8.1 and later. */ 8 /* */ 9 /* The description and User's Guide ("The decNumber C Library") for */ 10 /* this software is called decNumber.pdf. This document is */ 11 /* available, together with arithmetic and format specifications, */ 12 /* testcases, and Web links, on the General Decimal Arithmetic page. */ 13 /* */ 14 /* Please send comments, suggestions, and corrections to the author: */ 15 /* mfc@uk.ibm.com */ 16 /* Mike Cowlishaw, IBM Fellow */ 17 /* IBM UK, PO Box 31, Birmingham Road, Warwick CV34 5JL, UK */ 18 /* ------------------------------------------------------------------ */ 19 /* This module comprises the routines for decimal64 format numbers. */ 20 /* Conversions are supplied to and from decNumber and String. */ 21 /* */ 22 /* This is used when decNumber provides operations, either for all */ 23 /* operations or as a proxy between decNumber and decSingle. */ 24 /* */ 25 /* Error handling is the same as decNumber (qv.). */ 26 /* ------------------------------------------------------------------ */ 27 #include <string.h> // [for memset/memcpy] 28 #include <stdio.h> // [for printf] 29 30 #define DECNUMDIGITS 16 // make decNumbers with space for 16 31 #include "decNumber.h" // base number library 32 #include "decNumberLocal.h" // decNumber local types, etc. 33 #include "decimal64.h" // our primary include 34 35 /* Utility routines and tables [in decimal64.c]; externs for C++ */ 36 // DPD2BIN and the reverse are renamed to prevent link-time conflict 37 // if decQuad is also built in the same executable 38 #define DPD2BIN DPD2BINx 39 #define BIN2DPD BIN2DPDx 40 extern const uInt COMBEXP[32], COMBMSD[32]; 41 extern const uShort DPD2BIN[1024]; 42 extern const uShort BIN2DPD[1000]; 43 extern const uByte BIN2CHAR[4001]; 44 45 extern void decDigitsFromDPD(decNumber *, const uInt *, Int); 46 extern void decDigitsToDPD(const decNumber *, uInt *, Int); 47 48 #if DECTRACE || DECCHECK 49 void decimal64Show(const decimal64 *); // for debug 50 extern void decNumberShow(const decNumber *); // .. 51 #endif 52 53 /* Useful macro */ 54 // Clear a structure (e.g., a decNumber) 55 #define DEC_clear(d) memset(d, 0, sizeof(*d)) 56 57 /* define and include the tables to use for conversions */ 58 #define DEC_BIN2CHAR 1 59 #define DEC_DPD2BIN 1 60 #define DEC_BIN2DPD 1 // used for all sizes 61 #include "decDPD.h" // lookup tables 62 63 /* ------------------------------------------------------------------ */ 64 /* decimal64FromNumber -- convert decNumber to decimal64 */ 65 /* */ 66 /* ds is the target decimal64 */ 67 /* dn is the source number (assumed valid) */ 68 /* set is the context, used only for reporting errors */ 69 /* */ 70 /* The set argument is used only for status reporting and for the */ 71 /* rounding mode (used if the coefficient is more than DECIMAL64_Pmax */ 72 /* digits or an overflow is detected). If the exponent is out of the */ 73 /* valid range then Overflow or Underflow will be raised. */ 74 /* After Underflow a subnormal result is possible. */ 75 /* */ 76 /* DEC_Clamped is set if the number has to be 'folded down' to fit, */ 77 /* by reducing its exponent and multiplying the coefficient by a */ 78 /* power of ten, or if the exponent on a zero had to be clamped. */ 79 /* ------------------------------------------------------------------ */ 80 decimal64 * decimal64FromNumber(decimal64 *d64, const decNumber *dn, 81 decContext *set) { 82 uInt status=0; // status accumulator 83 Int ae; // adjusted exponent 84 decNumber dw; // work 85 decContext dc; // .. 86 uInt comb, exp; // .. 87 uInt uiwork; // for macros 88 uInt targar[2]={0, 0}; // target 64-bit 89 #define targhi targar[1] // name the word with the sign 90 #define targlo targar[0] // and the other 91 92 // If the number has too many digits, or the exponent could be 93 // out of range then reduce the number under the appropriate 94 // constraints. This could push the number to Infinity or zero, 95 // so this check and rounding must be done before generating the 96 // decimal64] 97 ae=dn->exponent+dn->digits-1; // [0 if special] 98 if (dn->digits>DECIMAL64_Pmax // too many digits 99 || ae>DECIMAL64_Emax // likely overflow 100 || ae<DECIMAL64_Emin) { // likely underflow 101 decContextDefault(&dc, DEC_INIT_DECIMAL64); // [no traps] 102 dc.round=set->round; // use supplied rounding 103 decNumberPlus(&dw, dn, &dc); // (round and check) 104 // [this changes -0 to 0, so enforce the sign...] 105 dw.bits|=dn->bits&DECNEG; 106 status=dc.status; // save status 107 dn=&dw; // use the work number 108 } // maybe out of range 109 110 if (dn->bits&DECSPECIAL) { // a special value 111 if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24; 112 else { // sNaN or qNaN 113 if ((*dn->lsu!=0 || dn->digits>1) // non-zero coefficient 114 && (dn->digits<DECIMAL64_Pmax)) { // coefficient fits 115 decDigitsToDPD(dn, targar, 0); 116 } 117 if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24; 118 else targhi|=DECIMAL_sNaN<<24; 119 } // a NaN 120 } // special 121 122 else { // is finite 123 if (decNumberIsZero(dn)) { // is a zero 124 // set and clamp exponent 125 if (dn->exponent<-DECIMAL64_Bias) { 126 exp=0; // low clamp 127 status|=DEC_Clamped; 128 } 129 else { 130 exp=dn->exponent+DECIMAL64_Bias; // bias exponent 131 if (exp>DECIMAL64_Ehigh) { // top clamp 132 exp=DECIMAL64_Ehigh; 133 status|=DEC_Clamped; 134 } 135 } 136 comb=(exp>>5) & 0x18; // msd=0, exp top 2 bits .. 137 } 138 else { // non-zero finite number 139 uInt msd; // work 140 Int pad=0; // coefficient pad digits 141 142 // the dn is known to fit, but it may need to be padded 143 exp=(uInt)(dn->exponent+DECIMAL64_Bias); // bias exponent 144 if (exp>DECIMAL64_Ehigh) { // fold-down case 145 pad=exp-DECIMAL64_Ehigh; 146 exp=DECIMAL64_Ehigh; // [to maximum] 147 status|=DEC_Clamped; 148 } 149 150 // fastpath common case 151 if (DECDPUN==3 && pad==0) { 152 uInt dpd[6]={0,0,0,0,0,0}; 153 uInt i; 154 Int d=dn->digits; 155 for (i=0; d>0; i++, d-=3) dpd[i]=BIN2DPD[dn->lsu[i]]; 156 targlo =dpd[0]; 157 targlo|=dpd[1]<<10; 158 targlo|=dpd[2]<<20; 159 if (dn->digits>6) { 160 targlo|=dpd[3]<<30; 161 targhi =dpd[3]>>2; 162 targhi|=dpd[4]<<8; 163 } 164 msd=dpd[5]; // [did not really need conversion] 165 } 166 else { // general case 167 decDigitsToDPD(dn, targar, pad); 168 // save and clear the top digit 169 msd=targhi>>18; 170 targhi&=0x0003ffff; 171 } 172 173 // create the combination field 174 if (msd>=8) comb=0x18 | ((exp>>7) & 0x06) | (msd & 0x01); 175 else comb=((exp>>5) & 0x18) | msd; 176 } 177 targhi|=comb<<26; // add combination field .. 178 targhi|=(exp&0xff)<<18; // .. and exponent continuation 179 } // finite 180 181 if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit 182 183 // now write to storage; this is now always endian 184 if (DECLITEND) { 185 // lo int then hi 186 UBFROMUI(d64->bytes, targar[0]); 187 UBFROMUI(d64->bytes+4, targar[1]); 188 } 189 else { 190 // hi int then lo 191 UBFROMUI(d64->bytes, targar[1]); 192 UBFROMUI(d64->bytes+4, targar[0]); 193 } 194 195 if (status!=0) decContextSetStatus(set, status); // pass on status 196 // decimal64Show(d64); 197 return d64; 198 } // decimal64FromNumber 199 200 /* ------------------------------------------------------------------ */ 201 /* decimal64ToNumber -- convert decimal64 to decNumber */ 202 /* d64 is the source decimal64 */ 203 /* dn is the target number, with appropriate space */ 204 /* No error is possible. */ 205 /* ------------------------------------------------------------------ */ 206 decNumber * decimal64ToNumber(const decimal64 *d64, decNumber *dn) { 207 uInt msd; // coefficient MSD 208 uInt exp; // exponent top two bits 209 uInt comb; // combination field 210 Int need; // work 211 uInt uiwork; // for macros 212 uInt sourar[2]; // source 64-bit 213 #define sourhi sourar[1] // name the word with the sign 214 #define sourlo sourar[0] // and the lower word 215 216 // load source from storage; this is endian 217 if (DECLITEND) { 218 sourlo=UBTOUI(d64->bytes ); // directly load the low int 219 sourhi=UBTOUI(d64->bytes+4); // then the high int 220 } 221 else { 222 sourhi=UBTOUI(d64->bytes ); // directly load the high int 223 sourlo=UBTOUI(d64->bytes+4); // then the low int 224 } 225 226 comb=(sourhi>>26)&0x1f; // combination field 227 228 decNumberZero(dn); // clean number 229 if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative 230 231 msd=COMBMSD[comb]; // decode the combination field 232 exp=COMBEXP[comb]; // .. 233 234 if (exp==3) { // is a special 235 if (msd==0) { 236 dn->bits|=DECINF; 237 return dn; // no coefficient needed 238 } 239 else if (sourhi&0x02000000) dn->bits|=DECSNAN; 240 else dn->bits|=DECNAN; 241 msd=0; // no top digit 242 } 243 else { // is a finite number 244 dn->exponent=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; // unbiased 245 } 246 247 // get the coefficient 248 sourhi&=0x0003ffff; // clean coefficient continuation 249 if (msd) { // non-zero msd 250 sourhi|=msd<<18; // prefix to coefficient 251 need=6; // process 6 declets 252 } 253 else { // msd=0 254 if (!sourhi) { // top word 0 255 if (!sourlo) return dn; // easy: coefficient is 0 256 need=3; // process at least 3 declets 257 if (sourlo&0xc0000000) need++; // process 4 declets 258 // [could reduce some more, here] 259 } 260 else { // some bits in top word, msd=0 261 need=4; // process at least 4 declets 262 if (sourhi&0x0003ff00) need++; // top declet!=0, process 5 263 } 264 } //msd=0 265 266 decDigitsFromDPD(dn, sourar, need); // process declets 267 return dn; 268 } // decimal64ToNumber 269 270 271 /* ------------------------------------------------------------------ */ 272 /* to-scientific-string -- conversion to numeric string */ 273 /* to-engineering-string -- conversion to numeric string */ 274 /* */ 275 /* decimal64ToString(d64, string); */ 276 /* decimal64ToEngString(d64, string); */ 277 /* */ 278 /* d64 is the decimal64 format number to convert */ 279 /* string is the string where the result will be laid out */ 280 /* */ 281 /* string must be at least 24 characters */ 282 /* */ 283 /* No error is possible, and no status can be set. */ 284 /* ------------------------------------------------------------------ */ 285 char * decimal64ToEngString(const decimal64 *d64, char *string){ 286 decNumber dn; // work 287 decimal64ToNumber(d64, &dn); 288 decNumberToEngString(&dn, string); 289 return string; 290 } // decimal64ToEngString 291 292 char * decimal64ToString(const decimal64 *d64, char *string){ 293 uInt msd; // coefficient MSD 294 Int exp; // exponent top two bits or full 295 uInt comb; // combination field 296 char *cstart; // coefficient start 297 char *c; // output pointer in string 298 const uByte *u; // work 299 char *s, *t; // .. (source, target) 300 Int dpd; // .. 301 Int pre, e; // .. 302 uInt uiwork; // for macros 303 304 uInt sourar[2]; // source 64-bit 305 #define sourhi sourar[1] // name the word with the sign 306 #define sourlo sourar[0] // and the lower word 307 308 // load source from storage; this is endian 309 if (DECLITEND) { 310 sourlo=UBTOUI(d64->bytes ); // directly load the low int 311 sourhi=UBTOUI(d64->bytes+4); // then the high int 312 } 313 else { 314 sourhi=UBTOUI(d64->bytes ); // directly load the high int 315 sourlo=UBTOUI(d64->bytes+4); // then the low int 316 } 317 318 c=string; // where result will go 319 if (((Int)sourhi)<0) *c++='-'; // handle sign 320 321 comb=(sourhi>>26)&0x1f; // combination field 322 msd=COMBMSD[comb]; // decode the combination field 323 exp=COMBEXP[comb]; // .. 324 325 if (exp==3) { 326 if (msd==0) { // infinity 327 strcpy(c, "Inf"); 328 strcpy(c+3, "inity"); 329 return string; // easy 330 } 331 if (sourhi&0x02000000) *c++='s'; // sNaN 332 strcpy(c, "NaN"); // complete word 333 c+=3; // step past 334 if (sourlo==0 && (sourhi&0x0003ffff)==0) return string; // zero payload 335 // otherwise drop through to add integer; set correct exp 336 exp=0; msd=0; // setup for following code 337 } 338 else exp=(exp<<8)+((sourhi>>18)&0xff)-DECIMAL64_Bias; 339 340 // convert 16 digits of significand to characters 341 cstart=c; // save start of coefficient 342 if (msd) *c++='0'+(char)msd; // non-zero most significant digit 343 344 // Now decode the declets. After extracting each one, it is 345 // decoded to binary and then to a 4-char sequence by table lookup; 346 // the 4-chars are a 1-char length (significant digits, except 000 347 // has length 0). This allows us to left-align the first declet 348 // with non-zero content, then remaining ones are full 3-char 349 // length. We use fixed-length memcpys because variable-length 350 // causes a subroutine call in GCC. (These are length 4 for speed 351 // and are safe because the array has an extra terminator byte.) 352 #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; \ 353 if (c!=cstart) {memcpy(c, u+1, 4); c+=3;} \ 354 else if (*u) {memcpy(c, u+4-*u, 4); c+=*u;} 355 356 dpd=(sourhi>>8)&0x3ff; // declet 1 357 dpd2char; 358 dpd=((sourhi&0xff)<<2) | (sourlo>>30); // declet 2 359 dpd2char; 360 dpd=(sourlo>>20)&0x3ff; // declet 3 361 dpd2char; 362 dpd=(sourlo>>10)&0x3ff; // declet 4 363 dpd2char; 364 dpd=(sourlo)&0x3ff; // declet 5 365 dpd2char; 366 367 if (c==cstart) *c++='0'; // all zeros -- make 0 368 369 if (exp==0) { // integer or NaN case -- easy 370 *c='\0'; // terminate 371 return string; 372 } 373 374 /* non-0 exponent */ 375 e=0; // assume no E 376 pre=c-cstart+exp; 377 // [here, pre-exp is the digits count (==1 for zero)] 378 if (exp>0 || pre<-5) { // need exponential form 379 e=pre-1; // calculate E value 380 pre=1; // assume one digit before '.' 381 } // exponential form 382 383 /* modify the coefficient, adding 0s, '.', and E+nn as needed */ 384 s=c-1; // source (LSD) 385 if (pre>0) { // ddd.ddd (plain), perhaps with E 386 char *dotat=cstart+pre; 387 if (dotat<c) { // if embedded dot needed... 388 t=c; // target 389 for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap 390 *t='.'; // insert the dot 391 c++; // length increased by one 392 } 393 394 // finally add the E-part, if needed; it will never be 0, and has 395 // a maximum length of 3 digits 396 if (e!=0) { 397 *c++='E'; // starts with E 398 *c++='+'; // assume positive 399 if (e<0) { 400 *(c-1)='-'; // oops, need '-' 401 e=-e; // uInt, please 402 } 403 u=&BIN2CHAR[e*4]; // -> length byte 404 memcpy(c, u+4-*u, 4); // copy fixed 4 characters [is safe] 405 c+=*u; // bump pointer appropriately 406 } 407 *c='\0'; // add terminator 408 //printf("res %s\n", string); 409 return string; 410 } // pre>0 411 412 /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */ 413 t=c+1-pre; 414 *(t+1)='\0'; // can add terminator now 415 for (; s>=cstart; s--, t--) *t=*s; // shift whole coefficient right 416 c=cstart; 417 *c++='0'; // always starts with 0. 418 *c++='.'; 419 for (; pre<0; pre++) *c++='0'; // add any 0's after '.' 420 //printf("res %s\n", string); 421 return string; 422 } // decimal64ToString 423 424 /* ------------------------------------------------------------------ */ 425 /* to-number -- conversion from numeric string */ 426 /* */ 427 /* decimal64FromString(result, string, set); */ 428 /* */ 429 /* result is the decimal64 format number which gets the result of */ 430 /* the conversion */ 431 /* *string is the character string which should contain a valid */ 432 /* number (which may be a special value) */ 433 /* set is the context */ 434 /* */ 435 /* The context is supplied to this routine is used for error handling */ 436 /* (setting of status and traps) and for the rounding mode, only. */ 437 /* If an error occurs, the result will be a valid decimal64 NaN. */ 438 /* ------------------------------------------------------------------ */ 439 decimal64 * decimal64FromString(decimal64 *result, const char *string, 440 decContext *set) { 441 decContext dc; // work 442 decNumber dn; // .. 443 444 decContextDefault(&dc, DEC_INIT_DECIMAL64); // no traps, please 445 dc.round=set->round; // use supplied rounding 446 447 decNumberFromString(&dn, string, &dc); // will round if needed 448 449 decimal64FromNumber(result, &dn, &dc); 450 if (dc.status!=0) { // something happened 451 decContextSetStatus(set, dc.status); // .. pass it on 452 } 453 return result; 454 } // decimal64FromString 455 456 /* ------------------------------------------------------------------ */ 457 /* decimal64IsCanonical -- test whether encoding is canonical */ 458 /* d64 is the source decimal64 */ 459 /* returns 1 if the encoding of d64 is canonical, 0 otherwise */ 460 /* No error is possible. */ 461 /* ------------------------------------------------------------------ */ 462 uInt decimal64IsCanonical(const decimal64 *d64) { 463 decNumber dn; // work 464 decimal64 canon; // .. 465 decContext dc; // .. 466 decContextDefault(&dc, DEC_INIT_DECIMAL64); 467 decimal64ToNumber(d64, &dn); 468 decimal64FromNumber(&canon, &dn, &dc);// canon will now be canonical 469 return memcmp(d64, &canon, DECIMAL64_Bytes)==0; 470 } // decimal64IsCanonical 471 472 /* ------------------------------------------------------------------ */ 473 /* decimal64Canonical -- copy an encoding, ensuring it is canonical */ 474 /* d64 is the source decimal64 */ 475 /* result is the target (may be the same decimal64) */ 476 /* returns result */ 477 /* No error is possible. */ 478 /* ------------------------------------------------------------------ */ 479 decimal64 * decimal64Canonical(decimal64 *result, const decimal64 *d64) { 480 decNumber dn; // work 481 decContext dc; // .. 482 decContextDefault(&dc, DEC_INIT_DECIMAL64); 483 decimal64ToNumber(d64, &dn); 484 decimal64FromNumber(result, &dn, &dc);// result will now be canonical 485 return result; 486 } // decimal64Canonical 487 488 #if DECTRACE || DECCHECK 489 /* Macros for accessing decimal64 fields. These assume the 490 argument is a reference (pointer) to the decimal64 structure, 491 and the decimal64 is in network byte order (big-endian) */ 492 // Get sign 493 #define decimal64Sign(d) ((unsigned)(d)->bytes[0]>>7) 494 495 // Get combination field 496 #define decimal64Comb(d) (((d)->bytes[0] & 0x7c)>>2) 497 498 // Get exponent continuation [does not remove bias] 499 #define decimal64ExpCon(d) ((((d)->bytes[0] & 0x03)<<6) \ 500 | ((unsigned)(d)->bytes[1]>>2)) 501 502 // Set sign [this assumes sign previously 0] 503 #define decimal64SetSign(d, b) { \ 504 (d)->bytes[0]|=((unsigned)(b)<<7);} 505 506 // Set exponent continuation [does not apply bias] 507 // This assumes range has been checked and exponent previously 0; 508 // type of exponent must be unsigned 509 #define decimal64SetExpCon(d, e) { \ 510 (d)->bytes[0]|=(uByte)((e)>>6); \ 511 (d)->bytes[1]|=(uByte)(((e)&0x3F)<<2);} 512 513 /* ------------------------------------------------------------------ */ 514 /* decimal64Show -- display a decimal64 in hexadecimal [debug aid] */ 515 /* d64 -- the number to show */ 516 /* ------------------------------------------------------------------ */ 517 // Also shows sign/cob/expconfields extracted 518 void decimal64Show(const decimal64 *d64) { 519 char buf[DECIMAL64_Bytes*2+1]; 520 Int i, j=0; 521 522 if (DECLITEND) { 523 for (i=0; i<DECIMAL64_Bytes; i++, j+=2) { 524 sprintf(&buf[j], "%02x", d64->bytes[7-i]); 525 } 526 printf(" D64> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf, 527 d64->bytes[7]>>7, (d64->bytes[7]>>2)&0x1f, 528 ((d64->bytes[7]&0x3)<<6)| (d64->bytes[6]>>2)); 529 } 530 else { // big-endian 531 for (i=0; i<DECIMAL64_Bytes; i++, j+=2) { 532 sprintf(&buf[j], "%02x", d64->bytes[i]); 533 } 534 printf(" D64> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf, 535 decimal64Sign(d64), decimal64Comb(d64), decimal64ExpCon(d64)); 536 } 537 } // decimal64Show 538 #endif 539 540 /* ================================================================== */ 541 /* Shared utility routines and tables */ 542 /* ================================================================== */ 543 // define and include the conversion tables to use for shared code 544 #if DECDPUN==3 545 #define DEC_DPD2BIN 1 546 #else 547 #define DEC_DPD2BCD 1 548 #endif 549 #include "decDPD.h" // lookup tables 550 551 // The maximum number of decNumberUnits needed for a working copy of 552 // the units array is the ceiling of digits/DECDPUN, where digits is 553 // the maximum number of digits in any of the formats for which this 554 // is used. decimal128.h must not be included in this module, so, as 555 // a very special case, that number is defined as a literal here. 556 #define DECMAX754 34 557 #define DECMAXUNITS ((DECMAX754+DECDPUN-1)/DECDPUN) 558 559 /* ------------------------------------------------------------------ */ 560 /* Combination field lookup tables (uInts to save measurable work) */ 561 /* */ 562 /* COMBEXP - 2-bit most-significant-bits of exponent */ 563 /* [11 if an Infinity or NaN] */ 564 /* COMBMSD - 4-bit most-significant-digit */ 565 /* [0=Infinity, 1=NaN if COMBEXP=11] */ 566 /* */ 567 /* Both are indexed by the 5-bit combination field (0-31) */ 568 /* ------------------------------------------------------------------ */ 569 const uInt COMBEXP[32]={0, 0, 0, 0, 0, 0, 0, 0, 570 1, 1, 1, 1, 1, 1, 1, 1, 571 2, 2, 2, 2, 2, 2, 2, 2, 572 0, 0, 1, 1, 2, 2, 3, 3}; 573 const uInt COMBMSD[32]={0, 1, 2, 3, 4, 5, 6, 7, 574 0, 1, 2, 3, 4, 5, 6, 7, 575 0, 1, 2, 3, 4, 5, 6, 7, 576 8, 9, 8, 9, 8, 9, 0, 1}; 577 578 /* ------------------------------------------------------------------ */ 579 /* decDigitsToDPD -- pack coefficient into DPD form */ 580 /* */ 581 /* dn is the source number (assumed valid, max DECMAX754 digits) */ 582 /* targ is 1, 2, or 4-element uInt array, which the caller must */ 583 /* have cleared to zeros */ 584 /* shift is the number of 0 digits to add on the right (normally 0) */ 585 /* */ 586 /* The coefficient must be known small enough to fit. The full */ 587 /* coefficient is copied, including the leading 'odd' digit. This */ 588 /* digit is retrieved and packed into the combination field by the */ 589 /* caller. */ 590 /* */ 591 /* The target uInts are altered only as necessary to receive the */ 592 /* digits of the decNumber. When more than one uInt is needed, they */ 593 /* are filled from left to right (that is, the uInt at offset 0 will */ 594 /* end up with the least-significant digits). */ 595 /* */ 596 /* shift is used for 'fold-down' padding. */ 597 /* */ 598 /* No error is possible. */ 599 /* ------------------------------------------------------------------ */ 600 #if DECDPUN<=4 601 // Constant multipliers for divide-by-power-of five using reciprocal 602 // multiply, after removing powers of 2 by shifting, and final shift 603 // of 17 [we only need up to **4] 604 static const uInt multies[]={131073, 26215, 5243, 1049, 210}; 605 // QUOT10 -- macro to return the quotient of unit u divided by 10**n 606 #define QUOT10(u, n) ((((uInt)(u)>>(n))*multies[n])>>17) 607 #endif 608 void decDigitsToDPD(const decNumber *dn, uInt *targ, Int shift) { 609 Int cut; // work 610 Int n; // output bunch counter 611 Int digits=dn->digits; // digit countdown 612 uInt dpd; // densely packed decimal value 613 uInt bin; // binary value 0-999 614 uInt *uout=targ; // -> current output uInt 615 uInt uoff=0; // -> current output offset [from right] 616 const Unit *inu=dn->lsu; // -> current input unit 617 Unit uar[DECMAXUNITS]; // working copy of units, iff shifted 618 #if DECDPUN!=3 // not fast path 619 Unit in; // current unit 620 #endif 621 622 if (shift!=0) { // shift towards most significant required 623 // shift the units array to the left by pad digits and copy 624 // [this code is a special case of decShiftToMost, which could 625 // be used instead if exposed and the array were copied first] 626 const Unit *source; // .. 627 Unit *target, *first; // .. 628 uInt next=0; // work 629 630 source=dn->lsu+D2U(digits)-1; // where msu comes from 631 target=uar+D2U(digits)-1+D2U(shift);// where upper part of first cut goes 632 cut=DECDPUN-MSUDIGITS(shift); // where to slice 633 if (cut==0) { // unit-boundary case 634 for (; source>=dn->lsu; source--, target--) *target=*source; 635 } 636 else { 637 first=uar+D2U(digits+shift)-1; // where msu will end up 638 for (; source>=dn->lsu; source--, target--) { 639 // split the source Unit and accumulate remainder for next 640 #if DECDPUN<=4 641 uInt quot=QUOT10(*source, cut); 642 uInt rem=*source-quot*DECPOWERS[cut]; 643 next+=quot; 644 #else 645 uInt rem=*source%DECPOWERS[cut]; 646 next+=*source/DECPOWERS[cut]; 647 #endif 648 if (target<=first) *target=(Unit)next; // write to target iff valid 649 next=rem*DECPOWERS[DECDPUN-cut]; // save remainder for next Unit 650 } 651 } // shift-move 652 // propagate remainder to one below and clear the rest 653 for (; target>=uar; target--) { 654 *target=(Unit)next; 655 next=0; 656 } 657 digits+=shift; // add count (shift) of zeros added 658 inu=uar; // use units in working array 659 } 660 661 /* now densely pack the coefficient into DPD declets */ 662 663 #if DECDPUN!=3 // not fast path 664 in=*inu; // current unit 665 cut=0; // at lowest digit 666 bin=0; // [keep compiler quiet] 667 #endif 668 669 for(n=0; digits>0; n++) { // each output bunch 670 #if DECDPUN==3 // fast path, 3-at-a-time 671 bin=*inu; // 3 digits ready for convert 672 digits-=3; // [may go negative] 673 inu++; // may need another 674 675 #else // must collect digit-by-digit 676 Unit dig; // current digit 677 Int j; // digit-in-declet count 678 for (j=0; j<3; j++) { 679 #if DECDPUN<=4 680 Unit temp=(Unit)((uInt)(in*6554)>>16); 681 dig=(Unit)(in-X10(temp)); 682 in=temp; 683 #else 684 dig=in%10; 685 in=in/10; 686 #endif 687 if (j==0) bin=dig; 688 else if (j==1) bin+=X10(dig); 689 else /* j==2 */ bin+=X100(dig); 690 digits--; 691 if (digits==0) break; // [also protects *inu below] 692 cut++; 693 if (cut==DECDPUN) {inu++; in=*inu; cut=0;} 694 } 695 #endif 696 // here there are 3 digits in bin, or have used all input digits 697 698 dpd=BIN2DPD[bin]; 699 700 // write declet to uInt array 701 *uout|=dpd<<uoff; 702 uoff+=10; 703 if (uoff<32) continue; // no uInt boundary cross 704 uout++; 705 uoff-=32; 706 *uout|=dpd>>(10-uoff); // collect top bits 707 } // n declets 708 return; 709 } // decDigitsToDPD 710 711 /* ------------------------------------------------------------------ */ 712 /* decDigitsFromDPD -- unpack a format's coefficient */ 713 /* */ 714 /* dn is the target number, with 7, 16, or 34-digit space. */ 715 /* sour is a 1, 2, or 4-element uInt array containing only declets */ 716 /* declets is the number of (right-aligned) declets in sour to */ 717 /* be processed. This may be 1 more than the obvious number in */ 718 /* a format, as any top digit is prefixed to the coefficient */ 719 /* continuation field. It also may be as small as 1, as the */ 720 /* caller may pre-process leading zero declets. */ 721 /* */ 722 /* When doing the 'extra declet' case care is taken to avoid writing */ 723 /* extra digits when there are leading zeros, as these could overflow */ 724 /* the units array when DECDPUN is not 3. */ 725 /* */ 726 /* The target uInts are used only as necessary to process declets */ 727 /* declets into the decNumber. When more than one uInt is needed, */ 728 /* they are used from left to right (that is, the uInt at offset 0 */ 729 /* provides the least-significant digits). */ 730 /* */ 731 /* dn->digits is set, but not the sign or exponent. */ 732 /* No error is possible [the redundant 888 codes are allowed]. */ 733 /* ------------------------------------------------------------------ */ 734 void decDigitsFromDPD(decNumber *dn, const uInt *sour, Int declets) { 735 736 uInt dpd; // collector for 10 bits 737 Int n; // counter 738 Unit *uout=dn->lsu; // -> current output unit 739 Unit *last=uout; // will be unit containing msd 740 const uInt *uin=sour; // -> current input uInt 741 uInt uoff=0; // -> current input offset [from right] 742 743 #if DECDPUN!=3 744 uInt bcd; // BCD result 745 uInt nibble; // work 746 Unit out=0; // accumulator 747 Int cut=0; // power of ten in current unit 748 #endif 749 #if DECDPUN>4 750 uInt const *pow; // work 751 #endif 752 753 // Expand the densely-packed integer, right to left 754 for (n=declets-1; n>=0; n--) { // count down declets of 10 bits 755 dpd=*uin>>uoff; 756 uoff+=10; 757 if (uoff>32) { // crossed uInt boundary 758 uin++; 759 uoff-=32; // [if using this code for wider, check this] 760 dpd|=*uin<<(10-uoff); // get waiting bits 761 } 762 dpd&=0x3ff; // clear uninteresting bits 763 764 #if DECDPUN==3 765 if (dpd==0) *uout=0; 766 else { 767 *uout=DPD2BIN[dpd]; // convert 10 bits to binary 0-999 768 last=uout; // record most significant unit 769 } 770 uout++; 771 } // n 772 773 #else // DECDPUN!=3 774 if (dpd==0) { // fastpath [e.g., leading zeros] 775 // write out three 0 digits (nibbles); out may have digit(s) 776 cut++; 777 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} 778 if (n==0) break; // [as below, works even if MSD=0] 779 cut++; 780 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} 781 cut++; 782 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} 783 continue; 784 } 785 786 bcd=DPD2BCD[dpd]; // convert 10 bits to 12 bits BCD 787 788 // now accumulate the 3 BCD nibbles into units 789 nibble=bcd & 0x00f; 790 if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); 791 cut++; 792 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} 793 bcd>>=4; 794 795 // if this is the last declet and the remaining nibbles in bcd 796 // are 00 then process no more nibbles, because this could be 797 // the 'odd' MSD declet and writing any more Units would then 798 // overflow the unit array 799 if (n==0 && !bcd) break; 800 801 nibble=bcd & 0x00f; 802 if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); 803 cut++; 804 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} 805 bcd>>=4; 806 807 nibble=bcd & 0x00f; 808 if (nibble) out=(Unit)(out+nibble*DECPOWERS[cut]); 809 cut++; 810 if (cut==DECDPUN) {*uout=out; if (out) {last=uout; out=0;} uout++; cut=0;} 811 } // n 812 if (cut!=0) { // some more left over 813 *uout=out; // write out final unit 814 if (out) last=uout; // and note if non-zero 815 } 816 #endif 817 818 // here, last points to the most significant unit with digits; 819 // inspect it to get the final digits count -- this is essentially 820 // the same code as decGetDigits in decNumber.c 821 dn->digits=(last-dn->lsu)*DECDPUN+1; // floor of digits, plus 822 // must be at least 1 digit 823 #if DECDPUN>1 824 if (*last<10) return; // common odd digit or 0 825 dn->digits++; // must be 2 at least 826 #if DECDPUN>2 827 if (*last<100) return; // 10-99 828 dn->digits++; // must be 3 at least 829 #if DECDPUN>3 830 if (*last<1000) return; // 100-999 831 dn->digits++; // must be 4 at least 832 #if DECDPUN>4 833 for (pow=&DECPOWERS[4]; *last>=*pow; pow++) dn->digits++; 834 #endif 835 #endif 836 #endif 837 #endif 838 return; 839 } //decDigitsFromDPD