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