Date: Friday, March 3, 2006 @ 18:18:15
  Author: gilles
    Path: /cvsroot/carob/carob

Modified: Makefile (1.33 -> 1.34) include/BigDecimal.hpp (1.13 -> 1.14)
          src/BigDecimal.cpp (1.16 -> 1.17)

Implemented BigDecimal::operator wstring() using GMP
Lots of temporary code for remaining or non-working other operators


------------------------+
 Makefile               |    3 
 include/BigDecimal.hpp |   52 ++++----
 src/BigDecimal.cpp     |  280 ++++++++++++++++-------------------------------
 3 files changed, 126 insertions(+), 209 deletions(-)


Index: carob/Makefile
diff -u carob/Makefile:1.33 carob/Makefile:1.34
--- carob/Makefile:1.33 Tue Feb 14 18:35:47 2006
+++ carob/Makefile      Fri Mar  3 18:18:15 2006
@@ -66,6 +66,9 @@
 #CXXFLAGS            += -DCAROB_USE_LOG4CXX
 #LDFLAGS                               += -llog4cxx
 
+# for GMP
+LDFLAGS                                += -lgmpxx -lgmp
+
 #Doc
 # DOC_DIR is duplicated in Doxyfile
 DOC_DIR                                = doxygen
Index: carob/include/BigDecimal.hpp
diff -u carob/include/BigDecimal.hpp:1.13 carob/include/BigDecimal.hpp:1.14
--- carob/include/BigDecimal.hpp:1.13   Thu Jan 26 12:12:53 2006
+++ carob/include/BigDecimal.hpp        Fri Mar  3 18:18:15 2006
@@ -25,6 +25,7 @@
 #include "CarobException.hpp"
 #include "Common.hpp" //for java_byte and ResultSetDataType
 
+#include <gmpxx.h>
 #include <string>
 
 namespace CarobNS {
@@ -65,10 +66,29 @@
   BigDecimal::BigDecimal(const DriverSocket& input)
       throw (SocketIOException, UnexpectedException);
   /**
-   * Convertion to string. Handy for displaying the number
-   * FIXME: This is dummy code for now (testing state), correct it
+   * Converts this BigDecimal to a GMP integer
+   */
+  mpz_class toBigInteger() const;
+  /**
+   * Convertion to string.
+   * A leading minus sign is used to indicate sign, and the number of digits to
+   * the right of the decimal point is used to indicate scale.
    */ 
   operator std::wstring() const;
+  /**
+   * Convertion to int.
+   * Any fractional part of this BigDecimal will be discarded, and if the
+   * resulting "BigInteger" is too big to fit in an int, only the low-order 32
+   * bits are returned
+   */ 
+  operator int() const;
+  /**
+   * Convertion to long.
+   * Any fractional part of this BigDecimal will be discarded, and if the
+   * resulting "BigInteger" is too big to fit in a long, only the low-order
+   * 64 bits are returned
+   */ 
+  operator long() const;
 private:
     
   /** Length of the unscaled value java_byte-array */
@@ -81,34 +101,12 @@
   java_byte*    byteArray;
 
   /** Scale of this BigDecimal. */
-  int32_t       scale;
+  int           scale;
 
   /** Sign (+ or - or 0) */
   int           signum;
-  /**
-   * Converts internal 2's complement java_byte array to an array of ints
-   * @param intArrayLength (out) size of the generated int array
-   * @return converted int array
-   */
-  int*          toIntArray(int& intArrayLength) const;
-
-  /**
-   * Returns a copy of the member java_byte array stripped of any leading zero
-   * bytes.
-   * @param intArrayLength (out) size of the generated int array
-   * @return stripped java_byte array as an int array 
-   */
-  int*          stripByteArrayLeadingZeroBytes(int& intArrayLength) const;
-  /**
-   * From the member array representing a negative 2's-complement number,
-   * returns the minimal (no leading zero bytes) unsigned whose value is -a 
into
-   * an array of int
-   * @param intArrayLength (out) size of the generated int array
-   * @return positive int array corresponding to the java_byte array
-   */
-  int*          makeByteArrayPositive(int& intArrayLength) const;
-
-
+  /** Unscaled value as a GMP integer */
+  mpz_class     unscaled_value;
 };
 
 } //namespace CarobNS
Index: carob/src/BigDecimal.cpp
diff -u carob/src/BigDecimal.cpp:1.16 carob/src/BigDecimal.cpp:1.17
--- carob/src/BigDecimal.cpp:1.16       Wed Feb 15 11:03:42 2006
+++ carob/src/BigDecimal.cpp    Fri Mar  3 18:18:15 2006
@@ -23,11 +23,14 @@
 #include "DriverSocket.hpp"
 #include "Common.hpp"
 
+#include <iostream> // REMOVE ME !
+#include <sstream> //for wostringstream
+
 using std::wstring;
 
 using namespace CarobNS;
 
-BigDecimal::BigDecimal()
+BigDecimal::BigDecimal() : unscaled_value(0)
 {
   byteArrayLength = 0;
   byteArray = NULL;
@@ -44,7 +47,7 @@
 }
 
 BigDecimal::BigDecimal(const DriverSocket& input)
-    throw (SocketIOException, UnexpectedException)
+    throw (SocketIOException, UnexpectedException) : unscaled_value(0)
 {
   //1. Read intVal:
   //1.1 Read intValLength
@@ -56,7 +59,7 @@
   if (this->byteArrayLength == 0)
   {
     //This is a zero, no byte array
-    // FIXME: for safety, create an empty byte array instead
+    // FIXME: for safety, create an empty byte array instead ?
     ;
   }
   else
@@ -87,204 +90,117 @@
       this->byteArray[idx+3] = static_cast<java_byte> (wordRead     &0xFF);
     }
   }
-  
-  // UNTESTED
+
   // 1.4 read sign
   input>>this->signum;
   
   //2. Read scale
   input>>this->scale;
-}
 
-int* BigDecimal::toIntArray(int& intArrayLength) const
-{
-  if (byteArrayLength == 0)
-      return NULL;
-
-  int* intArray;
-  int  signum = 0;
-  if (byteArray[0] < 0)
-  {
-    intArray = makeByteArrayPositive(intArrayLength);
-    signum = -1;
-  }
-  else
+  //3. Compute gmp value
+  if (signum != 0)// 0 signum means 0 value => no useless computations !
   {
-    intArray = stripByteArrayLeadingZeroBytes(intArrayLength);
-    signum = (intArrayLength == 0 ? 0 : 1);
+    // convert byte array into and unscaled int
+    mpz_t imported;
+    mpz_init(imported);
+    mpz_import(imported, byteArrayLength, 1 /*MSB 1st*/,
+          sizeof(java_byte), 1 /*MSB 1st*/, 0, byteArray);
+    unscaled_value = static_cast<mpz_class>(imported);
+    mpz_clear(imported);
+#if 0
+    mpz_t unscaledVal;
+    mpz_init(unscaledVal);
+    // convert byte array into and unscaled int
+    mpz_import(unscaledVal, byteArrayLength, 1 /*MSB 1st*/,
+          sizeof(java_byte), 1 /*MSB 1st*/, 0, byteArray);
+    // apply scale
+    mpz_t scaler; // will be 10^scale
+    mpz_init(scaler);
+    mpq_t rat_scaler;
+    mpq_init(rat_scaler);
+    mpz_ui_pow_ui(scaler, 10, scale);
+    mpf_init2(gmp_value, mpz_sizeinbase(unscaledVal, 2/*binary*/) + 2); // + 1 
for '.'
+    mpq_t rat_uv;
+    mpq_init(rat_uv);
+    mpq_set_z(rat_uv, unscaledVal);
+    mpq_set_z(rat_scaler, scaler);
+    mpq_div(rat_uv, rat_uv, rat_scaler);
+    mpf_set_q(gmp_value, rat_uv);
+    // free tmp data
+    mpq_clear(rat_uv);
+    mpq_clear(rat_scaler);
+    mpz_clear(scaler);
+    mpz_clear(unscaledVal);
+    if (signum < 0)
+    {
+      mpf_neg(gmp_value, gmp_value);
+    }
+#endif
   }
-  return intArray;
 }
-
-int* BigDecimal::stripByteArrayLeadingZeroBytes(int& intArrayLength) const
-{
-  unsigned int keep;
-  // Find first nonzero byte
-  for (keep=0; keep<byteArrayLength && byteArray[keep]==0; keep++);
-
-  // Allocate new array and copy relevant part of input array
-  intArrayLength = ((byteArrayLength - keep) + 3)/4;
-  int* result = new int[intArrayLength];
-  int b = byteArrayLength - 1;
-  for (int i = intArrayLength-1; i >= 0; i--)
-  {
-    result[i] = byteArray[b--] & 0xff;
-    int bytesRemaining = b - keep + 1;
-    int bytesToTransfer = std::min(3, bytesRemaining);
-    for (int j=8; j <= 8*bytesToTransfer; j += 8)
-      result[i] |= ((byteArray[b--] & 0xff) << j);
-  }
-  return result;
-}
-
-int* BigDecimal::makeByteArrayPositive(int& intArrayLength) const
-{
-  unsigned int keep, k;
-
-  // Find first non-sign (0xff) byte of input
-  for (keep=0; keep<byteArrayLength && byteArray[keep]==-1; keep++)
-    ;
-
-  /* Allocate output array.  If all non-sign bytes are 0x00, we must
-   * allocate space for one extra output byte. */
-  for (k=keep; k<byteArrayLength && byteArray[k]==0; k++)
-    ;
-
-  int extraByte = (k==byteArrayLength) ? 1 : 0;
-  intArrayLength = ((byteArrayLength - keep + extraByte) + 3)/4;
-  int* result = new int[intArrayLength];
-
-  /* Copy one's complement of input into into output, leaving extra
-   * byte (if it exists) == 0x00 */
-  int b = byteArrayLength - 1;
-  for (int i = intArrayLength-1; i >= 0; i--)
-  {
-    result[i] = byteArray[b--] & 0xff;
-    unsigned int numBytesToTransfer = std::min(3, static_cast<int>(b-keep+1));
-    if (numBytesToTransfer < 0)
-      numBytesToTransfer = 0;
-    for (unsigned int j=8; j <= 8*numBytesToTransfer; j += 8)
-      result[i] |= ((byteArray[b--] & 0xff) << j);
-
-    // Mask indicates which bits must be complemented
-    int mask = ((uint32_t)-1 >> 8*(3-numBytesToTransfer));
-    result[i] = ~result[i] & mask;
-  }
-
-  // Add one to one's complement to generate two's complement
-  for (int i=intArrayLength-1; i>=0; i--)
-  {
-    result[i] = (result[i] & 0xffffffffL) + 1;
-    if (result[i] != 0)
-      break;
-  }
-  return result;
+/**
+ * Converts this BigDecimal to a GMP integer
+ */
+mpz_class BigDecimal::toBigInteger() const
+{
+  if (scale == 0)
+    return unscaled_value;
+  mpz_t scaler; // will be 10^scale
+  mpz_init(scaler);
+  mpz_ui_pow_ui(scaler, 10, scale);
+  mpz_class ret = unscaled_value / mpz_class(scaler);
+  mpz_tdiv_q (ret.get_mpz_t(), unscaled_value.get_mpz_t(), scaler);
+  mpz_clear(scaler);
+  return ret;
 }
 
 BigDecimal::operator wstring() const
 {
-  // !!!!!!!    THAT IS JUST A DUMMY FUNCTION FOR TESTING    !!!!!!
-/*  wstring sRet;
-  int idx = 0, word = 0;
-  int padding = byteArrayLength%4;
-  if (padding > 0)
+  wstring sRet(L"0");
+  if (signum != 0) // 0 signum means 0 value => no useless computations !
   {
-    for (idx=0; idx<padding; idx++)
+    //convert to string, then to wstring (no direct mpz->wstring converter)
+    std::ostringstream buffer;
+    buffer << unscaled_value;
+    sRet = fromString(buffer.str());
+    //Add the '.' TODO: get this separator from locale
+    if (sRet.length()-scale > 0 && scale != 0)
     {
-      word |= ((int)byteArray[idx] & 0xFF) << (8*(padding-idx-1));
+      sRet.insert(sRet.length()-scale, L".");
     }
-    sRet+=toWString(word);
-  }
-  for (; idx<byteArrayLength; idx+=4)
-  {
-    word = ((int)byteArray[idx]   & 0xFF) << 24
-         | ((int)byteArray[idx+1] & 0xFF) << 16
-         | ((int)byteArray[idx+2] & 0xFF) <<  8
-         |  (int)byteArray[idx+3] & 0xFF;
-    sRet+=toWString(word);
-  }
-  for (int i=0; i<byteArrayLength; i++)
-  {
-    if (i==0 && (int)byteArray[i] == 0)
-      continue;
-    sRet+=toWString((int)byteArray[i]);
+    if (signum < 0)
+      sRet.insert(0, L"-");
   }
-*/
-  wstring sRet;
-  if (signum == 0)
-    sRet = L'0';
-  else if (signum < 0)
-    sRet = L'-';
-  // else this is a +, we don't put it
-  
-  int l = 0;
-  int* test = toIntArray(l);
-  for (int i=0; i<l; i++)
-  {
-    sRet+=toWString(test[i]);
-  }
-  //Add the '.'
-  if (sRet.length()-scale > 0 && scale != 0)
-  {
-    sRet.insert(sRet.length()-scale,L".");
-  }
-
-       delete []test;
-       
   return sRet;
+}
 
-/*  wstring sRet;
+BigDecimal::operator int() const
+{
+  //TODO
+#if 1
+  return 0;
+#else
   if (signum == 0)
-    sRet = "0";
+    return 0;
+  mpz_class bi(toBigInteger());
+//BYTES_PER_MP_LIMB
+//  int bytesPerInt = sizeof(int)/8;
+//mpz_export (void *rop, size_t *countp, int order, int size, int endian, 
size_t nails, mpz_t op)
+//  mpz_import(imported, byteArrayLength, 1 /*MSB 1st*/,
+  int ret = bi.get_si();
+  return (signum > 0 ? ret : -ret);
+#endif
+}
+
+BigDecimal::operator long() const
+{
+  //TODO
+#if 1
+  return 0;
+#else
   if (signum == 0)
-    sRet = L'0';
-  else if (signum < 0)
-    sRet = L'-';
-  // else this is a +, we don't put it
-  
-  int intArrayLength = 0;
-  int* intArray = toIntArray(l);
-
-  // Compute upper bound on number of digit groups and allocate space
-  int maxNumDigitGroups = (4*intArrayLength + 6)/7;
-  wstring* digitGroup = new wstring[maxNumDigitGroups];
-
-  // Translate number to string, a digit group at a time
-  BigDecimal tmp = new BigDecimal();
-  tmp.byteArrayLength = byteArrayLength;
-  memcpy(tmp.byteArray, byteArray, byteArrayLength);
-  int numGroups = 0;
-  while (tmp.signum != 0) {
-            BigInteger d = longRadix[radix];
-
-            MutableBigInteger q = new MutableBigInteger(),
-                              r = new MutableBigInteger(),
-                              a = new MutableBigInteger(tmp.mag),
-                              b = new MutableBigInteger(d.mag);
-            a.divide(b, q, r);
-            BigInteger q2 = new BigInteger(q, tmp.signum * d.signum);
-            BigInteger r2 = new BigInteger(r, tmp.signum * d.signum);
-
-            digitGroup[numGroups++] = Long.toString(r2.longValue(), radix);
-            tmp = q2;
-  }
-
-  // Put sign (if any) and first digit group into result buffer
-  StringBuffer buf = new StringBuffer(numGroups*digitsPerLong[radix]+1);
-  if (signum<0)
-      buf.append('-');
-  buf.append(digitGroup[numGroups-1]);
-
-  // Append remaining digit groups padded with leading zeros
-  for (int i=numGroups-2; i>=0; i--) {
-      // Prepend (any) leading zeros for this digit group
-      int numLeadingZeros = digitsPerLong[radix]-digitGroup[i].length();
-      if (numLeadingZeros != 0)
-    buf.append(zeros[numLeadingZeros]);
-      buf.append(digitGroup[i]);
-  }
-  return buf.toString();
-*/
-
+    return 0;
+  mpz_class bi(toBigInteger());
+  return (signum > 0 ? bi.get_si() : -bi.get_si());
+#endif
 }
-

_______________________________________________
Carob-commits mailing list
[email protected]
https://forge.continuent.org/mailman/listinfo/carob-commits

Reply via email to