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
This commit is contained in:
Tomasz Sowa 2009-06-11 02:31:41 +00:00
parent bb2583649e
commit d789ac5396
8 changed files with 127 additions and 61 deletions

View File

@ -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 * fixed: Big::Mod(x) didn't correctly return a carry
and the result was sometimes very big (even greater than x) and the result was sometimes very big (even greater than x)
* fixed: global function Mod(x) didn't set an ErrorCode object * 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) * changed: function Sin(x) to Sin(x, ErrorCode * err=0)
when x was very big the function returns zero when x was very big the function returns zero
now it sets ErrorCode object to err_overflow 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 the same is to Cos() function
* changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period * changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
should be a little accurate especially on a very big 'x' 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) 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 three forms: asm x86, asm x86_64, no-asm
those methods are used by the Karatsuba multiplication algorithm 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): Version 0.8.4 (2009.05.08):

View File

@ -45,6 +45,12 @@
\brief Mathematics functions. \brief Mathematics functions.
*/ */
#ifdef _MSC_VER
//warning C4127: conditional expression is constant
#pragma warning( disable: 4127 )
#endif
#include "ttmathbig.h" #include "ttmathbig.h"
#include "ttmathobjects.h" #include "ttmathobjects.h"
@ -1727,7 +1733,7 @@ namespace ttmath
template<class ValueType> template<class ValueType>
bool RootCheckIndexOne(ValueType & x, const ValueType & index, ErrorCode * err) bool RootCheckIndexOne(const ValueType & index, ErrorCode * err)
{ {
ValueType one; ValueType one;
one.SetOne(); one.SetOne();
@ -1769,11 +1775,12 @@ namespace ttmath
template<class ValueType> template<class ValueType>
bool RootCheckXZero(ValueType & x, const ValueType & index, ErrorCode * err) bool RootCheckXZero(ValueType & x, ErrorCode * err)
{ {
if( x.IsZero() ) if( x.IsZero() )
{ {
// root(0;index) is zero (if index!=0) // root(0;index) is zero (if index!=0)
// RootCheckIndexZero() must be called beforehand
x.SetZero(); x.SetZero();
if( err ) if( err )
@ -1842,9 +1849,9 @@ namespace ttmath
if( RootCheckIndexSign(x, index, err) ) return x; if( RootCheckIndexSign(x, index, err) ) return x;
if( RootCheckIndexZero(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( RootCheckIndexFrac(x, index, err) ) return x;
if( RootCheckXZero (x, index, err) ) return x; if( RootCheckXZero (x, err) ) return x;
// index integer and index!=0 // index integer and index!=0
// x!=0 // x!=0
@ -2079,4 +2086,9 @@ namespace ttmath
*/ */
#include "ttmathparser.h" #include "ttmathparser.h"
#ifdef _MSC_VER
#pragma warning( default: 4127 )
#endif
#endif #endif

View File

@ -704,7 +704,12 @@ public:
// there shouldn't be a carry here because // there shouldn't be a carry here because
// (1) (2) guarantee that the mantissa of this // (1) (2) guarantee that the mantissa of this
// is greater than or equal to the mantissa of the ss2 // 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 ) 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 1, then V=-Infinity
// If E=2047 and F is zero and S is 0, 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 else
if( e > 0 ) 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 1, then V=-Infinity
// If E=2047 and F is zero and S is 0, 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 else
if( e > 0 ) if( e > 0 )
@ -2227,12 +2234,19 @@ public:
return 0; return 0;
} }
if( IsNan() )
{
result = ToDouble_SetDouble( false, 2047, 0, false, true);
return 0;
}
sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1; sint e_correction = sint(man*TTMATH_BITS_PER_UINT) - 1;
if( exponent >= 1024 - e_correction ) if( exponent >= 1024 - e_correction )
{ {
// +/- infinity // +/- infinity
result = ToDouble_SetDouble( IsSign(), 2047, 0, true); result = ToDouble_SetDouble( 0, 2047, 0, true);
return 1; return 1;
} }
@ -2267,7 +2281,7 @@ private:
#ifdef TTMATH_PLATFORM32 #ifdef TTMATH_PLATFORM32
// 32bit platforms // 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 union
{ {
@ -2282,6 +2296,12 @@ private:
temp.u[1] |= (e << 20) & 0x7FF00000u; temp.u[1] |= (e << 20) & 0x7FF00000u;
if( nan )
{
temp.u[0] |= 1;
return temp.d;
}
if( infinity ) if( infinity )
return temp.d; return temp.d;
@ -2304,7 +2324,7 @@ private:
#else #else
// 64bit platforms // 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 union
{ {
@ -2319,6 +2339,12 @@ private:
temp.u |= (e << 52) & 0x7FF0000000000000ul; temp.u |= (e << 52) & 0x7FF0000000000000ul;
if( nan )
{
temp.u |= 1;
return temp.d;
}
if( infinity ) if( infinity )
return temp.d; return temp.d;
@ -3088,7 +3114,7 @@ private:
else else
was_carry = false; was_carry = false;
new_man[i] = UInt<man>::DigitToChar( digit ); new_man[i] = static_cast<char>( UInt<man>::DigitToChar(digit) );
} }
if( i<0 && was_carry ) if( i<0 && was_carry )

View File

@ -1316,5 +1316,4 @@ public:
} // namespace } // namespace
#endif #endif

View File

@ -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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/ */
@ -984,7 +984,7 @@ void Not(int sindex, int amount_of_args, ValueType & result)
void DegToRad(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 ) 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) void DegToGrad(int sindex, int amount_of_args, ValueType & result)
{ {
ErrorCode err; ErrorCode err = err_ok;
if( amount_of_args == 1 ) if( amount_of_args == 1 )
{ {
@ -1566,7 +1566,7 @@ int character;
do do
{ {
result += character; result += static_cast<char>( character );
character = * ++pstring; character = * ++pstring;
} }
while( (character>='a' && character<='z') || while( (character>='a' && character<='z') ||

View File

@ -360,7 +360,7 @@ namespace ttmath
foo.Add(foo); foo.Add(foo);
but there are only few methods which can do that 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: public:
@ -392,7 +392,7 @@ namespace ttmath
the name and the line of a file where the macro TTMATH_ASSERT the name and the line of a file where the macro TTMATH_ASSERT
was used) was used)
*/ */
class RuntimeError : public std::runtime_error, ExceptionInfo class RuntimeError : public std::runtime_error, public ExceptionInfo
{ {
public: public:

View File

@ -40,6 +40,7 @@
#ifndef headerfilettmathuint #ifndef headerfilettmathuint
#define headerfilettmathuint #define headerfilettmathuint
/*! /*!
\file ttmathuint.h \file ttmathuint.h
\brief template class UInt<uint> \brief template class UInt<uint>
@ -48,6 +49,7 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include "ttmathtypes.h" #include "ttmathtypes.h"
@ -1813,7 +1815,7 @@ private:
if( Div2_DivisorGreaterOrEqual( divisor, remainder, if( Div2_DivisorGreaterOrEqual( divisor, remainder,
table_id, index, table_id, index,
divisor_table_id, divisor_index) ) divisor_index) )
{ {
TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck") TTMATH_LOG("UInt::Div2_FindLeadingBitsAndCheck")
return 0; return 0;
@ -1833,7 +1835,7 @@ private:
bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor, bool Div2_DivisorGreaterOrEqual( const UInt<value_size> & divisor,
UInt<value_size> * remainder, UInt<value_size> * remainder,
uint table_id, uint index, uint table_id, uint index,
uint divisor_table_id, uint divisor_index ) uint divisor_index )
{ {
if( divisor_index > index ) if( divisor_index > index )
{ {
@ -2706,7 +2708,7 @@ public:
do do
{ {
temp.DivInt(b, &rem); temp.DivInt(b, &rem);
character = DigitToChar( rem ); character = static_cast<char>( DigitToChar(rem) );
result.insert(result.begin(), character); result.insert(result.begin(), character);
} }
while( !temp.IsZero() ); while( !temp.IsZero() );

View File

@ -105,13 +105,13 @@ namespace ttmath
mov eax,[c] mov eax,[c]
neg eax // CF=1 if rax!=0 , CF=0 if rax==0 neg eax // CF=1 if rax!=0 , CF=0 if rax==0
p: ttmath_loop:
mov eax,[esi+edx*4] mov eax,[esi+edx*4]
adc [ebx+edx*4],eax adc [ebx+edx*4],eax
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
adc ecx, ecx adc ecx, ecx
mov [c], ecx mov [c], ecx
@ -204,16 +204,16 @@ namespace ttmath
mov eax, [value] mov eax, [value]
p: ttmath_loop:
add [ebx+edx*4], eax add [ebx+edx*4], eax
jnc end jnc ttmath_end
mov eax, 1 mov eax, 1
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
end: ttmath_end:
setc al setc al
movzx edx, al movzx edx, al
mov [c], edx mov [c], edx
@ -321,16 +321,16 @@ namespace ttmath
mov eax, [x2] mov eax, [x2]
p: ttmath_loop:
adc [ebx+edx*4], eax adc [ebx+edx*4], eax
jnc end jnc ttmath_end
mov eax, 0 mov eax, 0
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
end: ttmath_end:
setc al setc al
movzx edx, al movzx edx, al
mov [c], edx mov [c], edx
@ -423,36 +423,37 @@ namespace ttmath
mov ebx, [ss2] mov ebx, [ss2]
mov edi, [result] mov edi, [result]
p: ttmath_loop:
mov eax, [esi+edx*4] mov eax, [esi+edx*4]
adc eax, [ebx+edx*4] adc eax, [ebx+edx*4]
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
adc ecx, ecx // ecx has the cf state adc ecx, ecx // ecx has the cf state
mov ebx, [rest] mov ebx, [rest]
or ebx, ebx or ebx, ebx
jz end jz ttmath_end
xor ebx, ebx // ebx = 0 xor ebx, ebx // ebx = 0
neg ecx // setting cf from ecx neg ecx // setting cf from ecx
mov ecx, [rest] // ecx is != 0 mov ecx, [rest] // ecx is != 0
p2:
ttmath_loop2:
mov eax, [esi+edx*4] mov eax, [esi+edx*4]
adc eax, ebx adc eax, ebx
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx inc edx
dec ecx dec ecx
jnz p2 jnz ttmath_loop2
adc ecx, ecx adc ecx, ecx
end: ttmath_end:
mov [c], ecx mov [c], ecx
popad popad
@ -548,13 +549,13 @@ namespace ttmath
mov eax,[c] mov eax,[c]
neg eax // CF=1 if rax!=0 , CF=0 if rax==0 neg eax // CF=1 if rax!=0 , CF=0 if rax==0
p: ttmath_loop:
mov eax,[esi+edx*4] mov eax,[esi+edx*4]
sbb [ebx+edx*4],eax sbb [ebx+edx*4],eax
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
adc ecx, ecx adc ecx, ecx
mov [c], ecx mov [c], ecx
@ -646,16 +647,16 @@ namespace ttmath
mov eax, [value] mov eax, [value]
p: ttmath_loop:
sub [ebx+edx*4], eax sub [ebx+edx*4], eax
jnc end jnc ttmath_end
mov eax, 1 mov eax, 1
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
end: ttmath_end:
setc al setc al
movzx edx, al movzx edx, al
mov [c], edx mov [c], edx
@ -750,36 +751,37 @@ namespace ttmath
mov ebx, [ss2] mov ebx, [ss2]
mov edi, [result] mov edi, [result]
p: ttmath_loop:
mov eax, [esi+edx*4] mov eax, [esi+edx*4]
sbb eax, [ebx+edx*4] sbb eax, [ebx+edx*4]
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
adc ecx, ecx // ecx has the cf state adc ecx, ecx // ecx has the cf state
mov ebx, [rest] mov ebx, [rest]
or ebx, ebx or ebx, ebx
jz end jz ttmath_end
xor ebx, ebx // ebx = 0 xor ebx, ebx // ebx = 0
neg ecx // setting cf from ecx neg ecx // setting cf from ecx
mov ecx, [rest] // ecx is != 0 mov ecx, [rest] // ecx is != 0
p2:
ttmath_loop2:
mov eax, [esi+edx*4] mov eax, [esi+edx*4]
sbb eax, ebx sbb eax, ebx
mov [edi+edx*4], eax mov [edi+edx*4], eax
inc edx inc edx
dec ecx dec ecx
jnz p2 jnz ttmath_loop2
adc ecx, ecx adc ecx, ecx
end: ttmath_end:
mov [c], ecx mov [c], ecx
popad popad
@ -870,12 +872,12 @@ namespace ttmath
neg ecx neg ecx
mov ecx, [b] mov ecx, [b]
p: ttmath_loop:
rcl dword ptr [ebx+edx*4], 1 rcl dword ptr [ebx+edx*4], 1
inc edx inc edx
dec ecx dec ecx
jnz p jnz ttmath_loop
adc ecx, ecx adc ecx, ecx
mov [c], ecx mov [c], ecx
@ -946,11 +948,11 @@ namespace ttmath
neg ecx neg ecx
mov ecx, [b] mov ecx, [b]
p: ttmath_loop:
rcr dword ptr [ebx+ecx*4-4], 1 rcr dword ptr [ebx+ecx*4-4], 1
dec ecx dec ecx
jnz p jnz ttmath_loop
adc ecx, ecx adc ecx, ecx
mov [c], ecx mov [c], ecx
@ -1045,7 +1047,7 @@ namespace ttmath
or eax, eax or eax, eax
cmovnz esi, ebp // if(c) esi=mask else esi=0 cmovnz esi, ebp // if(c) esi=mask else esi=0
p: ttmath_loop:
rol dword ptr [ebx+edx*4], cl rol dword ptr [ebx+edx*4], cl
mov eax, [ebx+edx*4] mov eax, [ebx+edx*4]
@ -1056,7 +1058,7 @@ namespace ttmath
inc edx inc edx
dec edi dec edi
jnz p jnz ttmath_loop
pop ebp // restoring ebp pop ebp // restoring ebp
@ -1175,7 +1177,7 @@ namespace ttmath
or eax, eax or eax, eax
cmovnz esi, ebp // if(c) esi=mask else esi=0 cmovnz esi, ebp // if(c) esi=mask else esi=0
p: ttmath_loop:
ror dword ptr [ebx+edx*4], cl ror dword ptr [ebx+edx*4], cl
mov eax, [ebx+edx*4] mov eax, [ebx+edx*4]
@ -1186,7 +1188,7 @@ namespace ttmath
dec edx dec edx
dec edi dec edi
jnz p jnz ttmath_loop
pop ebp // restoring ebp pop ebp // restoring ebp