changed: UInt::ToString() had O(n^2) complexity

where n was the number of digits to print
         now it has O(n)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@340 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2011-02-07 22:37:44 +00:00
parent 231164f6ea
commit e8daa77d75
2 changed files with 73 additions and 15 deletions

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2010, Tomasz Sowa * Copyright (c) 2006-2011, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -1315,13 +1315,11 @@ private:
{ {
Int<value_size> temp(*this); Int<value_size> temp(*this);
temp.Abs(); temp.Abs();
temp.UInt<value_size>::ToStringBase(result, b, true);
temp.UInt<value_size>::ToString(result, b);
result.insert(result.begin(), '-');
} }
else else
{ {
UInt<value_size>::ToString(result, b); UInt<value_size>::ToStringBase(result, b, false);
} }
} }

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (c) 2006-2010, Tomasz Sowa * Copyright (c) 2006-2011, Tomasz Sowa
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -3204,36 +3204,96 @@ public:
private: protected:
/*!
an auxiliary method for converting into the string
it returns the log (with the base 2) from x
where x is in <2;16>
*/
double ToStringLog2(uint x) const
{
static double log_tab[] = {
1.000000000000000000,
0.630929753571457437,
0.500000000000000000,
0.430676558073393050,
0.386852807234541586,
0.356207187108022176,
0.333333333333333333,
0.315464876785728718,
0.301029995663981195,
0.289064826317887859,
0.278942945651129843,
0.270238154427319741,
0.262649535037193547,
0.255958024809815489,
0.250000000000000000
};
if( x<2 || x>16 )
return 0;
return log_tab[x-2];
}
/*! /*!
an auxiliary method for converting to a string an auxiliary method for converting to a string
it's used from Int::ToString() too (negative is set true then)
*/ */
template<class string_type> template<class string_type>
void ToStringBase(string_type & result, uint b = 10) const void ToStringBase(string_type & result, uint b = 10, bool negative = false) const
{ {
UInt<value_size> temp( *this ); UInt<value_size> temp(*this);
uint rest, table_id, index, digits;
double digits_d;
char character; char character;
uint rem;
result.clear(); result.clear();
if( b<2 || b>16 ) if( b<2 || b>16 )
return; return;
if( !FindLeadingBit(table_id, index) )
{
result = '0';
return;
}
if( negative )
result = '-';
digits_d = table_id; // for not making an overflow in uint type
digits_d *= TTMATH_BITS_PER_UINT;
digits_d += index + 1;
digits_d *= ToStringLog2(b);
digits = static_cast<uint>(digits_d) + 3; // plus some epsilon
if( result.capacity() < digits )
result.reserve(digits);
do do
{ {
temp.DivInt(b, &rem); temp.DivInt(b, &rest);
character = static_cast<char>( Misc::DigitToChar(rem) ); character = static_cast<char>(Misc::DigitToChar(rest));
result.insert(result.begin(), character); // !! it has O(n^2) complexity, change it result.insert(result.end(), character);
// take the one from winix
} }
while( !temp.IsZero() ); while( !temp.IsZero() );
return; size_t i1 = negative ? 1 : 0; // the first is a hyphen (when negative is true)
size_t i2 = result.size() - 1;
for( ; i1 < i2 ; ++i1, --i2 )
{
char tempc = static_cast<char>(result[i1]);
result[i1] = result[i2];
result[i2] = tempc;
}
} }
public: public:
/*! /*!