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.
*
* Redistribution and use in source and binary forms, with or without
@ -1315,13 +1315,11 @@ private:
{
Int<value_size> temp(*this);
temp.Abs();
temp.UInt<value_size>::ToString(result, b);
result.insert(result.begin(), '-');
temp.UInt<value_size>::ToStringBase(result, b, true);
}
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.
*
* 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
it's used from Int::ToString() too (negative is set true then)
*/
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;
uint rem;
result.clear();
if( b<2 || b>16 )
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
{
temp.DivInt(b, &rem);
character = static_cast<char>( Misc::DigitToChar(rem) );
result.insert(result.begin(), character); // !! it has O(n^2) complexity, change it
// take the one from winix
temp.DivInt(b, &rest);
character = static_cast<char>(Misc::DigitToChar(rest));
result.insert(result.end(), character);
}
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:
/*!