Date: Tuesday, May 2, 2006 @ 12:34:59
  Author: gilles
    Path: /cvsroot/carob/carob

Modified: Makefile (1.38 -> 1.39) include/BigDecimal.hpp (1.22 -> 1.23)
          src/BigDecimal.cpp (1.26 -> 1.27)

Removed dependency to libgmpxx: use of the C++ wrapper was minimal, having one 
less dependency is much better


------------------------+
 Makefile               |    2 
 include/BigDecimal.hpp |    9 +-
 src/BigDecimal.cpp     |  158 +++++++++++++++++++++++++++++++----------------
 3 files changed, 113 insertions(+), 56 deletions(-)


Index: carob/Makefile
diff -u carob/Makefile:1.38 carob/Makefile:1.39
--- carob/Makefile:1.38 Mon Apr 24 12:11:16 2006
+++ carob/Makefile      Tue May  2 12:34:59 2006
@@ -68,7 +68,7 @@
 # mandatory LDFLAGS
 override LDFLAGS       += -fPIC -shared
 # for GMP
-override LDFLAGS       += -lgmpxx -lgmp
+override LDFLAGS       += -lgmp
 
 ARFLAGS                                = rcs
 LIB_CAROB                      = carob
Index: carob/include/BigDecimal.hpp
diff -u carob/include/BigDecimal.hpp:1.22 carob/include/BigDecimal.hpp:1.23
--- carob/include/BigDecimal.hpp:1.22   Thu Apr 20 12:26:00 2006
+++ carob/include/BigDecimal.hpp        Tue May  2 12:34:59 2006
@@ -36,7 +36,7 @@
 // - "Incompatibilities Between ISO C and ISO C++" - David R. Tribble
 // - C++ Technical Report 1 (TR1)
 
-#include <gmpxx.h>
+#include <gmp.h>
 #include <string>
 #include <sstream>
 
@@ -204,8 +204,9 @@
   /**
    * Converts this BigDecimal's absolute value to a GMP integer by scaling
    * its unscaled_value (thus discarding fractional part)
+   * @param     result the scaled value. Note: result must be initialized !
    */
-  mpz_class     toBigInteger() const;
+  void          toBigInteger(mpz_t result) const;
   /**
    * Converts the given gmp integer to an array of integers.
    * The integer array will be allocated by this function, and must be deleted
@@ -214,7 +215,7 @@
    *            toBigInteger)
    * @param intArrayLength size of the returned array
    */
-  int*          toIntArray(mpz_class scaled_val, int* intArrayLength) const;
+  int*          toIntArray(mpz_t scaled_val, int* intArrayLength) const;
   /**
    * Convertion to string with the given decimal point
    * A leading minus sign is used to indicate sign, and the number of digits to
@@ -237,7 +238,7 @@
   /** Sign (+ or - or 0) */
   int           signum;
   /** Unscaled value as a GMP integer */
-  mpz_class     unscaled_value;
+  mpz_t         unscaled_value;
 };
 
 } //namespace CarobNS
Index: carob/src/BigDecimal.cpp
diff -u carob/src/BigDecimal.cpp:1.26 carob/src/BigDecimal.cpp:1.27
--- carob/src/BigDecimal.cpp:1.26       Thu Mar 30 14:19:07 2006
+++ carob/src/BigDecimal.cpp    Tue May  2 12:34:59 2006
@@ -36,7 +36,6 @@
 
 void BigDecimal::initToZero()
 {
-  unscaled_value = 0;
   byteArrayLength = 0;
   byteArray = NULL;
   scale = 0;
@@ -45,16 +44,21 @@
 
 BigDecimal::BigDecimal()
 {
+  // mpz_init must be called in every constructor and only there. If mpz_init 
is
+  // called multiple times, a memory leak will appear !
+  mpz_init(unscaled_value);
   initToZero();
 }
 
 BigDecimal::BigDecimal(const std::wstring& wstr) throw (ConversionException, 
UnexpectedException)
 {
+  mpz_init(unscaled_value);
   createFromString(StaticCodecs::toString(wstr));
 }
 
 BigDecimal::BigDecimal(const std::string& str) throw (ConversionException, 
UnexpectedException)
 {
+  mpz_init(unscaled_value);
   createFromString(str);
 }
 
@@ -91,16 +95,17 @@
         scale++;
     }
   }
-  if (mpz_set_str(unscaled_value.get_mpz_t(), unscaledStr.c_str(), 10) != 0)
+  if (mpz_set_str(unscaled_value, unscaledStr.c_str(), 10) != 0)
   {
     throw ConversionException(fromString(str) + L"does not represent a valid 
BigDecimal value", L"FIXME");
   }
-  if (unscaled_value < 0)
+  int uv_sign = mpz_sgn(unscaled_value);
+  if (uv_sign < 0)
   {
-    unscaled_value = -unscaled_value;
+    mpz_neg(unscaled_value, unscaled_value);
     signum = -1;
   }
-  else if (unscaled_value == 0)
+  else if (uv_sign == 0)
     signum = 0;
   else
     signum = 1;
@@ -108,6 +113,7 @@
 
 BigDecimal::BigDecimal(const int arg)
 {
+  mpz_init(unscaled_value);
   initToZero();
   if (arg > 0)
     signum = 1;
@@ -115,13 +121,14 @@
     signum = -1;
   else
     return;
-  mpz_set_si(unscaled_value.get_mpz_t(), arg);
+  mpz_set_si(unscaled_value, arg);
   if (signum<0) //take the abs()
-    mpz_neg(unscaled_value.get_mpz_t(), unscaled_value.get_mpz_t());
+    mpz_neg(unscaled_value, unscaled_value);
 }
 
 BigDecimal::BigDecimal(const long arg)
 {
+  mpz_init(unscaled_value);
   initToZero();
   if (arg > 0L)
     signum = 1;
@@ -129,13 +136,14 @@
     signum = -1;
   else
     return;
-  mpz_set_si(unscaled_value.get_mpz_t(), arg);
+  mpz_set_si(unscaled_value, arg);
   if (signum<0) //take the abs()
-    mpz_neg(unscaled_value.get_mpz_t(), unscaled_value.get_mpz_t());
+    mpz_neg(unscaled_value, unscaled_value);
 }
 
 BigDecimal::BigDecimal(const int64_t arg)
 {
+  mpz_init(unscaled_value);
   initToZero();
   if (arg > 0)
     signum = 1;
@@ -157,7 +165,7 @@
       handleMinLL = true;
     }
   }
-  mpz_import (unscaled_value.get_mpz_t(),
+  mpz_import (unscaled_value,
               1,
               0, // only one "64bits word" to import => order doesn't matter
               sizeof(int64_t),
@@ -165,29 +173,33 @@
               0, // sign bit has been removed by the previous mask
               &import);
   if (handleMinLL) // special case, see above min int64 handling
-    mpz_add_ui(unscaled_value.get_mpz_t(), unscaled_value.get_mpz_t(), 1);
+    mpz_add_ui(unscaled_value, unscaled_value, 1);
 }
 
 #if 0
 BigDecimal::BigDecimal(const float arg)
 {
+  mpz_init(unscaled_value);
   //TODO
 }
 
 BigDecimal::BigDecimal(const double)
 {
+  mpz_init(unscaled_value);
   //TODO
 }
 #endif
 
 BigDecimal::BigDecimal(const BigDecimal& ref)
 {
+  mpz_init(unscaled_value);
   *this = ref; //make use of = operator
 }
 
 BigDecimal::BigDecimal(const DriverSocket& input)
-    throw (SocketIOException, UnexpectedException) : unscaled_value(0)
+    throw (SocketIOException, UnexpectedException)
 {
+  mpz_init(unscaled_value);
   initToZero();
   //1. Read intVal:
   //1.1 Read intValLength
@@ -238,12 +250,8 @@
   if (signum != 0)// 0 signum means 0 value => no useless computations !
   {
     // convert byte array into and unscaled int
-    mpz_t imported;
-    mpz_init(imported);
-    mpz_import(imported, byteArrayLength, 1 /*MSB 1st*/,
+    mpz_import(unscaled_value, byteArrayLength, 1 /*MSB 1st*/,
           sizeof(java_byte), 1 /*MSB 1st*/, 0, byteArray);
-    unscaled_value = static_cast<mpz_class>(imported);
-    mpz_clear(imported);
   }
   
   // TODO: if ODBC/odbsequoia doesn't need the byte array, we should
@@ -252,6 +260,7 @@
 
 BigDecimal::~BigDecimal()
 {
+  mpz_clear(unscaled_value);
   if (byteArrayLength > 0 && byteArray != NULL)
   {
     delete[] byteArray;
@@ -262,7 +271,7 @@
 {
   signum = ref.signum;
   scale = ref.scale;
-  unscaled_value = ref.unscaled_value;
+  mpz_set(unscaled_value, ref.unscaled_value);
   byteArrayLength = ref.byteArrayLength;
   if (byteArrayLength != 0)
   {
@@ -280,29 +289,30 @@
 {
   return (signum == ref.signum
       && scale == ref.scale
-      && mpz_cmp(unscaled_value.get_mpz_t(), ref.unscaled_value.get_mpz_t()) 
== 0);
+      && mpz_cmp(unscaled_value, ref.unscaled_value) == 0);
 }
 
-mpz_class BigDecimal::toBigInteger() const
+void BigDecimal::toBigInteger(mpz_t result) const
 {
   if (scale == 0)
-    return unscaled_value;
-
+  {
+    mpz_set(result, unscaled_value);
+    return;
+  }
   // TODO: optimization = if scale > number of digits in unscaled_value, 
return 0
 
   // TODO: multiply by 10^(-scale) instead of dividing by 10^(scale)
   //we have to apply scale
   mpz_t scaler; mpz_init(scaler);                       //int scaler;
   mpz_ui_pow_ui(scaler, 10, scale);                     //scaler = 10^scale;
-  mpz_class ret = unscaled_value / mpz_class(scaler);   //ret = unscaled_value 
/ scaler;
+
+  mpz_tdiv_q(result, unscaled_value, scaler);              //ret = 
unscaled_value / scaler;
   mpz_clear(scaler);
-  return ret;
 }
 
-int* BigDecimal::toIntArray(mpz_class scaled_int, int* mag_length) const
+int* BigDecimal::toIntArray(mpz_t scaled_int, int* mag_length) const
 {
-  size_t sizeInInts = mpz_size(scaled_int.get_mpz_t()) * sizeof(mp_limb_t)
-                      / sizeof(int);
+  size_t sizeInInts = mpz_size(scaled_int) * sizeof(mp_limb_t) / sizeof(int);
   int* mag = new int[sizeInInts];
   size_t exported = 0;
   mpz_export(static_cast<void*>(mag), &exported,
@@ -310,7 +320,7 @@
       sizeof(int), /*words of integers*/
       0, /*native word endianess*/
       0, /*full words*/
-      scaled_int.get_mpz_t());
+      scaled_int);
   *mag_length = static_cast<int>(exported);
   return mag;
 }
@@ -324,9 +334,27 @@
 std::wstring BigDecimal::toString(const wchar_t decimal_point) const
 {
   //convert to string, then to wstring (no direct mpz->wstring converter)
-  std::ostringstream buffer;
-  buffer << unscaled_value;
-  wstring sRet = fromString(buffer.str());
+  // First compute space needed by the resulting string
+  // number of digits in the unscaled value
+  size_t nbDigits = mpz_sizeinbase(unscaled_value, 10);
+  // the real size needed by the string
+  int size_needed = static_cast<int>(nbDigits);
+  // compute room for heading zeros
+  if (scale > size_needed)
+    size_needed = scale;
+  // add room for the decimal point
+  if (scale != 0)
+    //TODO: rather take decimal point length in case of multi char decimal 
point
+    size_needed++;
+  // space for the heading '-' (minus) sign
+  if (signum < 0)
+    size_needed++;
+  char* as_string = new char[size_needed+1]; // +1 for the \0
+
+  gmp_snprintf(as_string, nbDigits+1, "%Zd", unscaled_value);
+
+  wstring sRet = fromString(as_string);
+  delete[] as_string;
   int sRetLength = static_cast<int>(sRet.length());
   if (scale != 0)
   {
@@ -349,25 +377,30 @@
 {
   if (signum == 0)
     return 0;
-  mpz_class scaled_int = toBigInteger(); // truncate value
-  if (mpz_size(scaled_int.get_mpz_t()) == 0) // ie. if (scaled_int == 0)
+  mpz_t scaled_int; mpz_init(scaled_int);
+  toBigInteger(scaled_int); // truncate value
+  if (mpz_size(scaled_int) == 0) // ie. if (scaled_int == 0)
+  {
+    mpz_clear(scaled_int);
     return 0;
+  }
   // Check that we can convert to int
   // TODO: the same with only one "mpz_fits" and a test on int min
   if (signum>0)
   {
-    if (!mpz_fits_sint_p(scaled_int.get_mpz_t()))
+    if (!mpz_fits_sint_p(scaled_int))
       throw (ConversionException(L"BigDecimal " + static_cast<wstring>(*this)
           + L" is to big to be converted into an int", CONV_NUM_RANGE));
   }
   else
   {
     // We have to negate the value for the test
-    mpz_class tmp;
-    mpz_neg(tmp.get_mpz_t(), scaled_int.get_mpz_t());
-    if (!mpz_fits_sint_p(tmp.get_mpz_t()))
+    mpz_t tmp; mpz_init(tmp);
+    mpz_neg(tmp, scaled_int);
+    if (!mpz_fits_sint_p(tmp))
       throw (ConversionException(L"BigDecimal " + static_cast<wstring>(*this)
           + L" is to big to be converted into an int", CONV_NUM_RANGE));
+    mpz_clear(tmp);
   }
   int mag_length = -1;
   int* mag = toIntArray(scaled_int, &mag_length);
@@ -378,6 +411,8 @@
   }
   int res = mag[mag_length-1];
   delete[] mag;
+  mpz_clear(scaled_int);
+
   if (signum < 0)
     res = -res;
   return res;
@@ -387,37 +422,51 @@
 {
   if (signum == 0)
     return 0;
-  mpz_class scaled_int = toBigInteger();
-  if (mpz_size(scaled_int.get_mpz_t()) == 0) // ie. if scaled_int == 0
+  mpz_t scaled_int; mpz_init(scaled_int);
+  toBigInteger(scaled_int);
+  if (mpz_size(scaled_int) == 0) // ie. if scaled_int == 0
+  {
+    mpz_clear(scaled_int);
     return 0;
+  }
   // Check we can convert to int
   if (signum>0)
   {
-    if (!mpz_fits_slong_p(scaled_int.get_mpz_t()))
+    if (!mpz_fits_slong_p(scaled_int))
       throw (ConversionException(L"BigDecimal " + static_cast<wstring>(*this)
           + L" is to big to be converted into a long", CONV_NUM_RANGE));
   }
   else
   {
     // We have to negate the value for the test
-    mpz_class tmp;
-    mpz_neg(tmp.get_mpz_t(), scaled_int.get_mpz_t());
-    if (!mpz_fits_slong_p(tmp.get_mpz_t()))
+    mpz_t tmp; mpz_init(tmp);
+    mpz_neg(tmp, scaled_int);
+    if (!mpz_fits_slong_p(tmp))
       throw (ConversionException(L"BigDecimal " + static_cast<wstring>(*this)
           + L" is to big to be converted into a long", CONV_NUM_RANGE));
+    mpz_clear(tmp);
   }
-  return (signum > 0 ? scaled_int.get_si() : -scaled_int.get_si());
+  long ret = mpz_get_si(scaled_int);
+  if (signum < 0)
+    ret = -ret;
+  mpz_clear(scaled_int);
+  return ret;
 }
+
 //TODO: optimize this horribly slow stuff
 BigDecimal::operator int64_t() const throw (ConversionException)
 {
   if (signum == 0)
     return 0;
-  mpz_class scaled_int = toBigInteger();
-  if (mpz_size(scaled_int.get_mpz_t()) == 0) // ie. if scaled_int == 0
+  mpz_t scaled_int; mpz_init(scaled_int);
+  toBigInteger(scaled_int);
+  if (mpz_size(scaled_int) == 0) // ie. if scaled_int == 0
+  {
+    mpz_clear(scaled_int);
     return 0;
+  }
   // check size
-  size_t nbBitsNeeded = mpz_sizeinbase(scaled_int.get_mpz_t(), 2);
+  size_t nbBitsNeeded = mpz_sizeinbase(scaled_int, 2);
   if (nbBitsNeeded+1 > sizeof(int64_t)*8) //+1 for the sign bit
   {
     bool numTooBig = true;
@@ -454,6 +503,8 @@
     result = (result<<(8*sizeof(int))) + (mag[i]&0xffffffffLL);
   }
   delete[] mag;
+  mpz_clear(scaled_int);
+
   if (signum < 0)
     result = -result;
   return result;
@@ -467,11 +518,15 @@
   if (signum < 0)
     throw (ConversionException(L"BigDecimal " + static_cast<wstring>(*this)
         +L" is negative ! it cannot be converted into an int64_t", 
CONV_NUM_RANGE));
-  mpz_class scaled_int = toBigInteger();
-  if (mpz_size(scaled_int.get_mpz_t()) == 0) // ie. if scaled_int == 0
+  mpz_t scaled_int; mpz_init(scaled_int);
+  toBigInteger(scaled_int);
+  if (mpz_size(scaled_int) == 0) // ie. if scaled_int == 0
+  {
+    mpz_clear(scaled_int);
     return 0;
+  }
   // check size
-  size_t nbBitsNeeded = mpz_sizeinbase(scaled_int.get_mpz_t(), 2);
+  size_t nbBitsNeeded = mpz_sizeinbase(scaled_int, 2);
   if (nbBitsNeeded > (sizeof(int64_t)*8))
     throw (ConversionException(L"BigDecimal " + static_cast<wstring>(*this)
         + L" is too big to be converted into an int64_t", CONV_NUM_RANGE));
@@ -490,6 +545,7 @@
     result = (result<<(8*sizeof(int))) + (mag[i]&0xffffffffLL);
   }
   delete[] mag;
+  mpz_clear(scaled_int);
   return result;
 }
 
@@ -517,7 +573,7 @@
   mpf_set_d(res, static_cast<double>(0));             // res = (double)0;
   mpf_set_d(scaler, static_cast<double>(10));         // scaler = (double)10;
   mpf_pow_ui(scaler, scaler, scale);                  // scaler = scaler^scale;
-  mpf_set_z(unscaled, unscaled_value.get_mpz_t());    // unscaled = 
unscaled_value;
+  mpf_set_z(unscaled, unscaled_value);                // unscaled = 
unscaled_value;
   mpf_div(res, unscaled, scaler);                     // ret = unscaled/scaler;
   if (signum < 0)
     mpf_neg(res, res);                                // ret = -ret;

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

Reply via email to