qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-ppc] [V2 PATCH 10/37] libdecnumber: Introduce decNumberIntegralToI


From: Tom Musta
Subject: [Qemu-ppc] [V2 PATCH 10/37] libdecnumber: Introduce decNumberIntegralToInt64
Date: Mon, 21 Apr 2014 15:54:54 -0500

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 <address@hidden>
---
 include/libdecnumber/decNumber.h      |    1 +
 include/libdecnumber/decNumberLocal.h |    2 +-
 libdecnumber/decContext.c             |    6 +++-
 libdecnumber/decNumber.c              |   46 ++++++++++++++++++++++++++++++++-
 4 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/include/libdecnumber/decNumber.h b/include/libdecnumber/decNumber.h
index f4bf994..9fa4e6a 100644
--- a/include/libdecnumber/decNumber.h
+++ b/include/libdecnumber/decNumber.h
@@ -122,6 +122,7 @@
   char     * decNumberToEngString(const decNumber *, char *);
   uint32_t    decNumberToUInt32(const decNumber *, decContext *);
   int32_t     decNumberToInt32(const decNumber *, decContext *);
+  int64_t     decNumberIntegralToInt64(const decNumber *dn, decContext *set);
   uint8_t   * decNumberGetBCD(const decNumber *, uint8_t *);
   decNumber * decNumberSetBCD(decNumber *, const uint8_t *, uint32_t);
 
diff --git a/include/libdecnumber/decNumberLocal.h 
b/include/libdecnumber/decNumberLocal.h
index f5f508f..cd4eb79 100644
--- a/include/libdecnumber/decNumberLocal.h
+++ b/include/libdecnumber/decNumberLocal.h
@@ -98,7 +98,7 @@
 
   /* Shared lookup tables                                            */
   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                        */
   extern const uShort DPD2BIN[1024];   /* DPD -> 0-999               */
   extern const uShort BIN2DPD[1000];   /* 0-999 -> DPD               */
diff --git a/libdecnumber/decContext.c b/libdecnumber/decContext.c
index 737cca9..88e5dd0 100644
--- a/libdecnumber/decContext.c
+++ b/libdecnumber/decContext.c
@@ -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)                         */
 /* ------------------------------------------------------------------ */
-const uInt DECPOWERS[10]={1, 10, 100, 1000, 10000, 100000, 1000000,
-                         10000000, 100000000, 1000000000};
+const uLong DECPOWERS[19] = {1, 10, 100, 1000, 10000, 100000, 1000000,
+  10000000, 100000000, 1000000000, 10000000000, 100000000000,
+  1000000000000, 10000000000000, 100000000000000, 1000000000000000,
+  10000000000000000, 100000000000000000, 1000000000000000000, };
 
 /* ------------------------------------------------------------------ */
 /* decContextClearStatus -- clear bits in current status             */
diff --git a/libdecnumber/decNumber.c b/libdecnumber/decNumber.c
index 6bd7565..6164a77 100644
--- a/libdecnumber/decNumber.c
+++ b/libdecnumber/decNumber.c
@@ -465,6 +465,50 @@ decNumber *decNumberFromUInt64(decNumber *dn, uint64_t uin)
     return dn;
 } /* 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                      */
@@ -4259,7 +4303,7 @@ static decNumber * decDivideOp(decNumber *res,
   uByte bits;                     /* working sign */
   Unit *target;                   /* work */
   const Unit *source;             /* .. */
-  uInt const *pow;                /* .. */
+  uLong const *pow;                /* .. */
   Int  shift, cut;                /* .. */
   #if DECSUBSET
   Int  dropped;                   /* work */
-- 
1.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]