15796c8dcSSimon Schubert /* Decimal 32-bit format module for the decNumber C Library.
2*ef5ccd6cSJohn Marino    Copyright (C) 2005-2013 Free Software Foundation, Inc.
35796c8dcSSimon Schubert    Contributed by IBM Corporation.  Author Mike Cowlishaw.
45796c8dcSSimon Schubert 
55796c8dcSSimon Schubert    This file is part of GCC.
65796c8dcSSimon Schubert 
75796c8dcSSimon Schubert    GCC is free software; you can redistribute it and/or modify it under
85796c8dcSSimon Schubert    the terms of the GNU General Public License as published by the Free
95796c8dcSSimon Schubert    Software Foundation; either version 3, or (at your option) any later
105796c8dcSSimon Schubert    version.
115796c8dcSSimon Schubert 
125796c8dcSSimon Schubert    GCC is distributed in the hope that it will be useful, but WITHOUT ANY
135796c8dcSSimon Schubert    WARRANTY; without even the implied warranty of MERCHANTABILITY or
145796c8dcSSimon Schubert    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
155796c8dcSSimon Schubert    for more details.
165796c8dcSSimon Schubert 
175796c8dcSSimon Schubert Under Section 7 of GPL version 3, you are granted additional
185796c8dcSSimon Schubert permissions described in the GCC Runtime Library Exception, version
195796c8dcSSimon Schubert 3.1, as published by the Free Software Foundation.
205796c8dcSSimon Schubert 
215796c8dcSSimon Schubert You should have received a copy of the GNU General Public License and
225796c8dcSSimon Schubert a copy of the GCC Runtime Library Exception along with this program;
235796c8dcSSimon Schubert see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
245796c8dcSSimon Schubert <http://www.gnu.org/licenses/>.  */
255796c8dcSSimon Schubert 
265796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
275796c8dcSSimon Schubert /* Decimal 32-bit format module 				      */
285796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
295796c8dcSSimon Schubert /* This module comprises the routines for decimal32 format numbers.   */
305796c8dcSSimon Schubert /* Conversions are supplied to and from decNumber and String.	      */
315796c8dcSSimon Schubert /*								      */
325796c8dcSSimon Schubert /* This is used when decNumber provides operations, either for all    */
335796c8dcSSimon Schubert /* operations or as a proxy between decNumber and decSingle.	      */
345796c8dcSSimon Schubert /*								      */
355796c8dcSSimon Schubert /* Error handling is the same as decNumber (qv.).		      */
365796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
375796c8dcSSimon Schubert #include <string.h>	      /* [for memset/memcpy] */
385796c8dcSSimon Schubert #include <stdio.h>	      /* [for printf] */
395796c8dcSSimon Schubert 
405796c8dcSSimon Schubert #include "dconfig.h"          /* GCC definitions */
415796c8dcSSimon Schubert #define  DECNUMDIGITS  7      /* make decNumbers with space for 7 */
425796c8dcSSimon Schubert #include "decNumber.h"	      /* base number library */
435796c8dcSSimon Schubert #include "decNumberLocal.h"   /* decNumber local types, etc. */
445796c8dcSSimon Schubert #include "decimal32.h"	      /* our primary include */
455796c8dcSSimon Schubert 
465796c8dcSSimon Schubert /* Utility tables and routines [in decimal64.c] */
475796c8dcSSimon Schubert extern const uInt   COMBEXP[32], COMBMSD[32];
485796c8dcSSimon Schubert extern const uShort DPD2BIN[1024];
495796c8dcSSimon Schubert extern const uShort BIN2DPD[1000];
505796c8dcSSimon Schubert extern const uByte  BIN2CHAR[4001];
515796c8dcSSimon Schubert 
525796c8dcSSimon Schubert extern void decDigitsToDPD(const decNumber *, uInt *, Int);
535796c8dcSSimon Schubert extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
545796c8dcSSimon Schubert 
555796c8dcSSimon Schubert #if DECTRACE || DECCHECK
565796c8dcSSimon Schubert void decimal32Show(const decimal32 *);		  /* for debug */
575796c8dcSSimon Schubert extern void decNumberShow(const decNumber *);	  /* .. */
585796c8dcSSimon Schubert #endif
595796c8dcSSimon Schubert 
605796c8dcSSimon Schubert /* Useful macro */
615796c8dcSSimon Schubert /* Clear a structure (e.g., a decNumber) */
625796c8dcSSimon Schubert #define DEC_clear(d) memset(d, 0, sizeof(*d))
635796c8dcSSimon Schubert 
645796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
655796c8dcSSimon Schubert /* decimal32FromNumber -- convert decNumber to decimal32	      */
665796c8dcSSimon Schubert /*								      */
675796c8dcSSimon Schubert /*   ds is the target decimal32 				      */
685796c8dcSSimon Schubert /*   dn is the source number (assumed valid)			      */
695796c8dcSSimon Schubert /*   set is the context, used only for reporting errors 	      */
705796c8dcSSimon Schubert /*								      */
715796c8dcSSimon Schubert /* The set argument is used only for status reporting and for the     */
725796c8dcSSimon Schubert /* rounding mode (used if the coefficient is more than DECIMAL32_Pmax */
735796c8dcSSimon Schubert /* digits or an overflow is detected).	If the exponent is out of the */
745796c8dcSSimon Schubert /* valid range then Overflow or Underflow will be raised.	      */
755796c8dcSSimon Schubert /* After Underflow a subnormal result is possible.		      */
765796c8dcSSimon Schubert /*								      */
775796c8dcSSimon Schubert /* DEC_Clamped is set if the number has to be 'folded down' to fit,   */
785796c8dcSSimon Schubert /* by reducing its exponent and multiplying the coefficient by a      */
795796c8dcSSimon Schubert /* power of ten, or if the exponent on a zero had to be clamped.      */
805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal32FromNumber(decimal32 * d32,const decNumber * dn,decContext * set)815796c8dcSSimon Schubert decimal32 * decimal32FromNumber(decimal32 *d32, const decNumber *dn,
825796c8dcSSimon Schubert 			      decContext *set) {
835796c8dcSSimon Schubert   uInt status=0;		   /* status accumulator */
845796c8dcSSimon Schubert   Int ae;			   /* adjusted exponent */
855796c8dcSSimon Schubert   decNumber  dw;		   /* work */
865796c8dcSSimon Schubert   decContext dc;		   /* .. */
875796c8dcSSimon Schubert   uInt comb, exp;		   /* .. */
885796c8dcSSimon Schubert   uInt uiwork;			   /* for macros */
895796c8dcSSimon Schubert   uInt targ=0;			   /* target 32-bit */
905796c8dcSSimon Schubert 
915796c8dcSSimon Schubert   /* If the number has too many digits, or the exponent could be */
925796c8dcSSimon Schubert   /* out of range then reduce the number under the appropriate */
935796c8dcSSimon Schubert   /* constraints.  This could push the number to Infinity or zero, */
945796c8dcSSimon Schubert   /* so this check and rounding must be done before generating the */
955796c8dcSSimon Schubert   /* decimal32] */
965796c8dcSSimon Schubert   ae=dn->exponent+dn->digits-1; 	     /* [0 if special] */
975796c8dcSSimon Schubert   if (dn->digits>DECIMAL32_Pmax 	     /* too many digits */
985796c8dcSSimon Schubert    || ae>DECIMAL32_Emax 		     /* likely overflow */
995796c8dcSSimon Schubert    || ae<DECIMAL32_Emin) {		     /* likely underflow */
1005796c8dcSSimon Schubert     decContextDefault(&dc, DEC_INIT_DECIMAL32); /* [no traps] */
1015796c8dcSSimon Schubert     dc.round=set->round;		     /* use supplied rounding */
1025796c8dcSSimon Schubert     decNumberPlus(&dw, dn, &dc);	     /* (round and check) */
1035796c8dcSSimon Schubert     /* [this changes -0 to 0, so enforce the sign...] */
1045796c8dcSSimon Schubert     dw.bits|=dn->bits&DECNEG;
1055796c8dcSSimon Schubert     status=dc.status;			     /* save status */
1065796c8dcSSimon Schubert     dn=&dw;				     /* use the work number */
1075796c8dcSSimon Schubert     } /* maybe out of range */
1085796c8dcSSimon Schubert 
1095796c8dcSSimon Schubert   if (dn->bits&DECSPECIAL) {			  /* a special value */
1105796c8dcSSimon Schubert     if (dn->bits&DECINF) targ=DECIMAL_Inf<<24;
1115796c8dcSSimon Schubert      else {					  /* sNaN or qNaN */
1125796c8dcSSimon Schubert       if ((*dn->lsu!=0 || dn->digits>1) 	  /* non-zero coefficient */
1135796c8dcSSimon Schubert        && (dn->digits<DECIMAL32_Pmax)) {	  /* coefficient fits */
1145796c8dcSSimon Schubert 	decDigitsToDPD(dn, &targ, 0);
1155796c8dcSSimon Schubert 	}
1165796c8dcSSimon Schubert       if (dn->bits&DECNAN) targ|=DECIMAL_NaN<<24;
1175796c8dcSSimon Schubert        else targ|=DECIMAL_sNaN<<24;
1185796c8dcSSimon Schubert       } /* a NaN */
1195796c8dcSSimon Schubert     } /* special */
1205796c8dcSSimon Schubert 
1215796c8dcSSimon Schubert    else { /* is finite */
1225796c8dcSSimon Schubert     if (decNumberIsZero(dn)) {		     /* is a zero */
1235796c8dcSSimon Schubert       /* set and clamp exponent */
1245796c8dcSSimon Schubert       if (dn->exponent<-DECIMAL32_Bias) {
1255796c8dcSSimon Schubert 	exp=0;				     /* low clamp */
1265796c8dcSSimon Schubert 	status|=DEC_Clamped;
1275796c8dcSSimon Schubert 	}
1285796c8dcSSimon Schubert        else {
1295796c8dcSSimon Schubert 	exp=dn->exponent+DECIMAL32_Bias;     /* bias exponent */
1305796c8dcSSimon Schubert 	if (exp>DECIMAL32_Ehigh) {	     /* top clamp */
1315796c8dcSSimon Schubert 	  exp=DECIMAL32_Ehigh;
1325796c8dcSSimon Schubert 	  status|=DEC_Clamped;
1335796c8dcSSimon Schubert 	  }
1345796c8dcSSimon Schubert 	}
1355796c8dcSSimon Schubert       comb=(exp>>3) & 0x18;		/* msd=0, exp top 2 bits .. */
1365796c8dcSSimon Schubert       }
1375796c8dcSSimon Schubert      else {				/* non-zero finite number */
1385796c8dcSSimon Schubert       uInt msd; 			/* work */
1395796c8dcSSimon Schubert       Int pad=0;			/* coefficient pad digits */
1405796c8dcSSimon Schubert 
1415796c8dcSSimon Schubert       /* the dn is known to fit, but it may need to be padded */
1425796c8dcSSimon Schubert       exp=(uInt)(dn->exponent+DECIMAL32_Bias);	  /* bias exponent */
1435796c8dcSSimon Schubert       if (exp>DECIMAL32_Ehigh) {		  /* fold-down case */
1445796c8dcSSimon Schubert 	pad=exp-DECIMAL32_Ehigh;
1455796c8dcSSimon Schubert 	exp=DECIMAL32_Ehigh;			  /* [to maximum] */
1465796c8dcSSimon Schubert 	status|=DEC_Clamped;
1475796c8dcSSimon Schubert 	}
1485796c8dcSSimon Schubert 
1495796c8dcSSimon Schubert       /* fastpath common case */
1505796c8dcSSimon Schubert       if (DECDPUN==3 && pad==0) {
1515796c8dcSSimon Schubert 	targ=BIN2DPD[dn->lsu[0]];
1525796c8dcSSimon Schubert 	if (dn->digits>3) targ|=(uInt)(BIN2DPD[dn->lsu[1]])<<10;
1535796c8dcSSimon Schubert 	msd=(dn->digits==7 ? dn->lsu[2] : 0);
1545796c8dcSSimon Schubert 	}
1555796c8dcSSimon Schubert        else { /* general case */
1565796c8dcSSimon Schubert 	decDigitsToDPD(dn, &targ, pad);
1575796c8dcSSimon Schubert 	/* save and clear the top digit */
1585796c8dcSSimon Schubert 	msd=targ>>20;
1595796c8dcSSimon Schubert 	targ&=0x000fffff;
1605796c8dcSSimon Schubert 	}
1615796c8dcSSimon Schubert 
1625796c8dcSSimon Schubert       /* create the combination field */
1635796c8dcSSimon Schubert       if (msd>=8) comb=0x18 | ((exp>>5) & 0x06) | (msd & 0x01);
1645796c8dcSSimon Schubert 	     else comb=((exp>>3) & 0x18) | msd;
1655796c8dcSSimon Schubert       }
1665796c8dcSSimon Schubert     targ|=comb<<26;		   /* add combination field .. */
1675796c8dcSSimon Schubert     targ|=(exp&0x3f)<<20;	   /* .. and exponent continuation */
1685796c8dcSSimon Schubert     } /* finite */
1695796c8dcSSimon Schubert 
1705796c8dcSSimon Schubert   if (dn->bits&DECNEG) targ|=0x80000000;  /* add sign bit */
1715796c8dcSSimon Schubert 
1725796c8dcSSimon Schubert   /* now write to storage; this is endian */
1735796c8dcSSimon Schubert   UBFROMUI(d32->bytes, targ);	   /* directly store the int */
1745796c8dcSSimon Schubert 
1755796c8dcSSimon Schubert   if (status!=0) decContextSetStatus(set, status); /* pass on status */
1765796c8dcSSimon Schubert   /* decimal32Show(d32); */
1775796c8dcSSimon Schubert   return d32;
1785796c8dcSSimon Schubert   } /* decimal32FromNumber */
1795796c8dcSSimon Schubert 
1805796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
1815796c8dcSSimon Schubert /* decimal32ToNumber -- convert decimal32 to decNumber		      */
1825796c8dcSSimon Schubert /*   d32 is the source decimal32				      */
1835796c8dcSSimon Schubert /*   dn is the target number, with appropriate space		      */
1845796c8dcSSimon Schubert /* No error is possible.					      */
1855796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal32ToNumber(const decimal32 * d32,decNumber * dn)1865796c8dcSSimon Schubert decNumber * decimal32ToNumber(const decimal32 *d32, decNumber *dn) {
1875796c8dcSSimon Schubert   uInt msd;			   /* coefficient MSD */
1885796c8dcSSimon Schubert   uInt exp;			   /* exponent top two bits */
1895796c8dcSSimon Schubert   uInt comb;			   /* combination field */
1905796c8dcSSimon Schubert   uInt sour;			   /* source 32-bit */
1915796c8dcSSimon Schubert   uInt uiwork;			   /* for macros */
1925796c8dcSSimon Schubert 
1935796c8dcSSimon Schubert   /* load source from storage; this is endian */
1945796c8dcSSimon Schubert   sour=UBTOUI(d32->bytes);	   /* directly load the int */
1955796c8dcSSimon Schubert 
1965796c8dcSSimon Schubert   comb=(sour>>26)&0x1f; 	   /* combination field */
1975796c8dcSSimon Schubert 
1985796c8dcSSimon Schubert   decNumberZero(dn);		   /* clean number */
1995796c8dcSSimon Schubert   if (sour&0x80000000) dn->bits=DECNEG; /* set sign if negative */
2005796c8dcSSimon Schubert 
2015796c8dcSSimon Schubert   msd=COMBMSD[comb];		   /* decode the combination field */
2025796c8dcSSimon Schubert   exp=COMBEXP[comb];		   /* .. */
2035796c8dcSSimon Schubert 
2045796c8dcSSimon Schubert   if (exp==3) { 		   /* is a special */
2055796c8dcSSimon Schubert     if (msd==0) {
2065796c8dcSSimon Schubert       dn->bits|=DECINF;
2075796c8dcSSimon Schubert       return dn;		   /* no coefficient needed */
2085796c8dcSSimon Schubert       }
2095796c8dcSSimon Schubert     else if (sour&0x02000000) dn->bits|=DECSNAN;
2105796c8dcSSimon Schubert     else dn->bits|=DECNAN;
2115796c8dcSSimon Schubert     msd=0;			   /* no top digit */
2125796c8dcSSimon Schubert     }
2135796c8dcSSimon Schubert    else {			   /* is a finite number */
2145796c8dcSSimon Schubert     dn->exponent=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
2155796c8dcSSimon Schubert     }
2165796c8dcSSimon Schubert 
2175796c8dcSSimon Schubert   /* get the coefficient */
2185796c8dcSSimon Schubert   sour&=0x000fffff;		   /* clean coefficient continuation */
2195796c8dcSSimon Schubert   if (msd) {			   /* non-zero msd */
2205796c8dcSSimon Schubert     sour|=msd<<20;		   /* prefix to coefficient */
2215796c8dcSSimon Schubert     decDigitsFromDPD(dn, &sour, 3); /* process 3 declets */
2225796c8dcSSimon Schubert     return dn;
2235796c8dcSSimon Schubert     }
2245796c8dcSSimon Schubert   /* msd=0 */
2255796c8dcSSimon Schubert   if (!sour) return dn; 	   /* easy: coefficient is 0 */
2265796c8dcSSimon Schubert   if (sour&0x000ffc00)		   /* need 2 declets? */
2275796c8dcSSimon Schubert     decDigitsFromDPD(dn, &sour, 2); /* process 2 declets */
2285796c8dcSSimon Schubert    else
2295796c8dcSSimon Schubert     decDigitsFromDPD(dn, &sour, 1); /* process 1 declet */
2305796c8dcSSimon Schubert   return dn;
2315796c8dcSSimon Schubert   } /* decimal32ToNumber */
2325796c8dcSSimon Schubert 
2335796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
2345796c8dcSSimon Schubert /* to-scientific-string -- conversion to numeric string 	      */
2355796c8dcSSimon Schubert /* to-engineering-string -- conversion to numeric string	      */
2365796c8dcSSimon Schubert /*								      */
2375796c8dcSSimon Schubert /*   decimal32ToString(d32, string);				      */
2385796c8dcSSimon Schubert /*   decimal32ToEngString(d32, string); 			      */
2395796c8dcSSimon Schubert /*								      */
2405796c8dcSSimon Schubert /*  d32 is the decimal32 format number to convert		      */
2415796c8dcSSimon Schubert /*  string is the string where the result will be laid out	      */
2425796c8dcSSimon Schubert /*								      */
2435796c8dcSSimon Schubert /*  string must be at least 24 characters			      */
2445796c8dcSSimon Schubert /*								      */
2455796c8dcSSimon Schubert /*  No error is possible, and no status can be set.		      */
2465796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal32ToEngString(const decimal32 * d32,char * string)2475796c8dcSSimon Schubert char * decimal32ToEngString(const decimal32 *d32, char *string){
2485796c8dcSSimon Schubert   decNumber dn; 			/* work */
2495796c8dcSSimon Schubert   decimal32ToNumber(d32, &dn);
2505796c8dcSSimon Schubert   decNumberToEngString(&dn, string);
2515796c8dcSSimon Schubert   return string;
2525796c8dcSSimon Schubert   } /* decimal32ToEngString */
2535796c8dcSSimon Schubert 
decimal32ToString(const decimal32 * d32,char * string)2545796c8dcSSimon Schubert char * decimal32ToString(const decimal32 *d32, char *string){
2555796c8dcSSimon Schubert   uInt msd;			   /* coefficient MSD */
2565796c8dcSSimon Schubert   Int  exp;			   /* exponent top two bits or full */
2575796c8dcSSimon Schubert   uInt comb;			   /* combination field */
2585796c8dcSSimon Schubert   char *cstart; 		   /* coefficient start */
2595796c8dcSSimon Schubert   char *c;			   /* output pointer in string */
2605796c8dcSSimon Schubert   const uByte *u;		   /* work */
2615796c8dcSSimon Schubert   char *s, *t;			   /* .. (source, target) */
2625796c8dcSSimon Schubert   Int  dpd;			   /* .. */
2635796c8dcSSimon Schubert   Int  pre, e;			   /* .. */
2645796c8dcSSimon Schubert   uInt uiwork;			   /* for macros */
2655796c8dcSSimon Schubert   uInt sour;			   /* source 32-bit */
2665796c8dcSSimon Schubert 
2675796c8dcSSimon Schubert   /* load source from storage; this is endian */
2685796c8dcSSimon Schubert   sour=UBTOUI(d32->bytes);	   /* directly load the int */
2695796c8dcSSimon Schubert 
2705796c8dcSSimon Schubert   c=string;			   /* where result will go */
2715796c8dcSSimon Schubert   if (((Int)sour)<0) *c++='-';	   /* handle sign */
2725796c8dcSSimon Schubert 
2735796c8dcSSimon Schubert   comb=(sour>>26)&0x1f; 	   /* combination field */
2745796c8dcSSimon Schubert   msd=COMBMSD[comb];		   /* decode the combination field */
2755796c8dcSSimon Schubert   exp=COMBEXP[comb];		   /* .. */
2765796c8dcSSimon Schubert 
2775796c8dcSSimon Schubert   if (exp==3) {
2785796c8dcSSimon Schubert     if (msd==0) {		   /* infinity */
2795796c8dcSSimon Schubert       strcpy(c,   "Inf");
2805796c8dcSSimon Schubert       strcpy(c+3, "inity");
2815796c8dcSSimon Schubert       return string;		   /* easy */
2825796c8dcSSimon Schubert       }
2835796c8dcSSimon Schubert     if (sour&0x02000000) *c++='s'; /* sNaN */
2845796c8dcSSimon Schubert     strcpy(c, "NaN");		   /* complete word */
2855796c8dcSSimon Schubert     c+=3;			   /* step past */
2865796c8dcSSimon Schubert     if ((sour&0x000fffff)==0) return string; /* zero payload */
2875796c8dcSSimon Schubert     /* otherwise drop through to add integer; set correct exp */
2885796c8dcSSimon Schubert     exp=0; msd=0;		   /* setup for following code */
2895796c8dcSSimon Schubert     }
2905796c8dcSSimon Schubert    else exp=(exp<<6)+((sour>>20)&0x3f)-DECIMAL32_Bias; /* unbiased */
2915796c8dcSSimon Schubert 
2925796c8dcSSimon Schubert   /* convert 7 digits of significand to characters */
2935796c8dcSSimon Schubert   cstart=c;			   /* save start of coefficient */
2945796c8dcSSimon Schubert   if (msd) *c++='0'+(char)msd;	   /* non-zero most significant digit */
2955796c8dcSSimon Schubert 
2965796c8dcSSimon Schubert   /* Now decode the declets.  After extracting each one, it is */
2975796c8dcSSimon Schubert   /* decoded to binary and then to a 4-char sequence by table lookup; */
2985796c8dcSSimon Schubert   /* the 4-chars are a 1-char length (significant digits, except 000 */
2995796c8dcSSimon Schubert   /* has length 0).  This allows us to left-align the first declet */
3005796c8dcSSimon Schubert   /* with non-zero content, then remaining ones are full 3-char */
3015796c8dcSSimon Schubert   /* length.  We use fixed-length memcpys because variable-length */
3025796c8dcSSimon Schubert   /* causes a subroutine call in GCC.  (These are length 4 for speed */
3035796c8dcSSimon Schubert   /* and are safe because the array has an extra terminator byte.) */
3045796c8dcSSimon Schubert   #define dpd2char u=&BIN2CHAR[DPD2BIN[dpd]*4]; 		  \
3055796c8dcSSimon Schubert 		   if (c!=cstart) {memcpy(c, u+1, 4); c+=3;}	  \
3065796c8dcSSimon Schubert 		    else if (*u)  {memcpy(c, u+4-*u, 4); c+=*u;}
3075796c8dcSSimon Schubert 
3085796c8dcSSimon Schubert   dpd=(sour>>10)&0x3ff; 	   /* declet 1 */
3095796c8dcSSimon Schubert   dpd2char;
3105796c8dcSSimon Schubert   dpd=(sour)&0x3ff;		   /* declet 2 */
3115796c8dcSSimon Schubert   dpd2char;
3125796c8dcSSimon Schubert 
3135796c8dcSSimon Schubert   if (c==cstart) *c++='0';	   /* all zeros -- make 0 */
3145796c8dcSSimon Schubert 
3155796c8dcSSimon Schubert   if (exp==0) { 		   /* integer or NaN case -- easy */
3165796c8dcSSimon Schubert     *c='\0';			   /* terminate */
3175796c8dcSSimon Schubert     return string;
3185796c8dcSSimon Schubert     }
3195796c8dcSSimon Schubert 
3205796c8dcSSimon Schubert   /* non-0 exponent */
3215796c8dcSSimon Schubert   e=0;				   /* assume no E */
3225796c8dcSSimon Schubert   pre=c-cstart+exp;
3235796c8dcSSimon Schubert   /* [here, pre-exp is the digits count (==1 for zero)] */
3245796c8dcSSimon Schubert   if (exp>0 || pre<-5) {	   /* need exponential form */
3255796c8dcSSimon Schubert     e=pre-1;			   /* calculate E value */
3265796c8dcSSimon Schubert     pre=1;			   /* assume one digit before '.' */
3275796c8dcSSimon Schubert     } /* exponential form */
3285796c8dcSSimon Schubert 
3295796c8dcSSimon Schubert   /* modify the coefficient, adding 0s, '.', and E+nn as needed */
3305796c8dcSSimon Schubert   s=c-1;			   /* source (LSD) */
3315796c8dcSSimon Schubert   if (pre>0) {			   /* ddd.ddd (plain), perhaps with E */
3325796c8dcSSimon Schubert     char *dotat=cstart+pre;
3335796c8dcSSimon Schubert     if (dotat<c) {		   /* if embedded dot needed... */
3345796c8dcSSimon Schubert       t=c;				/* target */
3355796c8dcSSimon Schubert       for (; s>=dotat; s--, t--) *t=*s; /* open the gap; leave t at gap */
3365796c8dcSSimon Schubert       *t='.';				/* insert the dot */
3375796c8dcSSimon Schubert       c++;				/* length increased by one */
3385796c8dcSSimon Schubert       }
3395796c8dcSSimon Schubert 
3405796c8dcSSimon Schubert     /* finally add the E-part, if needed; it will never be 0, and has */
3415796c8dcSSimon Schubert     /* a maximum length of 3 digits (E-101 case) */
3425796c8dcSSimon Schubert     if (e!=0) {
3435796c8dcSSimon Schubert       *c++='E'; 		   /* starts with E */
3445796c8dcSSimon Schubert       *c++='+'; 		   /* assume positive */
3455796c8dcSSimon Schubert       if (e<0) {
3465796c8dcSSimon Schubert 	*(c-1)='-';		   /* oops, need '-' */
3475796c8dcSSimon Schubert 	e=-e;			   /* uInt, please */
3485796c8dcSSimon Schubert 	}
3495796c8dcSSimon Schubert       u=&BIN2CHAR[e*4]; 	   /* -> length byte */
3505796c8dcSSimon Schubert       memcpy(c, u+4-*u, 4);	   /* copy fixed 4 characters [is safe] */
3515796c8dcSSimon Schubert       c+=*u;			   /* bump pointer appropriately */
3525796c8dcSSimon Schubert       }
3535796c8dcSSimon Schubert     *c='\0';			   /* add terminator */
3545796c8dcSSimon Schubert     /*printf("res %s\n", string); */
3555796c8dcSSimon Schubert     return string;
3565796c8dcSSimon Schubert     } /* pre>0 */
3575796c8dcSSimon Schubert 
3585796c8dcSSimon Schubert   /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
3595796c8dcSSimon Schubert   t=c+1-pre;
3605796c8dcSSimon Schubert   *(t+1)='\0';				/* can add terminator now */
3615796c8dcSSimon Schubert   for (; s>=cstart; s--, t--) *t=*s;	/* shift whole coefficient right */
3625796c8dcSSimon Schubert   c=cstart;
3635796c8dcSSimon Schubert   *c++='0';				/* always starts with 0. */
3645796c8dcSSimon Schubert   *c++='.';
3655796c8dcSSimon Schubert   for (; pre<0; pre++) *c++='0';	/* add any 0's after '.' */
3665796c8dcSSimon Schubert   /*printf("res %s\n", string); */
3675796c8dcSSimon Schubert   return string;
3685796c8dcSSimon Schubert   } /* decimal32ToString */
3695796c8dcSSimon Schubert 
3705796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
3715796c8dcSSimon Schubert /* to-number -- conversion from numeric string			      */
3725796c8dcSSimon Schubert /*								      */
3735796c8dcSSimon Schubert /*   decimal32FromString(result, string, set);			      */
3745796c8dcSSimon Schubert /*								      */
3755796c8dcSSimon Schubert /*  result  is the decimal32 format number which gets the result of   */
3765796c8dcSSimon Schubert /*	    the conversion					      */
3775796c8dcSSimon Schubert /*  *string is the character string which should contain a valid      */
3785796c8dcSSimon Schubert /*	    number (which may be a special value)		      */
3795796c8dcSSimon Schubert /*  set     is the context					      */
3805796c8dcSSimon Schubert /*								      */
3815796c8dcSSimon Schubert /* The context is supplied to this routine is used for error handling */
3825796c8dcSSimon Schubert /* (setting of status and traps) and for the rounding mode, only.     */
3835796c8dcSSimon Schubert /* If an error occurs, the result will be a valid decimal32 NaN.      */
3845796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal32FromString(decimal32 * result,const char * string,decContext * set)3855796c8dcSSimon Schubert decimal32 * decimal32FromString(decimal32 *result, const char *string,
3865796c8dcSSimon Schubert 				decContext *set) {
3875796c8dcSSimon Schubert   decContext dc;			     /* work */
3885796c8dcSSimon Schubert   decNumber dn; 			     /* .. */
3895796c8dcSSimon Schubert 
3905796c8dcSSimon Schubert   decContextDefault(&dc, DEC_INIT_DECIMAL32); /* no traps, please */
3915796c8dcSSimon Schubert   dc.round=set->round;			      /* use supplied rounding */
3925796c8dcSSimon Schubert 
3935796c8dcSSimon Schubert   decNumberFromString(&dn, string, &dc);     /* will round if needed */
3945796c8dcSSimon Schubert   decimal32FromNumber(result, &dn, &dc);
3955796c8dcSSimon Schubert   if (dc.status!=0) {			     /* something happened */
3965796c8dcSSimon Schubert     decContextSetStatus(set, dc.status);     /* .. pass it on */
3975796c8dcSSimon Schubert     }
3985796c8dcSSimon Schubert   return result;
3995796c8dcSSimon Schubert   } /* decimal32FromString */
4005796c8dcSSimon Schubert 
4015796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4025796c8dcSSimon Schubert /* decimal32IsCanonical -- test whether encoding is canonical	      */
4035796c8dcSSimon Schubert /*   d32 is the source decimal32				      */
4045796c8dcSSimon Schubert /*   returns 1 if the encoding of d32 is canonical, 0 otherwise       */
4055796c8dcSSimon Schubert /* No error is possible.					      */
4065796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal32IsCanonical(const decimal32 * d32)4075796c8dcSSimon Schubert uInt decimal32IsCanonical(const decimal32 *d32) {
4085796c8dcSSimon Schubert   decNumber dn; 			/* work */
4095796c8dcSSimon Schubert   decimal32 canon;			/* .. */
4105796c8dcSSimon Schubert   decContext dc;			/* .. */
4115796c8dcSSimon Schubert   decContextDefault(&dc, DEC_INIT_DECIMAL32);
4125796c8dcSSimon Schubert   decimal32ToNumber(d32, &dn);
4135796c8dcSSimon Schubert   decimal32FromNumber(&canon, &dn, &dc);/* canon will now be canonical */
4145796c8dcSSimon Schubert   return memcmp(d32, &canon, DECIMAL32_Bytes)==0;
4155796c8dcSSimon Schubert   } /* decimal32IsCanonical */
4165796c8dcSSimon Schubert 
4175796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4185796c8dcSSimon Schubert /* decimal32Canonical -- copy an encoding, ensuring it is canonical   */
4195796c8dcSSimon Schubert /*   d32 is the source decimal32				      */
4205796c8dcSSimon Schubert /*   result is the target (may be the same decimal32)		      */
4215796c8dcSSimon Schubert /*   returns result						      */
4225796c8dcSSimon Schubert /* No error is possible.					      */
4235796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
decimal32Canonical(decimal32 * result,const decimal32 * d32)4245796c8dcSSimon Schubert decimal32 * decimal32Canonical(decimal32 *result, const decimal32 *d32) {
4255796c8dcSSimon Schubert   decNumber dn; 			/* work */
4265796c8dcSSimon Schubert   decContext dc;			/* .. */
4275796c8dcSSimon Schubert   decContextDefault(&dc, DEC_INIT_DECIMAL32);
4285796c8dcSSimon Schubert   decimal32ToNumber(d32, &dn);
4295796c8dcSSimon Schubert   decimal32FromNumber(result, &dn, &dc);/* result will now be canonical */
4305796c8dcSSimon Schubert   return result;
4315796c8dcSSimon Schubert   } /* decimal32Canonical */
4325796c8dcSSimon Schubert 
4335796c8dcSSimon Schubert #if DECTRACE || DECCHECK
4345796c8dcSSimon Schubert /* Macros for accessing decimal32 fields.  These assume the argument
4355796c8dcSSimon Schubert    is a reference (pointer) to the decimal32 structure, and the
4365796c8dcSSimon Schubert    decimal32 is in network byte order (big-endian) */
4375796c8dcSSimon Schubert /* Get sign */
4385796c8dcSSimon Schubert #define decimal32Sign(d)       ((unsigned)(d)->bytes[0]>>7)
4395796c8dcSSimon Schubert 
4405796c8dcSSimon Schubert /* Get combination field */
4415796c8dcSSimon Schubert #define decimal32Comb(d)       (((d)->bytes[0] & 0x7c)>>2)
4425796c8dcSSimon Schubert 
4435796c8dcSSimon Schubert /* Get exponent continuation [does not remove bias] */
4445796c8dcSSimon Schubert #define decimal32ExpCon(d)     ((((d)->bytes[0] & 0x03)<<4)	      \
4455796c8dcSSimon Schubert 			     | ((unsigned)(d)->bytes[1]>>4))
4465796c8dcSSimon Schubert 
4475796c8dcSSimon Schubert /* Set sign [this assumes sign previously 0] */
4485796c8dcSSimon Schubert #define decimal32SetSign(d, b) {				      \
4495796c8dcSSimon Schubert   (d)->bytes[0]|=((unsigned)(b)<<7);}
4505796c8dcSSimon Schubert 
4515796c8dcSSimon Schubert /* Set exponent continuation [does not apply bias] */
4525796c8dcSSimon Schubert /* This assumes range has been checked and exponent previously 0; */
4535796c8dcSSimon Schubert /* type of exponent must be unsigned */
4545796c8dcSSimon Schubert #define decimal32SetExpCon(d, e) {				      \
4555796c8dcSSimon Schubert   (d)->bytes[0]|=(uByte)((e)>>4);				      \
4565796c8dcSSimon Schubert   (d)->bytes[1]|=(uByte)(((e)&0x0F)<<4);}
4575796c8dcSSimon Schubert 
4585796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4595796c8dcSSimon Schubert /* decimal32Show -- display a decimal32 in hexadecimal [debug aid]    */
4605796c8dcSSimon Schubert /*   d32 -- the number to show					      */
4615796c8dcSSimon Schubert /* ------------------------------------------------------------------ */
4625796c8dcSSimon Schubert /* Also shows sign/cob/expconfields extracted - valid bigendian only */
decimal32Show(const decimal32 * d32)4635796c8dcSSimon Schubert void decimal32Show(const decimal32 *d32) {
4645796c8dcSSimon Schubert   char buf[DECIMAL32_Bytes*2+1];
4655796c8dcSSimon Schubert   Int i, j=0;
4665796c8dcSSimon Schubert 
4675796c8dcSSimon Schubert   if (DECLITEND) {
4685796c8dcSSimon Schubert     for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
4695796c8dcSSimon Schubert       sprintf(&buf[j], "%02x", d32->bytes[3-i]);
4705796c8dcSSimon Schubert       }
4715796c8dcSSimon Schubert     printf(" D32> %s [S:%d Cb:%02x Ec:%02x] LittleEndian\n", buf,
4725796c8dcSSimon Schubert 	   d32->bytes[3]>>7, (d32->bytes[3]>>2)&0x1f,
4735796c8dcSSimon Schubert 	   ((d32->bytes[3]&0x3)<<4)| (d32->bytes[2]>>4));
4745796c8dcSSimon Schubert     }
4755796c8dcSSimon Schubert    else {
4765796c8dcSSimon Schubert     for (i=0; i<DECIMAL32_Bytes; i++, j+=2) {
4775796c8dcSSimon Schubert       sprintf(&buf[j], "%02x", d32->bytes[i]);
4785796c8dcSSimon Schubert       }
4795796c8dcSSimon Schubert     printf(" D32> %s [S:%d Cb:%02x Ec:%02x] BigEndian\n", buf,
4805796c8dcSSimon Schubert 	   decimal32Sign(d32), decimal32Comb(d32), decimal32ExpCon(d32));
4815796c8dcSSimon Schubert     }
4825796c8dcSSimon Schubert   } /* decimal32Show */
4835796c8dcSSimon Schubert #endif
484