From d789ac5396e3796d307d7f9c9d148ca5370294fc Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 11 Jun 2009 02:31:41 +0000 Subject: [PATCH] added: using NaN flag in method Big::ToDouble() and Big::FromDouble() changed: some cosmetic changes to get rid of warnings generated by MS Visual 2008 when warning level is 4 changed: names of labels in asm code: p to ttmath_loop, end to ttmath_end p2 to ttmath_loop2 Robert Muir reported that there was a confict with boost::end git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@156 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 29 ++++++++++++++-- ttmath/ttmath.h | 20 ++++++++--- ttmath/ttmathbig.h | 44 +++++++++++++++++++----- ttmath/ttmathint.h | 1 - ttmath/ttmathparser.h | 8 ++--- ttmath/ttmathtypes.h | 4 +-- ttmath/ttmathuint.h | 8 +++-- ttmath/ttmathuint_x86.h | 74 +++++++++++++++++++++-------------------- 8 files changed, 127 insertions(+), 61 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 0b98f9b..adcd0b0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Version 0.8.5 prerelease (2009.05.15): +Version 0.8.5 prerelease (2009.06.11): * fixed: Big::Mod(x) didn't correctly return a carry and the result was sometimes very big (even greater than x) * fixed: global function Mod(x) didn't set an ErrorCode object @@ -7,7 +7,7 @@ Version 0.8.5 prerelease (2009.05.15): * changed: function Sin(x) to Sin(x, ErrorCode * err=0) when x was very big the function returns zero now it sets ErrorCode object to err_overflow - and the result is undefined + and the result has a NaN flag set the same is to Cos() function * changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period should be a little accurate especially on a very big 'x' @@ -29,6 +29,31 @@ Version 0.8.5 prerelease (2009.05.15): uint SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result) three forms: asm x86, asm x86_64, no-asm those methods are used by the Karatsuba multiplication algorithm + * added: to Big<> class: support for NaN flag (Not a Number) + bool Big::IsNan() - returns true if the NaN flag is set + void Big::SetNan() - sets the NaN flag + The NaN flag is set by default after creating an object: + Big<1, 2> a; // NaN is set (it means the object has not a valid number) + std::cout << a; // cout gives "NaN" + a = 123; // now NaN is not set + std::cout << a; // cout gives "123" + The NaN is set if there was a carry during calculations + a.Mul(very_big_value); // a will have a NaN set + The NaN is set if an argument is NaN too + b.SetNan(); + a.Add(b); // a will have NaN because b has NaN too + If you try to do something on a NaN object, the result is a NaN too + a.SetNan(); + a.Add(2); // a is still a NaN + The NaN is set if you use incorrect arguments + a.Ln(-10); // a will have the NaN flag + The only way to clear the NaN flag is to assign a correct value or other correct object, + supposing 'a' has NaN flag, to remove the flag you can either: + a = 10; + a.FromInt(30); + a.SetOne(); + a.FromBig(other_object_without_nan); + etc. Version 0.8.4 (2009.05.08): diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index 88b1bbb..b807564 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -45,6 +45,12 @@ \brief Mathematics functions. */ +#ifdef _MSC_VER +//warning C4127: conditional expression is constant +#pragma warning( disable: 4127 ) +#endif + + #include "ttmathbig.h" #include "ttmathobjects.h" @@ -1727,7 +1733,7 @@ namespace ttmath template - bool RootCheckIndexOne(ValueType & x, const ValueType & index, ErrorCode * err) + bool RootCheckIndexOne(const ValueType & index, ErrorCode * err) { ValueType one; one.SetOne(); @@ -1769,11 +1775,12 @@ namespace ttmath template - bool RootCheckXZero(ValueType & x, const ValueType & index, ErrorCode * err) + bool RootCheckXZero(ValueType & x, ErrorCode * err) { if( x.IsZero() ) { // root(0;index) is zero (if index!=0) + // RootCheckIndexZero() must be called beforehand x.SetZero(); if( err ) @@ -1842,9 +1849,9 @@ namespace ttmath if( RootCheckIndexSign(x, index, err) ) return x; if( RootCheckIndexZero(x, index, err) ) return x; - if( RootCheckIndexOne (x, index, err) ) return x; + if( RootCheckIndexOne ( index, err) ) return x; if( RootCheckIndexFrac(x, index, err) ) return x; - if( RootCheckXZero (x, index, err) ) return x; + if( RootCheckXZero (x, err) ) return x; // index integer and index!=0 // x!=0 @@ -2079,4 +2086,9 @@ namespace ttmath */ #include "ttmathparser.h" + +#ifdef _MSC_VER +#pragma warning( default: 4127 ) +#endif + #endif diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index a78ed04..ad94254 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -704,7 +704,12 @@ public: // there shouldn't be a carry here because // (1) (2) guarantee that the mantissa of this // is greater than or equal to the mantissa of the ss2 - uint c_temp = mantissa.Sub(ss2.mantissa); + + #ifdef TTMATH_DEBUG + // this is to get rid of a warning saying that c_temp is not used + uint c_temp = /* mantissa.Sub(ss2.mantissa); */ + #endif + mantissa.Sub(ss2.mantissa); TTMATH_ASSERT( c_temp == 0 ) } @@ -2022,9 +2027,10 @@ public: // If E=2047 and F is zero and S is 1, then V=-Infinity // If E=2047 and F is zero and S is 0, then V=Infinity - // at the moment we do not support NaN, -Infinity and +Infinity + // we do not support -Infinity and +Infinity + // we assume that there is always NaN - SetZero(); + SetNaN(); } else if( e > 0 ) @@ -2135,9 +2141,10 @@ public: // If E=2047 and F is zero and S is 1, then V=-Infinity // If E=2047 and F is zero and S is 0, then V=Infinity - // at the moment we do not support NaN, -Infinity and +Infinity + // we do not support -Infinity and +Infinity + // we assume that there is always NaN - SetZero(); + SetNaN(); } else if( e > 0 ) @@ -2227,12 +2234,19 @@ public: return 0; } + if( IsNan() ) + { + result = ToDouble_SetDouble( false, 2047, 0, false, true); + + return 0; + } + sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1; if( exponent >= 1024 - e_correction ) { // +/- infinity - result = ToDouble_SetDouble( IsSign(), 2047, 0, true); + result = ToDouble_SetDouble( 0, 2047, 0, true); return 1; } @@ -2267,7 +2281,7 @@ private: #ifdef TTMATH_PLATFORM32 // 32bit platforms - double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false) const + double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const { union { @@ -2282,6 +2296,12 @@ private: temp.u[1] |= (e << 20) & 0x7FF00000u; + if( nan ) + { + temp.u[0] |= 1; + return temp.d; + } + if( infinity ) return temp.d; @@ -2304,7 +2324,7 @@ private: #else // 64bit platforms - double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false) const + double ToDouble_SetDouble(bool is_sign, uint e, sint move, bool infinity = false, bool nan = false) const { union { @@ -2319,6 +2339,12 @@ private: temp.u |= (e << 52) & 0x7FF0000000000000ul; + if( nan ) + { + temp.u |= 1; + return temp.d; + } + if( infinity ) return temp.d; @@ -3088,7 +3114,7 @@ private: else was_carry = false; - new_man[i] = UInt::DigitToChar( digit ); + new_man[i] = static_cast( UInt::DigitToChar(digit) ); } if( i<0 && was_carry ) diff --git a/ttmath/ttmathint.h b/ttmath/ttmathint.h index b5c5f97..71231ca 100644 --- a/ttmath/ttmathint.h +++ b/ttmath/ttmathint.h @@ -1316,5 +1316,4 @@ public: } // namespace - #endif diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index ce4c7f2..8ea1bb7 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -1,5 +1,5 @@ /* - * This file is a part of TTMath Mathematical Library + * This file is a part of TTMath Bignum Library * and is distributed under the (new) BSD licence. * Author: Tomasz Sowa */ @@ -984,7 +984,7 @@ void Not(int sindex, int amount_of_args, ValueType & result) void DegToRad(int sindex, int amount_of_args, ValueType & result) { - ErrorCode err; + ErrorCode err = err_ok; if( amount_of_args == 1 ) { @@ -1063,7 +1063,7 @@ void RadToGrad(int sindex, int amount_of_args, ValueType & result) void DegToGrad(int sindex, int amount_of_args, ValueType & result) { - ErrorCode err; + ErrorCode err = err_ok; if( amount_of_args == 1 ) { @@ -1566,7 +1566,7 @@ int character; do { - result += character; + result += static_cast( character ); character = * ++pstring; } while( (character>='a' && character<='z') || diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index 331522a..fe8dc07 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -360,7 +360,7 @@ namespace ttmath foo.Add(foo); but there are only few methods which can do that */ - class ReferenceError : public std::logic_error, ExceptionInfo + class ReferenceError : public std::logic_error, public ExceptionInfo { public: @@ -392,7 +392,7 @@ namespace ttmath the name and the line of a file where the macro TTMATH_ASSERT was used) */ - class RuntimeError : public std::runtime_error, ExceptionInfo + class RuntimeError : public std::runtime_error, public ExceptionInfo { public: diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index a089b3e..2605cb5 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -40,6 +40,7 @@ #ifndef headerfilettmathuint #define headerfilettmathuint + /*! \file ttmathuint.h \brief template class UInt @@ -48,6 +49,7 @@ #include #include + #include "ttmathtypes.h" @@ -1813,7 +1815,7 @@ private: if( Div2_DivisorGreaterOrEqual( divisor, remainder, table_id, index, - divisor_table_id, divisor_index) ) + divisor_index) ) { TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") return 0; @@ -1833,7 +1835,7 @@ private: bool Div2_DivisorGreaterOrEqual( const UInt & divisor, UInt * remainder, uint table_id, uint index, - uint divisor_table_id, uint divisor_index ) + uint divisor_index ) { if( divisor_index > index ) { @@ -2706,7 +2708,7 @@ public: do { temp.DivInt(b, &rem); - character = DigitToChar( rem ); + character = static_cast( DigitToChar(rem) ); result.insert(result.begin(), character); } while( !temp.IsZero() ); diff --git a/ttmath/ttmathuint_x86.h b/ttmath/ttmathuint_x86.h index 823194b..f11727e 100644 --- a/ttmath/ttmathuint_x86.h +++ b/ttmath/ttmathuint_x86.h @@ -105,13 +105,13 @@ namespace ttmath mov eax,[c] neg eax // CF=1 if rax!=0 , CF=0 if rax==0 - p: + ttmath_loop: mov eax,[esi+edx*4] adc [ebx+edx*4],eax inc edx dec ecx - jnz p + jnz ttmath_loop adc ecx, ecx mov [c], ecx @@ -204,16 +204,16 @@ namespace ttmath mov eax, [value] - p: + ttmath_loop: add [ebx+edx*4], eax - jnc end + jnc ttmath_end mov eax, 1 inc edx dec ecx - jnz p + jnz ttmath_loop - end: + ttmath_end: setc al movzx edx, al mov [c], edx @@ -321,16 +321,16 @@ namespace ttmath mov eax, [x2] - p: + ttmath_loop: adc [ebx+edx*4], eax - jnc end + jnc ttmath_end mov eax, 0 inc edx dec ecx - jnz p + jnz ttmath_loop - end: + ttmath_end: setc al movzx edx, al mov [c], edx @@ -423,36 +423,37 @@ namespace ttmath mov ebx, [ss2] mov edi, [result] - p: + ttmath_loop: mov eax, [esi+edx*4] adc eax, [ebx+edx*4] mov [edi+edx*4], eax inc edx dec ecx - jnz p + jnz ttmath_loop adc ecx, ecx // ecx has the cf state mov ebx, [rest] or ebx, ebx - jz end + jz ttmath_end xor ebx, ebx // ebx = 0 neg ecx // setting cf from ecx mov ecx, [rest] // ecx is != 0 - p2: + + ttmath_loop2: mov eax, [esi+edx*4] adc eax, ebx mov [edi+edx*4], eax inc edx dec ecx - jnz p2 + jnz ttmath_loop2 adc ecx, ecx - end: + ttmath_end: mov [c], ecx popad @@ -548,13 +549,13 @@ namespace ttmath mov eax,[c] neg eax // CF=1 if rax!=0 , CF=0 if rax==0 - p: + ttmath_loop: mov eax,[esi+edx*4] sbb [ebx+edx*4],eax inc edx dec ecx - jnz p + jnz ttmath_loop adc ecx, ecx mov [c], ecx @@ -646,16 +647,16 @@ namespace ttmath mov eax, [value] - p: + ttmath_loop: sub [ebx+edx*4], eax - jnc end + jnc ttmath_end mov eax, 1 inc edx dec ecx - jnz p + jnz ttmath_loop - end: + ttmath_end: setc al movzx edx, al mov [c], edx @@ -750,36 +751,37 @@ namespace ttmath mov ebx, [ss2] mov edi, [result] - p: + ttmath_loop: mov eax, [esi+edx*4] sbb eax, [ebx+edx*4] mov [edi+edx*4], eax inc edx dec ecx - jnz p + jnz ttmath_loop adc ecx, ecx // ecx has the cf state mov ebx, [rest] or ebx, ebx - jz end + jz ttmath_end xor ebx, ebx // ebx = 0 neg ecx // setting cf from ecx mov ecx, [rest] // ecx is != 0 - p2: + + ttmath_loop2: mov eax, [esi+edx*4] sbb eax, ebx mov [edi+edx*4], eax inc edx dec ecx - jnz p2 + jnz ttmath_loop2 adc ecx, ecx - end: + ttmath_end: mov [c], ecx popad @@ -870,12 +872,12 @@ namespace ttmath neg ecx mov ecx, [b] - p: + ttmath_loop: rcl dword ptr [ebx+edx*4], 1 inc edx dec ecx - jnz p + jnz ttmath_loop adc ecx, ecx mov [c], ecx @@ -946,11 +948,11 @@ namespace ttmath neg ecx mov ecx, [b] - p: + ttmath_loop: rcr dword ptr [ebx+ecx*4-4], 1 dec ecx - jnz p + jnz ttmath_loop adc ecx, ecx mov [c], ecx @@ -1045,7 +1047,7 @@ namespace ttmath or eax, eax cmovnz esi, ebp // if(c) esi=mask else esi=0 - p: + ttmath_loop: rol dword ptr [ebx+edx*4], cl mov eax, [ebx+edx*4] @@ -1056,7 +1058,7 @@ namespace ttmath inc edx dec edi - jnz p + jnz ttmath_loop pop ebp // restoring ebp @@ -1175,7 +1177,7 @@ namespace ttmath or eax, eax cmovnz esi, ebp // if(c) esi=mask else esi=0 - p: + ttmath_loop: ror dword ptr [ebx+edx*4], cl mov eax, [ebx+edx*4] @@ -1186,7 +1188,7 @@ namespace ttmath dec edx dec edi - jnz p + jnz ttmath_loop pop ebp // restoring ebp