added: bool UInt::IsOnlyTheHighestBitSet()
bool UInt::IsOnlyTheLowestBitSet() returning true if only the highest/lowest bit is set added: uint Int::MulInt(sint ss2) added: void UInt::Swap(UInt<value_size> & ss2) void Big::Swap(UInt<value_size> & ss2) method for swapping this for an argument changed: small optimization in Big::Sub() changed: now asm version is available only on x86 and amd64 (and only for GCC and MS VC compilers) removed: macro TTMATH_RELEASE for debug version define TTMATH_DEBUG macro TTMATH_DEBUG is also automatically defined when DEBUG or _DEBUG is set git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@304 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
69f065245e
commit
a1c41c02db
34
CHANGELOG
34
CHANGELOG
|
@ -1,7 +1,39 @@
|
|||
Version 0.9.2 prerelease (2009.03.01):
|
||||
Version 0.9.2 prerelease (2010.09.05):
|
||||
* fixed: Big::Add() sometimes incorrectly rounded the last bit from its mantissa
|
||||
* fixed: Big::BigAnd() Big::BigOr() Big::BigXor() should have set NaN
|
||||
when the argument was negative (they only returned 2)
|
||||
* fixed: recurrence calling in Big::FromString(const std::string &, uint, const wchar_t **, bool *)
|
||||
it should have the signature: Big::FromString(const std::string &, uint, const char **, bool *)
|
||||
* added: some missing operators
|
||||
UInt::operator~() /* bitwise neg */
|
||||
UInt::operator&() /* bitwise and */
|
||||
UInt::operator&=()
|
||||
UInt::operator|() /* bitwise or */
|
||||
UInt::operator|=()
|
||||
UInt::operator^() /* bitwise xor */
|
||||
UInt::operator^=()
|
||||
Big::operator&()
|
||||
Big::operator&=()
|
||||
Big::operator|()
|
||||
Big::operator|=()
|
||||
Big::operator^()
|
||||
Big::operator^=()
|
||||
for Big<> we do not define bitwise neg
|
||||
* added: macro TTMATH_DONT_USE_WCHAR
|
||||
if defined then the library does not use wide characters
|
||||
(wchar_t, std::wstring, ...) this is a workaround for some compilers
|
||||
* added: bool UInt::IsOnlyTheHighestBitSet()
|
||||
bool UInt::IsOnlyTheLowestBitSet()
|
||||
returning true if only the highest/lowest bit is set
|
||||
* added: uint Int::MulInt(sint ss2)
|
||||
* added: void UInt::Swap(UInt<value_size> & ss2)
|
||||
void Big::Swap(UInt<value_size> & ss2)
|
||||
method for swapping this for an argument
|
||||
* changed: now asm version is available only on x86 and amd64
|
||||
(and only for GCC and MS VC compilers)
|
||||
* removed: macro TTMATH_RELEASE
|
||||
for debug version define TTMATH_DEBUG macro
|
||||
TTMATH_DEBUG is also automatically defined when DEBUG or _DEBUG is set
|
||||
|
||||
|
||||
Version 0.9.1 (2010.02.07):
|
||||
|
|
|
@ -294,6 +294,20 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method swappes this for an argument
|
||||
*/
|
||||
void Swap(Big<exp, man> & ss2)
|
||||
{
|
||||
unsigned char info_temp = info;
|
||||
info = ss2.info;
|
||||
ss2.info = info_temp;
|
||||
|
||||
exponent.Swap(ss2.exponent);
|
||||
mantissa.Swap(ss2.mantissa);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
|
@ -862,7 +876,7 @@ public:
|
|||
|
||||
it returns carry if the sum is too big
|
||||
*/
|
||||
uint Add(Big<exp, man> ss2, bool round = true)
|
||||
uint Add(Big<exp, man> ss2, bool round = true, bool adding = true)
|
||||
{
|
||||
bool last_bit_set, rest_zero, do_adding, do_rounding, rounding_up;
|
||||
Int<exp> exp_offset( exponent );
|
||||
|
@ -871,18 +885,15 @@ public:
|
|||
if( IsNan() || ss2.IsNan() )
|
||||
return CheckCarry(1);
|
||||
|
||||
if( !adding )
|
||||
ss2.ChangeSign(); // subtracting
|
||||
|
||||
exp_offset.Sub( ss2.exponent );
|
||||
exp_offset.Abs();
|
||||
|
||||
// (1) abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
// !! use Swap here (not implemented yet)
|
||||
Big<exp, man> temp(ss2);
|
||||
|
||||
ss2 = *this;
|
||||
*this = temp;
|
||||
}
|
||||
Swap(ss2);
|
||||
|
||||
if( ss2.IsZero() )
|
||||
return 0;
|
||||
|
@ -908,17 +919,14 @@ public:
|
|||
}
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
Subtraction this = this - ss2
|
||||
|
||||
it returns carry if the result is too big
|
||||
*/
|
||||
uint Sub(Big<exp, man> ss2, bool round = true)
|
||||
uint Sub(const Big<exp, man> & ss2, bool round = true)
|
||||
{
|
||||
ss2.ChangeSign();
|
||||
|
||||
return Add(ss2, round);
|
||||
return Add(ss2, round, false);
|
||||
}
|
||||
|
||||
|
||||
|
@ -961,12 +969,7 @@ public:
|
|||
|
||||
// abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
Big<exp, man> temp(ss2);
|
||||
|
||||
ss2 = *this;
|
||||
*this = temp;
|
||||
}
|
||||
Swap(ss2);
|
||||
|
||||
if( exp_offset >= mantissa_size_in_bits )
|
||||
{
|
||||
|
@ -1024,12 +1027,7 @@ public:
|
|||
|
||||
// abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
Big<exp, man> temp(ss2);
|
||||
|
||||
ss2 = *this;
|
||||
*this = temp;
|
||||
}
|
||||
Swap(ss2);
|
||||
|
||||
if( exp_offset >= mantissa_size_in_bits )
|
||||
// the second value is too small
|
||||
|
@ -1084,12 +1082,7 @@ public:
|
|||
|
||||
// abs(this) will be >= abs(ss2)
|
||||
if( SmallerWithoutSignThan(ss2) )
|
||||
{
|
||||
Big<exp, man> temp(ss2);
|
||||
|
||||
ss2 = *this;
|
||||
*this = temp;
|
||||
}
|
||||
Swap(ss2);
|
||||
|
||||
if( exp_offset >= mantissa_size_in_bits )
|
||||
// the second value is too small
|
||||
|
|
|
@ -104,13 +104,10 @@ public:
|
|||
*/
|
||||
uint ChangeSign()
|
||||
{
|
||||
Int<value_size> temp;
|
||||
|
||||
temp.SetMin();
|
||||
|
||||
/*
|
||||
if the value is equal that one which has been returned from SetMin
|
||||
that means we can't change sign because the value is too big (bigger about one)
|
||||
(only the highest bit is set) that means we can't change sign
|
||||
because the value is too big (bigger about one)
|
||||
|
||||
e.g. when value_size = 1 and value is -2147483648 we can't change it to the
|
||||
2147483648 because the max value which can be held is 2147483647
|
||||
|
@ -119,13 +116,12 @@ public:
|
|||
(if we look on our value without the sign we get the correct value
|
||||
eg. -2147483648 in Int<1> will be 2147483648 on the UInt<1> type)
|
||||
*/
|
||||
if( operator==(temp) )
|
||||
if( UInt<value_size>::IsOnlyTheHighestBitSet() )
|
||||
return 1;
|
||||
|
||||
temp.SetZero();
|
||||
temp.UInt<value_size>::Sub(*this);
|
||||
|
||||
operator=(temp);
|
||||
UInt<value_size> temp(*this);
|
||||
UInt<value_size>::SetZero();
|
||||
UInt<value_size>::Sub(temp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -350,33 +346,11 @@ public:
|
|||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
/*!
|
||||
multiplication this = this * ss2
|
||||
|
||||
it returns carry if the result is too big
|
||||
(we're using the method from the base class but we have to make
|
||||
one correction in account of signs)
|
||||
*/
|
||||
uint Mul(Int<value_size> ss2)
|
||||
uint CheckMinCarry(bool ss1_is_sign, bool ss2_is_sign)
|
||||
{
|
||||
bool ss1_is_sign, ss2_is_sign;
|
||||
|
||||
ss1_is_sign = IsSign();
|
||||
ss2_is_sign = ss2.IsSign();
|
||||
|
||||
/*
|
||||
we don't have to check the carry from Abs (values will be correct
|
||||
because next we're using the method Mul from the base class UInt
|
||||
which is without a sign)
|
||||
*/
|
||||
Abs();
|
||||
ss2.Abs();
|
||||
|
||||
if( UInt<value_size>::Mul(ss2) )
|
||||
return 1;
|
||||
|
||||
|
||||
/*
|
||||
we have to examine the sign of the result now
|
||||
but if the result is with the sign then:
|
||||
|
@ -391,36 +365,100 @@ public:
|
|||
*/
|
||||
if( IsSign() )
|
||||
{
|
||||
/*
|
||||
there can be one case where signs are different and
|
||||
the result will be equal the value from SetMin()
|
||||
(this situation is ok)
|
||||
*/
|
||||
if( ss1_is_sign != ss2_is_sign )
|
||||
{
|
||||
Int<value_size> temp;
|
||||
temp.SetMin();
|
||||
|
||||
if( operator!=(temp) )
|
||||
/*
|
||||
the result is too big
|
||||
*/
|
||||
/*
|
||||
there can be one case where signs are different and
|
||||
the result will be equal the value from SetMin() (only the highest bit is set)
|
||||
(this situation is ok)
|
||||
*/
|
||||
if( !UInt<value_size>::IsOnlyTheHighestBitSet() )
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
the result is too big
|
||||
*/
|
||||
// signs were the same
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/*!
|
||||
multiplication: this = this * ss2
|
||||
|
||||
it can return a carry
|
||||
*/
|
||||
uint MulInt(sint ss2)
|
||||
{
|
||||
bool ss1_is_sign, ss2_is_sign;
|
||||
uint c;
|
||||
|
||||
ss1_is_sign = IsSign();
|
||||
|
||||
/*
|
||||
we don't have to check the carry from Abs (values will be correct
|
||||
because next we're using the method MulInt from the base class UInt
|
||||
which is without a sign)
|
||||
*/
|
||||
Abs();
|
||||
|
||||
if( ss2 < 0 )
|
||||
{
|
||||
ss2 = -ss2;
|
||||
ss2_is_sign = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss2_is_sign = false;
|
||||
}
|
||||
|
||||
c = UInt<value_size>::MulInt((uint)ss2);
|
||||
c += CheckMinCarry(ss1_is_sign, ss2_is_sign);
|
||||
|
||||
if( ss1_is_sign != ss2_is_sign )
|
||||
SetSign();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
/*!
|
||||
multiplication this = this * ss2
|
||||
|
||||
it returns carry if the result is too big
|
||||
(we're using the method from the base class but we have to make
|
||||
one correction in account of signs)
|
||||
*/
|
||||
uint Mul(Int<value_size> ss2)
|
||||
{
|
||||
bool ss1_is_sign, ss2_is_sign;
|
||||
uint c;
|
||||
|
||||
ss1_is_sign = IsSign();
|
||||
ss2_is_sign = ss2.IsSign();
|
||||
|
||||
/*
|
||||
we don't have to check the carry from Abs (values will be correct
|
||||
because next we're using the method Mul from the base class UInt
|
||||
which is without a sign)
|
||||
*/
|
||||
Abs();
|
||||
ss2.Abs();
|
||||
|
||||
c = UInt<value_size>::Mul(ss2);
|
||||
c += CheckMinCarry(ss1_is_sign, ss2_is_sign);
|
||||
|
||||
if( ss1_is_sign != ss2_is_sign )
|
||||
SetSign();
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -56,11 +56,13 @@
|
|||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
|
||||
/*!
|
||||
the version of the library
|
||||
|
||||
TTMATH_PRERELEASE_VER is either zero or one
|
||||
if zero that means this is the release version of the library
|
||||
(one means something like beta)
|
||||
*/
|
||||
#define TTMATH_MAJOR_VER 0
|
||||
#define TTMATH_MINOR_VER 9
|
||||
|
@ -68,58 +70,66 @@
|
|||
#define TTMATH_PRERELEASE_VER 1
|
||||
|
||||
|
||||
/*!
|
||||
TTMATH_DEBUG
|
||||
this macro enables further testing during writing your code
|
||||
you don't have to define it in a release mode
|
||||
|
||||
if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
|
||||
are set as well and these macros can throw an exception if a condition in it
|
||||
is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
|
||||
|
||||
TTMATH_RELEASE
|
||||
if you are confident that your code is perfect you can define TTMATH_RELEASE
|
||||
macro for example by using -D option in gcc
|
||||
gcc -DTTMATH_RELEASE -o myprogram myprogram.cpp
|
||||
or by defining this macro in your code before using any header files of this library
|
||||
#if !defined TTMATH_PLATFORM32 && !defined TTMATH_PLATFORM64
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
/*
|
||||
other platforms than x86 and amd64 are not recognized at the moment
|
||||
so you should set TTMATH_PLATFORMxx manually
|
||||
*/
|
||||
|
||||
/*!
|
||||
we're using a 32bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM32
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
we're using a 64bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM64
|
||||
|
||||
#endif
|
||||
|
||||
if TTMATH_RELEASE is not set then TTMATH_DEBUG is set automatically
|
||||
*/
|
||||
#ifndef TTMATH_RELEASE
|
||||
#define TTMATH_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined __i386__ && !defined _X86_ && !defined _M_IX86 && !defined __x86_64__ && !defined _M_X64
|
||||
/*!
|
||||
x86 architecture:
|
||||
__i386__ defined by GNU C
|
||||
_X86_ defined by MinGW32
|
||||
_M_IX86 defined by Visual Studio, Intel C/C++, Digital Mars and Watcom C/C++
|
||||
|
||||
amd64 architecture:
|
||||
__x86_64__ defined by GNU C and Sun Studio
|
||||
_M_X64 defined by Visual Studio
|
||||
|
||||
asm version is available only for x86 or amd64 platforms
|
||||
*/
|
||||
#define TTMATH_NOASM
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if !defined _MSC_VER && !defined __GNUC__
|
||||
/*!
|
||||
another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
|
||||
*/
|
||||
#define TTMATH_NOASM
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ttmath
|
||||
{
|
||||
|
||||
#if !defined _M_X64 && !defined __x86_64__
|
||||
|
||||
/*!
|
||||
we're using a 32bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM32
|
||||
|
||||
#else
|
||||
|
||||
/*!
|
||||
we're using a 64bit platform
|
||||
*/
|
||||
#define TTMATH_PLATFORM64
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
another compilers than MS VC or GCC by default use no asm version (TTMATH_NOASM)
|
||||
*/
|
||||
#if !defined _MSC_VER && !defined __GNUC__
|
||||
#define TTMATH_NOASM
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
|
@ -596,8 +606,21 @@ namespace ttmath
|
|||
|
||||
|
||||
/*!
|
||||
look at the description of macros TTMATH_RELEASE and TTMATH_DEBUG
|
||||
TTMATH_DEBUG
|
||||
this macro enables further testing during writing your code
|
||||
you don't have to define it in a release mode
|
||||
|
||||
if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
|
||||
are set as well and these macros can throw an exception if a condition in it
|
||||
is not fulfilled (look at the definition of TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT)
|
||||
|
||||
TTMATH_DEBUG is set automatically if DEBUG or _DEBUG are defined
|
||||
*/
|
||||
#if defined DEBUG || defined _DEBUG
|
||||
#define TTMATH_DEBUG
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TTMATH_DEBUG
|
||||
|
||||
#if defined(__FILE__) && defined(__LINE__)
|
||||
|
|
|
@ -233,6 +233,19 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method swappes this for an argument
|
||||
*/
|
||||
void Swap(UInt<value_size> & ss2)
|
||||
{
|
||||
for(uint i=0 ; i<value_size ; ++i)
|
||||
{
|
||||
uint temp = table[i];
|
||||
table[i] = ss2.table[i];
|
||||
ss2.table[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef TTMATH_PLATFORM32
|
||||
|
||||
|
@ -2391,6 +2404,38 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
returning true if only the highest bit is set
|
||||
*/
|
||||
bool IsOnlyTheHighestBitSet() const
|
||||
{
|
||||
for(uint i=0 ; i<value_size-1 ; ++i)
|
||||
if( table[i] != 0 )
|
||||
return false;
|
||||
|
||||
if( table[value_size-1] != TTMATH_UINT_HIGHEST_BIT )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
returning true if only the lowest bit is set
|
||||
*/
|
||||
bool IsOnlyTheLowestBitSet() const
|
||||
{
|
||||
if( table[0] != 1 )
|
||||
return false;
|
||||
|
||||
for(uint i=1 ; i<value_size ; ++i)
|
||||
if( table[i] != 0 )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
this method returns true if the value is equal zero
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue