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