github.com/matrixorigin/matrixone@v0.7.0/cgo/external/decNumber/decimal128.c (about)

     1  /* ------------------------------------------------------------------ */
     2  /* Decimal 128-bit format module                                      */
     3  /* ------------------------------------------------------------------ */
     4  /* Copyright (c) IBM Corporation, 2000, 2008.  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 decimal128 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 34      // make decNumbers with space for 34
    31  #include "decNumber.h"        // base number library
    32  #include "decNumberLocal.h"   // decNumber local types, etc.
    33  #include "decimal128.h"       // our primary include
    34  
    35  /* Utility routines and tables [in decimal64.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];      // [not used]
    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 decimal128Show(const decimal128 *);          // 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  /* ------------------------------------------------------------------ */
    58  /* decimal128FromNumber -- convert decNumber to decimal128            */
    59  /*                                                                    */
    60  /*   ds is the target decimal128                                      */
    61  /*   dn is the source number (assumed valid)                          */
    62  /*   set is the context, used only for reporting errors               */
    63  /*                                                                    */
    64  /* The set argument is used only for status reporting and for the     */
    65  /* rounding mode (used if the coefficient is more than DECIMAL128_Pmax*/
    66  /* digits or an overflow is detected).  If the exponent is out of the */
    67  /* valid range then Overflow or Underflow will be raised.             */
    68  /* After Underflow a subnormal result is possible.                    */
    69  /*                                                                    */
    70  /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
    71  /* by reducing its exponent and multiplying the coefficient by a      */
    72  /* power of ten, or if the exponent on a zero had to be clamped.      */
    73  /* ------------------------------------------------------------------ */
    74  decimal128 * decimal128FromNumber(decimal128 *d128, const decNumber *dn,
    75                                    decContext *set) {
    76    uInt status=0;                   // status accumulator
    77    Int ae;                          // adjusted exponent
    78    decNumber  dw;                   // work
    79    decContext dc;                   // ..
    80    uInt comb, exp;                  // ..
    81    uInt uiwork;                     // for macros
    82    uInt targar[4]={0,0,0,0};        // target 128-bit
    83    #define targhi targar[3]         // name the word with the sign
    84    #define targmh targar[2]         // name the words
    85    #define targml targar[1]         // ..
    86    #define targlo targar[0]         // ..
    87  
    88    // If the number has too many digits, or the exponent could be
    89    // out of range then reduce the number under the appropriate
    90    // constraints.  This could push the number to Infinity or zero,
    91    // so this check and rounding must be done before generating the
    92    // decimal128]
    93    ae=dn->exponent+dn->digits-1;              // [0 if special]
    94    if (dn->digits>DECIMAL128_Pmax             // too many digits
    95     || ae>DECIMAL128_Emax                     // likely overflow
    96     || ae<DECIMAL128_Emin) {                  // likely underflow
    97      decContextDefault(&dc, DEC_INIT_DECIMAL128); // [no traps]
    98      dc.round=set->round;                     // use supplied rounding
    99      decNumberPlus(&dw, dn, &dc);             // (round and check)
   100      // [this changes -0 to 0, so enforce the sign...]
   101      dw.bits|=dn->bits&DECNEG;
   102      status=dc.status;                        // save status
   103      dn=&dw;                                  // use the work number
   104      } // maybe out of range
   105  
   106    if (dn->bits&DECSPECIAL) {                      // a special value
   107      if (dn->bits&DECINF) targhi=DECIMAL_Inf<<24;
   108       else {                                       // sNaN or qNaN
   109        if ((*dn->lsu!=0 || dn->digits>1)           // non-zero coefficient
   110         && (dn->digits<DECIMAL128_Pmax)) {         // coefficient fits
   111          decDigitsToDPD(dn, targar, 0);
   112          }
   113        if (dn->bits&DECNAN) targhi|=DECIMAL_NaN<<24;
   114         else targhi|=DECIMAL_sNaN<<24;
   115        } // a NaN
   116      } // special
   117  
   118     else { // is finite
   119      if (decNumberIsZero(dn)) {               // is a zero
   120        // set and clamp exponent
   121        if (dn->exponent<-DECIMAL128_Bias) {
   122          exp=0;                               // low clamp
   123          status|=DEC_Clamped;
   124          }
   125         else {
   126          exp=dn->exponent+DECIMAL128_Bias;    // bias exponent
   127          if (exp>DECIMAL128_Ehigh) {          // top clamp
   128            exp=DECIMAL128_Ehigh;
   129            status|=DEC_Clamped;
   130            }
   131          }
   132        comb=(exp>>9) & 0x18;             // msd=0, exp top 2 bits ..
   133        }
   134       else {                             // non-zero finite number
   135        uInt msd;                         // work
   136        Int pad=0;                        // coefficient pad digits
   137  
   138        // the dn is known to fit, but it may need to be padded
   139        exp=(uInt)(dn->exponent+DECIMAL128_Bias);    // bias exponent
   140        if (exp>DECIMAL128_Ehigh) {                  // fold-down case
   141          pad=exp-DECIMAL128_Ehigh;
   142          exp=DECIMAL128_Ehigh;                      // [to maximum]
   143          status|=DEC_Clamped;
   144          }
   145  
   146        // [fastpath for common case is not a win, here]
   147        decDigitsToDPD(dn, targar, pad);
   148        // save and clear the top digit
   149        msd=targhi>>14;
   150        targhi&=0x00003fff;
   151  
   152        // create the combination field
   153        if (msd>=8) comb=0x18 | ((exp>>11) & 0x06) | (msd & 0x01);
   154               else comb=((exp>>9) & 0x18) | msd;
   155        }
   156      targhi|=comb<<26;              // add combination field ..
   157      targhi|=(exp&0xfff)<<14;       // .. and exponent continuation
   158      } // finite
   159  
   160    if (dn->bits&DECNEG) targhi|=0x80000000; // add sign bit
   161  
   162    // now write to storage; this is endian
   163    if (DECLITEND) {
   164      // lo -> hi
   165      UBFROMUI(d128->bytes,    targlo);
   166      UBFROMUI(d128->bytes+4,  targml);
   167      UBFROMUI(d128->bytes+8,  targmh);
   168      UBFROMUI(d128->bytes+12, targhi);
   169      }
   170     else {
   171      // hi -> lo
   172      UBFROMUI(d128->bytes,    targhi);
   173      UBFROMUI(d128->bytes+4,  targmh);
   174      UBFROMUI(d128->bytes+8,  targml);
   175      UBFROMUI(d128->bytes+12, targlo);
   176      }
   177  
   178    if (status!=0) decContextSetStatus(set, status); // pass on status
   179    // decimal128Show(d128);
   180    return d128;
   181    } // decimal128FromNumber
   182  
   183  /* ------------------------------------------------------------------ */
   184  /* decimal128ToNumber -- convert decimal128 to decNumber              */
   185  /*   d128 is the source decimal128                                    */
   186  /*   dn is the target number, with appropriate space                  */
   187  /* No error is possible.                                              */
   188  /* ------------------------------------------------------------------ */
   189  decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
   190    uInt msd;                        // coefficient MSD
   191    uInt exp;                        // exponent top two bits
   192    uInt comb;                       // combination field
   193    Int  need;                       // work
   194    uInt uiwork;                     // for macros
   195    uInt sourar[4];                  // source 128-bit
   196    #define sourhi sourar[3]         // name the word with the sign
   197    #define sourmh sourar[2]         // and the mid-high word
   198    #define sourml sourar[1]         // and the mod-low word
   199    #define sourlo sourar[0]         // and the lowest word
   200  
   201    // load source from storage; this is endian
   202    if (DECLITEND) {
   203      sourlo=UBTOUI(d128->bytes   ); // directly load the low int
   204      sourml=UBTOUI(d128->bytes+4 ); // then the mid-low
   205      sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high
   206      sourhi=UBTOUI(d128->bytes+12); // then the high int
   207      }
   208     else {
   209      sourhi=UBTOUI(d128->bytes   ); // directly load the high int
   210      sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high
   211      sourml=UBTOUI(d128->bytes+8 ); // then the mid-low
   212      sourlo=UBTOUI(d128->bytes+12); // then the low int
   213      }
   214  
   215    comb=(sourhi>>26)&0x1f;          // combination field
   216  
   217    decNumberZero(dn);               // clean number
   218    if (sourhi&0x80000000) dn->bits=DECNEG; // set sign if negative
   219  
   220    msd=COMBMSD[comb];               // decode the combination field
   221    exp=COMBEXP[comb];               // ..
   222  
   223    if (exp==3) {                    // is a special
   224      if (msd==0) {
   225        dn->bits|=DECINF;
   226        return dn;                   // no coefficient needed
   227        }
   228      else if (sourhi&0x02000000) dn->bits|=DECSNAN;
   229      else dn->bits|=DECNAN;
   230      msd=0;                         // no top digit
   231      }
   232     else {                          // is a finite number
   233      dn->exponent=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
   234      }
   235  
   236    // get the coefficient
   237    sourhi&=0x00003fff;              // clean coefficient continuation
   238    if (msd) {                       // non-zero msd
   239      sourhi|=msd<<14;               // prefix to coefficient
   240      need=12;                       // process 12 declets
   241      }
   242     else { // msd=0
   243      if (sourhi) need=11;           // declets to process
   244       else if (sourmh) need=10;
   245       else if (sourml) need=7;
   246       else if (sourlo) need=4;
   247       else return dn;               // easy: coefficient is 0
   248      } //msd=0
   249  
   250    decDigitsFromDPD(dn, sourar, need);   // process declets
   251    // decNumberShow(dn);
   252    return dn;
   253    } // decimal128ToNumber
   254  
   255  /* ------------------------------------------------------------------ */
   256  /* to-scientific-string -- conversion to numeric string               */
   257  /* to-engineering-string -- conversion to numeric string              */
   258  /*                                                                    */
   259  /*   decimal128ToString(d128, string);                                */
   260  /*   decimal128ToEngString(d128, string);                             */
   261  /*                                                                    */
   262  /*  d128 is the decimal128 format number to convert                   */
   263  /*  string is the string where the result will be laid out            */
   264  /*                                                                    */
   265  /*  string must be at least 24 characters                             */
   266  /*                                                                    */
   267  /*  No error is possible, and no status can be set.                   */
   268  /* ------------------------------------------------------------------ */
   269  char * decimal128ToEngString(const decimal128 *d128, char *string){
   270    decNumber dn;                         // work
   271    decimal128ToNumber(d128, &dn);
   272    decNumberToEngString(&dn, string);
   273    return string;
   274    } // decimal128ToEngString
   275  
   276  char * decimal128ToString(const decimal128 *d128, char *string){
   277    uInt msd;                        // coefficient MSD
   278    Int  exp;                        // exponent top two bits or full
   279    uInt comb;                       // combination field
   280    char *cstart;                    // coefficient start
   281    char *c;                         // output pointer in string
   282    const uByte *u;                  // work
   283    char *s, *t;                     // .. (source, target)
   284    Int  dpd;                        // ..
   285    Int  pre, e;                     // ..
   286    uInt uiwork;                     // for macros
   287  
   288    uInt sourar[4];                  // source 128-bit
   289    #define sourhi sourar[3]         // name the word with the sign
   290    #define sourmh sourar[2]         // and the mid-high word
   291    #define sourml sourar[1]         // and the mod-low word
   292    #define sourlo sourar[0]         // and the lowest word
   293  
   294    // load source from storage; this is endian
   295    if (DECLITEND) {
   296      sourlo=UBTOUI(d128->bytes   ); // directly load the low int
   297      sourml=UBTOUI(d128->bytes+4 ); // then the mid-low
   298      sourmh=UBTOUI(d128->bytes+8 ); // then the mid-high
   299      sourhi=UBTOUI(d128->bytes+12); // then the high int
   300      }
   301     else {
   302      sourhi=UBTOUI(d128->bytes   ); // directly load the high int
   303      sourmh=UBTOUI(d128->bytes+4 ); // then the mid-high
   304      sourml=UBTOUI(d128->bytes+8 ); // then the mid-low
   305      sourlo=UBTOUI(d128->bytes+12); // then the low int
   306      }
   307  
   308    c=string;                        // where result will go
   309    if (((Int)sourhi)<0) *c++='-';   // handle sign
   310  
   311    comb=(sourhi>>26)&0x1f;          // combination field
   312    msd=COMBMSD[comb];               // decode the combination field
   313    exp=COMBEXP[comb];               // ..
   314  
   315    if (exp==3) {
   316      if (msd==0) {                  // infinity
   317        strcpy(c,   "Inf");
   318        strcpy(c+3, "inity");
   319        return string;               // easy
   320        }
   321      if (sourhi&0x02000000) *c++='s'; // sNaN
   322      strcpy(c, "NaN");              // complete word
   323      c+=3;                          // step past
   324      if (sourlo==0 && sourml==0 && sourmh==0
   325       && (sourhi&0x0003ffff)==0) return string; // zero payload
   326      // otherwise drop through to add integer; set correct exp
   327      exp=0; msd=0;                  // setup for following code
   328      }
   329     else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; // unbiased
   330  
   331    // convert 34 digits of significand to characters
   332    cstart=c;                        // save start of coefficient
   333    if (msd) *c++='0'+(char)msd;     // non-zero most significant digit
   334  
   335    // Now decode the declets.  After extracting each one, it is
   336    // decoded to binary and then to a 4-char sequence by table lookup;
   337    // the 4-chars are a 1-char length (significant digits, except 000
   338    // has length 0).  This allows us to left-align the first declet
   339    // with non-zero content, then remaining ones are full 3-char
   340    // length.  We use fixed-length memcpys because variable-length
   341    // causes a subroutine call in GCC.  (These are length 4 for speed
   342    // and are safe because the array has an extra terminator byte.)
   343    #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                   \
   344                     if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
   345                      else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
   346    dpd=(sourhi>>4)&0x3ff;                     // declet 1
   347    dpd2char;
   348    dpd=((sourhi&0xf)<<6) | (sourmh>>26);      // declet 2
   349    dpd2char;
   350    dpd=(sourmh>>16)&0x3ff;                    // declet 3
   351    dpd2char;
   352    dpd=(sourmh>>6)&0x3ff;                     // declet 4
   353    dpd2char;
   354    dpd=((sourmh&0x3f)<<4) | (sourml>>28);     // declet 5
   355    dpd2char;
   356    dpd=(sourml>>18)&0x3ff;                    // declet 6
   357    dpd2char;
   358    dpd=(sourml>>8)&0x3ff;                     // declet 7
   359    dpd2char;
   360    dpd=((sourml&0xff)<<2) | (sourlo>>30);     // declet 8
   361    dpd2char;
   362    dpd=(sourlo>>20)&0x3ff;                    // declet 9
   363    dpd2char;
   364    dpd=(sourlo>>10)&0x3ff;                    // declet 10
   365    dpd2char;
   366    dpd=(sourlo)&0x3ff;                        // declet 11
   367    dpd2char;
   368  
   369    if (c==cstart) *c++='0';         // all zeros -- make 0
   370  
   371    if (exp==0) {                    // integer or NaN case -- easy
   372      *c='\0';                       // terminate
   373      return string;
   374      }
   375  
   376    /* non-0 exponent */
   377    e=0;                             // assume no E
   378    pre=c-cstart+exp;
   379    // [here, pre-exp is the digits count (==1 for zero)]
   380    if (exp>0 || pre<-5) {           // need exponential form
   381      e=pre-1;                       // calculate E value
   382      pre=1;                         // assume one digit before '.'
   383      } // exponential form
   384  
   385    /* modify the coefficient, adding 0s, '.', and E+nn as needed */
   386    s=c-1;                           // source (LSD)
   387    if (pre>0) {                     // ddd.ddd (plain), perhaps with E
   388      char *dotat=cstart+pre;
   389      if (dotat<c) {                 // if embedded dot needed...
   390        t=c;                              // target
   391        for (; s>=dotat; s--, t--) *t=*s; // open the gap; leave t at gap
   392        *t='.';                           // insert the dot
   393        c++;                              // length increased by one
   394        }
   395  
   396      // finally add the E-part, if needed; it will never be 0, and has
   397      // a maximum length of 4 digits
   398      if (e!=0) {
   399        *c++='E';                    // starts with E
   400        *c++='+';                    // assume positive
   401        if (e<0) {
   402          *(c-1)='-';                // oops, need '-'
   403          e=-e;                      // uInt, please
   404          }
   405        if (e<1000) {                // 3 (or fewer) digits case
   406          u=&BIN2CHAR[e*4];          // -> length byte
   407          memcpy(c, u+4-*u, 4);      // copy fixed 4 characters [is safe]
   408          c+=*u;                     // bump pointer appropriately
   409          }
   410         else {                      // 4-digits
   411          Int thou=((e>>3)*1049)>>17; // e/1000
   412          Int rem=e-(1000*thou);      // e%1000
   413          *c++='0'+(char)thou;
   414          u=&BIN2CHAR[rem*4];        // -> length byte
   415          memcpy(c, u+1, 4);         // copy fixed 3+1 characters [is safe]
   416          c+=3;                      // bump pointer, always 3 digits
   417          }
   418        }
   419      *c='\0';                       // add terminator
   420      //printf("res %s\n", string);
   421      return string;
   422      } // pre>0
   423  
   424    /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
   425    t=c+1-pre;
   426    *(t+1)='\0';                          // can add terminator now
   427    for (; s>=cstart; s--, t--) *t=*s;    // shift whole coefficient right
   428    c=cstart;
   429    *c++='0';                             // always starts with 0.
   430    *c++='.';
   431    for (; pre<0; pre++) *c++='0';        // add any 0's after '.'
   432    //printf("res %s\n", string);
   433    return string;
   434    } // decimal128ToString
   435  
   436  /* ------------------------------------------------------------------ */
   437  /* to-number -- conversion from numeric string                        */
   438  /*                                                                    */
   439  /*   decimal128FromString(result, string, set);                       */
   440  /*                                                                    */
   441  /*  result  is the decimal128 format number which gets the result of  */
   442  /*          the conversion                                            */
   443  /*  *string is the character string which should contain a valid      */
   444  /*          number (which may be a special value)                     */
   445  /*  set     is the context                                            */
   446  /*                                                                    */
   447  /* The context is supplied to this routine is used for error handling */
   448  /* (setting of status and traps) and for the rounding mode, only.     */
   449  /* If an error occurs, the result will be a valid decimal128 NaN.     */
   450  /* ------------------------------------------------------------------ */
   451  decimal128 * decimal128FromString(decimal128 *result, const char *string,
   452                                    decContext *set) {
   453    decContext dc;                             // work
   454    decNumber dn;                              // ..
   455  
   456    decContextDefault(&dc, DEC_INIT_DECIMAL128); // no traps, please
   457    dc.round=set->round;                         // use supplied rounding
   458  
   459    decNumberFromString(&dn, string, &dc);     // will round if needed
   460    decimal128FromNumber(result, &dn, &dc);
   461    if (dc.status!=0) {                        // something happened
   462      decContextSetStatus(set, dc.status);     // .. pass it on
   463      }
   464    return result;
   465    } // decimal128FromString
   466  
   467  /* ------------------------------------------------------------------ */
   468  /* decimal128IsCanonical -- test whether encoding is canonical        */
   469  /*   d128 is the source decimal128                                    */
   470  /*   returns 1 if the encoding of d128 is canonical, 0 otherwise      */
   471  /* No error is possible.                                              */
   472  /* ------------------------------------------------------------------ */
   473  uInt decimal128IsCanonical(const decimal128 *d128) {
   474    decNumber dn;                         // work
   475    decimal128 canon;                      // ..
   476    decContext dc;                        // ..
   477    decContextDefault(&dc, DEC_INIT_DECIMAL128);
   478    decimal128ToNumber(d128, &dn);
   479    decimal128FromNumber(&canon, &dn, &dc);// canon will now be canonical
   480    return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
   481    } // decimal128IsCanonical
   482  
   483  /* ------------------------------------------------------------------ */
   484  /* decimal128Canonical -- copy an encoding, ensuring it is canonical  */
   485  /*   d128 is the source decimal128                                    */
   486  /*   result is the target (may be the same decimal128)                */
   487  /*   returns result                                                   */
   488  /* No error is possible.                                              */
   489  /* ------------------------------------------------------------------ */
   490  decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
   491    decNumber dn;                         // work
   492    decContext dc;                        // ..
   493    decContextDefault(&dc, DEC_INIT_DECIMAL128);
   494    decimal128ToNumber(d128, &dn);
   495    decimal128FromNumber(result, &dn, &dc);// result will now be canonical
   496    return result;
   497    } // decimal128Canonical
   498  
   499  #if DECTRACE || DECCHECK
   500  /* Macros for accessing decimal128 fields.  These assume the argument
   501     is a reference (pointer) to the decimal128 structure, and the
   502     decimal128 is in network byte order (big-endian) */
   503  // Get sign
   504  #define decimal128Sign(d)       ((unsigned)(d)->bytes[0]>>7)
   505  
   506  // Get combination field
   507  #define decimal128Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
   508  
   509  // Get exponent continuation [does not remove bias]
   510  #define decimal128ExpCon(d)     ((((d)->bytes[0] & 0x03)<<10)         \
   511                                | ((unsigned)(d)->bytes[1]<<2)          \
   512                                | ((unsigned)(d)->bytes[2]>>6))
   513  
   514  // Set sign [this assumes sign previously 0]
   515  #define decimal128SetSign(d, b) {                                     \
   516    (d)->bytes[0]|=((unsigned)(b)<<7);}
   517  
   518  // Set exponent continuation [does not apply bias]
   519  // This assumes range has been checked and exponent previously 0;
   520  // type of exponent must be unsigned
   521  #define decimal128SetExpCon(d, e) {                                   \
   522    (d)->bytes[0]|=(uByte)((e)>>10);                                    \
   523    (d)->bytes[1] =(uByte)(((e)&0x3fc)>>2);                             \
   524    (d)->bytes[2]|=(uByte)(((e)&0x03)<<6);}
   525  
   526  /* ------------------------------------------------------------------ */
   527  /* decimal128Show -- display a decimal128 in hexadecimal [debug aid]  */
   528  /*   d128 -- the number to show                                       */
   529  /* ------------------------------------------------------------------ */
   530  // Also shows sign/cob/expconfields extracted
   531  void decimal128Show(const decimal128 *d128) {
   532    char buf[DECIMAL128_Bytes*2+1];
   533    Int i, j=0;
   534  
   535    if (DECLITEND) {
   536      for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
   537        sprintf(&buf[j], "%02x", d128->bytes[15-i]);
   538        }
   539      printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
   540             d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
   541             ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
   542             (d128->bytes[13]>>6));
   543      }
   544     else {
   545      for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
   546        sprintf(&buf[j], "%02x", d128->bytes[i]);
   547        }
   548      printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
   549             decimal128Sign(d128), decimal128Comb(d128),
   550             decimal128ExpCon(d128));
   551      }
   552    } // decimal128Show
   553  #endif