You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2007/08/10 01:56:14 UTC
svn commit: r564433 - in
/activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util:
BitOps.h FloatingPointParser.cpp FloatingPointParser.h
Author: tabish
Date: Thu Aug 9 16:56:13 2007
New Revision: 564433
URL: http://svn.apache.org/viewvc?view=rev&rev=564433
Log:
http://issues.apache.org/activemq/browse/AMQCPP-103
Adding in more Types wrappers
Modified:
activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/BitOps.h
activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.cpp
activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.h
Modified: activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/BitOps.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/BitOps.h?view=diff&rev=564433&r1=564432&r2=564433
==============================================================================
--- activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/BitOps.h (original)
+++ activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/BitOps.h Thu Aug 9 16:56:13 2007
@@ -63,6 +63,9 @@
static const int E_OFFSET = 1075;
static const long long INFINITE_LONGBITS = 0x7FF0000000000000LL;
+ static const int INFINITE_INTBITS = 0x7F800000;
+ static const int MINIMUM_INTBITS = 1;
+
static const unsigned long long MANTISSA_MASK = 0x000FFFFFFFFFFFFFULL;
static const unsigned long long EXPONENT_MASK = 0x7FF0000000000000ULL;
static const unsigned long long NORMAL_MASK = 0x0010000000000000ULL;
Modified: activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.cpp
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.cpp?view=diff&rev=564433&r1=564432&r2=564433
==============================================================================
--- activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.cpp (original)
+++ activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.cpp Thu Aug 9 16:56:13 2007
@@ -40,23 +40,17 @@
// assumes s is a null terminated string with at least one
// character in it
- unsigned long long def[17];
- unsigned long long defBackup[17];
- unsigned long long* f;
- unsigned long long* fNoOverflow;
- unsigned long long* g;
- unsigned long long* tempBackup;
+ unsigned long long def[17] = {0};
+ unsigned long long defBackup[17] = {0};
+ unsigned long long* f = def;
+ unsigned long long* fNoOverflow = defBackup;
+ unsigned long long* tempBackup = NULL;
unsigned int overflow = 0;
unsigned long long result = 0;
int index = 1;
int unprocessedDigits = 0;
std::string::const_iterator valItr = value.begin();
- f = def;
- fNoOverflow = defBackup;
- (*f) = 0;
- tempBackup = g = 0;
-
do {
if( *valItr >= '0' && *valItr <= '9' ) {
@@ -450,3 +444,382 @@
return value;
}
+
+////////////////////////////////////////////////////////////////////////////////
+float FloatingPointParser::createFloat( const std::string&s, int exp ) {
+
+ // assumes s is a null terminated string with at least one
+ // character in it
+ unsigned long long def[DEFAULT_WIDTH] = {0};
+ unsigned long long defBackup[DEFAULT_WIDTH] = {0};
+ unsigned long long* f = def;
+ unsigned long long* fNoOverflow = defBackup;
+ unsigned long long* tempBackup = NULL;
+ unsigned int overflow;
+ unsigned int result;
+ int index = 1;
+ int unprocessedDigits = 0;
+ std::string::const_iterator sIter = s.begin();
+
+ do {
+
+ if( *sIter >= '0' && *sIter <= '9' ) {
+
+ /* Make a back up of f before appending, so that we can
+ * back out of it if there is no more room, i.e. index >
+ * MAX_ACCURACY_WIDTH.
+ */
+ memcpy( fNoOverflow, f, sizeof(unsigned long long)* index );
+ overflow = BigInt::simpleAppendDecimalDigitHighPrecision(
+ f, index, *sIter - '0' );
+
+ if( overflow ) {
+
+ f[index++] = overflow;
+
+ // There is an overflow, but there is no more room
+ // to store the result. We really only need the top 52
+ // bits anyway, so we must back out of the overflow,
+ // and ignore the rest of the string.
+ if( index >= MAX_ACCURACY_WIDTH ) {
+ index--;
+ memcpy( f, fNoOverflow, sizeof(unsigned long long)* index );
+ break;
+ }
+
+ if( tempBackup ) {
+ fNoOverflow = tempBackup;
+ }
+ }
+
+ } else {
+ index = -1;
+ }
+ }
+ while( index > 0 && *(++sIter) != '\0' );
+
+ // We've broken out of the parse loop either because we've reached
+ // the end of the string or we've overflowed the maximum accuracy
+ // limit of a double. If we still have unprocessed digits in the
+ // given string, then there are three possible results:
+ // 1. (unprocessed digits + e) == 0, in which case we simply
+ // convert the existing bits that are already parsed
+ // 2. (unprocessed digits + e) < 0, in which case we simply
+ // convert the existing bits that are already parsed along
+ // with the given e
+ // 3. (unprocessed digits + e) > 0 indicates that the value is
+ // simply too big to be stored as a double, so return Infinity
+
+ if( ( unprocessedDigits = s.size() ) > 0 ) {
+
+ exp += unprocessedDigits;
+ if( index > -1 ) {
+ if( exp <= 0 ) {
+ return createFloat1( f, index, exp );
+ } else {
+ result = BitOps::INFINITE_INTBITS;
+ }
+ } else {
+ result = index;
+ }
+ } else {
+
+ if( index > -1 ) {
+ return createFloat1( f, index, exp );
+ } else {
+ result = index;
+ }
+ }
+
+ return Float::intBitsToFloat( result );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+float FloatingPointParser::createFloat1( unsigned long long* f, int length, int exp ) {
+
+ int numBits = BigInt::highestSetBitHighPrecision (f, length) + 1;
+ double dresult;
+ int result;
+
+ numBits -= BigInt::lowestSetBitHighPrecision( f, length );
+
+ if( numBits < 25 && exp >= 0 && exp < LOG5_OF_TWO_TO_THE_N ) {
+ return ((float) LOW_I32_FROM_PTR (f)) * tenToTheE (exp);
+ } else if( numBits < 25 && exp < 0 && (-exp) < LOG5_OF_TWO_TO_THE_N ) {
+ return ((float) LOW_I32_FROM_PTR (f)) / tenToTheE (-exp);
+ } else if (exp >= 0 && exp < 39) {
+ result = (float) (BigInt::toDoubleHighPrecision (f, length) * pow (10.0, exp));
+ } else if( exp >= 39 ) {
+ // Convert the partial result to make sure that the
+ // non-exponential part is not zero. This check fixes the case
+ // where the user enters 0.0e309! */
+ dresult = BigInt::toDoubleHighPrecision( f, length );
+
+ if( dresult == 0.0 ) {
+ result = BitOps::MINIMUM_INTBITS;
+ } else {
+ result = BitOps::INFINITE_INTBITS;
+ }
+
+ } else if( exp > -309 ) {
+
+ int dexp;
+ unsigned int fmant, fovfl;
+ unsigned long long dmant;
+ dresult = BigInt::toDoubleHighPrecision( f, length ) / Math::pow( 10.0, -exp );
+ if( IS_DENORMAL_DBL( dresult ) ) {
+ return 0.0f;
+ }
+
+ dexp = BigInt::doubleExponent( dresult ) + 51;
+ dmant = BigInt::doubleMantissa( dresult );
+
+ // Is it too small to be represented by a single-precision
+ // float?
+ if( dexp <= -155 ) {
+ return 0.0f;
+ }
+
+ // Is it a denormalized single-precision float?
+ if( (dexp <= -127) && (dexp > -155) ) {
+
+ // Only interested in 24 msb bits of the 53-bit double mantissa
+ fmant = (unsigned int) (dmant >> 29);
+ fovfl = ((unsigned int) (dmant & 0x1FFFFFFF)) << 3;
+
+ while( (dexp < -127) && ((fmant | fovfl) != 0) ) {
+ if( (fmant & 1) != 0 ) {
+ fovfl |= 0x80000000;
+ }
+ fovfl >>= 1;
+ fmant >>= 1;
+ dexp++;
+ }
+
+ if( (fovfl & 0x80000000) != 0) {
+ if( (fovfl & 0x7FFFFFFC) != 0 ) {
+ fmant++;
+ } else if( (fmant & 1) != 0 ) {
+ fmant++;
+ }
+ } else if( (fovfl & 0x40000000) != 0 ) {
+
+ if( (fovfl & 0x3FFFFFFC) != 0 ) {
+ fmant++;
+ }
+ }
+
+ result = fmant;
+ }
+ else
+ {
+ result = dresult;
+ }
+ }
+
+ // Don't go straight to zero as the fact that x*0 = 0 independent
+ // of x might cause the algorithm to produce an incorrect result.
+ // Instead try the min value first and let it fall to zero if need be.
+ if( exp <= -309 || result == 0 ) {
+ result = BitOps::MINIMUM_INTBITS;
+ }
+
+ return floatAlgorithm( f, length, exp, Float::intBitsToFloat( result ) );
+}
+
+/* The algorithm for the function floatAlgorithm() below can be found
+ * in:
+ *
+ * "How to Read Floating-Point Numbers Accurately", William D.
+ * Clinger, Proceedings of the ACM SIGPLAN '90 Conference on
+ * Programming Language Design and Implementation, June 20-22,
+ * 1990, pp. 92-101.
+ *
+ * There is a possibility that the function will end up in an endless
+ * loop if the given approximating floating-point number (a very small
+ * floating-point whose value is very close to zero) straddles between
+ * two approximating integer values. We modified the algorithm slightly
+ * to detect the case where it oscillates back and forth between
+ * incrementing and decrementing the floating-point approximation. It
+ * is currently set such that if the oscillation occurs more than twice
+ * then return the original approximation.
+ */
+////////////////////////////////////////////////////////////////////////////////
+float FloatingPointParser::floatAlgorithm(
+ unsigned long long* f, int length, int exp, float z ) {
+
+ unsigned long long m;
+ int k = 0;
+ int comparison = 0;
+ int comparison2 = 0;
+ unsigned long long* x = NULL;
+ unsigned long long* y = NULL;
+ unsigned long long* D = NULL;
+ unsigned long long* D2 = NULL;
+ int xLength = 0;
+ int yLength = 0;
+ int DLength = 0;
+ int D2Length = 0;
+ int decApproxCount = 0;
+ int incApproxCount = 0;
+
+ do {
+
+ m = BigInt::floatMantissa (z);
+ k = BigInt::floatExponent (z);
+
+ if( exp >= 0 && k >= 0 ) {
+
+ xLength = sizeOfTenToTheE( exp ) + length;
+ x = new unsigned long long[xLength];
+ memset( x + length, 0, sizeof(unsigned long long) * (xLength - length) );
+ memcpy( x, f, sizeof(unsigned long long) * length );
+ BigInt::timesTenToTheEHighPrecision( x, xLength, exp );
+
+ yLength = (k >> 6) + 2;
+ y = new unsigned long long[yLength];
+ memset( y + 1, 0, sizeof(unsigned long long) * (yLength - 1) );
+ *y = m;
+ BigInt::simpleShiftLeftHighPrecision (y, yLength, k);
+
+ } else if( exp >= 0 ) {
+
+ xLength = sizeOfTenToTheE (exp) + length + ((-k) >> 6) + 1;
+ x = new unsigned long long[xLength];
+ memset( x + length, 0, sizeof(unsigned long long) * (xLength - length) );
+ memcpy( x, f, sizeof(unsigned long long) * length );
+ BigInt::timesTenToTheEHighPrecision( x, xLength, exp );
+ BigInt::simpleShiftLeftHighPrecision( x, xLength, -k );
+
+ yLength = 1;
+ y = new unsigned long long[yLength];
+ *y = m;
+
+ } else if( k >= 0 ) {
+
+ xLength = length;
+ x = f;
+
+ yLength = sizeOfTenToTheE( -exp ) + 2 + ( k >> 6 );
+ y = new unsigned long long[yLength];
+ memset( y + 1, 0, sizeof(unsigned long long) * (yLength - 1)) ;
+ *y = m;
+ BigInt::timesTenToTheEHighPrecision( y, yLength, -exp );
+ BigInt::simpleShiftLeftHighPrecision( y, yLength, k );
+
+ } else {
+
+ xLength = length + ((-k) >> 6) + 1;
+ x = new unsigned long long[xLength];
+ memset( x + length, 0, sizeof(unsigned long long) * (xLength - length) );
+ memcpy( x, f, sizeof (unsigned long long) * length );
+ BigInt::simpleShiftLeftHighPrecision( x, xLength, -k );
+
+ yLength = sizeOfTenToTheE( -exp ) + 1;
+ y = new unsigned long long[yLength];
+ memset( y + 1, 0, sizeof(unsigned long long) * (yLength - 1) );
+ *y = m;
+ BigInt::timesTenToTheEHighPrecision( y, yLength, -exp );
+ }
+
+ comparison = BigInt::compareHighPrecision( x, xLength, y, yLength );
+ if( comparison > 0 ) {
+ // x > y
+ DLength = xLength;
+ D = new unsigned long long[DLength];
+ memcpy( D, x, DLength * sizeof(unsigned long long) );
+ BigInt::subtractHighPrecision( D, DLength, y, yLength );
+ } else if( comparison ) {
+ // y > x
+ DLength = yLength;
+ D = new unsigned long long[DLength];
+ memcpy (D, y, DLength * sizeof (unsigned long long));
+ BigInt::subtractHighPrecision (D, DLength, x, xLength);
+ } else {
+ /* y == x */
+ DLength = 1;
+ D = new unsigned long long[DLength];
+ *D = 0;
+ }
+
+ D2Length = DLength + 1;
+ allocateU64 (D2, D2Length);
+ m <<= 1;
+ BigInt::multiplyHighPrecision (D, DLength, &m, 1, D2, D2Length);
+ m >>= 1;
+
+ comparison2 = BigInt::compareHighPrecision (D2, D2Length, y, yLength);
+ if( comparison2 < 0 ) {
+ if( comparison < 0 && m == NORMAL_MASK ) {
+
+ BigInt::simpleShiftLeftHighPrecision (D2, D2Length, 1);
+ if( BigInt::compareHighPrecision (D2, D2Length, y, yLength) > 0 ) {
+ DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ } else if (comparison2 == 0) {
+
+ if ((m & 1) == 0) {
+ if (comparison < 0 && m == NORMAL_MASK) {
+ DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
+ } else {
+ break;
+ }
+ } else if (comparison < 0) {
+ DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
+ break;
+ } else {
+ INCREMENT_FLOAT (z, decApproxCount, incApproxCount);
+ break;
+ }
+ } else if (comparison < 0) {
+ DECREMENT_FLOAT (z, decApproxCount, incApproxCount);
+ } else {
+ if (FLOAT_TO_INTBITS (z) == EXPONENT_MASK)
+ break;
+ INCREMENT_FLOAT (z, decApproxCount, incApproxCount);
+ }
+ }
+ while (1);
+
+ delete x;
+ delete y;
+ delete D;
+ delete D2;
+
+ return z;
+}
+
+
+/**
+#define INCREMENT_FLOAT(_x, _decCount, _incCount) \
+ { \
+ ++FLOAT_TO_INTBITS(_x); \
+ _incCount++; \
+ if( (_incCount > 2) && (_decCount > 2) ) { \
+ if( _decCount > _incCount ) { \
+ FLOAT_TO_INTBITS(_x) += _decCount - _incCount; \
+ } else if( _incCount > _decCount ) { \
+ FLOAT_TO_INTBITS(_x) -= _incCount - _decCount; \
+ } \
+ break; \
+ } \
+ }
+#define DECREMENT_FLOAT(_x, _decCount, _incCount) \
+ { \
+ --FLOAT_TO_INTBITS(_x); \
+ _decCount++; \
+ if( (_incCount > 2) && (_decCount > 2) ) { \
+ if( _decCount > _incCount ) { \
+ FLOAT_TO_INTBITS(_x) += _decCount - _incCount; \
+ } else if( _incCount > _decCount ) { \
+ FLOAT_TO_INTBITS(_x) -= _incCount - _decCount; \
+ } \
+ break; \
+ } \
+ }
+*/
Modified: activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.h
URL: http://svn.apache.org/viewvc/activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.h?view=diff&rev=564433&r1=564432&r2=564433
==============================================================================
--- activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.h (original)
+++ activemq/activemq-cpp/trunk/src/decaf/src/main/decaf/internal/util/FloatingPointParser.h Thu Aug 9 16:56:13 2007
@@ -49,6 +49,7 @@
static const int MAX_ACCURACY_WIDTH = 17;
static const int DEFAULT_WIDTH = MAX_ACCURACY_WIDTH;
+ static const int LOG5_OF_TWO_TO_THE_N = 11;
public:
@@ -76,6 +77,10 @@
private:
+ static int sizeOfTenToTheE( int e) {
+ return ( e / 19 ) + 1;
+ }
+
/**
* Takes a String and an integer exponent. The String should hold a positive
* integer value (or zero). The exponent will be used to calculate the
@@ -152,6 +157,42 @@
* @param returns a reference to the string passed for chaining
*/
static std::string& toLowerCase( std::string& value );
+
+ /**
+ * Create a float from the given string and exponent
+ */
+ static float createFloat( const std::string& s, int exp );
+
+ /**
+ * Create a float from the given long long array and exponent
+ */
+ static float createFloat1( unsigned long long* f, int length, int exp );
+
+ /**
+ * The algorithm for the function floatAlgorithm() below can be found
+ * in:
+ *
+ * "How to Read Floating-Point Numbers Accurately", William D.
+ * Clinger, Proceedings of the ACM SIGPLAN '90 Conference on
+ * Programming Language Design and Implementation, June 20-22,
+ * 1990, pp. 92-101.
+ *
+ * There is a possibility that the function will end up in an endless
+ * loop if the given approximating floating-point number (a very small
+ * floating-point whose value is very close to zero) straddles between
+ * two approximating integer values. We modified the algorithm slightly
+ * to detect the case where it oscillates back and forth between
+ * incrementing and decrementing the floating-point approximation. It
+ * is currently set such that if the oscillation occurs more than twice
+ * then return the original approximation.
+ * @returns a newly parse float.
+ */
+ static float floatAlgorithm( unsigned long long* f, int length,
+ int e, float z );
+
+// static IS_DENORMAL_DBL_PTR(dblptr) {
+// (((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_EXPONENT_MASK_HI) == 0) && ((HIGH_U32_FROM_DBL_PTR(dblptr) & DOUBLE_MANTISSA_MASK_HI) != 0 || (LOW_U32_FROM_DBL_PTR(dblptr) != 0)))
+// }
};