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