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
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):

View File

@ -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<class ValueType>
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<class ValueType>
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

View File

@ -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<man>::DigitToChar( digit );
new_man[i] = static_cast<char>( UInt<man>::DigitToChar(digit) );
}
if( i<0 && was_carry )

View File

@ -1316,5 +1316,4 @@ public:
} // namespace
#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.
* 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)
{
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<char>( character );
character = * ++pstring;
}
while( (character>='a' && character<='z') ||

View File

@ -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:

View File

@ -40,6 +40,7 @@
#ifndef headerfilettmathuint
#define headerfilettmathuint
/*!
\file ttmathuint.h
\brief template class UInt<uint>
@ -48,6 +49,7 @@
#include <iostream>
#include <iomanip>
#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<value_size> & divisor,
UInt<value_size> * 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<char>( DigitToChar(rem) );
result.insert(result.begin(), character);
}
while( !temp.IsZero() );

View File

@ -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