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