136ac495dSmrg /* Common code for fixed-size types in the decNumber C Library.
2*8feb0f0bSmrg Copyright (C) 2007-2020 Free Software Foundation, Inc.
336ac495dSmrg Contributed by IBM Corporation. Author Mike Cowlishaw.
436ac495dSmrg
536ac495dSmrg This file is part of GCC.
636ac495dSmrg
736ac495dSmrg GCC is free software; you can redistribute it and/or modify it under
836ac495dSmrg the terms of the GNU General Public License as published by the Free
936ac495dSmrg Software Foundation; either version 3, or (at your option) any later
1036ac495dSmrg version.
1136ac495dSmrg
1236ac495dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1336ac495dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
1436ac495dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1536ac495dSmrg for more details.
1636ac495dSmrg
1736ac495dSmrg Under Section 7 of GPL version 3, you are granted additional
1836ac495dSmrg permissions described in the GCC Runtime Library Exception, version
1936ac495dSmrg 3.1, as published by the Free Software Foundation.
2036ac495dSmrg
2136ac495dSmrg You should have received a copy of the GNU General Public License and
2236ac495dSmrg a copy of the GCC Runtime Library Exception along with this program;
2336ac495dSmrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2436ac495dSmrg <http://www.gnu.org/licenses/>. */
2536ac495dSmrg
2636ac495dSmrg /* ------------------------------------------------------------------ */
2736ac495dSmrg /* decCommon.c -- common code for all three fixed-size types */
2836ac495dSmrg /* ------------------------------------------------------------------ */
2936ac495dSmrg /* This module comprises code that is shared between all the formats */
3036ac495dSmrg /* (decSingle, decDouble, and decQuad); it includes set and extract */
3136ac495dSmrg /* of format components, widening, narrowing, and string conversions. */
3236ac495dSmrg /* */
3336ac495dSmrg /* Unlike decNumber, parameterization takes place at compile time */
3436ac495dSmrg /* rather than at runtime. The parameters are set in the decDouble.c */
3536ac495dSmrg /* (etc.) files, which then include this one to produce the compiled */
3636ac495dSmrg /* code. The functions here, therefore, are code shared between */
3736ac495dSmrg /* multiple formats. */
3836ac495dSmrg /* ------------------------------------------------------------------ */
3936ac495dSmrg /* Names here refer to decFloat rather than to decDouble, etc., and */
4036ac495dSmrg /* the functions are in strict alphabetical order. */
4136ac495dSmrg /* Constants, tables, and debug function(s) are included only for QUAD */
4236ac495dSmrg /* (which will always be compiled if DOUBLE or SINGLE are used). */
4336ac495dSmrg /* */
4436ac495dSmrg /* Whenever a decContext is used, only the status may be set (using */
4536ac495dSmrg /* OR) or the rounding mode read; all other fields are ignored and */
4636ac495dSmrg /* untouched. */
4736ac495dSmrg
4836ac495dSmrg #include "decCommonSymbols.h"
4936ac495dSmrg
5036ac495dSmrg /* names for simpler testing and default context */
5136ac495dSmrg #if DECPMAX==7
5236ac495dSmrg #define SINGLE 1
5336ac495dSmrg #define DOUBLE 0
5436ac495dSmrg #define QUAD 0
5536ac495dSmrg #define DEFCONTEXT DEC_INIT_DECIMAL32
5636ac495dSmrg #elif DECPMAX==16
5736ac495dSmrg #define SINGLE 0
5836ac495dSmrg #define DOUBLE 1
5936ac495dSmrg #define QUAD 0
6036ac495dSmrg #define DEFCONTEXT DEC_INIT_DECIMAL64
6136ac495dSmrg #elif DECPMAX==34
6236ac495dSmrg #define SINGLE 0
6336ac495dSmrg #define DOUBLE 0
6436ac495dSmrg #define QUAD 1
6536ac495dSmrg #define DEFCONTEXT DEC_INIT_DECIMAL128
6636ac495dSmrg #else
6736ac495dSmrg #error Unexpected DECPMAX value
6836ac495dSmrg #endif
6936ac495dSmrg
7036ac495dSmrg /* Assertions */
7136ac495dSmrg
7236ac495dSmrg #if DECPMAX!=7 && DECPMAX!=16 && DECPMAX!=34
7336ac495dSmrg #error Unexpected Pmax (DECPMAX) value for this module
7436ac495dSmrg #endif
7536ac495dSmrg
7636ac495dSmrg /* Assert facts about digit characters, etc. */
7736ac495dSmrg #if ('9'&0x0f)!=9
7836ac495dSmrg #error This module assumes characters are of the form 0b....nnnn
7936ac495dSmrg /* where .... are don't care 4 bits and nnnn is 0000 through 1001 */
8036ac495dSmrg #endif
8136ac495dSmrg #if ('9'&0xf0)==('.'&0xf0)
8236ac495dSmrg #error This module assumes '.' has a different mask than a digit
8336ac495dSmrg #endif
8436ac495dSmrg
8536ac495dSmrg /* Assert ToString lay-out conditions */
8636ac495dSmrg #if DECSTRING<DECPMAX+9
8736ac495dSmrg #error ToString needs at least 8 characters for lead-in and dot
8836ac495dSmrg #endif
8936ac495dSmrg #if DECPMAX+DECEMAXD+5 > DECSTRING
9036ac495dSmrg #error Exponent form can be too long for ToString to lay out safely
9136ac495dSmrg #endif
9236ac495dSmrg #if DECEMAXD > 4
9336ac495dSmrg #error Exponent form is too long for ToString to lay out
9436ac495dSmrg /* Note: code for up to 9 digits exists in archives [decOct] */
9536ac495dSmrg #endif
9636ac495dSmrg
9736ac495dSmrg /* Private functions used here and possibly in decBasic.c, etc. */
9836ac495dSmrg static decFloat * decFinalize(decFloat *, bcdnum *, decContext *);
9936ac495dSmrg static Flag decBiStr(const char *, const char *, const char *);
10036ac495dSmrg
10136ac495dSmrg /* Macros and private tables; those which are not format-dependent */
10236ac495dSmrg /* are only included if decQuad is being built. */
10336ac495dSmrg
10436ac495dSmrg /* ------------------------------------------------------------------ */
10536ac495dSmrg /* Combination field lookup tables (uInts to save measurable work) */
10636ac495dSmrg /* */
10736ac495dSmrg /* DECCOMBEXP - 2 most-significant-bits of exponent (00, 01, or */
10836ac495dSmrg /* 10), shifted left for format, or DECFLOAT_Inf/NaN */
10936ac495dSmrg /* DECCOMBWEXP - The same, for the next-wider format (unless QUAD) */
11036ac495dSmrg /* DECCOMBMSD - 4-bit most-significant-digit */
11136ac495dSmrg /* [0 if the index is a special (Infinity or NaN)] */
11236ac495dSmrg /* DECCOMBFROM - 5-bit combination field from EXP top bits and MSD */
11336ac495dSmrg /* (placed in uInt so no shift is needed) */
11436ac495dSmrg /* */
11536ac495dSmrg /* DECCOMBEXP, DECCOMBWEXP, and DECCOMBMSD are indexed by the sign */
11636ac495dSmrg /* and 5-bit combination field (0-63, the second half of the table */
11736ac495dSmrg /* identical to the first half) */
11836ac495dSmrg /* DECCOMBFROM is indexed by expTopTwoBits*16 + msd */
11936ac495dSmrg /* */
12036ac495dSmrg /* DECCOMBMSD and DECCOMBFROM are not format-dependent and so are */
12136ac495dSmrg /* only included once, when QUAD is being built */
12236ac495dSmrg /* ------------------------------------------------------------------ */
12336ac495dSmrg static const uInt DECCOMBEXP[64]={
12436ac495dSmrg 0, 0, 0, 0, 0, 0, 0, 0,
12536ac495dSmrg 1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
12636ac495dSmrg 1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
12736ac495dSmrg 2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
12836ac495dSmrg 2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
12936ac495dSmrg 0, 0, 1<<DECECONL, 1<<DECECONL,
13036ac495dSmrg 2<<DECECONL, 2<<DECECONL, DECFLOAT_Inf, DECFLOAT_NaN,
13136ac495dSmrg 0, 0, 0, 0, 0, 0, 0, 0,
13236ac495dSmrg 1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
13336ac495dSmrg 1<<DECECONL, 1<<DECECONL, 1<<DECECONL, 1<<DECECONL,
13436ac495dSmrg 2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
13536ac495dSmrg 2<<DECECONL, 2<<DECECONL, 2<<DECECONL, 2<<DECECONL,
13636ac495dSmrg 0, 0, 1<<DECECONL, 1<<DECECONL,
13736ac495dSmrg 2<<DECECONL, 2<<DECECONL, DECFLOAT_Inf, DECFLOAT_NaN};
13836ac495dSmrg #if !QUAD
13936ac495dSmrg static const uInt DECCOMBWEXP[64]={
14036ac495dSmrg 0, 0, 0, 0, 0, 0, 0, 0,
14136ac495dSmrg 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
14236ac495dSmrg 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
14336ac495dSmrg 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
14436ac495dSmrg 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
14536ac495dSmrg 0, 0, 1<<DECWECONL, 1<<DECWECONL,
14636ac495dSmrg 2<<DECWECONL, 2<<DECWECONL, DECFLOAT_Inf, DECFLOAT_NaN,
14736ac495dSmrg 0, 0, 0, 0, 0, 0, 0, 0,
14836ac495dSmrg 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
14936ac495dSmrg 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL, 1<<DECWECONL,
15036ac495dSmrg 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
15136ac495dSmrg 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL, 2<<DECWECONL,
15236ac495dSmrg 0, 0, 1<<DECWECONL, 1<<DECWECONL,
15336ac495dSmrg 2<<DECWECONL, 2<<DECWECONL, DECFLOAT_Inf, DECFLOAT_NaN};
15436ac495dSmrg #endif
15536ac495dSmrg
15636ac495dSmrg #if QUAD
15736ac495dSmrg const uInt DECCOMBMSD[64]={
15836ac495dSmrg 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
15936ac495dSmrg 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0,
16036ac495dSmrg 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
16136ac495dSmrg 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 8, 9, 8, 9, 0, 0};
16236ac495dSmrg
16336ac495dSmrg const uInt DECCOMBFROM[48]={
16436ac495dSmrg 0x00000000, 0x04000000, 0x08000000, 0x0C000000, 0x10000000, 0x14000000,
16536ac495dSmrg 0x18000000, 0x1C000000, 0x60000000, 0x64000000, 0x00000000, 0x00000000,
16636ac495dSmrg 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x20000000, 0x24000000,
16736ac495dSmrg 0x28000000, 0x2C000000, 0x30000000, 0x34000000, 0x38000000, 0x3C000000,
16836ac495dSmrg 0x68000000, 0x6C000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
16936ac495dSmrg 0x00000000, 0x00000000, 0x40000000, 0x44000000, 0x48000000, 0x4C000000,
17036ac495dSmrg 0x50000000, 0x54000000, 0x58000000, 0x5C000000, 0x70000000, 0x74000000,
17136ac495dSmrg 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000};
17236ac495dSmrg
17336ac495dSmrg /* ------------------------------------------------------------------ */
17436ac495dSmrg /* Request and include the tables to use for conversions */
17536ac495dSmrg /* ------------------------------------------------------------------ */
17636ac495dSmrg #define DEC_BCD2DPD 1 /* 0-0x999 -> DPD */
17736ac495dSmrg #define DEC_BIN2DPD 1 /* 0-999 -> DPD */
17836ac495dSmrg #define DEC_BIN2BCD8 1 /* 0-999 -> ddd, len */
17936ac495dSmrg #define DEC_DPD2BCD8 1 /* DPD -> ddd, len */
18036ac495dSmrg #define DEC_DPD2BIN 1 /* DPD -> 0-999 */
18136ac495dSmrg #define DEC_DPD2BINK 1 /* DPD -> 0-999000 */
18236ac495dSmrg #define DEC_DPD2BINM 1 /* DPD -> 0-999000000 */
18336ac495dSmrg #include "decDPD.h" /* source of the lookup tables */
18436ac495dSmrg
18536ac495dSmrg #endif
18636ac495dSmrg
18736ac495dSmrg /* ----------------------------------------------------------------- */
18836ac495dSmrg /* decBiStr -- compare string with pairwise options */
18936ac495dSmrg /* */
19036ac495dSmrg /* targ is the string to compare */
19136ac495dSmrg /* str1 is one of the strings to compare against (length may be 0) */
19236ac495dSmrg /* str2 is the other; it must be the same length as str1 */
19336ac495dSmrg /* */
19436ac495dSmrg /* returns 1 if strings compare equal, (that is, targ is the same */
19536ac495dSmrg /* length as str1 and str2, and each character of targ is in one */
19636ac495dSmrg /* of str1 or str2 in the corresponding position), or 0 otherwise */
19736ac495dSmrg /* */
19836ac495dSmrg /* This is used for generic caseless compare, including the awkward */
19936ac495dSmrg /* case of the Turkish dotted and dotless Is. Use as (for example): */
20036ac495dSmrg /* if (decBiStr(test, "mike", "MIKE")) ... */
20136ac495dSmrg /* ----------------------------------------------------------------- */
decBiStr(const char * targ,const char * str1,const char * str2)20236ac495dSmrg static Flag decBiStr(const char *targ, const char *str1, const char *str2) {
20336ac495dSmrg for (;;targ++, str1++, str2++) {
20436ac495dSmrg if (*targ!=*str1 && *targ!=*str2) return 0;
20536ac495dSmrg /* *targ has a match in one (or both, if terminator) */
20636ac495dSmrg if (*targ=='\0') break;
20736ac495dSmrg } /* forever */
20836ac495dSmrg return 1;
20936ac495dSmrg } /* decBiStr */
21036ac495dSmrg
21136ac495dSmrg /* ------------------------------------------------------------------ */
21236ac495dSmrg /* decFinalize -- adjust and store a final result */
21336ac495dSmrg /* */
21436ac495dSmrg /* df is the decFloat format number which gets the final result */
21536ac495dSmrg /* num is the descriptor of the number to be checked and encoded */
21636ac495dSmrg /* [its values, including the coefficient, may be modified] */
21736ac495dSmrg /* set is the context to use */
21836ac495dSmrg /* returns df */
21936ac495dSmrg /* */
22036ac495dSmrg /* The num descriptor may point to a bcd8 string of any length; this */
22136ac495dSmrg /* string may have leading insignificant zeros. If it has more than */
22236ac495dSmrg /* DECPMAX digits then the final digit can be a round-for-reround */
22336ac495dSmrg /* digit (i.e., it may include a sticky bit residue). */
22436ac495dSmrg /* */
22536ac495dSmrg /* The exponent (q) may be one of the codes for a special value and */
22636ac495dSmrg /* can be up to 999999999 for conversion from string. */
22736ac495dSmrg /* */
22836ac495dSmrg /* No error is possible, but Inexact, Underflow, and/or Overflow may */
22936ac495dSmrg /* be set. */
23036ac495dSmrg /* ------------------------------------------------------------------ */
23136ac495dSmrg /* Constant whose size varies with format; also the check for surprises */
23236ac495dSmrg static uByte allnines[DECPMAX]=
23336ac495dSmrg #if SINGLE
23436ac495dSmrg {9, 9, 9, 9, 9, 9, 9};
23536ac495dSmrg #elif DOUBLE
23636ac495dSmrg {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
23736ac495dSmrg #elif QUAD
23836ac495dSmrg {9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
23936ac495dSmrg 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9};
24036ac495dSmrg #endif
24136ac495dSmrg
decFinalize(decFloat * df,bcdnum * num,decContext * set)24236ac495dSmrg static decFloat * decFinalize(decFloat *df, bcdnum *num,
24336ac495dSmrg decContext *set) {
24436ac495dSmrg uByte *ub; /* work */
24536ac495dSmrg uInt dpd; /* .. */
24636ac495dSmrg uInt uiwork; /* for macros */
24736ac495dSmrg uByte *umsd=num->msd; /* local copy */
24836ac495dSmrg uByte *ulsd=num->lsd; /* .. */
24936ac495dSmrg uInt encode; /* encoding accumulator */
25036ac495dSmrg Int length; /* coefficient length */
25136ac495dSmrg
25236ac495dSmrg #if DECCHECK
25336ac495dSmrg Int clen=ulsd-umsd+1;
25436ac495dSmrg #if QUAD
25536ac495dSmrg #define COEXTRA 2 /* extra-long coefficent */
25636ac495dSmrg #else
25736ac495dSmrg #define COEXTRA 0
25836ac495dSmrg #endif
25936ac495dSmrg if (clen<1 || clen>DECPMAX*3+2+COEXTRA)
26036ac495dSmrg printf("decFinalize: suspect coefficient [length=%ld]\n", (LI)clen);
26136ac495dSmrg if (num->sign!=0 && num->sign!=DECFLOAT_Sign)
26236ac495dSmrg printf("decFinalize: bad sign [%08lx]\n", (LI)num->sign);
26336ac495dSmrg if (!EXPISSPECIAL(num->exponent)
26436ac495dSmrg && (num->exponent>1999999999 || num->exponent<-1999999999))
26536ac495dSmrg printf("decFinalize: improbable exponent [%ld]\n", (LI)num->exponent);
26636ac495dSmrg /* decShowNum(num, "final"); */
26736ac495dSmrg #endif
26836ac495dSmrg
26936ac495dSmrg /* A special will have an 'exponent' which is very positive and a */
27036ac495dSmrg /* coefficient < DECPMAX */
27136ac495dSmrg length=(uInt)(ulsd-umsd+1); /* coefficient length */
27236ac495dSmrg
27336ac495dSmrg if (!NUMISSPECIAL(num)) {
27436ac495dSmrg Int drop; /* digits to be dropped */
27536ac495dSmrg /* skip leading insignificant zeros to calculate an exact length */
27636ac495dSmrg /* [this is quite expensive] */
27736ac495dSmrg if (*umsd==0) {
27836ac495dSmrg for (; umsd+3<ulsd && UBTOUI(umsd)==0;) umsd+=4;
27936ac495dSmrg for (; *umsd==0 && umsd<ulsd;) umsd++;
28036ac495dSmrg length=ulsd-umsd+1; /* recalculate */
28136ac495dSmrg }
28236ac495dSmrg drop=MAXI(length-DECPMAX, DECQTINY-num->exponent);
28336ac495dSmrg /* drop can now be > digits for bottom-clamp (subnormal) cases */
28436ac495dSmrg if (drop>0) { /* rounding needed */
28536ac495dSmrg /* (decFloatQuantize has very similar code to this, so any */
28636ac495dSmrg /* changes may need to be made there, too) */
28736ac495dSmrg uByte *roundat; /* -> re-round digit */
28836ac495dSmrg uByte reround; /* reround value */
28936ac495dSmrg /* printf("Rounding; drop=%ld\n", (LI)drop); */
29036ac495dSmrg
29136ac495dSmrg num->exponent+=drop; /* always update exponent */
29236ac495dSmrg
29336ac495dSmrg /* Three cases here: */
29436ac495dSmrg /* 1. new LSD is in coefficient (almost always) */
29536ac495dSmrg /* 2. new LSD is digit to left of coefficient (so MSD is */
29636ac495dSmrg /* round-for-reround digit) */
29736ac495dSmrg /* 3. new LSD is to left of case 2 (whole coefficient is sticky) */
29836ac495dSmrg /* [duplicate check-stickies code to save a test] */
29936ac495dSmrg /* [by-digit check for stickies as runs of zeros are rare] */
30036ac495dSmrg if (drop<length) { /* NB lengths not addresses */
30136ac495dSmrg roundat=umsd+length-drop;
30236ac495dSmrg reround=*roundat;
30336ac495dSmrg for (ub=roundat+1; ub<=ulsd; ub++) {
30436ac495dSmrg if (*ub!=0) { /* non-zero to be discarded */
30536ac495dSmrg reround=DECSTICKYTAB[reround]; /* apply sticky bit */
30636ac495dSmrg break; /* [remainder don't-care] */
30736ac495dSmrg }
30836ac495dSmrg } /* check stickies */
30936ac495dSmrg ulsd=roundat-1; /* new LSD */
31036ac495dSmrg }
31136ac495dSmrg else { /* edge case */
31236ac495dSmrg if (drop==length) {
31336ac495dSmrg roundat=umsd;
31436ac495dSmrg reround=*roundat;
31536ac495dSmrg }
31636ac495dSmrg else {
31736ac495dSmrg roundat=umsd-1;
31836ac495dSmrg reround=0;
31936ac495dSmrg }
32036ac495dSmrg for (ub=roundat+1; ub<=ulsd; ub++) {
32136ac495dSmrg if (*ub!=0) { /* non-zero to be discarded */
32236ac495dSmrg reround=DECSTICKYTAB[reround]; /* apply sticky bit */
32336ac495dSmrg break; /* [remainder don't-care] */
32436ac495dSmrg }
32536ac495dSmrg } /* check stickies */
32636ac495dSmrg *umsd=0; /* coefficient is a 0 */
32736ac495dSmrg ulsd=umsd; /* .. */
32836ac495dSmrg }
32936ac495dSmrg
33036ac495dSmrg if (reround!=0) { /* discarding non-zero */
33136ac495dSmrg uInt bump=0;
33236ac495dSmrg set->status|=DEC_Inexact;
33336ac495dSmrg /* if adjusted exponent [exp+digits-1] is < EMIN then num is */
33436ac495dSmrg /* subnormal -- so raise Underflow */
33536ac495dSmrg if (num->exponent<DECEMIN && (num->exponent+(ulsd-umsd+1)-1)<DECEMIN)
33636ac495dSmrg set->status|=DEC_Underflow;
33736ac495dSmrg
33836ac495dSmrg /* next decide whether increment of the coefficient is needed */
33936ac495dSmrg if (set->round==DEC_ROUND_HALF_EVEN) { /* fastpath slowest case */
34036ac495dSmrg if (reround>5) bump=1; /* >0.5 goes up */
34136ac495dSmrg else if (reround==5) /* exactly 0.5000 .. */
34236ac495dSmrg bump=*ulsd & 0x01; /* .. up iff [new] lsd is odd */
34336ac495dSmrg } /* r-h-e */
34436ac495dSmrg else switch (set->round) {
34536ac495dSmrg case DEC_ROUND_DOWN: {
34636ac495dSmrg /* no change */
34736ac495dSmrg break;} /* r-d */
34836ac495dSmrg case DEC_ROUND_HALF_DOWN: {
34936ac495dSmrg if (reround>5) bump=1;
35036ac495dSmrg break;} /* r-h-d */
35136ac495dSmrg case DEC_ROUND_HALF_UP: {
35236ac495dSmrg if (reround>=5) bump=1;
35336ac495dSmrg break;} /* r-h-u */
35436ac495dSmrg case DEC_ROUND_UP: {
35536ac495dSmrg if (reround>0) bump=1;
35636ac495dSmrg break;} /* r-u */
35736ac495dSmrg case DEC_ROUND_CEILING: {
35836ac495dSmrg /* same as _UP for positive numbers, and as _DOWN for negatives */
35936ac495dSmrg if (!num->sign && reround>0) bump=1;
36036ac495dSmrg break;} /* r-c */
36136ac495dSmrg case DEC_ROUND_FLOOR: {
36236ac495dSmrg /* same as _UP for negative numbers, and as _DOWN for positive */
36336ac495dSmrg /* [negative reround cannot occur on 0] */
36436ac495dSmrg if (num->sign && reround>0) bump=1;
36536ac495dSmrg break;} /* r-f */
36636ac495dSmrg case DEC_ROUND_05UP: {
36736ac495dSmrg if (reround>0) { /* anything out there is 'sticky' */
36836ac495dSmrg /* bump iff lsd=0 or 5; this cannot carry so it could be */
36936ac495dSmrg /* effected immediately with no bump -- but the code */
37036ac495dSmrg /* is clearer if this is done the same way as the others */
37136ac495dSmrg if (*ulsd==0 || *ulsd==5) bump=1;
37236ac495dSmrg }
37336ac495dSmrg break;} /* r-r */
37436ac495dSmrg default: { /* e.g., DEC_ROUND_MAX */
37536ac495dSmrg set->status|=DEC_Invalid_context;
37636ac495dSmrg #if DECCHECK
37736ac495dSmrg printf("Unknown rounding mode: %ld\n", (LI)set->round);
37836ac495dSmrg #endif
37936ac495dSmrg break;}
38036ac495dSmrg } /* switch (not r-h-e) */
38136ac495dSmrg /* printf("ReRound: %ld bump: %ld\n", (LI)reround, (LI)bump); */
38236ac495dSmrg
38336ac495dSmrg if (bump!=0) { /* need increment */
38436ac495dSmrg /* increment the coefficient; this might end up with 1000... */
38536ac495dSmrg /* (after the all nines case) */
38636ac495dSmrg ub=ulsd;
38736ac495dSmrg for(; ub-3>=umsd && UBTOUI(ub-3)==0x09090909; ub-=4) {
38836ac495dSmrg UBFROMUI(ub-3, 0); /* to 00000000 */
38936ac495dSmrg }
39036ac495dSmrg /* [note ub could now be to left of msd, and it is not safe */
39136ac495dSmrg /* to write to the the left of the msd] */
39236ac495dSmrg /* now at most 3 digits left to non-9 (usually just the one) */
39336ac495dSmrg for (; ub>=umsd; *ub=0, ub--) {
39436ac495dSmrg if (*ub==9) continue; /* carry */
39536ac495dSmrg *ub+=1;
39636ac495dSmrg break;
39736ac495dSmrg }
39836ac495dSmrg if (ub<umsd) { /* had all-nines */
39936ac495dSmrg *umsd=1; /* coefficient to 1000... */
40036ac495dSmrg /* usually the 1000... coefficient can be used as-is */
40136ac495dSmrg if ((ulsd-umsd+1)==DECPMAX) {
40236ac495dSmrg num->exponent++;
40336ac495dSmrg }
40436ac495dSmrg else {
40536ac495dSmrg /* if coefficient is shorter than Pmax then num is */
40636ac495dSmrg /* subnormal, so extend it; this is safe as drop>0 */
40736ac495dSmrg /* (or, if the coefficient was supplied above, it could */
40836ac495dSmrg /* not be 9); this may make the result normal. */
40936ac495dSmrg ulsd++;
41036ac495dSmrg *ulsd=0;
41136ac495dSmrg /* [exponent unchanged] */
41236ac495dSmrg #if DECCHECK
41336ac495dSmrg if (num->exponent!=DECQTINY) /* sanity check */
41436ac495dSmrg printf("decFinalize: bad all-nines extend [^%ld, %ld]\n",
41536ac495dSmrg (LI)num->exponent, (LI)(ulsd-umsd+1));
41636ac495dSmrg #endif
41736ac495dSmrg } /* subnormal extend */
41836ac495dSmrg } /* had all-nines */
41936ac495dSmrg } /* bump needed */
42036ac495dSmrg } /* inexact rounding */
42136ac495dSmrg
42236ac495dSmrg length=ulsd-umsd+1; /* recalculate (may be <DECPMAX) */
42336ac495dSmrg } /* need round (drop>0) */
42436ac495dSmrg
42536ac495dSmrg /* The coefficient will now fit and has final length unless overflow */
42636ac495dSmrg /* decShowNum(num, "rounded"); */
42736ac495dSmrg
42836ac495dSmrg /* if exponent is >=emax may have to clamp, overflow, or fold-down */
42936ac495dSmrg if (num->exponent>DECEMAX-(DECPMAX-1)) { /* is edge case */
43036ac495dSmrg /* printf("overflow checks...\n"); */
43136ac495dSmrg if (*ulsd==0 && ulsd==umsd) { /* have zero */
43236ac495dSmrg num->exponent=DECEMAX-(DECPMAX-1); /* clamp to max */
43336ac495dSmrg }
43436ac495dSmrg else if ((num->exponent+length-1)>DECEMAX) { /* > Nmax */
43536ac495dSmrg /* Overflow -- these could go straight to encoding, here, but */
43636ac495dSmrg /* instead num is adjusted to keep the code cleaner */
43736ac495dSmrg Flag needmax=0; /* 1 for finite result */
43836ac495dSmrg set->status|=(DEC_Overflow | DEC_Inexact);
43936ac495dSmrg switch (set->round) {
44036ac495dSmrg case DEC_ROUND_DOWN: {
44136ac495dSmrg needmax=1; /* never Infinity */
44236ac495dSmrg break;} /* r-d */
44336ac495dSmrg case DEC_ROUND_05UP: {
44436ac495dSmrg needmax=1; /* never Infinity */
44536ac495dSmrg break;} /* r-05 */
44636ac495dSmrg case DEC_ROUND_CEILING: {
44736ac495dSmrg if (num->sign) needmax=1; /* Infinity iff non-negative */
44836ac495dSmrg break;} /* r-c */
44936ac495dSmrg case DEC_ROUND_FLOOR: {
45036ac495dSmrg if (!num->sign) needmax=1; /* Infinity iff negative */
45136ac495dSmrg break;} /* r-f */
45236ac495dSmrg default: break; /* Infinity in all other cases */
45336ac495dSmrg }
45436ac495dSmrg if (!needmax) { /* easy .. set Infinity */
45536ac495dSmrg num->exponent=DECFLOAT_Inf;
45636ac495dSmrg *umsd=0; /* be clean: coefficient to 0 */
45736ac495dSmrg ulsd=umsd; /* .. */
45836ac495dSmrg }
45936ac495dSmrg else { /* return Nmax */
46036ac495dSmrg umsd=allnines; /* use constant array */
46136ac495dSmrg ulsd=allnines+DECPMAX-1;
46236ac495dSmrg num->exponent=DECEMAX-(DECPMAX-1);
46336ac495dSmrg }
46436ac495dSmrg }
46536ac495dSmrg else { /* no overflow but non-zero and may have to fold-down */
46636ac495dSmrg Int shift=num->exponent-(DECEMAX-(DECPMAX-1));
46736ac495dSmrg if (shift>0) { /* fold-down needed */
46836ac495dSmrg /* fold down needed; must copy to buffer in order to pad */
46936ac495dSmrg /* with zeros safely; fortunately this is not the worst case */
47036ac495dSmrg /* path because cannot have had a round */
47136ac495dSmrg uByte buffer[ROUNDUP(DECPMAX+3, 4)]; /* [+3 allows uInt padding] */
47236ac495dSmrg uByte *s=umsd; /* source */
47336ac495dSmrg uByte *t=buffer; /* safe target */
47436ac495dSmrg uByte *tlsd=buffer+(ulsd-umsd)+shift; /* target LSD */
47536ac495dSmrg /* printf("folddown shift=%ld\n", (LI)shift); */
47636ac495dSmrg for (; s<=ulsd; s+=4, t+=4) UBFROMUI(t, UBTOUI(s));
47736ac495dSmrg for (t=tlsd-shift+1; t<=tlsd; t+=4) UBFROMUI(t, 0); /* pad 0s */
47836ac495dSmrg num->exponent-=shift;
47936ac495dSmrg umsd=buffer;
48036ac495dSmrg ulsd=tlsd;
48136ac495dSmrg }
48236ac495dSmrg } /* fold-down? */
48336ac495dSmrg length=ulsd-umsd+1; /* recalculate length */
48436ac495dSmrg } /* high-end edge case */
48536ac495dSmrg } /* finite number */
48636ac495dSmrg
48736ac495dSmrg /*------------------------------------------------------------------*/
48836ac495dSmrg /* At this point the result will properly fit the decFloat */
48936ac495dSmrg /* encoding, and it can be encoded with no possibility of error */
49036ac495dSmrg /*------------------------------------------------------------------*/
49136ac495dSmrg /* Following code does not alter coefficient (could be allnines array) */
49236ac495dSmrg
49336ac495dSmrg /* fast path possible when DECPMAX digits */
49436ac495dSmrg if (length==DECPMAX) {
49536ac495dSmrg return decFloatFromBCD(df, num->exponent, umsd, num->sign);
49636ac495dSmrg } /* full-length */
49736ac495dSmrg
49836ac495dSmrg /* slower path when not a full-length number; must care about length */
49936ac495dSmrg /* [coefficient length here will be < DECPMAX] */
50036ac495dSmrg if (!NUMISSPECIAL(num)) { /* is still finite */
50136ac495dSmrg /* encode the combination field and exponent continuation */
50236ac495dSmrg uInt uexp=(uInt)(num->exponent+DECBIAS); /* biased exponent */
50336ac495dSmrg uInt code=(uexp>>DECECONL)<<4; /* top two bits of exp */
50436ac495dSmrg /* [msd==0] */
50536ac495dSmrg /* look up the combination field and make high word */
50636ac495dSmrg encode=DECCOMBFROM[code]; /* indexed by (0-2)*16+msd */
50736ac495dSmrg encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; /* exponent continuation */
50836ac495dSmrg }
50936ac495dSmrg else encode=num->exponent; /* special [already in word] */
51036ac495dSmrg encode|=num->sign; /* add sign */
51136ac495dSmrg
51236ac495dSmrg /* private macro to extract a declet, n (where 0<=n<DECLETS and 0 */
51336ac495dSmrg /* refers to the declet from the least significant three digits) */
51436ac495dSmrg /* and put the corresponding DPD code into dpd. Access to umsd and */
51536ac495dSmrg /* ulsd (pointers to the most and least significant digit of the */
51636ac495dSmrg /* variable-length coefficient) is assumed, along with use of a */
51736ac495dSmrg /* working pointer, uInt *ub. */
51836ac495dSmrg /* As not full-length then chances are there are many leading zeros */
51936ac495dSmrg /* [and there may be a partial triad] */
52036ac495dSmrg #define getDPDt(dpd, n) ub=ulsd-(3*(n))-2; \
52136ac495dSmrg if (ub<umsd-2) dpd=0; \
52236ac495dSmrg else if (ub>=umsd) dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)]; \
52336ac495dSmrg else {dpd=*(ub+2); if (ub+1==umsd) dpd+=*(ub+1)*16; dpd=BCD2DPD[dpd];}
52436ac495dSmrg
52536ac495dSmrg /* place the declets in the encoding words and copy to result (df), */
52636ac495dSmrg /* according to endianness; in all cases complete the sign word */
52736ac495dSmrg /* first */
52836ac495dSmrg #if DECPMAX==7
52936ac495dSmrg getDPDt(dpd, 1);
53036ac495dSmrg encode|=dpd<<10;
53136ac495dSmrg getDPDt(dpd, 0);
53236ac495dSmrg encode|=dpd;
53336ac495dSmrg DFWORD(df, 0)=encode; /* just the one word */
53436ac495dSmrg
53536ac495dSmrg #elif DECPMAX==16
53636ac495dSmrg getDPDt(dpd, 4); encode|=dpd<<8;
53736ac495dSmrg getDPDt(dpd, 3); encode|=dpd>>2;
53836ac495dSmrg DFWORD(df, 0)=encode;
53936ac495dSmrg encode=dpd<<30;
54036ac495dSmrg getDPDt(dpd, 2); encode|=dpd<<20;
54136ac495dSmrg getDPDt(dpd, 1); encode|=dpd<<10;
54236ac495dSmrg getDPDt(dpd, 0); encode|=dpd;
54336ac495dSmrg DFWORD(df, 1)=encode;
54436ac495dSmrg
54536ac495dSmrg #elif DECPMAX==34
54636ac495dSmrg getDPDt(dpd,10); encode|=dpd<<4;
54736ac495dSmrg getDPDt(dpd, 9); encode|=dpd>>6;
54836ac495dSmrg DFWORD(df, 0)=encode;
54936ac495dSmrg
55036ac495dSmrg encode=dpd<<26;
55136ac495dSmrg getDPDt(dpd, 8); encode|=dpd<<16;
55236ac495dSmrg getDPDt(dpd, 7); encode|=dpd<<6;
55336ac495dSmrg getDPDt(dpd, 6); encode|=dpd>>4;
55436ac495dSmrg DFWORD(df, 1)=encode;
55536ac495dSmrg
55636ac495dSmrg encode=dpd<<28;
55736ac495dSmrg getDPDt(dpd, 5); encode|=dpd<<18;
55836ac495dSmrg getDPDt(dpd, 4); encode|=dpd<<8;
55936ac495dSmrg getDPDt(dpd, 3); encode|=dpd>>2;
56036ac495dSmrg DFWORD(df, 2)=encode;
56136ac495dSmrg
56236ac495dSmrg encode=dpd<<30;
56336ac495dSmrg getDPDt(dpd, 2); encode|=dpd<<20;
56436ac495dSmrg getDPDt(dpd, 1); encode|=dpd<<10;
56536ac495dSmrg getDPDt(dpd, 0); encode|=dpd;
56636ac495dSmrg DFWORD(df, 3)=encode;
56736ac495dSmrg #endif
56836ac495dSmrg
56936ac495dSmrg /* printf("Status: %08lx\n", (LI)set->status); */
57036ac495dSmrg /* decFloatShow(df, "final2"); */
57136ac495dSmrg return df;
57236ac495dSmrg } /* decFinalize */
57336ac495dSmrg
57436ac495dSmrg /* ------------------------------------------------------------------ */
57536ac495dSmrg /* decFloatFromBCD -- set decFloat from exponent, BCD8, and sign */
57636ac495dSmrg /* */
57736ac495dSmrg /* df is the target decFloat */
57836ac495dSmrg /* exp is the in-range unbiased exponent, q, or a special value in */
57936ac495dSmrg /* the form returned by decFloatGetExponent */
58036ac495dSmrg /* bcdar holds DECPMAX digits to set the coefficient from, one */
58136ac495dSmrg /* digit in each byte (BCD8 encoding); the first (MSD) is ignored */
58236ac495dSmrg /* if df is a NaN; all are ignored if df is infinite. */
58336ac495dSmrg /* All bytes must be in 0-9; results are undefined otherwise. */
58436ac495dSmrg /* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */
58536ac495dSmrg /* returns df, which will be canonical */
58636ac495dSmrg /* */
58736ac495dSmrg /* No error is possible, and no status will be set. */
58836ac495dSmrg /* ------------------------------------------------------------------ */
decFloatFromBCD(decFloat * df,Int exp,const uByte * bcdar,Int sig)58936ac495dSmrg decFloat * decFloatFromBCD(decFloat *df, Int exp, const uByte *bcdar,
59036ac495dSmrg Int sig) {
59136ac495dSmrg uInt encode, dpd; /* work */
59236ac495dSmrg const uByte *ub; /* .. */
59336ac495dSmrg
59436ac495dSmrg if (EXPISSPECIAL(exp)) encode=exp|sig;/* specials already encoded */
59536ac495dSmrg else { /* is finite */
59636ac495dSmrg /* encode the combination field and exponent continuation */
59736ac495dSmrg uInt uexp=(uInt)(exp+DECBIAS); /* biased exponent */
59836ac495dSmrg uInt code=(uexp>>DECECONL)<<4; /* top two bits of exp */
59936ac495dSmrg code+=bcdar[0]; /* add msd */
60036ac495dSmrg /* look up the combination field and make high word */
60136ac495dSmrg encode=DECCOMBFROM[code]|sig; /* indexed by (0-2)*16+msd */
60236ac495dSmrg encode|=(uexp<<(32-6-DECECONL)) & 0x03ffffff; /* exponent continuation */
60336ac495dSmrg }
60436ac495dSmrg
60536ac495dSmrg /* private macro to extract a declet, n (where 0<=n<DECLETS and 0 */
60636ac495dSmrg /* refers to the declet from the least significant three digits) */
60736ac495dSmrg /* and put the corresponding DPD code into dpd. */
60836ac495dSmrg /* Use of a working pointer, uInt *ub, is assumed. */
60936ac495dSmrg
61036ac495dSmrg #define getDPDb(dpd, n) ub=bcdar+DECPMAX-1-(3*(n))-2; \
61136ac495dSmrg dpd=BCD2DPD[(*ub*256)+(*(ub+1)*16)+*(ub+2)];
61236ac495dSmrg
61336ac495dSmrg /* place the declets in the encoding words and copy to result (df), */
61436ac495dSmrg /* according to endianness; in all cases complete the sign word */
61536ac495dSmrg /* first */
61636ac495dSmrg #if DECPMAX==7
61736ac495dSmrg getDPDb(dpd, 1);
61836ac495dSmrg encode|=dpd<<10;
61936ac495dSmrg getDPDb(dpd, 0);
62036ac495dSmrg encode|=dpd;
62136ac495dSmrg DFWORD(df, 0)=encode; /* just the one word */
62236ac495dSmrg
62336ac495dSmrg #elif DECPMAX==16
62436ac495dSmrg getDPDb(dpd, 4); encode|=dpd<<8;
62536ac495dSmrg getDPDb(dpd, 3); encode|=dpd>>2;
62636ac495dSmrg DFWORD(df, 0)=encode;
62736ac495dSmrg encode=dpd<<30;
62836ac495dSmrg getDPDb(dpd, 2); encode|=dpd<<20;
62936ac495dSmrg getDPDb(dpd, 1); encode|=dpd<<10;
63036ac495dSmrg getDPDb(dpd, 0); encode|=dpd;
63136ac495dSmrg DFWORD(df, 1)=encode;
63236ac495dSmrg
63336ac495dSmrg #elif DECPMAX==34
63436ac495dSmrg getDPDb(dpd,10); encode|=dpd<<4;
63536ac495dSmrg getDPDb(dpd, 9); encode|=dpd>>6;
63636ac495dSmrg DFWORD(df, 0)=encode;
63736ac495dSmrg
63836ac495dSmrg encode=dpd<<26;
63936ac495dSmrg getDPDb(dpd, 8); encode|=dpd<<16;
64036ac495dSmrg getDPDb(dpd, 7); encode|=dpd<<6;
64136ac495dSmrg getDPDb(dpd, 6); encode|=dpd>>4;
64236ac495dSmrg DFWORD(df, 1)=encode;
64336ac495dSmrg
64436ac495dSmrg encode=dpd<<28;
64536ac495dSmrg getDPDb(dpd, 5); encode|=dpd<<18;
64636ac495dSmrg getDPDb(dpd, 4); encode|=dpd<<8;
64736ac495dSmrg getDPDb(dpd, 3); encode|=dpd>>2;
64836ac495dSmrg DFWORD(df, 2)=encode;
64936ac495dSmrg
65036ac495dSmrg encode=dpd<<30;
65136ac495dSmrg getDPDb(dpd, 2); encode|=dpd<<20;
65236ac495dSmrg getDPDb(dpd, 1); encode|=dpd<<10;
65336ac495dSmrg getDPDb(dpd, 0); encode|=dpd;
65436ac495dSmrg DFWORD(df, 3)=encode;
65536ac495dSmrg #endif
65636ac495dSmrg /* decFloatShow(df, "fromB"); */
65736ac495dSmrg return df;
65836ac495dSmrg } /* decFloatFromBCD */
65936ac495dSmrg
66036ac495dSmrg /* ------------------------------------------------------------------ */
66136ac495dSmrg /* decFloatFromPacked -- set decFloat from exponent and packed BCD */
66236ac495dSmrg /* */
66336ac495dSmrg /* df is the target decFloat */
66436ac495dSmrg /* exp is the in-range unbiased exponent, q, or a special value in */
66536ac495dSmrg /* the form returned by decFloatGetExponent */
66636ac495dSmrg /* packed holds DECPMAX packed decimal digits plus a sign nibble */
66736ac495dSmrg /* (all 6 codes are OK); the first (MSD) is ignored if df is a NaN */
66836ac495dSmrg /* and all except sign are ignored if df is infinite. For DOUBLE */
66936ac495dSmrg /* and QUAD the first (pad) nibble is also ignored in all cases. */
67036ac495dSmrg /* All coefficient nibbles must be in 0-9 and sign in A-F; results */
67136ac495dSmrg /* are undefined otherwise. */
67236ac495dSmrg /* returns df, which will be canonical */
67336ac495dSmrg /* */
67436ac495dSmrg /* No error is possible, and no status will be set. */
67536ac495dSmrg /* ------------------------------------------------------------------ */
decFloatFromPacked(decFloat * df,Int exp,const uByte * packed)67636ac495dSmrg decFloat * decFloatFromPacked(decFloat *df, Int exp, const uByte *packed) {
67736ac495dSmrg uByte bcdar[DECPMAX+2]; /* work [+1 for pad, +1 for sign] */
67836ac495dSmrg const uByte *ip; /* .. */
67936ac495dSmrg uByte *op; /* .. */
68036ac495dSmrg Int sig=0; /* sign */
68136ac495dSmrg
68236ac495dSmrg /* expand coefficient and sign to BCDAR */
68336ac495dSmrg #if SINGLE
68436ac495dSmrg op=bcdar+1; /* no pad digit */
68536ac495dSmrg #else
68636ac495dSmrg op=bcdar; /* first (pad) digit ignored */
68736ac495dSmrg #endif
68836ac495dSmrg for (ip=packed; ip<packed+((DECPMAX+2)/2); ip++) {
68936ac495dSmrg *op++=*ip>>4;
69036ac495dSmrg *op++=(uByte)(*ip&0x0f); /* [final nibble is sign] */
69136ac495dSmrg }
69236ac495dSmrg op--; /* -> sign byte */
69336ac495dSmrg if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign;
69436ac495dSmrg
69536ac495dSmrg if (EXPISSPECIAL(exp)) { /* Infinity or NaN */
69636ac495dSmrg if (!EXPISINF(exp)) bcdar[1]=0; /* a NaN: ignore MSD */
69736ac495dSmrg else memset(bcdar+1, 0, DECPMAX); /* Infinite: coefficient to 0 */
69836ac495dSmrg }
69936ac495dSmrg return decFloatFromBCD(df, exp, bcdar+1, sig);
70036ac495dSmrg } /* decFloatFromPacked */
70136ac495dSmrg
70236ac495dSmrg /* ------------------------------------------------------------------ */
70336ac495dSmrg /* decFloatFromPackedChecked -- set from exponent and packed; checked */
70436ac495dSmrg /* */
70536ac495dSmrg /* df is the target decFloat */
70636ac495dSmrg /* exp is the in-range unbiased exponent, q, or a special value in */
70736ac495dSmrg /* the form returned by decFloatGetExponent */
70836ac495dSmrg /* packed holds DECPMAX packed decimal digits plus a sign nibble */
70936ac495dSmrg /* (all 6 codes are OK); the first (MSD) must be 0 if df is a NaN */
71036ac495dSmrg /* and all digits must be 0 if df is infinite. For DOUBLE and */
71136ac495dSmrg /* QUAD the first (pad) nibble must be 0. */
71236ac495dSmrg /* All coefficient nibbles must be in 0-9 and sign in A-F. */
71336ac495dSmrg /* returns df, which will be canonical or NULL if any of the */
71436ac495dSmrg /* requirements are not met (if this case df is unchanged); that */
71536ac495dSmrg /* is, the input data must be as returned by decFloatToPacked, */
71636ac495dSmrg /* except that all six sign codes are accepted. */
71736ac495dSmrg /* */
71836ac495dSmrg /* No status will be set. */
71936ac495dSmrg /* ------------------------------------------------------------------ */
decFloatFromPackedChecked(decFloat * df,Int exp,const uByte * packed)72036ac495dSmrg decFloat * decFloatFromPackedChecked(decFloat *df, Int exp,
72136ac495dSmrg const uByte *packed) {
72236ac495dSmrg uByte bcdar[DECPMAX+2]; /* work [+1 for pad, +1 for sign] */
72336ac495dSmrg const uByte *ip; /* .. */
72436ac495dSmrg uByte *op; /* .. */
72536ac495dSmrg Int sig=0; /* sign */
72636ac495dSmrg
72736ac495dSmrg /* expand coefficient and sign to BCDAR */
72836ac495dSmrg #if SINGLE
72936ac495dSmrg op=bcdar+1; /* no pad digit */
73036ac495dSmrg #else
73136ac495dSmrg op=bcdar; /* first (pad) digit here */
73236ac495dSmrg #endif
73336ac495dSmrg for (ip=packed; ip<packed+((DECPMAX+2)/2); ip++) {
73436ac495dSmrg *op=*ip>>4;
73536ac495dSmrg if (*op>9) return NULL;
73636ac495dSmrg op++;
73736ac495dSmrg *op=(uByte)(*ip&0x0f); /* [final nibble is sign] */
73836ac495dSmrg if (*op>9 && ip<packed+((DECPMAX+2)/2)-1) return NULL;
73936ac495dSmrg op++;
74036ac495dSmrg }
74136ac495dSmrg op--; /* -> sign byte */
74236ac495dSmrg if (*op<=9) return NULL; /* bad sign */
74336ac495dSmrg if (*op==DECPMINUS || *op==DECPMINUSALT) sig=DECFLOAT_Sign;
74436ac495dSmrg
74536ac495dSmrg #if !SINGLE
74636ac495dSmrg if (bcdar[0]!=0) return NULL; /* bad pad nibble */
74736ac495dSmrg #endif
74836ac495dSmrg
74936ac495dSmrg if (EXPISNAN(exp)) { /* a NaN */
75036ac495dSmrg if (bcdar[1]!=0) return NULL; /* bad msd */
75136ac495dSmrg } /* NaN */
75236ac495dSmrg else if (EXPISINF(exp)) { /* is infinite */
75336ac495dSmrg Int i;
75436ac495dSmrg for (i=0; i<DECPMAX; i++) {
75536ac495dSmrg if (bcdar[i+1]!=0) return NULL; /* should be all zeros */
75636ac495dSmrg }
75736ac495dSmrg } /* infinity */
75836ac495dSmrg else { /* finite */
75936ac495dSmrg /* check the exponent is in range */
76036ac495dSmrg if (exp>DECEMAX-DECPMAX+1) return NULL;
76136ac495dSmrg if (exp<DECEMIN-DECPMAX+1) return NULL;
76236ac495dSmrg }
76336ac495dSmrg return decFloatFromBCD(df, exp, bcdar+1, sig);
76436ac495dSmrg } /* decFloatFromPacked */
76536ac495dSmrg
76636ac495dSmrg /* ------------------------------------------------------------------ */
76736ac495dSmrg /* decFloatFromString -- conversion from numeric string */
76836ac495dSmrg /* */
76936ac495dSmrg /* result is the decFloat format number which gets the result of */
77036ac495dSmrg /* the conversion */
77136ac495dSmrg /* *string is the character string which should contain a valid */
77236ac495dSmrg /* number (which may be a special value), \0-terminated */
77336ac495dSmrg /* If there are too many significant digits in the */
77436ac495dSmrg /* coefficient it will be rounded. */
77536ac495dSmrg /* set is the context */
77636ac495dSmrg /* returns result */
77736ac495dSmrg /* */
77836ac495dSmrg /* The length of the coefficient and the size of the exponent are */
77936ac495dSmrg /* checked by this routine, so the correct error (Underflow or */
78036ac495dSmrg /* Overflow) can be reported or rounding applied, as necessary. */
78136ac495dSmrg /* */
78236ac495dSmrg /* There is no limit to the coefficient length for finite inputs; */
78336ac495dSmrg /* NaN payloads must be integers with no more than DECPMAX-1 digits. */
78436ac495dSmrg /* Exponents may have up to nine significant digits. */
78536ac495dSmrg /* */
78636ac495dSmrg /* If bad syntax is detected, the result will be a quiet NaN. */
78736ac495dSmrg /* ------------------------------------------------------------------ */
decFloatFromString(decFloat * result,const char * string,decContext * set)78836ac495dSmrg decFloat * decFloatFromString(decFloat *result, const char *string,
78936ac495dSmrg decContext *set) {
79036ac495dSmrg Int digits; /* count of digits in coefficient */
79136ac495dSmrg const char *dotchar=NULL; /* where dot was found [NULL if none] */
79236ac495dSmrg const char *cfirst=string; /* -> first character of decimal part */
79336ac495dSmrg const char *c; /* work */
79436ac495dSmrg uByte *ub; /* .. */
79536ac495dSmrg uInt uiwork; /* for macros */
79636ac495dSmrg bcdnum num; /* collects data for finishing */
79736ac495dSmrg uInt error=DEC_Conversion_syntax; /* assume the worst */
79836ac495dSmrg uByte buffer[ROUNDUP(DECSTRING+11, 8)]; /* room for most coefficents, */
79936ac495dSmrg /* some common rounding, +3, & pad */
80036ac495dSmrg #if DECTRACE
80136ac495dSmrg /* printf("FromString %s ...\n", string); */
80236ac495dSmrg #endif
80336ac495dSmrg
80436ac495dSmrg for(;;) { /* once-only 'loop' */
80536ac495dSmrg num.sign=0; /* assume non-negative */
80636ac495dSmrg num.msd=buffer; /* MSD is here always */
80736ac495dSmrg
80836ac495dSmrg /* detect and validate the coefficient, including any leading, */
80936ac495dSmrg /* trailing, or embedded '.' */
81036ac495dSmrg /* [could test four-at-a-time here (saving 10% for decQuads), */
81136ac495dSmrg /* but that risks storage violation because the position of the */
81236ac495dSmrg /* terminator is unknown] */
81336ac495dSmrg for (c=string;; c++) { /* -> input character */
81436ac495dSmrg if (((unsigned)(*c-'0'))<=9) continue; /* '0' through '9' is good */
81536ac495dSmrg if (*c=='\0') break; /* most common non-digit */
81636ac495dSmrg if (*c=='.') {
81736ac495dSmrg if (dotchar!=NULL) break; /* not first '.' */
81836ac495dSmrg dotchar=c; /* record offset into decimal part */
81936ac495dSmrg continue;}
82036ac495dSmrg if (c==string) { /* first in string... */
82136ac495dSmrg if (*c=='-') { /* valid - sign */
82236ac495dSmrg cfirst++;
82336ac495dSmrg num.sign=DECFLOAT_Sign;
82436ac495dSmrg continue;}
82536ac495dSmrg if (*c=='+') { /* valid + sign */
82636ac495dSmrg cfirst++;
82736ac495dSmrg continue;}
82836ac495dSmrg }
82936ac495dSmrg /* *c is not a digit, terminator, or a valid +, -, or '.' */
83036ac495dSmrg break;
83136ac495dSmrg } /* c loop */
83236ac495dSmrg
83336ac495dSmrg digits=(uInt)(c-cfirst); /* digits (+1 if a dot) */
83436ac495dSmrg
83536ac495dSmrg if (digits>0) { /* had digits and/or dot */
83636ac495dSmrg const char *clast=c-1; /* note last coefficient char position */
83736ac495dSmrg Int exp=0; /* exponent accumulator */
83836ac495dSmrg if (*c!='\0') { /* something follows the coefficient */
83936ac495dSmrg uInt edig; /* unsigned work */
84036ac495dSmrg /* had some digits and more to come; expect E[+|-]nnn now */
84136ac495dSmrg const char *firstexp; /* exponent first non-zero */
84236ac495dSmrg if (*c!='E' && *c!='e') break;
84336ac495dSmrg c++; /* to (optional) sign */
84436ac495dSmrg if (*c=='-' || *c=='+') c++; /* step over sign (c=clast+2) */
84536ac495dSmrg if (*c=='\0') break; /* no digits! (e.g., '1.2E') */
84636ac495dSmrg for (; *c=='0';) c++; /* skip leading zeros [even last] */
84736ac495dSmrg firstexp=c; /* remember start [maybe '\0'] */
84836ac495dSmrg /* gather exponent digits */
84936ac495dSmrg edig=(uInt)*c-(uInt)'0';
85036ac495dSmrg if (edig<=9) { /* [check not bad or terminator] */
85136ac495dSmrg exp+=edig; /* avoid initial X10 */
85236ac495dSmrg c++;
85336ac495dSmrg for (;; c++) {
85436ac495dSmrg edig=(uInt)*c-(uInt)'0';
85536ac495dSmrg if (edig>9) break;
85636ac495dSmrg exp=exp*10+edig;
85736ac495dSmrg }
85836ac495dSmrg }
85936ac495dSmrg /* if not now on the '\0', *c must not be a digit */
86036ac495dSmrg if (*c!='\0') break;
86136ac495dSmrg
86236ac495dSmrg /* (this next test must be after the syntax checks) */
86336ac495dSmrg /* if definitely more than the possible digits for format then */
86436ac495dSmrg /* the exponent may have wrapped, so simply set it to a certain */
86536ac495dSmrg /* over/underflow value */
86636ac495dSmrg if (c>firstexp+DECEMAXD) exp=DECEMAX*2;
86736ac495dSmrg if (*(clast+2)=='-') exp=-exp; /* was negative */
86836ac495dSmrg } /* digits>0 */
86936ac495dSmrg
87036ac495dSmrg if (dotchar!=NULL) { /* had a '.' */
87136ac495dSmrg digits--; /* remove from digits count */
87236ac495dSmrg if (digits==0) break; /* was dot alone: bad syntax */
87336ac495dSmrg exp-=(Int)(clast-dotchar); /* adjust exponent */
87436ac495dSmrg /* [the '.' can now be ignored] */
87536ac495dSmrg }
87636ac495dSmrg num.exponent=exp; /* exponent is good; store it */
87736ac495dSmrg
87836ac495dSmrg /* Here when whole string has been inspected and syntax is good */
87936ac495dSmrg /* cfirst->first digit or dot, clast->last digit or dot */
88036ac495dSmrg error=0; /* no error possible now */
88136ac495dSmrg
88236ac495dSmrg /* if the number of digits in the coefficient will fit in buffer */
88336ac495dSmrg /* then it can simply be converted to bcd8 and copied -- decFinalize */
88436ac495dSmrg /* will take care of leading zeros and rounding; the buffer is big */
88536ac495dSmrg /* enough for all canonical coefficients, including 0.00000nn... */
88636ac495dSmrg ub=buffer;
88736ac495dSmrg if (digits<=(Int)(sizeof(buffer)-3)) { /* [-3 allows by-4s copy] */
88836ac495dSmrg c=cfirst;
88936ac495dSmrg if (dotchar!=NULL) { /* a dot to worry about */
89036ac495dSmrg if (*(c+1)=='.') { /* common canonical case */
89136ac495dSmrg *ub++=(uByte)(*c-'0'); /* copy leading digit */
89236ac495dSmrg c+=2; /* prepare to handle rest */
89336ac495dSmrg }
89436ac495dSmrg else for (; c<=clast;) { /* '.' could be anywhere */
89536ac495dSmrg /* as usual, go by fours when safe; NB it has been asserted */
89636ac495dSmrg /* that a '.' does not have the same mask as a digit */
89736ac495dSmrg if (c<=clast-3 /* safe for four */
89836ac495dSmrg && (UBTOUI(c)&0xf0f0f0f0)==CHARMASK) { /* test four */
89936ac495dSmrg UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f); /* to BCD8 */
90036ac495dSmrg ub+=4;
90136ac495dSmrg c+=4;
90236ac495dSmrg continue;
90336ac495dSmrg }
90436ac495dSmrg if (*c=='.') { /* found the dot */
90536ac495dSmrg c++; /* step over it .. */
90636ac495dSmrg break; /* .. and handle the rest */
90736ac495dSmrg }
90836ac495dSmrg *ub++=(uByte)(*c++-'0');
90936ac495dSmrg }
91036ac495dSmrg } /* had dot */
91136ac495dSmrg /* Now no dot; do this by fours (where safe) */
91236ac495dSmrg for (; c<=clast-3; c+=4, ub+=4) UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f);
91336ac495dSmrg for (; c<=clast; c++, ub++) *ub=(uByte)(*c-'0');
91436ac495dSmrg num.lsd=buffer+digits-1; /* record new LSD */
91536ac495dSmrg } /* fits */
91636ac495dSmrg
91736ac495dSmrg else { /* too long for buffer */
91836ac495dSmrg /* [This is a rare and unusual case; arbitrary-length input] */
91936ac495dSmrg /* strip leading zeros [but leave final 0 if all 0's] */
92036ac495dSmrg if (*cfirst=='.') cfirst++; /* step past dot at start */
92136ac495dSmrg if (*cfirst=='0') { /* [cfirst always -> digit] */
92236ac495dSmrg for (; cfirst<clast; cfirst++) {
92336ac495dSmrg if (*cfirst!='0') { /* non-zero found */
92436ac495dSmrg if (*cfirst=='.') continue; /* [ignore] */
92536ac495dSmrg break; /* done */
92636ac495dSmrg }
92736ac495dSmrg digits--; /* 0 stripped */
92836ac495dSmrg } /* cfirst */
92936ac495dSmrg } /* at least one leading 0 */
93036ac495dSmrg
93136ac495dSmrg /* the coefficient is now as short as possible, but may still */
93236ac495dSmrg /* be too long; copy up to Pmax+1 digits to the buffer, then */
93336ac495dSmrg /* just record any non-zeros (set round-for-reround digit) */
93436ac495dSmrg for (c=cfirst; c<=clast && ub<=buffer+DECPMAX; c++) {
93536ac495dSmrg /* (see commentary just above) */
93636ac495dSmrg if (c<=clast-3 /* safe for four */
93736ac495dSmrg && (UBTOUI(c)&0xf0f0f0f0)==CHARMASK) { /* four digits */
93836ac495dSmrg UBFROMUI(ub, UBTOUI(c)&0x0f0f0f0f); /* to BCD8 */
93936ac495dSmrg ub+=4;
94036ac495dSmrg c+=3; /* [will become 4] */
94136ac495dSmrg continue;
94236ac495dSmrg }
94336ac495dSmrg if (*c=='.') continue; /* [ignore] */
94436ac495dSmrg *ub++=(uByte)(*c-'0');
94536ac495dSmrg }
94636ac495dSmrg ub--; /* -> LSD */
94736ac495dSmrg for (; c<=clast; c++) { /* inspect remaining chars */
94836ac495dSmrg if (*c!='0') { /* sticky bit needed */
94936ac495dSmrg if (*c=='.') continue; /* [ignore] */
95036ac495dSmrg *ub=DECSTICKYTAB[*ub]; /* update round-for-reround */
95136ac495dSmrg break; /* no need to look at more */
95236ac495dSmrg }
95336ac495dSmrg }
95436ac495dSmrg num.lsd=ub; /* record LSD */
95536ac495dSmrg /* adjust exponent for dropped digits */
95636ac495dSmrg num.exponent+=digits-(Int)(ub-buffer+1);
95736ac495dSmrg } /* too long for buffer */
95836ac495dSmrg } /* digits or dot */
95936ac495dSmrg
96036ac495dSmrg else { /* no digits or dot were found */
96136ac495dSmrg if (*c=='\0') break; /* nothing to come is bad */
96236ac495dSmrg /* only Infinities and NaNs are allowed, here */
96336ac495dSmrg buffer[0]=0; /* default a coefficient of 0 */
96436ac495dSmrg num.lsd=buffer; /* .. */
96536ac495dSmrg if (decBiStr(c, "infinity", "INFINITY")
96636ac495dSmrg || decBiStr(c, "inf", "INF")) num.exponent=DECFLOAT_Inf;
96736ac495dSmrg else { /* should be a NaN */
96836ac495dSmrg num.exponent=DECFLOAT_qNaN; /* assume quiet NaN */
96936ac495dSmrg if (*c=='s' || *c=='S') { /* probably an sNaN */
97036ac495dSmrg c++;
97136ac495dSmrg num.exponent=DECFLOAT_sNaN; /* assume is in fact sNaN */
97236ac495dSmrg }
97336ac495dSmrg if (*c!='N' && *c!='n') break; /* check caseless "NaN" */
97436ac495dSmrg c++;
97536ac495dSmrg if (*c!='a' && *c!='A') break; /* .. */
97636ac495dSmrg c++;
97736ac495dSmrg if (*c!='N' && *c!='n') break; /* .. */
97836ac495dSmrg c++;
97936ac495dSmrg /* now either nothing, or nnnn payload (no dots), expected */
98036ac495dSmrg /* -> start of integer, and skip leading 0s [including plain 0] */
98136ac495dSmrg for (cfirst=c; *cfirst=='0';) cfirst++;
98236ac495dSmrg if (*cfirst!='\0') { /* not empty or all-0, payload */
98336ac495dSmrg /* payload found; check all valid digits and copy to buffer as bcd8 */
98436ac495dSmrg ub=buffer;
98536ac495dSmrg for (c=cfirst;; c++, ub++) {
98636ac495dSmrg if ((unsigned)(*c-'0')>9) break; /* quit if not 0-9 */
98736ac495dSmrg if (c-cfirst==DECPMAX-1) break; /* too many digits */
98836ac495dSmrg *ub=(uByte)(*c-'0'); /* good bcd8 */
98936ac495dSmrg }
99036ac495dSmrg if (*c!='\0') break; /* not all digits, or too many */
99136ac495dSmrg num.lsd=ub-1; /* record new LSD */
99236ac495dSmrg }
99336ac495dSmrg } /* NaN or sNaN */
99436ac495dSmrg error=0; /* syntax is OK */
99536ac495dSmrg break; /* done with specials */
99636ac495dSmrg } /* digits=0 (special expected) */
99736ac495dSmrg break;
99836ac495dSmrg } /* [for(;;) break] */
99936ac495dSmrg
100036ac495dSmrg /* decShowNum(&num, "fromStr"); */
100136ac495dSmrg
100236ac495dSmrg if (error!=0) {
100336ac495dSmrg set->status|=error;
100436ac495dSmrg num.exponent=DECFLOAT_qNaN; /* set up quiet NaN */
100536ac495dSmrg num.sign=0; /* .. with 0 sign */
100636ac495dSmrg buffer[0]=0; /* .. and coefficient */
100736ac495dSmrg num.lsd=buffer; /* .. */
100836ac495dSmrg /* decShowNum(&num, "oops"); */
100936ac495dSmrg }
101036ac495dSmrg
101136ac495dSmrg /* decShowNum(&num, "dffs"); */
101236ac495dSmrg decFinalize(result, &num, set); /* round, check, and lay out */
101336ac495dSmrg /* decFloatShow(result, "fromString"); */
101436ac495dSmrg return result;
101536ac495dSmrg } /* decFloatFromString */
101636ac495dSmrg
101736ac495dSmrg /* ------------------------------------------------------------------ */
101836ac495dSmrg /* decFloatFromWider -- conversion from next-wider format */
101936ac495dSmrg /* */
102036ac495dSmrg /* result is the decFloat format number which gets the result of */
102136ac495dSmrg /* the conversion */
102236ac495dSmrg /* wider is the decFloatWider format number which will be narrowed */
102336ac495dSmrg /* set is the context */
102436ac495dSmrg /* returns result */
102536ac495dSmrg /* */
102636ac495dSmrg /* Narrowing can cause rounding, overflow, etc., but not Invalid */
102736ac495dSmrg /* operation (sNaNs are copied and do not signal). */
102836ac495dSmrg /* ------------------------------------------------------------------ */
102936ac495dSmrg /* narrow-to is not possible for decQuad format numbers; simply omit */
103036ac495dSmrg #if !QUAD
decFloatFromWider(decFloat * result,const decFloatWider * wider,decContext * set)103136ac495dSmrg decFloat * decFloatFromWider(decFloat *result, const decFloatWider *wider,
103236ac495dSmrg decContext *set) {
103336ac495dSmrg bcdnum num; /* collects data for finishing */
103436ac495dSmrg uByte bcdar[DECWPMAX]; /* room for wider coefficient */
103536ac495dSmrg uInt widerhi=DFWWORD(wider, 0); /* top word */
103636ac495dSmrg Int exp;
103736ac495dSmrg
103836ac495dSmrg GETWCOEFF(wider, bcdar);
103936ac495dSmrg
104036ac495dSmrg num.msd=bcdar; /* MSD is here always */
104136ac495dSmrg num.lsd=bcdar+DECWPMAX-1; /* LSD is here always */
104236ac495dSmrg num.sign=widerhi&0x80000000; /* extract sign [DECFLOAT_Sign=Neg] */
104336ac495dSmrg
104436ac495dSmrg /* decode the wider combination field to exponent */
104536ac495dSmrg exp=DECCOMBWEXP[widerhi>>26]; /* decode from wider combination field */
104636ac495dSmrg /* if it is a special there's nothing to do unless sNaN; if it's */
104736ac495dSmrg /* finite then add the (wider) exponent continuation and unbias */
104836ac495dSmrg if (EXPISSPECIAL(exp)) exp=widerhi&0x7e000000; /* include sNaN selector */
104936ac495dSmrg else exp+=GETWECON(wider)-DECWBIAS;
105036ac495dSmrg num.exponent=exp;
105136ac495dSmrg
105236ac495dSmrg /* decShowNum(&num, "dffw"); */
105336ac495dSmrg return decFinalize(result, &num, set);/* round, check, and lay out */
105436ac495dSmrg } /* decFloatFromWider */
105536ac495dSmrg #endif
105636ac495dSmrg
105736ac495dSmrg /* ------------------------------------------------------------------ */
105836ac495dSmrg /* decFloatGetCoefficient -- get coefficient as BCD8 */
105936ac495dSmrg /* */
106036ac495dSmrg /* df is the decFloat from which to extract the coefficient */
106136ac495dSmrg /* bcdar is where DECPMAX bytes will be written, one BCD digit in */
106236ac495dSmrg /* each byte (BCD8 encoding); if df is a NaN the first byte will */
106336ac495dSmrg /* be zero, and if it is infinite they will all be zero */
106436ac495dSmrg /* returns the sign of the coefficient (DECFLOAT_Sign if negative, */
106536ac495dSmrg /* 0 otherwise) */
106636ac495dSmrg /* */
106736ac495dSmrg /* No error is possible, and no status will be set. If df is a */
106836ac495dSmrg /* special value the array is set to zeros (for Infinity) or to the */
106936ac495dSmrg /* payload of a qNaN or sNaN. */
107036ac495dSmrg /* ------------------------------------------------------------------ */
decFloatGetCoefficient(const decFloat * df,uByte * bcdar)107136ac495dSmrg Int decFloatGetCoefficient(const decFloat *df, uByte *bcdar) {
107236ac495dSmrg if (DFISINF(df)) memset(bcdar, 0, DECPMAX);
107336ac495dSmrg else {
107436ac495dSmrg GETCOEFF(df, bcdar); /* use macro */
107536ac495dSmrg if (DFISNAN(df)) bcdar[0]=0; /* MSD needs correcting */
107636ac495dSmrg }
107736ac495dSmrg return DFISSIGNED(df);
107836ac495dSmrg } /* decFloatGetCoefficient */
107936ac495dSmrg
108036ac495dSmrg /* ------------------------------------------------------------------ */
108136ac495dSmrg /* decFloatGetExponent -- get unbiased exponent */
108236ac495dSmrg /* */
108336ac495dSmrg /* df is the decFloat from which to extract the exponent */
108436ac495dSmrg /* returns the exponent, q. */
108536ac495dSmrg /* */
108636ac495dSmrg /* No error is possible, and no status will be set. If df is a */
108736ac495dSmrg /* special value the first seven bits of the decFloat are returned, */
108836ac495dSmrg /* left adjusted and with the first (sign) bit set to 0 (followed by */
108936ac495dSmrg /* 25 0 bits). e.g., -sNaN would return 0x7e000000 (DECFLOAT_sNaN). */
109036ac495dSmrg /* ------------------------------------------------------------------ */
decFloatGetExponent(const decFloat * df)109136ac495dSmrg Int decFloatGetExponent(const decFloat *df) {
109236ac495dSmrg if (DFISSPECIAL(df)) return DFWORD(df, 0)&0x7e000000;
109336ac495dSmrg return GETEXPUN(df);
109436ac495dSmrg } /* decFloatGetExponent */
109536ac495dSmrg
109636ac495dSmrg /* ------------------------------------------------------------------ */
109736ac495dSmrg /* decFloatSetCoefficient -- set coefficient from BCD8 */
109836ac495dSmrg /* */
109936ac495dSmrg /* df is the target decFloat (and source of exponent/special value) */
110036ac495dSmrg /* bcdar holds DECPMAX digits to set the coefficient from, one */
110136ac495dSmrg /* digit in each byte (BCD8 encoding); the first (MSD) is ignored */
110236ac495dSmrg /* if df is a NaN; all are ignored if df is infinite. */
110336ac495dSmrg /* sig is DECFLOAT_Sign to set the sign bit, 0 otherwise */
110436ac495dSmrg /* returns df, which will be canonical */
110536ac495dSmrg /* */
110636ac495dSmrg /* No error is possible, and no status will be set. */
110736ac495dSmrg /* ------------------------------------------------------------------ */
decFloatSetCoefficient(decFloat * df,const uByte * bcdar,Int sig)110836ac495dSmrg decFloat * decFloatSetCoefficient(decFloat *df, const uByte *bcdar,
110936ac495dSmrg Int sig) {
111036ac495dSmrg uInt exp; /* for exponent */
111136ac495dSmrg uByte bcdzero[DECPMAX]; /* for infinities */
111236ac495dSmrg
111336ac495dSmrg /* Exponent/special code is extracted from df */
111436ac495dSmrg if (DFISSPECIAL(df)) {
111536ac495dSmrg exp=DFWORD(df, 0)&0x7e000000;
111636ac495dSmrg if (DFISINF(df)) {
111736ac495dSmrg memset(bcdzero, 0, DECPMAX);
111836ac495dSmrg return decFloatFromBCD(df, exp, bcdzero, sig);
111936ac495dSmrg }
112036ac495dSmrg }
112136ac495dSmrg else exp=GETEXPUN(df);
112236ac495dSmrg return decFloatFromBCD(df, exp, bcdar, sig);
112336ac495dSmrg } /* decFloatSetCoefficient */
112436ac495dSmrg
112536ac495dSmrg /* ------------------------------------------------------------------ */
112636ac495dSmrg /* decFloatSetExponent -- set exponent or special value */
112736ac495dSmrg /* */
112836ac495dSmrg /* df is the target decFloat (and source of coefficient/payload) */
112936ac495dSmrg /* set is the context for reporting status */
113036ac495dSmrg /* exp is the unbiased exponent, q, or a special value in the form */
113136ac495dSmrg /* returned by decFloatGetExponent */
113236ac495dSmrg /* returns df, which will be canonical */
113336ac495dSmrg /* */
113436ac495dSmrg /* No error is possible, but Overflow or Underflow might occur. */
113536ac495dSmrg /* ------------------------------------------------------------------ */
decFloatSetExponent(decFloat * df,decContext * set,Int exp)113636ac495dSmrg decFloat * decFloatSetExponent(decFloat *df, decContext *set, Int exp) {
113736ac495dSmrg uByte bcdcopy[DECPMAX]; /* for coefficient */
113836ac495dSmrg bcdnum num; /* work */
113936ac495dSmrg num.exponent=exp;
114036ac495dSmrg num.sign=decFloatGetCoefficient(df, bcdcopy); /* extract coefficient */
114136ac495dSmrg if (DFISSPECIAL(df)) { /* MSD or more needs correcting */
114236ac495dSmrg if (DFISINF(df)) memset(bcdcopy, 0, DECPMAX);
114336ac495dSmrg bcdcopy[0]=0;
114436ac495dSmrg }
114536ac495dSmrg num.msd=bcdcopy;
114636ac495dSmrg num.lsd=bcdcopy+DECPMAX-1;
114736ac495dSmrg return decFinalize(df, &num, set);
114836ac495dSmrg } /* decFloatSetExponent */
114936ac495dSmrg
115036ac495dSmrg /* ------------------------------------------------------------------ */
115136ac495dSmrg /* decFloatRadix -- returns the base (10) */
115236ac495dSmrg /* */
115336ac495dSmrg /* df is any decFloat of this format */
115436ac495dSmrg /* ------------------------------------------------------------------ */
decFloatRadix(const decFloat * df)115536ac495dSmrg uInt decFloatRadix(const decFloat *df) {
115636ac495dSmrg if (df) return 10; /* to placate compiler */
115736ac495dSmrg return 10;
115836ac495dSmrg } /* decFloatRadix */
115936ac495dSmrg
116036ac495dSmrg #if (DECCHECK || DECTRACE)
116136ac495dSmrg /* ------------------------------------------------------------------ */
116236ac495dSmrg /* decFloatShow -- printf a decFloat in hexadecimal and decimal */
116336ac495dSmrg /* df is the decFloat to show */
116436ac495dSmrg /* tag is a tag string displayed with the number */
116536ac495dSmrg /* */
116636ac495dSmrg /* This is a debug aid; the precise format of the string may change. */
116736ac495dSmrg /* ------------------------------------------------------------------ */
decFloatShow(const decFloat * df,const char * tag)116836ac495dSmrg void decFloatShow(const decFloat *df, const char *tag) {
116936ac495dSmrg char hexbuf[DECBYTES*2+DECBYTES/4+1]; /* NB blank after every fourth */
117036ac495dSmrg char buff[DECSTRING]; /* for value in decimal */
117136ac495dSmrg Int i, j=0;
117236ac495dSmrg
117336ac495dSmrg for (i=0; i<DECBYTES; i++) {
117436ac495dSmrg #if DECLITEND
117536ac495dSmrg sprintf(&hexbuf[j], "%02x", df->bytes[DECBYTES-1-i]);
117636ac495dSmrg #else
117736ac495dSmrg sprintf(&hexbuf[j], "%02x", df->bytes[i]);
117836ac495dSmrg #endif
117936ac495dSmrg j+=2;
118036ac495dSmrg /* the next line adds blank (and terminator) after final pair, too */
118136ac495dSmrg if ((i+1)%4==0) {strcpy(&hexbuf[j], " "); j++;}
118236ac495dSmrg }
118336ac495dSmrg decFloatToString(df, buff);
118436ac495dSmrg printf(">%s> %s [big-endian] %s\n", tag, hexbuf, buff);
118536ac495dSmrg return;
118636ac495dSmrg } /* decFloatShow */
118736ac495dSmrg #endif
118836ac495dSmrg
118936ac495dSmrg /* ------------------------------------------------------------------ */
119036ac495dSmrg /* decFloatToBCD -- get sign, exponent, and BCD8 from a decFloat */
119136ac495dSmrg /* */
119236ac495dSmrg /* df is the source decFloat */
119336ac495dSmrg /* exp will be set to the unbiased exponent, q, or to a special */
119436ac495dSmrg /* value in the form returned by decFloatGetExponent */
119536ac495dSmrg /* bcdar is where DECPMAX bytes will be written, one BCD digit in */
119636ac495dSmrg /* each byte (BCD8 encoding); if df is a NaN the first byte will */
119736ac495dSmrg /* be zero, and if it is infinite they will all be zero */
119836ac495dSmrg /* returns the sign of the coefficient (DECFLOAT_Sign if negative, */
119936ac495dSmrg /* 0 otherwise) */
120036ac495dSmrg /* */
120136ac495dSmrg /* No error is possible, and no status will be set. */
120236ac495dSmrg /* ------------------------------------------------------------------ */
decFloatToBCD(const decFloat * df,Int * exp,uByte * bcdar)120336ac495dSmrg Int decFloatToBCD(const decFloat *df, Int *exp, uByte *bcdar) {
120436ac495dSmrg if (DFISINF(df)) {
120536ac495dSmrg memset(bcdar, 0, DECPMAX);
120636ac495dSmrg *exp=DFWORD(df, 0)&0x7e000000;
120736ac495dSmrg }
120836ac495dSmrg else {
120936ac495dSmrg GETCOEFF(df, bcdar); /* use macro */
121036ac495dSmrg if (DFISNAN(df)) {
121136ac495dSmrg bcdar[0]=0; /* MSD needs correcting */
121236ac495dSmrg *exp=DFWORD(df, 0)&0x7e000000;
121336ac495dSmrg }
121436ac495dSmrg else { /* finite */
121536ac495dSmrg *exp=GETEXPUN(df);
121636ac495dSmrg }
121736ac495dSmrg }
121836ac495dSmrg return DFISSIGNED(df);
121936ac495dSmrg } /* decFloatToBCD */
122036ac495dSmrg
122136ac495dSmrg /* ------------------------------------------------------------------ */
122236ac495dSmrg /* decFloatToEngString -- conversion to numeric string, engineering */
122336ac495dSmrg /* */
122436ac495dSmrg /* df is the decFloat format number to convert */
122536ac495dSmrg /* string is the string where the result will be laid out */
122636ac495dSmrg /* */
122736ac495dSmrg /* string must be at least DECPMAX+9 characters (the worst case is */
122836ac495dSmrg /* "-0.00000nnn...nnn\0", which is as long as the exponent form when */
122936ac495dSmrg /* DECEMAXD<=4); this condition is asserted above */
123036ac495dSmrg /* */
123136ac495dSmrg /* No error is possible, and no status will be set */
123236ac495dSmrg /* ------------------------------------------------------------------ */
decFloatToEngString(const decFloat * df,char * string)123336ac495dSmrg char * decFloatToEngString(const decFloat *df, char *string){
123436ac495dSmrg uInt msd; /* coefficient MSD */
123536ac495dSmrg Int exp; /* exponent top two bits or full */
123636ac495dSmrg uInt comb; /* combination field */
123736ac495dSmrg char *cstart; /* coefficient start */
123836ac495dSmrg char *c; /* output pointer in string */
123936ac495dSmrg char *s, *t; /* .. (source, target) */
124036ac495dSmrg Int pre, e; /* work */
124136ac495dSmrg const uByte *u; /* .. */
124236ac495dSmrg uInt uiwork; /* for macros [one compiler needs */
124336ac495dSmrg /* volatile here to avoid bug, but */
124436ac495dSmrg /* that doubles execution time] */
124536ac495dSmrg
124636ac495dSmrg /* Source words; macro handles endianness */
124736ac495dSmrg uInt sourhi=DFWORD(df, 0); /* word with sign */
124836ac495dSmrg #if DECPMAX==16
124936ac495dSmrg uInt sourlo=DFWORD(df, 1);
125036ac495dSmrg #elif DECPMAX==34
125136ac495dSmrg uInt sourmh=DFWORD(df, 1);
125236ac495dSmrg uInt sourml=DFWORD(df, 2);
125336ac495dSmrg uInt sourlo=DFWORD(df, 3);
125436ac495dSmrg #endif
125536ac495dSmrg
125636ac495dSmrg c=string; /* where result will go */
125736ac495dSmrg if (((Int)sourhi)<0) *c++='-'; /* handle sign */
125836ac495dSmrg comb=sourhi>>26; /* sign+combination field */
125936ac495dSmrg msd=DECCOMBMSD[comb]; /* decode the combination field */
126036ac495dSmrg exp=DECCOMBEXP[comb]; /* .. */
126136ac495dSmrg
126236ac495dSmrg if (EXPISSPECIAL(exp)) { /* special */
126336ac495dSmrg if (exp==DECFLOAT_Inf) { /* infinity */
126436ac495dSmrg strcpy(c, "Inf");
126536ac495dSmrg strcpy(c+3, "inity");
126636ac495dSmrg return string; /* easy */
126736ac495dSmrg }
126836ac495dSmrg if (sourhi&0x02000000) *c++='s'; /* sNaN */
126936ac495dSmrg strcpy(c, "NaN"); /* complete word */
127036ac495dSmrg c+=3; /* step past */
127136ac495dSmrg /* quick exit if the payload is zero */
127236ac495dSmrg #if DECPMAX==7
127336ac495dSmrg if ((sourhi&0x000fffff)==0) return string;
127436ac495dSmrg #elif DECPMAX==16
127536ac495dSmrg if (sourlo==0 && (sourhi&0x0003ffff)==0) return string;
127636ac495dSmrg #elif DECPMAX==34
127736ac495dSmrg if (sourlo==0 && sourml==0 && sourmh==0
127836ac495dSmrg && (sourhi&0x00003fff)==0) return string;
127936ac495dSmrg #endif
128036ac495dSmrg /* otherwise drop through to add integer; set correct exp etc. */
128136ac495dSmrg exp=0; msd=0; /* setup for following code */
128236ac495dSmrg }
128336ac495dSmrg else { /* complete exponent; top two bits are in place */
128436ac495dSmrg exp+=GETECON(df)-DECBIAS; /* .. + continuation and unbias */
128536ac495dSmrg }
128636ac495dSmrg
128736ac495dSmrg /* convert the digits of the significand to characters */
128836ac495dSmrg cstart=c; /* save start of coefficient */
128936ac495dSmrg if (msd) *c++=(char)('0'+(char)msd); /* non-zero most significant digit */
129036ac495dSmrg
129136ac495dSmrg /* Decode the declets. After extracting each declet, it is */
129236ac495dSmrg /* decoded to a 4-uByte sequence by table lookup; the four uBytes */
129336ac495dSmrg /* are the three encoded BCD8 digits followed by a 1-byte length */
129436ac495dSmrg /* (significant digits, except that 000 has length 0). This allows */
129536ac495dSmrg /* us to left-align the first declet with non-zero content, then */
129636ac495dSmrg /* the remaining ones are full 3-char length. Fixed-length copies */
129736ac495dSmrg /* are used because variable-length memcpy causes a subroutine call */
129836ac495dSmrg /* in at least two compilers. (The copies are length 4 for speed */
129936ac495dSmrg /* and are safe because the last item in the array is of length */
130036ac495dSmrg /* three and has the length byte following.) */
130136ac495dSmrg #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \
130236ac495dSmrg if (c!=cstart) {UBFROMUI(c, UBTOUI(u)|CHARMASK); c+=3;} \
130336ac495dSmrg else if (*(u+3)) { \
130436ac495dSmrg UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); c+=*(u+3);}
130536ac495dSmrg
130636ac495dSmrg #if DECPMAX==7
130736ac495dSmrg dpd2char(sourhi>>10); /* declet 1 */
130836ac495dSmrg dpd2char(sourhi); /* declet 2 */
130936ac495dSmrg
131036ac495dSmrg #elif DECPMAX==16
131136ac495dSmrg dpd2char(sourhi>>8); /* declet 1 */
131236ac495dSmrg dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */
131336ac495dSmrg dpd2char(sourlo>>20); /* declet 3 */
131436ac495dSmrg dpd2char(sourlo>>10); /* declet 4 */
131536ac495dSmrg dpd2char(sourlo); /* declet 5 */
131636ac495dSmrg
131736ac495dSmrg #elif DECPMAX==34
131836ac495dSmrg dpd2char(sourhi>>4); /* declet 1 */
131936ac495dSmrg dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */
132036ac495dSmrg dpd2char(sourmh>>16); /* declet 3 */
132136ac495dSmrg dpd2char(sourmh>>6); /* declet 4 */
132236ac495dSmrg dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */
132336ac495dSmrg dpd2char(sourml>>18); /* declet 6 */
132436ac495dSmrg dpd2char(sourml>>8); /* declet 7 */
132536ac495dSmrg dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */
132636ac495dSmrg dpd2char(sourlo>>20); /* declet 9 */
132736ac495dSmrg dpd2char(sourlo>>10); /* declet 10 */
132836ac495dSmrg dpd2char(sourlo); /* declet 11 */
132936ac495dSmrg #endif
133036ac495dSmrg
133136ac495dSmrg if (c==cstart) *c++='0'; /* all zeros, empty -- make "0" */
133236ac495dSmrg
133336ac495dSmrg if (exp==0) { /* integer or NaN case -- easy */
133436ac495dSmrg *c='\0'; /* terminate */
133536ac495dSmrg return string;
133636ac495dSmrg }
133736ac495dSmrg /* non-0 exponent */
133836ac495dSmrg
133936ac495dSmrg e=0; /* assume no E */
134036ac495dSmrg pre=(Int)(c-cstart)+exp; /* length+exp [c->LSD+1] */
134136ac495dSmrg /* [here, pre-exp is the digits count (==1 for zero)] */
134236ac495dSmrg
134336ac495dSmrg if (exp>0 || pre<-5) { /* need exponential form */
134436ac495dSmrg e=pre-1; /* calculate E value */
134536ac495dSmrg pre=1; /* assume one digit before '.' */
134636ac495dSmrg if (e!=0) { /* engineering: may need to adjust */
134736ac495dSmrg Int adj; /* adjustment */
134836ac495dSmrg /* The C remainder operator is undefined for negative numbers, so */
134936ac495dSmrg /* a positive remainder calculation must be used here */
135036ac495dSmrg if (e<0) {
135136ac495dSmrg adj=(-e)%3;
135236ac495dSmrg if (adj!=0) adj=3-adj;
135336ac495dSmrg }
135436ac495dSmrg else { /* e>0 */
135536ac495dSmrg adj=e%3;
135636ac495dSmrg }
135736ac495dSmrg e=e-adj;
135836ac495dSmrg /* if dealing with zero still produce an exponent which is a */
135936ac495dSmrg /* multiple of three, as expected, but there will only be the */
136036ac495dSmrg /* one zero before the E, still. Otherwise note the padding. */
136136ac495dSmrg if (!DFISZERO(df)) pre+=adj;
136236ac495dSmrg else { /* is zero */
136336ac495dSmrg if (adj!=0) { /* 0.00Esnn needed */
136436ac495dSmrg e=e+3;
136536ac495dSmrg pre=-(2-adj);
136636ac495dSmrg }
136736ac495dSmrg } /* zero */
136836ac495dSmrg } /* engineering adjustment */
136936ac495dSmrg } /* exponential form */
137036ac495dSmrg /* printf("e=%ld pre=%ld exp=%ld\n", (LI)e, (LI)pre, (LI)exp); */
137136ac495dSmrg
137236ac495dSmrg /* modify the coefficient, adding 0s, '.', and E+nn as needed */
137336ac495dSmrg if (pre>0) { /* ddd.ddd (plain), perhaps with E */
137436ac495dSmrg /* or dd00 padding for engineering */
137536ac495dSmrg char *dotat=cstart+pre;
137636ac495dSmrg if (dotat<c) { /* if embedded dot needed... */
137736ac495dSmrg /* move by fours; there must be space for junk at the end */
137836ac495dSmrg /* because there is still space for exponent */
137936ac495dSmrg s=dotat+ROUNDDOWN4(c-dotat); /* source */
138036ac495dSmrg t=s+1; /* target */
138136ac495dSmrg /* open the gap [cannot use memcpy] */
138236ac495dSmrg for (; s>=dotat; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
138336ac495dSmrg *dotat='.';
138436ac495dSmrg c++; /* length increased by one */
138536ac495dSmrg } /* need dot? */
138636ac495dSmrg else for (; c<dotat; c++) *c='0'; /* pad for engineering */
138736ac495dSmrg } /* pre>0 */
138836ac495dSmrg else {
138936ac495dSmrg /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (may have
139036ac495dSmrg E, but only for 0.00E+3 kind of case -- with plenty of spare
139136ac495dSmrg space in this case */
139236ac495dSmrg pre=-pre+2; /* gap width, including "0." */
139336ac495dSmrg t=cstart+ROUNDDOWN4(c-cstart)+pre; /* preferred first target point */
139436ac495dSmrg /* backoff if too far to the right */
139536ac495dSmrg if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */
139636ac495dSmrg /* now shift the entire coefficient to the right, being careful not */
139736ac495dSmrg /* to access to the left of string [cannot use memcpy] */
139836ac495dSmrg for (s=t-pre; s>=string; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
139936ac495dSmrg /* for Quads and Singles there may be a character or two left... */
140036ac495dSmrg s+=3; /* where next would come from */
140136ac495dSmrg for(; s>=cstart; s--, t--) *(t+3)=*(s);
140236ac495dSmrg /* now have fill 0. through 0.00000; use overlaps to avoid tests */
140336ac495dSmrg if (pre>=4) {
140436ac495dSmrg memcpy(cstart+pre-4, "0000", 4);
140536ac495dSmrg memcpy(cstart, "0.00", 4);
140636ac495dSmrg }
140736ac495dSmrg else { /* 2 or 3 */
140836ac495dSmrg *(cstart+pre-1)='0';
140936ac495dSmrg memcpy(cstart, "0.", 2);
141036ac495dSmrg }
141136ac495dSmrg c+=pre; /* to end */
141236ac495dSmrg }
141336ac495dSmrg
141436ac495dSmrg /* finally add the E-part, if needed; it will never be 0, and has */
141536ac495dSmrg /* a maximum length of 3 or 4 digits (asserted above) */
141636ac495dSmrg if (e!=0) {
141736ac495dSmrg memcpy(c, "E+", 2); /* starts with E, assume + */
141836ac495dSmrg c++;
141936ac495dSmrg if (e<0) {
142036ac495dSmrg *c='-'; /* oops, need '-' */
142136ac495dSmrg e=-e; /* uInt, please */
142236ac495dSmrg }
142336ac495dSmrg c++;
142436ac495dSmrg /* Three-character exponents are easy; 4-character a little trickier */
142536ac495dSmrg #if DECEMAXD<=3
142636ac495dSmrg u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
142736ac495dSmrg /* copy fixed 4 characters [is safe], starting at non-zero */
142836ac495dSmrg /* and with character mask to convert BCD to char */
142936ac495dSmrg UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK);
143036ac495dSmrg c+=*(u+3); /* bump pointer appropriately */
143136ac495dSmrg #elif DECEMAXD==4
143236ac495dSmrg if (e<1000) { /* 3 (or fewer) digits case */
143336ac495dSmrg u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
143436ac495dSmrg UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); /* [as above] */
143536ac495dSmrg c+=*(u+3); /* bump pointer appropriately */
143636ac495dSmrg }
143736ac495dSmrg else { /* 4-digits */
143836ac495dSmrg Int thou=((e>>3)*1049)>>17; /* e/1000 */
143936ac495dSmrg Int rem=e-(1000*thou); /* e%1000 */
144036ac495dSmrg *c++=(char)('0'+(char)thou); /* the thousands digit */
144136ac495dSmrg u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */
144236ac495dSmrg UBFROMUI(c, UBTOUI(u)|CHARMASK);/* copy fixed 3+1 characters [is safe] */
144336ac495dSmrg c+=3; /* bump pointer, always 3 digits */
144436ac495dSmrg }
144536ac495dSmrg #endif
144636ac495dSmrg }
144736ac495dSmrg *c='\0'; /* terminate */
144836ac495dSmrg /*printf("res %s\n", string); */
144936ac495dSmrg return string;
145036ac495dSmrg } /* decFloatToEngString */
145136ac495dSmrg
145236ac495dSmrg /* ------------------------------------------------------------------ */
145336ac495dSmrg /* decFloatToPacked -- convert decFloat to Packed decimal + exponent */
145436ac495dSmrg /* */
145536ac495dSmrg /* df is the source decFloat */
145636ac495dSmrg /* exp will be set to the unbiased exponent, q, or to a special */
145736ac495dSmrg /* value in the form returned by decFloatGetExponent */
145836ac495dSmrg /* packed is where DECPMAX nibbles will be written with the sign as */
145936ac495dSmrg /* final nibble (0x0c for +, 0x0d for -); a NaN has a first nibble */
146036ac495dSmrg /* of zero, and an infinity is all zeros. decDouble and decQuad */
146136ac495dSmrg /* have a additional leading zero nibble, leading to result */
146236ac495dSmrg /* lengths of 4, 9, and 18 bytes. */
146336ac495dSmrg /* returns the sign of the coefficient (DECFLOAT_Sign if negative, */
146436ac495dSmrg /* 0 otherwise) */
146536ac495dSmrg /* */
146636ac495dSmrg /* No error is possible, and no status will be set. */
146736ac495dSmrg /* ------------------------------------------------------------------ */
decFloatToPacked(const decFloat * df,Int * exp,uByte * packed)146836ac495dSmrg Int decFloatToPacked(const decFloat *df, Int *exp, uByte *packed) {
146936ac495dSmrg uByte bcdar[DECPMAX+2]; /* work buffer */
147036ac495dSmrg uByte *ip=bcdar, *op=packed; /* work pointers */
147136ac495dSmrg if (DFISINF(df)) {
147236ac495dSmrg memset(bcdar, 0, DECPMAX+2);
147336ac495dSmrg *exp=DECFLOAT_Inf;
147436ac495dSmrg }
147536ac495dSmrg else {
147636ac495dSmrg GETCOEFF(df, bcdar+1); /* use macro */
147736ac495dSmrg if (DFISNAN(df)) {
147836ac495dSmrg bcdar[1]=0; /* MSD needs clearing */
147936ac495dSmrg *exp=DFWORD(df, 0)&0x7e000000;
148036ac495dSmrg }
148136ac495dSmrg else { /* finite */
148236ac495dSmrg *exp=GETEXPUN(df);
148336ac495dSmrg }
148436ac495dSmrg }
148536ac495dSmrg /* now pack; coefficient currently at bcdar+1 */
148636ac495dSmrg #if SINGLE
148736ac495dSmrg ip++; /* ignore first byte */
148836ac495dSmrg #else
148936ac495dSmrg *ip=0; /* need leading zero */
149036ac495dSmrg #endif
149136ac495dSmrg /* set final byte to Packed BCD sign value */
149236ac495dSmrg bcdar[DECPMAX+1]=(DFISSIGNED(df) ? DECPMINUS : DECPPLUS);
149336ac495dSmrg /* pack an even number of bytes... */
149436ac495dSmrg for (; op<packed+((DECPMAX+2)/2); op++, ip+=2) {
149536ac495dSmrg *op=(uByte)((*ip<<4)+*(ip+1));
149636ac495dSmrg }
149736ac495dSmrg return (bcdar[DECPMAX+1]==DECPMINUS ? DECFLOAT_Sign : 0);
149836ac495dSmrg } /* decFloatToPacked */
149936ac495dSmrg
150036ac495dSmrg /* ------------------------------------------------------------------ */
150136ac495dSmrg /* decFloatToString -- conversion to numeric string */
150236ac495dSmrg /* */
150336ac495dSmrg /* df is the decFloat format number to convert */
150436ac495dSmrg /* string is the string where the result will be laid out */
150536ac495dSmrg /* */
150636ac495dSmrg /* string must be at least DECPMAX+9 characters (the worst case is */
150736ac495dSmrg /* "-0.00000nnn...nnn\0", which is as long as the exponent form when */
150836ac495dSmrg /* DECEMAXD<=4); this condition is asserted above */
150936ac495dSmrg /* */
151036ac495dSmrg /* No error is possible, and no status will be set */
151136ac495dSmrg /* ------------------------------------------------------------------ */
decFloatToString(const decFloat * df,char * string)151236ac495dSmrg char * decFloatToString(const decFloat *df, char *string){
151336ac495dSmrg uInt msd; /* coefficient MSD */
151436ac495dSmrg Int exp; /* exponent top two bits or full */
151536ac495dSmrg uInt comb; /* combination field */
151636ac495dSmrg char *cstart; /* coefficient start */
151736ac495dSmrg char *c; /* output pointer in string */
151836ac495dSmrg char *s, *t; /* .. (source, target) */
151936ac495dSmrg Int pre, e; /* work */
152036ac495dSmrg const uByte *u; /* .. */
152136ac495dSmrg uInt uiwork; /* for macros [one compiler needs */
152236ac495dSmrg /* volatile here to avoid bug, but */
152336ac495dSmrg /* that doubles execution time] */
152436ac495dSmrg
152536ac495dSmrg /* Source words; macro handles endianness */
152636ac495dSmrg uInt sourhi=DFWORD(df, 0); /* word with sign */
152736ac495dSmrg #if DECPMAX==16
152836ac495dSmrg uInt sourlo=DFWORD(df, 1);
152936ac495dSmrg #elif DECPMAX==34
153036ac495dSmrg uInt sourmh=DFWORD(df, 1);
153136ac495dSmrg uInt sourml=DFWORD(df, 2);
153236ac495dSmrg uInt sourlo=DFWORD(df, 3);
153336ac495dSmrg #endif
153436ac495dSmrg
153536ac495dSmrg c=string; /* where result will go */
153636ac495dSmrg if (((Int)sourhi)<0) *c++='-'; /* handle sign */
153736ac495dSmrg comb=sourhi>>26; /* sign+combination field */
153836ac495dSmrg msd=DECCOMBMSD[comb]; /* decode the combination field */
153936ac495dSmrg exp=DECCOMBEXP[comb]; /* .. */
154036ac495dSmrg
154136ac495dSmrg if (!EXPISSPECIAL(exp)) { /* finite */
154236ac495dSmrg /* complete exponent; top two bits are in place */
154336ac495dSmrg exp+=GETECON(df)-DECBIAS; /* .. + continuation and unbias */
154436ac495dSmrg }
154536ac495dSmrg else { /* IS special */
154636ac495dSmrg if (exp==DECFLOAT_Inf) { /* infinity */
154736ac495dSmrg strcpy(c, "Infinity");
154836ac495dSmrg return string; /* easy */
154936ac495dSmrg }
155036ac495dSmrg if (sourhi&0x02000000) *c++='s'; /* sNaN */
155136ac495dSmrg strcpy(c, "NaN"); /* complete word */
155236ac495dSmrg c+=3; /* step past */
155336ac495dSmrg /* quick exit if the payload is zero */
155436ac495dSmrg #if DECPMAX==7
155536ac495dSmrg if ((sourhi&0x000fffff)==0) return string;
155636ac495dSmrg #elif DECPMAX==16
155736ac495dSmrg if (sourlo==0 && (sourhi&0x0003ffff)==0) return string;
155836ac495dSmrg #elif DECPMAX==34
155936ac495dSmrg if (sourlo==0 && sourml==0 && sourmh==0
156036ac495dSmrg && (sourhi&0x00003fff)==0) return string;
156136ac495dSmrg #endif
156236ac495dSmrg /* otherwise drop through to add integer; set correct exp etc. */
156336ac495dSmrg exp=0; msd=0; /* setup for following code */
156436ac495dSmrg }
156536ac495dSmrg
156636ac495dSmrg /* convert the digits of the significand to characters */
156736ac495dSmrg cstart=c; /* save start of coefficient */
156836ac495dSmrg if (msd) *c++=(char)('0'+(char)msd); /* non-zero most significant digit */
156936ac495dSmrg
157036ac495dSmrg /* Decode the declets. After extracting each declet, it is */
157136ac495dSmrg /* decoded to a 4-uByte sequence by table lookup; the four uBytes */
157236ac495dSmrg /* are the three encoded BCD8 digits followed by a 1-byte length */
157336ac495dSmrg /* (significant digits, except that 000 has length 0). This allows */
157436ac495dSmrg /* us to left-align the first declet with non-zero content, then */
157536ac495dSmrg /* the remaining ones are full 3-char length. Fixed-length copies */
157636ac495dSmrg /* are used because variable-length memcpy causes a subroutine call */
157736ac495dSmrg /* in at least two compilers. (The copies are length 4 for speed */
157836ac495dSmrg /* and are safe because the last item in the array is of length */
157936ac495dSmrg /* three and has the length byte following.) */
158036ac495dSmrg #define dpd2char(dpdin) u=&DPD2BCD8[((dpdin)&0x3ff)*4]; \
158136ac495dSmrg if (c!=cstart) {UBFROMUI(c, UBTOUI(u)|CHARMASK); c+=3;} \
158236ac495dSmrg else if (*(u+3)) { \
158336ac495dSmrg UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); c+=*(u+3);}
158436ac495dSmrg
158536ac495dSmrg #if DECPMAX==7
158636ac495dSmrg dpd2char(sourhi>>10); /* declet 1 */
158736ac495dSmrg dpd2char(sourhi); /* declet 2 */
158836ac495dSmrg
158936ac495dSmrg #elif DECPMAX==16
159036ac495dSmrg dpd2char(sourhi>>8); /* declet 1 */
159136ac495dSmrg dpd2char((sourhi<<2) | (sourlo>>30)); /* declet 2 */
159236ac495dSmrg dpd2char(sourlo>>20); /* declet 3 */
159336ac495dSmrg dpd2char(sourlo>>10); /* declet 4 */
159436ac495dSmrg dpd2char(sourlo); /* declet 5 */
159536ac495dSmrg
159636ac495dSmrg #elif DECPMAX==34
159736ac495dSmrg dpd2char(sourhi>>4); /* declet 1 */
159836ac495dSmrg dpd2char((sourhi<<6) | (sourmh>>26)); /* declet 2 */
159936ac495dSmrg dpd2char(sourmh>>16); /* declet 3 */
160036ac495dSmrg dpd2char(sourmh>>6); /* declet 4 */
160136ac495dSmrg dpd2char((sourmh<<4) | (sourml>>28)); /* declet 5 */
160236ac495dSmrg dpd2char(sourml>>18); /* declet 6 */
160336ac495dSmrg dpd2char(sourml>>8); /* declet 7 */
160436ac495dSmrg dpd2char((sourml<<2) | (sourlo>>30)); /* declet 8 */
160536ac495dSmrg dpd2char(sourlo>>20); /* declet 9 */
160636ac495dSmrg dpd2char(sourlo>>10); /* declet 10 */
160736ac495dSmrg dpd2char(sourlo); /* declet 11 */
160836ac495dSmrg #endif
160936ac495dSmrg
161036ac495dSmrg if (c==cstart) *c++='0'; /* all zeros, empty -- make "0" */
161136ac495dSmrg
161236ac495dSmrg /*[This fast path is valid but adds 3-5 cycles to worst case length] */
161336ac495dSmrg /*if (exp==0) { // integer or NaN case -- easy */
161436ac495dSmrg /* *c='\0'; // terminate */
161536ac495dSmrg /* return string; */
161636ac495dSmrg /* } */
161736ac495dSmrg
161836ac495dSmrg e=0; /* assume no E */
161936ac495dSmrg pre=(Int)(c-cstart)+exp; /* length+exp [c->LSD+1] */
162036ac495dSmrg /* [here, pre-exp is the digits count (==1 for zero)] */
162136ac495dSmrg
162236ac495dSmrg if (exp>0 || pre<-5) { /* need exponential form */
162336ac495dSmrg e=pre-1; /* calculate E value */
162436ac495dSmrg pre=1; /* assume one digit before '.' */
162536ac495dSmrg } /* exponential form */
162636ac495dSmrg
162736ac495dSmrg /* modify the coefficient, adding 0s, '.', and E+nn as needed */
162836ac495dSmrg if (pre>0) { /* ddd.ddd (plain), perhaps with E */
162936ac495dSmrg char *dotat=cstart+pre;
163036ac495dSmrg if (dotat<c) { /* if embedded dot needed... */
163136ac495dSmrg /* [memmove is a disaster, here] */
163236ac495dSmrg /* move by fours; there must be space for junk at the end */
163336ac495dSmrg /* because exponent is still possible */
163436ac495dSmrg s=dotat+ROUNDDOWN4(c-dotat); /* source */
163536ac495dSmrg t=s+1; /* target */
163636ac495dSmrg /* open the gap [cannot use memcpy] */
163736ac495dSmrg for (; s>=dotat; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
163836ac495dSmrg *dotat='.';
163936ac495dSmrg c++; /* length increased by one */
164036ac495dSmrg } /* need dot? */
164136ac495dSmrg
164236ac495dSmrg /* finally add the E-part, if needed; it will never be 0, and has */
164336ac495dSmrg /* a maximum length of 3 or 4 digits (asserted above) */
164436ac495dSmrg if (e!=0) {
164536ac495dSmrg memcpy(c, "E+", 2); /* starts with E, assume + */
164636ac495dSmrg c++;
164736ac495dSmrg if (e<0) {
164836ac495dSmrg *c='-'; /* oops, need '-' */
164936ac495dSmrg e=-e; /* uInt, please */
165036ac495dSmrg }
165136ac495dSmrg c++;
165236ac495dSmrg /* Three-character exponents are easy; 4-character a little trickier */
165336ac495dSmrg #if DECEMAXD<=3
165436ac495dSmrg u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
165536ac495dSmrg /* copy fixed 4 characters [is safe], starting at non-zero */
165636ac495dSmrg /* and with character mask to convert BCD to char */
165736ac495dSmrg UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK);
165836ac495dSmrg c+=*(u+3); /* bump pointer appropriately */
165936ac495dSmrg #elif DECEMAXD==4
166036ac495dSmrg if (e<1000) { /* 3 (or fewer) digits case */
166136ac495dSmrg u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
166236ac495dSmrg UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); /* [as above] */
166336ac495dSmrg c+=*(u+3); /* bump pointer appropriately */
166436ac495dSmrg }
166536ac495dSmrg else { /* 4-digits */
166636ac495dSmrg Int thou=((e>>3)*1049)>>17; /* e/1000 */
166736ac495dSmrg Int rem=e-(1000*thou); /* e%1000 */
166836ac495dSmrg *c++=(char)('0'+(char)thou); /* the thousands digit */
166936ac495dSmrg u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */
167036ac495dSmrg UBFROMUI(c, UBTOUI(u)|CHARMASK); /* copy fixed 3+1 characters [is safe] */
167136ac495dSmrg c+=3; /* bump pointer, always 3 digits */
167236ac495dSmrg }
167336ac495dSmrg #endif
167436ac495dSmrg }
167536ac495dSmrg *c='\0'; /* add terminator */
167636ac495dSmrg /*printf("res %s\n", string); */
167736ac495dSmrg return string;
167836ac495dSmrg } /* pre>0 */
167936ac495dSmrg
168036ac495dSmrg /* -5<=pre<=0: here for plain 0.ddd or 0.000ddd forms (can never have E) */
168136ac495dSmrg /* Surprisingly, this is close to being the worst-case path, so the */
168236ac495dSmrg /* shift is done by fours; this is a little tricky because the */
168336ac495dSmrg /* rightmost character to be written must not be beyond where the */
168436ac495dSmrg /* rightmost terminator could be -- so backoff to not touch */
168536ac495dSmrg /* terminator position if need be (this can make exact alignments */
168636ac495dSmrg /* for full Doubles, but in some cases needs care not to access too */
168736ac495dSmrg /* far to the left) */
168836ac495dSmrg
168936ac495dSmrg pre=-pre+2; /* gap width, including "0." */
169036ac495dSmrg t=cstart+ROUNDDOWN4(c-cstart)+pre; /* preferred first target point */
169136ac495dSmrg /* backoff if too far to the right */
169236ac495dSmrg if (t>string+DECSTRING-5) t=string+DECSTRING-5; /* adjust to fit */
169336ac495dSmrg /* now shift the entire coefficient to the right, being careful not */
169436ac495dSmrg /* to access to the left of string [cannot use memcpy] */
169536ac495dSmrg for (s=t-pre; s>=string; s-=4, t-=4) UBFROMUI(t, UBTOUI(s));
169636ac495dSmrg /* for Quads and Singles there may be a character or two left... */
169736ac495dSmrg s+=3; /* where next would come from */
169836ac495dSmrg for(; s>=cstart; s--, t--) *(t+3)=*(s);
169936ac495dSmrg /* now have fill 0. through 0.00000; use overlaps to avoid tests */
170036ac495dSmrg if (pre>=4) {
170136ac495dSmrg memcpy(cstart+pre-4, "0000", 4);
170236ac495dSmrg memcpy(cstart, "0.00", 4);
170336ac495dSmrg }
170436ac495dSmrg else { /* 2 or 3 */
170536ac495dSmrg *(cstart+pre-1)='0';
170636ac495dSmrg memcpy(cstart, "0.", 2);
170736ac495dSmrg }
170836ac495dSmrg *(c+pre)='\0'; /* terminate */
170936ac495dSmrg return string;
171036ac495dSmrg } /* decFloatToString */
171136ac495dSmrg
171236ac495dSmrg /* ------------------------------------------------------------------ */
171336ac495dSmrg /* decFloatToWider -- conversion to next-wider format */
171436ac495dSmrg /* */
171536ac495dSmrg /* source is the decFloat format number which gets the result of */
171636ac495dSmrg /* the conversion */
171736ac495dSmrg /* wider is the decFloatWider format number which will be narrowed */
171836ac495dSmrg /* returns wider */
171936ac495dSmrg /* */
172036ac495dSmrg /* Widening is always exact; no status is set (sNaNs are copied and */
172136ac495dSmrg /* do not signal). The result will be canonical if the source is, */
172236ac495dSmrg /* and may or may not be if the source is not. */
172336ac495dSmrg /* ------------------------------------------------------------------ */
172436ac495dSmrg /* widening is not possible for decQuad format numbers; simply omit */
172536ac495dSmrg #if !QUAD
decFloatToWider(const decFloat * source,decFloatWider * wider)172636ac495dSmrg decFloatWider * decFloatToWider(const decFloat *source, decFloatWider *wider) {
172736ac495dSmrg uInt msd;
172836ac495dSmrg
172936ac495dSmrg /* Construct and copy the sign word */
173036ac495dSmrg if (DFISSPECIAL(source)) {
173136ac495dSmrg /* copy sign, combination, and first bit of exponent (sNaN selector) */
173236ac495dSmrg DFWWORD(wider, 0)=DFWORD(source, 0)&0xfe000000;
173336ac495dSmrg msd=0;
173436ac495dSmrg }
173536ac495dSmrg else { /* is finite number */
173636ac495dSmrg uInt exp=GETEXPUN(source)+DECWBIAS; /* get unbiased exponent and rebias */
173736ac495dSmrg uInt code=(exp>>DECWECONL)<<29; /* set two bits of exp [msd=0] */
173836ac495dSmrg code|=(exp<<(32-6-DECWECONL)) & 0x03ffffff; /* add exponent continuation */
173936ac495dSmrg code|=DFWORD(source, 0)&0x80000000; /* add sign */
174036ac495dSmrg DFWWORD(wider, 0)=code; /* .. and place top word in wider */
174136ac495dSmrg msd=GETMSD(source); /* get source coefficient MSD [0-9] */
174236ac495dSmrg }
174336ac495dSmrg /* Copy the coefficient and clear any 'unused' words to left */
174436ac495dSmrg #if SINGLE
174536ac495dSmrg DFWWORD(wider, 1)=(DFWORD(source, 0)&0x000fffff)|(msd<<20);
174636ac495dSmrg #elif DOUBLE
174736ac495dSmrg DFWWORD(wider, 2)=(DFWORD(source, 0)&0x0003ffff)|(msd<<18);
174836ac495dSmrg DFWWORD(wider, 3)=DFWORD(source, 1);
174936ac495dSmrg DFWWORD(wider, 1)=0;
175036ac495dSmrg #endif
175136ac495dSmrg return wider;
175236ac495dSmrg } /* decFloatToWider */
175336ac495dSmrg #endif
175436ac495dSmrg
175536ac495dSmrg /* ------------------------------------------------------------------ */
175636ac495dSmrg /* decFloatVersion -- return package version string */
175736ac495dSmrg /* */
175836ac495dSmrg /* returns a constant string describing this package */
175936ac495dSmrg /* ------------------------------------------------------------------ */
decFloatVersion(void)176036ac495dSmrg const char *decFloatVersion(void) {
176136ac495dSmrg return DECVERSION;
176236ac495dSmrg } /* decFloatVersion */
176336ac495dSmrg
176436ac495dSmrg /* ------------------------------------------------------------------ */
176536ac495dSmrg /* decFloatZero -- set to canonical (integer) zero */
176636ac495dSmrg /* */
176736ac495dSmrg /* df is the decFloat format number to integer +0 (q=0, c=+0) */
176836ac495dSmrg /* returns df */
176936ac495dSmrg /* */
177036ac495dSmrg /* No error is possible, and no status can be set. */
177136ac495dSmrg /* ------------------------------------------------------------------ */
decFloatZero(decFloat * df)177236ac495dSmrg decFloat * decFloatZero(decFloat *df){
177336ac495dSmrg DFWORD(df, 0)=ZEROWORD; /* set appropriate top word */
177436ac495dSmrg #if DOUBLE || QUAD
177536ac495dSmrg DFWORD(df, 1)=0;
177636ac495dSmrg #if QUAD
177736ac495dSmrg DFWORD(df, 2)=0;
177836ac495dSmrg DFWORD(df, 3)=0;
177936ac495dSmrg #endif
178036ac495dSmrg #endif
178136ac495dSmrg /* decFloatShow(df, "zero"); */
178236ac495dSmrg return df;
178336ac495dSmrg } /* decFloatZero */
178436ac495dSmrg
178536ac495dSmrg /* ------------------------------------------------------------------ */
178636ac495dSmrg /* Private generic function (not format-specific) for development use */
178736ac495dSmrg /* ------------------------------------------------------------------ */
178836ac495dSmrg /* This is included once only, for all to use */
178936ac495dSmrg #if QUAD && (DECCHECK || DECTRACE)
179036ac495dSmrg /* ---------------------------------------------------------------- */
179136ac495dSmrg /* decShowNum -- display bcd8 number in debug form */
179236ac495dSmrg /* */
179336ac495dSmrg /* num is the bcdnum to display */
179436ac495dSmrg /* tag is a string to label the display */
179536ac495dSmrg /* ---------------------------------------------------------------- */
decShowNum(const bcdnum * num,const char * tag)179636ac495dSmrg void decShowNum(const bcdnum *num, const char *tag) {
179736ac495dSmrg const char *csign="+"; /* sign character */
179836ac495dSmrg uByte *ub; /* work */
179936ac495dSmrg uInt uiwork; /* for macros */
180036ac495dSmrg if (num->sign==DECFLOAT_Sign) csign="-";
180136ac495dSmrg
180236ac495dSmrg printf(">%s> ", tag);
180336ac495dSmrg if (num->exponent==DECFLOAT_Inf) printf("%sInfinity", csign);
180436ac495dSmrg else if (num->exponent==DECFLOAT_qNaN) printf("%sqNaN", csign);
180536ac495dSmrg else if (num->exponent==DECFLOAT_sNaN) printf("%ssNaN", csign);
180636ac495dSmrg else { /* finite */
180736ac495dSmrg char qbuf[10]; /* for right-aligned q */
180836ac495dSmrg char *c; /* work */
180936ac495dSmrg const uByte *u; /* .. */
181036ac495dSmrg Int e=num->exponent; /* .. exponent */
181136ac495dSmrg strcpy(qbuf, "q=");
181236ac495dSmrg c=&qbuf[2]; /* where exponent will go */
181336ac495dSmrg /* lay out the exponent */
181436ac495dSmrg if (e<0) {
181536ac495dSmrg *c++='-'; /* add '-' */
181636ac495dSmrg e=-e; /* uInt, please */
181736ac495dSmrg }
181836ac495dSmrg #if DECEMAXD>4
181936ac495dSmrg #error Exponent form is too long for ShowNum to lay out
182036ac495dSmrg #endif
182136ac495dSmrg if (e==0) *c++='0'; /* 0-length case */
182236ac495dSmrg else if (e<1000) { /* 3 (or fewer) digits case */
182336ac495dSmrg u=&BIN2BCD8[e*4]; /* -> 3 digits + length byte */
182436ac495dSmrg UBFROMUI(c, UBTOUI(u+3-*(u+3))|CHARMASK); /* [as above] */
182536ac495dSmrg c+=*(u+3); /* bump pointer appropriately */
182636ac495dSmrg }
182736ac495dSmrg else { /* 4-digits */
182836ac495dSmrg Int thou=((e>>3)*1049)>>17; /* e/1000 */
182936ac495dSmrg Int rem=e-(1000*thou); /* e%1000 */
183036ac495dSmrg *c++=(char)('0'+(char)thou); /* the thousands digit */
183136ac495dSmrg u=&BIN2BCD8[rem*4]; /* -> 3 digits + length byte */
183236ac495dSmrg UBFROMUI(c, UBTOUI(u)|CHARMASK); /* copy fixed 3+1 characters [is safe] */
183336ac495dSmrg c+=3; /* bump pointer, always 3 digits */
183436ac495dSmrg }
183536ac495dSmrg *c='\0'; /* add terminator */
183636ac495dSmrg printf("%7s c=%s", qbuf, csign);
183736ac495dSmrg }
183836ac495dSmrg
183936ac495dSmrg if (!EXPISSPECIAL(num->exponent) || num->msd!=num->lsd || *num->lsd!=0) {
184036ac495dSmrg for (ub=num->msd; ub<=num->lsd; ub++) { /* coefficient... */
184136ac495dSmrg printf("%1x", *ub);
184236ac495dSmrg if ((num->lsd-ub)%3==0 && ub!=num->lsd) printf(" "); /* 4-space */
184336ac495dSmrg }
184436ac495dSmrg }
184536ac495dSmrg printf("\n");
184636ac495dSmrg } /* decShowNum */
184736ac495dSmrg #endif
1848