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