From e8daa77d756c6a8d34b704a19b320ebd2fbb087a Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 7 Feb 2011 22:37:44 +0000 Subject: [PATCH] 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 --- ttmath/ttmathint.h | 8 ++--- ttmath/ttmathuint.h | 80 +++++++++++++++++++++++++++++++++++++++------ 2 files changed, 73 insertions(+), 15 deletions(-) diff --git a/ttmath/ttmathint.h b/ttmath/ttmathint.h index abc9c28..ad306f0 100644 --- a/ttmath/ttmathint.h +++ b/ttmath/ttmathint.h @@ -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 temp(*this); temp.Abs(); - - temp.UInt::ToString(result, b); - result.insert(result.begin(), '-'); + temp.UInt::ToStringBase(result, b, true); } else { - UInt::ToString(result, b); + UInt::ToStringBase(result, b, false); } } diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index 2c96a60..d0f6df1 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -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 - void ToStringBase(string_type & result, uint b = 10) const + void ToStringBase(string_type & result, uint b = 10, bool negative = false) const { - UInt temp( *this ); + UInt 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(digits_d) + 3; // plus some epsilon + + if( result.capacity() < digits ) + result.reserve(digits); + do { - temp.DivInt(b, &rem); - character = static_cast( 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(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(result[i1]); + result[i1] = result[i2]; + result[i2] = tempc; + } } + public: /*!