libdecnumber: Introduce decNumberIntegralToInt64
Introduce a new conversion function to the libdecnumber library. This function converts a decNumber to a signed 64-bit integer. In order to support 64-bit integers (which may have up to 19 decimal digits), the existing "powers of 10" array is expanded from 10 to 19 entries. Signed-off-by: Tom Musta <tommusta@gmail.com> [agraf: fix 32bit host compile] Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
8e706db21e
commit
79af357225
@ -122,6 +122,7 @@
|
|||||||
char * decNumberToEngString(const decNumber *, char *);
|
char * decNumberToEngString(const decNumber *, char *);
|
||||||
uint32_t decNumberToUInt32(const decNumber *, decContext *);
|
uint32_t decNumberToUInt32(const decNumber *, decContext *);
|
||||||
int32_t decNumberToInt32(const decNumber *, decContext *);
|
int32_t decNumberToInt32(const decNumber *, decContext *);
|
||||||
|
int64_t decNumberIntegralToInt64(const decNumber *dn, decContext *set);
|
||||||
uint8_t * decNumberGetBCD(const decNumber *, uint8_t *);
|
uint8_t * decNumberGetBCD(const decNumber *, uint8_t *);
|
||||||
decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
|
decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@
|
|||||||
|
|
||||||
/* Shared lookup tables */
|
/* Shared lookup tables */
|
||||||
extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */
|
extern const uByte DECSTICKYTAB[10]; /* re-round digits if sticky */
|
||||||
extern const uInt DECPOWERS[10]; /* powers of ten table */
|
extern const uLong DECPOWERS[19]; /* powers of ten table */
|
||||||
/* The following are included from decDPD.h */
|
/* The following are included from decDPD.h */
|
||||||
extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */
|
extern const uShort DPD2BIN[1024]; /* DPD -> 0-999 */
|
||||||
extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */
|
extern const uShort BIN2DPD[1000]; /* 0-999 -> DPD */
|
||||||
|
@ -56,8 +56,10 @@ const uByte DECSTICKYTAB[10]={1,1,2,3,4,6,6,7,8,9}; /* used if sticky */
|
|||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* Powers of ten (powers[n]==10**n, 0<=n<=9) */
|
/* Powers of ten (powers[n]==10**n, 0<=n<=9) */
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
|
const uLong DECPOWERS[19] = {1, 10, 100, 1000, 10000, 100000, 1000000,
|
||||||
10000000, 100000000, 1000000000};
|
10000000, 100000000, 1000000000, 10000000000ULL, 100000000000ULL,
|
||||||
|
1000000000000ULL, 10000000000000ULL, 100000000000000ULL, 1000000000000000ULL,
|
||||||
|
10000000000000000ULL, 100000000000000000ULL, 1000000000000000000ULL, };
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* decContextClearStatus -- clear bits in current status */
|
/* decContextClearStatus -- clear bits in current status */
|
||||||
|
@ -465,6 +465,50 @@ decNumber *decNumberFromUInt64(decNumber *dn, uint64_t uin)
|
|||||||
return dn;
|
return dn;
|
||||||
} /* decNumberFromUInt64 */
|
} /* decNumberFromUInt64 */
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
/* to-int64 -- conversion to int64 */
|
||||||
|
/* */
|
||||||
|
/* dn is the decNumber to convert. dn is assumed to have been */
|
||||||
|
/* rounded to a floating point integer value. */
|
||||||
|
/* set is the context for reporting errors */
|
||||||
|
/* returns the converted decNumber, or 0 if Invalid is set */
|
||||||
|
/* */
|
||||||
|
/* Invalid is set if the decNumber is a NaN, Infinite or is out of */
|
||||||
|
/* range for a signed 64 bit integer. */
|
||||||
|
/* ------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
int64_t decNumberIntegralToInt64(const decNumber *dn, decContext *set)
|
||||||
|
{
|
||||||
|
if (decNumberIsSpecial(dn) || (dn->exponent < 0) ||
|
||||||
|
(dn->digits + dn->exponent > 19)) {
|
||||||
|
goto Invalid;
|
||||||
|
} else {
|
||||||
|
int64_t d; /* work */
|
||||||
|
const Unit *up; /* .. */
|
||||||
|
uint64_t hi = 0;
|
||||||
|
up = dn->lsu; /* -> lsu */
|
||||||
|
|
||||||
|
for (d = 1; d <= dn->digits; up++, d += DECDPUN) {
|
||||||
|
uint64_t prev = hi;
|
||||||
|
hi += *up * powers[d-1];
|
||||||
|
if ((hi < prev) || (hi > INT64_MAX)) {
|
||||||
|
goto Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t prev = hi;
|
||||||
|
hi *= (uint64_t)powers[dn->exponent];
|
||||||
|
if ((hi < prev) || (hi > INT64_MAX)) {
|
||||||
|
goto Invalid;
|
||||||
|
}
|
||||||
|
return (decNumberIsNegative(dn)) ? -((int64_t)hi) : (int64_t)hi;
|
||||||
|
}
|
||||||
|
|
||||||
|
Invalid:
|
||||||
|
decContextSetStatus(set, DEC_Invalid_operation);
|
||||||
|
return 0;
|
||||||
|
} /* decNumberIntegralToInt64 */
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------ */
|
||||||
/* to-scientific-string -- conversion to numeric string */
|
/* to-scientific-string -- conversion to numeric string */
|
||||||
@ -4259,7 +4303,7 @@ static decNumber * decDivideOp(decNumber *res,
|
|||||||
uByte bits; /* working sign */
|
uByte bits; /* working sign */
|
||||||
Unit *target; /* work */
|
Unit *target; /* work */
|
||||||
const Unit *source; /* .. */
|
const Unit *source; /* .. */
|
||||||
uInt const *pow; /* .. */
|
uLong const *pow; /* .. */
|
||||||
Int shift, cut; /* .. */
|
Int shift, cut; /* .. */
|
||||||
#if DECSUBSET
|
#if DECSUBSET
|
||||||
Int dropped; /* work */
|
Int dropped; /* work */
|
||||||
|
Loading…
Reference in New Issue
Block a user