From d789ac5396e3796d307d7f9c9d148ca5370294fc Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 11 Jun 2009 02:31:41 +0000 Subject: [PATCH 1/7] 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 From 1b6858616dae3cef72fa7b0299994caf13c474f9 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 11 Jun 2009 10:04:50 +0000 Subject: [PATCH 2/7] fixed: in Big::FromDouble(): SetNaN() should be SetNan(); git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@157 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmathbig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index ad94254..1c7f4d7 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -2144,7 +2144,7 @@ public: // we do not support -Infinity and +Infinity // we assume that there is always NaN - SetNaN(); + SetNan(); } else if( e > 0 ) From 9e42a5a9fd89ab56256179c66c2fe503f88fd4d0 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 11 Jun 2009 15:03:22 +0000 Subject: [PATCH 3/7] fixed: Big::FromDouble() on a 32 bit platform: SetNaN() should be SetNan() /*compilation error*/ git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@158 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmathbig.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 1c7f4d7..e6f8b5a 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -2030,7 +2030,7 @@ public: // we do not support -Infinity and +Infinity // we assume that there is always NaN - SetNaN(); + SetNan(); } else if( e > 0 ) From 74553109a50c92553b4095a34e7b65467ee9880f Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 14 Jun 2009 18:45:36 +0000 Subject: [PATCH 4/7] fixed: (performance) in Big::LnSurrounding1() and Big::ExpSurrounding0() we can copy 'old_value = *this' only when 'testing' is true git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@160 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmathbig.h | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index e6f8b5a..422d563 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -1424,13 +1424,15 @@ public: // there shouldn't be a carry here Add( next_part ); - if( testing && old_value==*this ) - // we've added next few parts of the formula but the result - // is still the same then we break the loop - break; - else - old_value = *this; - + if( testing ) + { + if( old_value == *this ) + // we've added next few parts of the formula but the result + // is still the same then we break the loop + break; + else + old_value = *this; + } // we set the denominator and the numerator for a next part of the formula if( denominator_i.Add(one) ) @@ -1591,12 +1593,15 @@ public: // there shouldn't be a carry here Add(next_part); - if( testing && old_value == *this ) - // we've added next (step_test) parts of the formula but the result - // is still the same then we break the loop - break; - else - old_value = *this; + if( testing ) + { + if( old_value == *this ) + // we've added next (step_test) parts of the formula but the result + // is still the same then we break the loop + break; + else + old_value = *this; + } if( x1.Mul(x2) ) // if there is a carry here the result we return as good From 019a902fed05d173edcf3f0ae116f774334a25dc Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sun, 14 Jun 2009 19:55:15 +0000 Subject: [PATCH 5/7] changed: small optimization in Big::ExpSurrounding0() and Big::LnSurrounding1() the remainder from a division '%' was changed with a bitwise And operation '&' ((i % 5) == 0) was changed to: ((i & 3) == 0) - it means ((i % 4) == 0) now the test if performed after 4 iterations (early were after 5 iterations) we can do that when the divisor is a power of 2 changed: optimization in Factorial() we're testing WasStopSignal() only after a few iterations it's faster now about 4 times on GCC 4.3.3 (when stop object is provided to the factorial) git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@161 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmath.h | 28 ++++++++++++++++++---------- ttmath/ttmathbig.h | 13 ++++--------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index b807564..3883108 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -1902,13 +1902,16 @@ namespace ttmath while( !carry && multiplerWasStopSignal() ) + if( stop && (multipler & 127)==0 ) // it means 'stop && (multipler % 128)==0' { - if( err ) - *err = err_interrupt; + // after each 128 iterations we make a test + if( stop->WasStopSignal() ) + { + if( err ) + *err = err_interrupt; - return 2; + return 2; + } } ++multipler; @@ -1932,20 +1935,25 @@ namespace ttmath one.SetOne(); uint carry = 0; + uint iter = 1; // only for testing the stop object while( !carry && multipler < x ) { - // !! the test here we don't have to make in all iterations (performance) - if( stop && stop->WasStopSignal() ) + if( stop && (iter & 31)==0 ) // it means 'stop && (iter % 32)==0' { - if( err ) - *err = err_interrupt; + // after each 32 iterations we make a test + if( stop->WasStopSignal() ) + { + if( err ) + *err = err_interrupt; - return 2; + return 2; + } } carry += multipler.Add(one); carry += result.Mul(multipler); + ++iter; } if( err ) diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 422d563..2b5057a 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -1399,19 +1399,17 @@ public: denominator.SetOne(); denominator_i.SetOne(); - // every 'step_test' times we make a test - const uint step_test = 5; uint i; old_value = *this; - // we begin from 1 in order to not testing at the beginning + // we begin from 1 in order to not test at the beginning #ifdef TTMATH_CONSTANTSGENERATOR for(i=1 ; true ; ++i) #else for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) #endif { - bool testing = ((i % step_test) == 0); + bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' next_part = numerator; @@ -1567,20 +1565,17 @@ public: SetZero(); old_value = *this; - - // every 'step_test' times we make a test - const uint step_test = 5; uint i; #ifdef TTMATH_CONSTANTSGENERATOR for(i=1 ; true ; ++i) #else - // we begin from 1 in order to not testing at the beginning + // we begin from 1 in order to not test at the beginning for(i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i) #endif { - bool testing = ((i % step_test) == 0); + bool testing = ((i & 3) == 0); // it means '(i % 4) == 0' next_part = x1; From 8972fdfdb3c39d81c832bc991c3837c3adea2a03 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 16 Jun 2009 18:31:39 +0000 Subject: [PATCH 6/7] fixed: Sqrt(), Root() and Factorial() didn't correctly treat the NaN flag fixed: some methods should set 'err_improper_argument' when the argument is a NaN object (was: err_overflow) changed: version of the library: 0.8.5 now git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@163 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmath.h | 227 ++++++++++++++++++++++++++++++++++++++++--- ttmath/ttmathbig.h | 18 +++- ttmath/ttmathtypes.h | 2 +- 3 files changed, 228 insertions(+), 19 deletions(-) diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index 3883108..f8b6ee0 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -102,6 +102,14 @@ namespace ttmath template ValueType Round(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType result( x ); uint c = result.Round(); @@ -127,6 +135,14 @@ namespace ttmath template ValueType Ceil(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType result(x); uint c = 0; @@ -166,6 +182,14 @@ namespace ttmath template ValueType Floor(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType result(x); uint c = 0; @@ -206,8 +230,15 @@ namespace ttmath template ValueType Ln(const ValueType & x, ErrorCode * err = 0) { - ValueType result; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + return x; // NaN + } + + ValueType result; uint state = result.Ln(x); if( err ) @@ -240,8 +271,15 @@ namespace ttmath template ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0) { - ValueType result; + if( x.IsNan() || base.IsNan() ) + { + if( err ) + *err = err_improper_argument; + return ValueType(); // default NaN + } + + ValueType result; uint state = result.Log(x, base); if( err ) @@ -274,8 +312,15 @@ namespace ttmath template ValueType Exp(const ValueType & x, ErrorCode * err = 0) { - ValueType result; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + return x; // NaN + } + + ValueType result; uint c = result.Exp(x); if( err ) @@ -471,6 +516,14 @@ namespace ttmath ValueType one, result; bool change_sign; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + if( err ) *err = err_ok; @@ -482,7 +535,7 @@ namespace ttmath // result has NaN flag set by default if( err ) - *err = err_overflow; // maybe another error code? + *err = err_overflow; // maybe another error code? err_improper_argument? return result; // NaN is set by default } @@ -514,6 +567,14 @@ namespace ttmath template ValueType Cos(ValueType x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType pi05; pi05.Set05Pi(); @@ -786,6 +847,14 @@ namespace ttmath one.SetOne(); bool change_sign = false; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + if( x.GreaterWithoutSignThan(one) ) { if( err ) @@ -830,7 +899,7 @@ namespace ttmath ValueType temp; temp.Set05Pi(); - temp.Sub(ASin(x,err)); + temp.Sub(ASin(x, err)); return temp; } @@ -1008,6 +1077,9 @@ namespace ttmath one.SetOne(); bool change_sign = false; + if( x.IsNan() ) + return result; // NaN is set by default + // if x is negative we're using the formula: // atan(-x) = -atan(x) if( x.IsSign() ) @@ -1088,6 +1160,14 @@ namespace ttmath template ValueType Sinh(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType ex, emx; uint c = 0; @@ -1112,6 +1192,14 @@ namespace ttmath template ValueType Cosh(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType ex, emx; uint c = 0; @@ -1136,6 +1224,14 @@ namespace ttmath template ValueType Tanh(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType ex, emx, nominator, denominator; uint c = 0; @@ -1176,6 +1272,14 @@ namespace ttmath template ValueType Coth(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + if( x.IsZero() ) { if( err ) @@ -1233,6 +1337,14 @@ namespace ttmath template ValueType ASinh(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType xx(x), one, result; uint c = 0; one.SetOne(); @@ -1261,6 +1373,14 @@ namespace ttmath template ValueType ACosh(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType xx(x), one, result; uint c = 0; one.SetOne(); @@ -1302,6 +1422,14 @@ namespace ttmath template ValueType ATanh(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType nominator(x), denominator, one, result; uint c = 0; one.SetOne(); @@ -1347,6 +1475,14 @@ namespace ttmath template ValueType ACoth(const ValueType & x, ErrorCode * err = 0) { + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return x; // NaN + } + ValueType nominator(x), denominator(x), one, result; uint c = 0; one.SetOne(); @@ -1405,6 +1541,14 @@ namespace ttmath ValueType result, temp; uint c = 0; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + result = x; // it is better to make division first and then multiplication @@ -1433,6 +1577,14 @@ namespace ttmath ValueType result, delimiter; uint c = 0; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + result = 180; c += result.Mul(x); @@ -1470,12 +1622,12 @@ namespace ttmath ValueType delimiter, multipler; uint c = 0; - if( m.IsSign() || s.IsSign() ) + if( d.IsNan() || m.IsNan() || s.IsNan() || m.IsSign() || s.IsSign() ) { if( err ) *err = err_improper_argument; - return delimiter; // NaN is set by default + return delimiter ; // NaN is set by default } multipler = 60; @@ -1524,6 +1676,14 @@ namespace ttmath ValueType result, temp; uint c = 0; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + result = x; // it is better to make division first and then multiplication @@ -1552,6 +1712,14 @@ namespace ttmath ValueType result, delimiter; uint c = 0; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + result = 200; c += result.Mul(x); @@ -1576,6 +1744,14 @@ namespace ttmath ValueType result, temp; uint c = 0; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + result = x; temp = 200; @@ -1618,6 +1794,14 @@ namespace ttmath ValueType result, temp; uint c = 0; + if( x.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return result; // NaN is set by default + } + result = x; temp = 180; @@ -1651,7 +1835,7 @@ namespace ttmath template ValueType Sqrt(ValueType x, ErrorCode * err = 0) { - if( x.IsSign() ) + if( x.IsNan() || x.IsSign() ) { if( err ) *err = err_improper_argument; @@ -1847,6 +2031,14 @@ namespace ttmath { using namespace auxiliaryfunctions; + if( x.IsNan() || index.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return ValueType(); // NaN is set by default + } + if( RootCheckIndexSign(x, index, err) ) return x; if( RootCheckIndexZero(x, index, err) ) return x; if( RootCheckIndexOne ( index, err) ) return x; @@ -1980,18 +2172,16 @@ namespace ttmath static History history; ValueType result; - result.SetOne(); - - if( x.IsSign() ) + if( x.IsNan() || x.IsSign() ) { if( err ) *err = err_improper_argument; - result.SetNan(); - - return result; + return result; // NaN set by default } + result.SetOne(); + if( !x.exponent.IsSign() && !x.exponent.IsZero() ) { // when x.exponent>0 there's no sense to calculate the formula @@ -2075,6 +2265,14 @@ namespace ttmath template ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0) { + if( a.IsNan() || b.IsNan() ) + { + if( err ) + *err = err_improper_argument; + + return ValueType(); // NaN is set by default + } + uint c = a.Mod(b); if( err ) @@ -2097,6 +2295,7 @@ namespace ttmath #ifdef _MSC_VER #pragma warning( default: 4127 ) +//warning C4127: conditional expression is constant #endif #endif diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 2b5057a..6c909ec 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -139,9 +139,8 @@ public: return 0; uint comp = mantissa.CompensationToLeft(); - uint c = exponent.Sub( comp ); - return CheckCarry(c); + return exponent.Sub( comp ); } @@ -536,6 +535,7 @@ public: /* we only have to test the mantissa also we don't check the NaN flag + (maybe this method should return false if there is NaN flag set?) */ return mantissa.IsZero(); } @@ -583,6 +583,7 @@ public: */ void Sgn() { + // we have to check the NaN flag, because the next SetOne() method would clear it if( IsNan() ) return; @@ -618,6 +619,7 @@ public: /*! this method changes the sign + when there is a value of zero then the sign is not changed e.g. -1 -> 1 @@ -625,6 +627,8 @@ public: */ void ChangeSign() { + // we don't have to check the NaN flag here + if( info & TTMATH_BIG_SIGN ) { info &= ~TTMATH_BIG_SIGN; @@ -2627,7 +2631,12 @@ public: */ Big() { - SetNan(); + info = TTMATH_BIG_NAN; + + /* + we're directly setting 'info' (instead of calling SetNan()) + in order to get rid of a warning saying that 'info' is uninitialized + */ } @@ -2697,7 +2706,8 @@ public: output: return value: 0 - ok and 'result' will be an object of type std::string which holds the value - 1 - if there was a carry + 1 - if there was a carry (shoudn't be in a normal situation - if is that means there + is somewhere an error in the library) */ uint ToString( std::string & result, uint base = 10, diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index fe8dc07..a27f58f 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -65,7 +65,7 @@ #define TTMATH_MAJOR_VER 0 #define TTMATH_MINOR_VER 8 #define TTMATH_REVISION_VER 5 -#define TTMATH_PRERELEASE_VER 1 +#define TTMATH_PRERELEASE_VER 0 /*! From c70a947c07bbb5df8339bc56e174fa91d5b0cff5 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Tue, 16 Jun 2009 18:33:20 +0000 Subject: [PATCH 7/7] updated changelog to previous commit git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@164 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index adcd0b0..e0a02d0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Version 0.8.5 prerelease (2009.06.11): +Version 0.8.5 (2009.06.16): * 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