Import gcc-4.4.1
[dragonfly.git] / contrib / gcc-4.4 / libdecnumber / dpd / decimal128.c
1 /* Decimal 128-bit format module for the decNumber C Library.
2    Copyright (C) 2005, 2007, 2009 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 *pu;                        /* .. */
88   uInt comb, exp;                  /* .. */
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   pu=(uInt *)d128->bytes;          /* overlay */
171   if (DECLITEND) {
172     pu[0]=targlo;                  /* directly store the low int */
173     pu[1]=targml;                  /* then the mid-low */
174     pu[2]=targmh;                  /* then the mid-high */
175     pu[3]=targhi;                  /* then the high int */
176     }
177    else {
178     pu[0]=targhi;                  /* directly store the high int */
179     pu[1]=targmh;                  /* then the mid-high */
180     pu[2]=targml;                  /* then the mid-low */
181     pu[3]=targlo;                  /* then the low int */
182     }
183
184   if (status!=0) decContextSetStatus(set, status); /* pass on status */
185   /* decimal128Show(d128); */
186   return d128;
187   } /* decimal128FromNumber */
188
189 /* ------------------------------------------------------------------ */
190 /* decimal128ToNumber -- convert decimal128 to decNumber              */
191 /*   d128 is the source decimal128                                    */
192 /*   dn is the target number, with appropriate space                  */
193 /* No error is possible.                                              */
194 /* ------------------------------------------------------------------ */
195 decNumber * decimal128ToNumber(const decimal128 *d128, decNumber *dn) {
196   uInt msd;                        /* coefficient MSD */
197   uInt exp;                        /* exponent top two bits */
198   uInt comb;                       /* combination field */
199   const uInt *pu;                  /* work */
200   Int  need;                       /* .. */
201   uInt sourar[4];                  /* source 128-bit */
202   #define sourhi sourar[3]         /* name the word with the sign */
203   #define sourmh sourar[2]         /* and the mid-high word */
204   #define sourml sourar[1]         /* and the mod-low word */
205   #define sourlo sourar[0]         /* and the lowest word */
206
207   /* load source from storage; this is endian */
208   pu=(const uInt *)d128->bytes;    /* overlay */
209   if (DECLITEND) {
210     sourlo=pu[0];                  /* directly load the low int */
211     sourml=pu[1];                  /* then the mid-low */
212     sourmh=pu[2];                  /* then the mid-high */
213     sourhi=pu[3];                  /* then the high int */
214     }
215    else {
216     sourhi=pu[0];                  /* directly load the high int */
217     sourmh=pu[1];                  /* then the mid-high */
218     sourml=pu[2];                  /* then the mid-low */
219     sourlo=pu[3];                  /* 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 uInt *pu;                  /* work */
290   char *s, *t;                     /* .. (source, target) */
291   Int  dpd;                        /* .. */
292   Int  pre, e;                     /* .. */
293   const uByte *u;                  /* .. */
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   pu=(const uInt *)d128->bytes;    /* overlay */
303   if (DECLITEND) {
304     sourlo=pu[0];                  /* directly load the low int */
305     sourml=pu[1];                  /* then the mid-low */
306     sourmh=pu[2];                  /* then the mid-high */
307     sourhi=pu[3];                  /* then the high int */
308     }
309    else {
310     sourhi=pu[0];                  /* directly load the high int */
311     sourmh=pu[1];                  /* then the mid-high */
312     sourml=pu[2];                  /* then the mid-low */
313     sourlo=pu[3];                  /* then the low int */
314     }
315
316   c=string;                        /* where result will go */
317   if (((Int)sourhi)<0) *c++='-';   /* handle sign */
318
319   comb=(sourhi>>26)&0x1f;          /* combination field */
320   msd=COMBMSD[comb];               /* decode the combination field */
321   exp=COMBEXP[comb];               /* .. */
322
323   if (exp==3) {
324     if (msd==0) {                  /* infinity */
325       strcpy(c,   "Inf");
326       strcpy(c+3, "inity");
327       return string;               /* easy */
328       }
329     if (sourhi&0x02000000) *c++='s'; /* sNaN */
330     strcpy(c, "NaN");              /* complete word */
331     c+=3;                          /* step past */
332     if (sourlo==0 && sourml==0 && sourmh==0
333      && (sourhi&0x0003ffff)==0) return string; /* zero payload */
334     /* otherwise drop through to add integer; set correct exp */
335     exp=0; msd=0;                  /* setup for following code */
336     }
337    else exp=(exp<<12)+((sourhi>>14)&0xfff)-DECIMAL128_Bias; /* unbiased */
338
339   /* convert 34 digits of significand to characters */
340   cstart=c;                        /* save start of coefficient */
341   if (msd) *c++='0'+(char)msd;     /* non-zero most significant digit */
342
343   /* Now decode the declets.  After extracting each one, it is */
344   /* decoded to binary and then to a 4-char sequence by table lookup; */
345   /* the 4-chars are a 1-char length (significant digits, except 000 */
346   /* has length 0).  This allows us to left-align the first declet */
347   /* with non-zero content, then remaining ones are full 3-char */
348   /* length.  We use fixed-length memcpys because variable-length */
349   /* causes a subroutine call in GCC.  (These are length 4 for speed */
350   /* and are safe because the array has an extra terminator byte.) */
351   #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4];                   \
352                    if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}      \
353                     else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
354   dpd=(sourhi>>4)&0x3ff;                     /* declet 1 */
355   dpd2char;
356   dpd=((sourhi&0xf)<<6) | (sourmh>>26);      /* declet 2 */
357   dpd2char;
358   dpd=(sourmh>>16)&0x3ff;                    /* declet 3 */
359   dpd2char;
360   dpd=(sourmh>>6)&0x3ff;                     /* declet 4 */
361   dpd2char;
362   dpd=((sourmh&0x3f)<<4) | (sourml>>28);     /* declet 5 */
363   dpd2char;
364   dpd=(sourml>>18)&0x3ff;                    /* declet 6 */
365   dpd2char;
366   dpd=(sourml>>8)&0x3ff;                     /* declet 7 */
367   dpd2char;
368   dpd=((sourml&0xff)<<2) | (sourlo>>30);     /* declet 8 */
369   dpd2char;
370   dpd=(sourlo>>20)&0x3ff;                    /* declet 9 */
371   dpd2char;
372   dpd=(sourlo>>10)&0x3ff;                    /* declet 10 */
373   dpd2char;
374   dpd=(sourlo)&0x3ff;                        /* declet 11 */
375   dpd2char;
376
377   if (c==cstart) *c++='0';         /* all zeros -- make 0 */
378
379   if (exp==0) {                    /* integer or NaN case -- easy */
380     *c='\0';                       /* terminate */
381     return string;
382     }
383
384   /* non-0 exponent */
385   e=0;                             /* assume no E */
386   pre=c-cstart+exp;
387   /* [here, pre-exp is the digits count (==1 for zero)] */
388   if (exp>0 || pre<-5) {           /* need exponential form */
389     e=pre-1;                       /* calculate E value */
390     pre=1;                         /* assume one digit before '.' */
391     } /* exponential form */
392
393   /* modify the coefficient, adding 0s, '.', and E+nn as needed */
394   s=c-1;                           /* source (LSD) */
395   if (pre>0) {                     /* ddd.ddd (plain), perhaps with E */
396     char *dotat=cstart+pre;
397     if (dotat<c) {                 /* if embedded dot needed... */
398       t=c;                              /* target */
399       for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
400       *t='.';                           /* insert the dot */
401       c++;                              /* length increased by one */
402       }
403
404     /* finally add the E-part, if needed; it will never be 0, and has */
405     /* a maximum length of 4 digits */
406     if (e!=0) {
407       *c++='E';                    /* starts with E */
408       *c++='+';                    /* assume positive */
409       if (e<0) {
410         *(c-1)='-';                /* oops, need '-' */
411         e=-e;                      /* uInt, please */
412         }
413       if (e<1000) {                /* 3 (or fewer) digits case */
414         u=&BIN2CHAR[e*4];          /* -> length byte */
415         memcpy(c, u+4-*u, 4);      /* copy fixed 4 characters [is safe] */
416         c+=*u;                     /* bump pointer appropriately */
417         }
418        else {                      /* 4-digits */
419         Int thou=((e>>3)*1049)>>17; /* e/1000 */
420         Int rem=e-(1000*thou);      /* e%1000 */
421         *c++='0'+(char)thou;
422         u=&BIN2CHAR[rem*4];        /* -> length byte */
423         memcpy(c, u+1, 4);         /* copy fixed 3+1 characters [is safe] */
424         c+=3;                      /* bump pointer, always 3 digits */
425         }
426       }
427     *c='\0';                       /* add terminator */
428     /*printf("res %s\n", string); */
429     return string;
430     } /* pre>0 */
431
432   /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
433   t=c+1-pre;
434   *(t+1)='\0';                          /* can add terminator now */
435   for (; s>=cstart; s--, t--) *t=*s;    /* shift whole coefficient right */
436   c=cstart;
437   *c++='0';                             /* always starts with 0. */
438   *c++='.';
439   for (; pre<0; pre++) *c++='0';        /* add any 0's after '.' */
440   /*printf("res %s\n", string); */
441   return string;
442   } /* decimal128ToString */
443
444 /* ------------------------------------------------------------------ */
445 /* to-number -- conversion from numeric string                        */
446 /*                                                                    */
447 /*   decimal128FromString(result, string, set);                       */
448 /*                                                                    */
449 /*  result  is the decimal128 format number which gets the result of  */
450 /*          the conversion                                            */
451 /*  *string is the character string which should contain a valid      */
452 /*          number (which may be a special value)                     */
453 /*  set     is the context                                            */
454 /*                                                                    */
455 /* The context is supplied to this routine is used for error handling */
456 /* (setting of status and traps) and for the rounding mode, only.     */
457 /* If an error occurs, the result will be a valid decimal128 NaN.     */
458 /* ------------------------------------------------------------------ */
459 decimal128 * decimal128FromString(decimal128 *result, const char *string,
460                                   decContext *set) {
461   decContext dc;                             /* work */
462   decNumber dn;                              /* .. */
463
464   decContextDefault(&dc, DEC_INIT_DECIMAL128); /* no traps, please */
465   dc.round=set->round;                         /* use supplied rounding */
466
467   decNumberFromString(&dn, string, &dc);     /* will round if needed */
468   decimal128FromNumber(result, &dn, &dc);
469   if (dc.status!=0) {                        /* something happened */
470     decContextSetStatus(set, dc.status);     /* .. pass it on */
471     }
472   return result;
473   } /* decimal128FromString */
474
475 /* ------------------------------------------------------------------ */
476 /* decimal128IsCanonical -- test whether encoding is canonical        */
477 /*   d128 is the source decimal128                                    */
478 /*   returns 1 if the encoding of d128 is canonical, 0 otherwise      */
479 /* No error is possible.                                              */
480 /* ------------------------------------------------------------------ */
481 uint32_t decimal128IsCanonical(const decimal128 *d128) {
482   decNumber dn;                         /* work */
483   decimal128 canon;                      /* .. */
484   decContext dc;                        /* .. */
485   decContextDefault(&dc, DEC_INIT_DECIMAL128);
486   decimal128ToNumber(d128, &dn);
487   decimal128FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
488   return memcmp(d128, &canon, DECIMAL128_Bytes)==0;
489   } /* decimal128IsCanonical */
490
491 /* ------------------------------------------------------------------ */
492 /* decimal128Canonical -- copy an encoding, ensuring it is canonical  */
493 /*   d128 is the source decimal128                                    */
494 /*   result is the target (may be the same decimal128)                */
495 /*   returns result                                                   */
496 /* No error is possible.                                              */
497 /* ------------------------------------------------------------------ */
498 decimal128 * decimal128Canonical(decimal128 *result, const decimal128 *d128) {
499   decNumber dn;                         /* work */
500   decContext dc;                        /* .. */
501   decContextDefault(&dc, DEC_INIT_DECIMAL128);
502   decimal128ToNumber(d128, &dn);
503   decimal128FromNumber(result, &dn, &dc);/* result will now be canonical */
504   return result;
505   } /* decimal128Canonical */
506
507 #if DECTRACE || DECCHECK
508 /* Macros for accessing decimal128 fields.  These assume the argument
509    is a reference (pointer) to the decimal128 structure, and the
510    decimal128 is in network byte order (big-endian) */
511 /* Get sign */
512 #define decimal128Sign(d)       ((unsigned)(d)->bytes[0]>>7)
513
514 /* Get combination field */
515 #define decimal128Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
516
517 /* Get exponent continuation [does not remove bias] */
518 #define decimal128ExpCon(d)     ((((d)->bytes[0] & 0x03)<<10)         \
519                               | ((unsigned)(d)->bytes[1]<<2)          \
520                               | ((unsigned)(d)->bytes[2]>>6))
521
522 /* Set sign [this assumes sign previously 0] */
523 #define decimal128SetSign(d, b) {                                     \
524   (d)->bytes[0]|=((unsigned)(b)<<7);}
525
526 /* Set exponent continuation [does not apply bias] */
527 /* This assumes range has been checked and exponent previously 0; */
528 /* type of exponent must be unsigned */
529 #define decimal128SetExpCon(d, e) {                                   \
530   (d)->bytes[0]|=(uint8_t)((e)>>10);                                  \
531   (d)->bytes[1] =(uint8_t)(((e)&0x3fc)>>2);                           \
532   (d)->bytes[2]|=(uint8_t)(((e)&0x03)<<6);}
533
534 /* ------------------------------------------------------------------ */
535 /* decimal128Show -- display a decimal128 in hexadecimal [debug aid]  */
536 /*   d128 -- the number to show                                       */
537 /* ------------------------------------------------------------------ */
538 /* Also shows sign/cob/expconfields extracted */
539 void decimal128Show(const decimal128 *d128) {
540   char buf[DECIMAL128_Bytes*2+1];
541   Int i, j=0;
542
543   if (DECLITEND) {
544     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
545       sprintf(&buf[j], "%02x", d128->bytes[15-i]);
546       }
547     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
548            d128->bytes[15]>>7, (d128->bytes[15]>>2)&0x1f,
549            ((d128->bytes[15]&0x3)<<10)|(d128->bytes[14]<<2)|
550            (d128->bytes[13]>>6));
551     }
552    else {
553     for (i=0; i<DECIMAL128_Bytes; i++, j+=2) {
554       sprintf(&buf[j], "%02x", d128->bytes[i]);
555       }
556     printf(" D128> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
557            decimal128Sign(d128), decimal128Comb(d128),
558            decimal128ExpCon(d128));
559     }
560   } /* decimal128Show */
561 #endif