fixed the problem with a sign in the mathematical parser /-(1) was 1/
added UInt::AddInt and UInt::SubInt changed UInt::AddOne and UInt::SubOne (much faster now) added UInt::SetBitInWord changed UInt::SetBit (much faster now) UInt::AddTwoUints renamed to UInt::AddTwoInts UInt::FindLeadingBit32 renamed to UInt::FindLeadingBitInWord added UInt::SetBitInWord UInt::Mul64 renamed to UInt::MulTwoWords UInt::Div64 renamed to UInt::DivTwoWords and more small changes in UInt type start adding support for Amd64 (not finished yet) (added ttmathuint64.h) git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@12 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
1dabd725cb
commit
b59de36095
14
CHANGELOG
14
CHANGELOG
|
@ -1,3 +1,17 @@
|
||||||
|
Version 0.6.4 (2007.01.29):
|
||||||
|
* fixed the problem with a sign in the mathematical parser /-(1) was 1/
|
||||||
|
* added UInt::AddInt and UInt::SubInt
|
||||||
|
* changed UInt::AddOne and UInt::SubOne (much faster now)
|
||||||
|
* added UInt::SetBitInWord
|
||||||
|
* changed UInt::SetBit (much faster now)
|
||||||
|
* UInt::AddTwoUints renamed to UInt::AddTwoInts
|
||||||
|
* UInt::FindLeadingBit32 renamed to UInt::FindLeadingBitInWord
|
||||||
|
* added UInt::SetBitInWord
|
||||||
|
* UInt::Mul64 renamed to UInt::MulTwoWords
|
||||||
|
* UInt::Div64 renamed to UInt::DivTwoWords
|
||||||
|
* and more small changes in UInt type
|
||||||
|
* start adding support for Amd64 (not finished yet) (added ttmathuint64.h)
|
||||||
|
|
||||||
Version 0.6.3 (2007.01.22):
|
Version 0.6.3 (2007.01.22):
|
||||||
* position of arguments (x and base) in logarithm functions are swapped
|
* position of arguments (x and base) in logarithm functions are swapped
|
||||||
* it's possible to use any multiplication algorithms in the same time
|
* it's possible to use any multiplication algorithms in the same time
|
||||||
|
|
|
@ -378,11 +378,11 @@ namespace ttmath
|
||||||
d_denominator = one;
|
d_denominator = one;
|
||||||
}
|
}
|
||||||
|
|
||||||
int c = 0;
|
uint c = 0;
|
||||||
bool addition = false;
|
bool addition = false;
|
||||||
|
|
||||||
old_result = result;
|
old_result = result;
|
||||||
for(int i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
|
||||||
{
|
{
|
||||||
// we're starting from a second part of the formula
|
// we're starting from a second part of the formula
|
||||||
c += numerator. Mul( d_numerator );
|
c += numerator. Mul( d_numerator );
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace ttmath
|
||||||
/*!
|
/*!
|
||||||
\brief it implements the big value
|
\brief it implements the big value
|
||||||
*/
|
*/
|
||||||
template <int exp,int man>
|
template <uint exp,uint man>
|
||||||
class Big
|
class Big
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ public:
|
||||||
// (first is the highest word)
|
// (first is the highest word)
|
||||||
|
|
||||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
|
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
|
||||||
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 2;
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||||
info = 0;
|
info = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ public:
|
||||||
void Set05Pi()
|
void Set05Pi()
|
||||||
{
|
{
|
||||||
SetPi();
|
SetPi();
|
||||||
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 1;
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ public:
|
||||||
void Set2Pi()
|
void Set2Pi()
|
||||||
{
|
{
|
||||||
SetPi();
|
SetPi();
|
||||||
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 3;
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
|
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
|
||||||
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 2;
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT) + 2;
|
||||||
info = 0;
|
info = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
|
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
|
||||||
exponent = -int(man)*int(TTMATH_BITS_PER_UINT);
|
exponent = -sint(man)*sint(TTMATH_BITS_PER_UINT);
|
||||||
info = 0;
|
info = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,7 @@ public:
|
||||||
{
|
{
|
||||||
Int<exp> exp_offset( exponent );
|
Int<exp> exp_offset( exponent );
|
||||||
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
|
||||||
int c = 0;
|
uint c = 0;
|
||||||
|
|
||||||
exp_offset.Sub( ss2.exponent );
|
exp_offset.Sub( ss2.exponent );
|
||||||
exp_offset.Abs();
|
exp_offset.Abs();
|
||||||
|
@ -475,7 +475,7 @@ public:
|
||||||
TTMATH_REFERENCE_ASSERT( ss2 )
|
TTMATH_REFERENCE_ASSERT( ss2 )
|
||||||
|
|
||||||
UInt<man*2> man_result;
|
UInt<man*2> man_result;
|
||||||
int i,c;
|
uint i,c;
|
||||||
|
|
||||||
// man_result = mantissa * ss2.mantissa
|
// man_result = mantissa * ss2.mantissa
|
||||||
mantissa.MulBig(ss2.mantissa, man_result);
|
mantissa.MulBig(ss2.mantissa, man_result);
|
||||||
|
@ -635,15 +635,16 @@ public:
|
||||||
*/
|
*/
|
||||||
bool Mod2() const
|
bool Mod2() const
|
||||||
{
|
{
|
||||||
if( exponent>int(0) || exponent<=-int(man*TTMATH_BITS_PER_UINT) )
|
if( exponent>sint(0) || exponent<=-sint(man*TTMATH_BITS_PER_UINT) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int exp_int = exponent.ToInt();
|
sint exp_int = exponent.ToInt();
|
||||||
// 'exp_int' is negative (or zero), we set its as positive
|
// 'exp_int' is negative (or zero), we set its as positive
|
||||||
exp_int = -exp_int;
|
exp_int = -exp_int;
|
||||||
|
|
||||||
int value = mantissa.table[ exp_int / TTMATH_BITS_PER_UINT ];
|
// !!! here we'll use a new method (method for testing a bit)
|
||||||
value >>= (exp_int % TTMATH_BITS_PER_UINT);
|
uint value = mantissa.table[ exp_int / TTMATH_BITS_PER_UINT ];
|
||||||
|
value >>= (uint(exp_int) % TTMATH_BITS_PER_UINT);
|
||||||
|
|
||||||
return bool(value & 1);
|
return bool(value & 1);
|
||||||
}
|
}
|
||||||
|
@ -727,7 +728,7 @@ public:
|
||||||
2 - incorrect argument ('this' or 'pow')
|
2 - incorrect argument ('this' or 'pow')
|
||||||
*/
|
*/
|
||||||
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||||
there should be 'int Pow(const Big<exp, man> & pow)'
|
there should be 'sint Pow(const Big<exp, man> & pow)'
|
||||||
but vc2005express doesn't want to compile it perfect, that means
|
but vc2005express doesn't want to compile it perfect, that means
|
||||||
when using 'Maximize Speed /O2' the result of compilation doesn't work property
|
when using 'Maximize Speed /O2' the result of compilation doesn't work property
|
||||||
for example 10^(1/2) is a big value
|
for example 10^(1/2) is a big value
|
||||||
|
@ -740,9 +741,9 @@ public:
|
||||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
int Pow(const Big<exp, man> & pow)
|
uint Pow(const Big<exp, man> & pow)
|
||||||
#else
|
#else
|
||||||
int Pow(const Big<exp, man> pow)
|
uint Pow(const Big<exp, man> pow)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
TTMATH_REFERENCE_ASSERT( pow )
|
TTMATH_REFERENCE_ASSERT( pow )
|
||||||
|
@ -869,7 +870,7 @@ public:
|
||||||
|
|
||||||
// m will be the value of the mantissa in range (-1,1)
|
// m will be the value of the mantissa in range (-1,1)
|
||||||
Big<exp,man> m(x);
|
Big<exp,man> m(x);
|
||||||
m.exponent = -int(man*TTMATH_BITS_PER_UINT);
|
m.exponent = -sint(man*TTMATH_BITS_PER_UINT);
|
||||||
|
|
||||||
// 'e_' will be the value of '2^exponent'
|
// 'e_' will be the value of '2^exponent'
|
||||||
// e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and
|
// e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and
|
||||||
|
@ -1031,7 +1032,7 @@ public:
|
||||||
|
|
||||||
// m will be the value of the mantissa in range <1,2)
|
// m will be the value of the mantissa in range <1,2)
|
||||||
Big<exp,man> m(x);
|
Big<exp,man> m(x);
|
||||||
m.exponent = -int(man*TTMATH_BITS_PER_UINT - 1);
|
m.exponent = -sint(man*TTMATH_BITS_PER_UINT - 1);
|
||||||
LnSurrounding1(m);
|
LnSurrounding1(m);
|
||||||
|
|
||||||
Big<exp,man> exponent_temp;
|
Big<exp,man> exponent_temp;
|
||||||
|
@ -1112,22 +1113,22 @@ public:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets 'result' as the one word of type int
|
this method sets 'result' as the one word of type sint
|
||||||
|
|
||||||
if the value is too big this method returns a carry (1)
|
if the value is too big this method returns a carry (1)
|
||||||
*/
|
*/
|
||||||
uint ToInt(int & result) const
|
uint ToInt(sint & result) const
|
||||||
{
|
{
|
||||||
result = 0;
|
result = 0;
|
||||||
|
|
||||||
if( IsZero() )
|
if( IsZero() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int maxbit = -int(man*TTMATH_BITS_PER_UINT);
|
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
|
||||||
|
|
||||||
if( exponent > maxbit + int(TTMATH_BITS_PER_UINT) )
|
if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
|
||||||
// if exponent > (maxbit + int(TTMATH_BITS_PER_UINT)) the value can't be passed
|
// if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
|
||||||
// into the 'int' type (it's too big)
|
// into the 'sint' type (it's too big)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( exponent <= maxbit )
|
if( exponent <= maxbit )
|
||||||
|
@ -1136,7 +1137,7 @@ public:
|
||||||
|
|
||||||
UInt<man> mantissa_temp(mantissa);
|
UInt<man> mantissa_temp(mantissa);
|
||||||
// exponent is from a range of (-maxbit,0>
|
// exponent is from a range of (-maxbit,0>
|
||||||
int how_many_bits = exponent.ToInt();
|
sint how_many_bits = exponent.ToInt();
|
||||||
|
|
||||||
// how_many_bits is negative, we'll make it positive
|
// how_many_bits is negative, we'll make it positive
|
||||||
how_many_bits = -how_many_bits;
|
how_many_bits = -how_many_bits;
|
||||||
|
@ -1154,7 +1155,7 @@ public:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( IsSign() )
|
if( IsSign() )
|
||||||
result = -int(result);
|
result = -sint(result);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1173,10 +1174,10 @@ public:
|
||||||
if( IsZero() )
|
if( IsZero() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int maxbit = -int(man*TTMATH_BITS_PER_UINT);
|
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
|
||||||
|
|
||||||
if( exponent > maxbit + int(int_size*TTMATH_BITS_PER_UINT) )
|
if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )
|
||||||
// if exponent > (maxbit + int(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
|
// if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
|
||||||
// into the 'Int<int_size>' type (it's too big)
|
// into the 'Int<int_size>' type (it's too big)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -1185,7 +1186,7 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
UInt<man> mantissa_temp(mantissa);
|
UInt<man> mantissa_temp(mantissa);
|
||||||
int how_many_bits = exponent.ToInt();
|
sint how_many_bits = exponent.ToInt();
|
||||||
|
|
||||||
if( how_many_bits < 0 )
|
if( how_many_bits < 0 )
|
||||||
{
|
{
|
||||||
|
@ -1228,9 +1229,9 @@ public:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a method for converting 'int' to this class
|
a method for converting 'sint' to this class
|
||||||
*/
|
*/
|
||||||
void FromInt(int value)
|
void FromInt(sint value)
|
||||||
{
|
{
|
||||||
bool is_sign = false;
|
bool is_sign = false;
|
||||||
|
|
||||||
|
@ -1247,15 +1248,15 @@ public:
|
||||||
if( is_sign )
|
if( is_sign )
|
||||||
SetSign();
|
SetSign();
|
||||||
|
|
||||||
// there shouldn't be a carry because 'value' has the type 'int'
|
// there shouldn't be a carry because 'value' has the type 'sint'
|
||||||
Standardizing();
|
Standardizing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
an operator= for converting 'int' to this class
|
an operator= for converting 'sint' to this class
|
||||||
*/
|
*/
|
||||||
Big<exp, man> & operator=(int value)
|
Big<exp, man> & operator=(sint value)
|
||||||
{
|
{
|
||||||
FromInt(value);
|
FromInt(value);
|
||||||
|
|
||||||
|
@ -1264,13 +1265,29 @@ public:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a constructor for converting 'int' to this class
|
a constructor for converting 'sint' and 'uint' to this class
|
||||||
*/
|
*/
|
||||||
Big(int value)
|
Big(sint value)
|
||||||
{
|
{
|
||||||
FromInt(value);
|
FromInt(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Big(uint value)
|
||||||
|
{
|
||||||
|
FromInt( sint(value) );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined _M_X64 || defined __x86_64__
|
||||||
|
/*!
|
||||||
|
a constructor for converting 'int' to this class
|
||||||
|
(on 64bit platforms 'sint' has 64 bits and 'int' has 32 bits
|
||||||
|
*/
|
||||||
|
Big(int value)
|
||||||
|
{
|
||||||
|
FromInt( sint(value) );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
a method for converting from 'Int<int_size>' to this class
|
a method for converting from 'Int<int_size>' to this class
|
||||||
|
@ -1287,8 +1304,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
uint minimum_size = (int_size < man)? int_size : man;
|
uint minimum_size = (int_size < man)? int_size : man;
|
||||||
int compensation = (int)value.CompensationToLeft();
|
sint compensation = (sint)value.CompensationToLeft();
|
||||||
exponent = (int(int_size)-int(man)) * int(TTMATH_BITS_PER_UINT) - compensation;
|
exponent = (sint(int_size)-sint(man)) * sint(TTMATH_BITS_PER_UINT) - compensation;
|
||||||
|
|
||||||
// copying the highest words
|
// copying the highest words
|
||||||
uint i;
|
uint i;
|
||||||
|
@ -1404,8 +1421,8 @@ public:
|
||||||
uint ToString( std::string & result,
|
uint ToString( std::string & result,
|
||||||
uint base = 10,
|
uint base = 10,
|
||||||
bool always_scientific = false,
|
bool always_scientific = false,
|
||||||
int when_scientific = 15,
|
sint when_scientific = 15,
|
||||||
int max_digit_after_comma = -2 ) const
|
sint max_digit_after_comma = -2 ) const
|
||||||
{
|
{
|
||||||
static char error_overflow_msg[] = "overflow";
|
static char error_overflow_msg[] = "overflow";
|
||||||
result.erase();
|
result.erase();
|
||||||
|
@ -1647,7 +1664,18 @@ private:
|
||||||
// (LnSurrounding1() will return one immediately)
|
// (LnSurrounding1() will return one immediately)
|
||||||
uint c = Ln(x);
|
uint c = Ln(x);
|
||||||
|
|
||||||
static Big<exp,man> log_history[15] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* this is only temporarily (for testing)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// static Big<exp,man> log_history[15] = { 0l,0l,0l,0l,0l,0l,0l,0l,0l,0l,
|
||||||
|
// 0l,0l,0l,0l,0l };
|
||||||
|
static Big<exp,man> log_history[15] = { 0,0,0,0,0,0,0,0,0,0,
|
||||||
|
0,0,0,0,0 };
|
||||||
|
|
||||||
Big<exp,man> * log_value = log_history + base - 2;
|
Big<exp,man> * log_value = log_history + base - 2;
|
||||||
|
|
||||||
if( log_value->IsZero() )
|
if( log_value->IsZero() )
|
||||||
|
@ -1689,14 +1717,14 @@ private:
|
||||||
if( !exponent.IsSign() )
|
if( !exponent.IsSign() )
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( exponent <= -int(man*TTMATH_BITS_PER_UINT) )
|
if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
|
||||||
// if 'exponent' is <= than '-int(man*TTMATH_BITS_PER_UINT)'
|
// if 'exponent' is <= than '-sint(man*TTMATH_BITS_PER_UINT)'
|
||||||
// it means that we must cut the whole mantissa
|
// it means that we must cut the whole mantissa
|
||||||
// (there'll not be any of the valid bits)
|
// (there'll not be any of the valid bits)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
// e will be from (-man*TTMATH_BITS_PER_UINT, 0>
|
// e will be from (-man*TTMATH_BITS_PER_UINT, 0>
|
||||||
int e = -( exponent.ToInt() );
|
sint e = -( exponent.ToInt() );
|
||||||
mantissa.Rcr(e,0);
|
mantissa.Rcr(e,0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1717,11 +1745,11 @@ private:
|
||||||
uint ToString_CreateNewMantissaAndExponent_Base2( std::string & new_man,
|
uint ToString_CreateNewMantissaAndExponent_Base2( std::string & new_man,
|
||||||
Int<exp+1> & new_exp ) const
|
Int<exp+1> & new_exp ) const
|
||||||
{
|
{
|
||||||
for( int i=man-1 ; i>=0 ; --i )
|
for( sint i=man-1 ; i>=0 ; --i )
|
||||||
{
|
{
|
||||||
uint value = mantissa.table[i];
|
uint value = mantissa.table[i];
|
||||||
|
|
||||||
for( unsigned int bit=0 ; bit<TTMATH_BITS_PER_UINT ; ++bit )
|
for( uint bit=0 ; bit<TTMATH_BITS_PER_UINT ; ++bit )
|
||||||
{
|
{
|
||||||
if( (value & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
if( (value & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
||||||
new_man += '1';
|
new_man += '1';
|
||||||
|
@ -1776,7 +1804,7 @@ private:
|
||||||
if( new_man.empty() )
|
if( new_man.empty() )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int i = int( new_man.length() ) - 1;
|
sint i = sint( new_man.length() ) - 1;
|
||||||
bool was_carry = true;
|
bool was_carry = true;
|
||||||
|
|
||||||
for( ; i>=0 && was_carry ; --i )
|
for( ; i>=0 && was_carry ; --i )
|
||||||
|
@ -1809,12 +1837,12 @@ private:
|
||||||
this method sets the comma operator and/or puts the exponent
|
this method sets the comma operator and/or puts the exponent
|
||||||
into the string
|
into the string
|
||||||
*/
|
*/
|
||||||
int ToString_SetCommaAndExponent( std::string & new_man, uint base, Int<exp+1> & new_exp,
|
uint ToString_SetCommaAndExponent( std::string & new_man, uint base, Int<exp+1> & new_exp,
|
||||||
bool always_scientific,
|
bool always_scientific,
|
||||||
int when_scientific,
|
sint when_scientific,
|
||||||
int max_digit_after_comma ) const
|
sint max_digit_after_comma ) const
|
||||||
{
|
{
|
||||||
int carry = 0;
|
uint carry = 0;
|
||||||
|
|
||||||
if( new_man.empty() )
|
if( new_man.empty() )
|
||||||
return carry;
|
return carry;
|
||||||
|
@ -1826,14 +1854,14 @@ private:
|
||||||
// we'd like to show it in this way:
|
// we'd like to show it in this way:
|
||||||
// 3.2342343234 (the 'scientific_exp' is connected with this example)
|
// 3.2342343234 (the 'scientific_exp' is connected with this example)
|
||||||
|
|
||||||
int offset = int( new_man.length() ) - 1;
|
sint offset = sint( new_man.length() ) - 1;
|
||||||
carry += scientific_exp.Add( offset );
|
carry += scientific_exp.Add( offset );
|
||||||
// there shouldn't have been a carry because we're using
|
// there shouldn't have been a carry because we're using
|
||||||
// a greater type -- 'Int<exp+1>' instead of 'Int<exp>'
|
// a greater type -- 'Int<exp+1>' instead of 'Int<exp>'
|
||||||
|
|
||||||
if( !always_scientific )
|
if( !always_scientific )
|
||||||
{
|
{
|
||||||
if( scientific_exp > when_scientific || scientific_exp < -int(when_scientific) )
|
if( scientific_exp > when_scientific || scientific_exp < -sint(when_scientific) )
|
||||||
always_scientific = true;
|
always_scientific = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1852,9 +1880,10 @@ private:
|
||||||
an auxiliary method for converting into the string
|
an auxiliary method for converting into the string
|
||||||
*/
|
*/
|
||||||
void ToString_SetCommaAndExponent_Normal(std::string & new_man, uint base,
|
void ToString_SetCommaAndExponent_Normal(std::string & new_man, uint base,
|
||||||
Int<exp+1> & new_exp, int max_digit_after_comma) const
|
Int<exp+1> & new_exp, sint max_digit_after_comma) const
|
||||||
{
|
{
|
||||||
if( new_exp >= 0 )
|
//if( new_exp >= 0 )
|
||||||
|
if( !new_exp.IsSign() )
|
||||||
return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp);
|
return ToString_SetCommaAndExponent_Normal_AddingZero(new_man, new_exp);
|
||||||
else
|
else
|
||||||
return ToString_SetCommaAndExponent_Normal_SetCommaInside(new_man, base, new_exp, max_digit_after_comma);
|
return ToString_SetCommaAndExponent_Normal_SetCommaInside(new_man, base, new_exp, max_digit_after_comma);
|
||||||
|
@ -1884,18 +1913,18 @@ private:
|
||||||
an auxiliary method for converting into the string
|
an auxiliary method for converting into the string
|
||||||
*/
|
*/
|
||||||
void ToString_SetCommaAndExponent_Normal_SetCommaInside(std::string & new_man,
|
void ToString_SetCommaAndExponent_Normal_SetCommaInside(std::string & new_man,
|
||||||
uint base, Int<exp+1> & new_exp, int max_digit_after_comma) const
|
uint base, Int<exp+1> & new_exp, sint max_digit_after_comma) const
|
||||||
{
|
{
|
||||||
// new_exp is < 0
|
// new_exp is < 0
|
||||||
|
|
||||||
int new_man_len = int(new_man.length()); // 'new_man_len' with a sign
|
sint new_man_len = sint(new_man.length()); // 'new_man_len' with a sign
|
||||||
int e = -( new_exp.ToInt() ); // 'e' will be positive
|
sint e = -( new_exp.ToInt() ); // 'e' will be positive
|
||||||
|
|
||||||
if( new_exp > -new_man_len )
|
if( new_exp > -new_man_len )
|
||||||
{
|
{
|
||||||
// we're setting the comma within the mantissa
|
// we're setting the comma within the mantissa
|
||||||
|
|
||||||
int index = new_man_len - e;
|
sint index = new_man_len - e;
|
||||||
new_man.insert( new_man.begin() + index, TTMATH_COMMA_CHARACTER_1);
|
new_man.insert( new_man.begin() + index, TTMATH_COMMA_CHARACTER_1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1919,7 +1948,7 @@ private:
|
||||||
void ToString_SetCommaAndExponent_Scientific( std::string & new_man,
|
void ToString_SetCommaAndExponent_Scientific( std::string & new_man,
|
||||||
uint base,
|
uint base,
|
||||||
Int<exp+1> & scientific_exp,
|
Int<exp+1> & scientific_exp,
|
||||||
int max_digit_after_comma ) const
|
sint max_digit_after_comma ) const
|
||||||
{
|
{
|
||||||
if( new_man.empty() )
|
if( new_man.empty() )
|
||||||
return;
|
return;
|
||||||
|
@ -1955,7 +1984,7 @@ private:
|
||||||
we can call this method only if we've put the comma operator into the mantissa's string
|
we can call this method only if we've put the comma operator into the mantissa's string
|
||||||
*/
|
*/
|
||||||
void ToString_CorrectDigitsAfterComma(std::string & new_man, uint base,
|
void ToString_CorrectDigitsAfterComma(std::string & new_man, uint base,
|
||||||
int max_digit_after_comma) const
|
sint max_digit_after_comma) const
|
||||||
{
|
{
|
||||||
switch( max_digit_after_comma )
|
switch( max_digit_after_comma )
|
||||||
{
|
{
|
||||||
|
@ -2005,7 +2034,7 @@ private:
|
||||||
an auxiliary method for converting into the string
|
an auxiliary method for converting into the string
|
||||||
*/
|
*/
|
||||||
void ToString_CorrectDigitsAfterComma_Round(std::string & new_man, uint base,
|
void ToString_CorrectDigitsAfterComma_Round(std::string & new_man, uint base,
|
||||||
int max_digit_after_comma) const
|
sint max_digit_after_comma) const
|
||||||
{
|
{
|
||||||
// first we're looking for the comma operator
|
// first we're looking for the comma operator
|
||||||
std::string::size_type index = new_man.find(TTMATH_COMMA_CHARACTER_1, 0);
|
std::string::size_type index = new_man.find(TTMATH_COMMA_CHARACTER_1, 0);
|
||||||
|
@ -2061,7 +2090,7 @@ public:
|
||||||
if 'after_source' is set that when this method will have finished its job
|
if 'after_source' is set that when this method will have finished its job
|
||||||
it set the pointer to the new first character after this parsed value
|
it set the pointer to the new first character after this parsed value
|
||||||
*/
|
*/
|
||||||
int FromString(const char * source, uint base = 10, const char ** after_source = 0)
|
uint FromString(const char * source, uint base = 10, const char ** after_source = 0)
|
||||||
{
|
{
|
||||||
bool is_sign;
|
bool is_sign;
|
||||||
|
|
||||||
|
@ -2077,7 +2106,7 @@ public:
|
||||||
FromString_TestNewBase( source, base );
|
FromString_TestNewBase( source, base );
|
||||||
FromString_TestSign( source, is_sign );
|
FromString_TestSign( source, is_sign );
|
||||||
|
|
||||||
int c = FromString_ReadPartBeforeComma( source, base );
|
uint c = FromString_ReadPartBeforeComma( source, base );
|
||||||
|
|
||||||
if( FromString_TestCommaOperator(source) )
|
if( FromString_TestCommaOperator(source) )
|
||||||
c += FromString_ReadPartAfterComma( source, base );
|
c += FromString_ReadPartAfterComma( source, base );
|
||||||
|
@ -2170,7 +2199,7 @@ private:
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartBeforeComma( const char * & source, uint base )
|
uint FromString_ReadPartBeforeComma( const char * & source, uint base )
|
||||||
{
|
{
|
||||||
int character;
|
sint character;
|
||||||
Big<exp, man> temp;
|
Big<exp, man> temp;
|
||||||
Big<exp, man> base_( base );
|
Big<exp, man> base_( base );
|
||||||
|
|
||||||
|
@ -2197,7 +2226,8 @@ private:
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartAfterComma( const char * & source, uint base )
|
uint FromString_ReadPartAfterComma( const char * & source, uint base )
|
||||||
{
|
{
|
||||||
int character, c = 0, index = 1;
|
sint character;
|
||||||
|
uint c = 0, index = 1;
|
||||||
Big<exp, man> part, power, old_value, base_( base );
|
Big<exp, man> part, power, old_value, base_( base );
|
||||||
|
|
||||||
// we don't remove any white characters here
|
// we don't remove any white characters here
|
||||||
|
@ -2267,7 +2297,7 @@ private:
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartScientific( const char * & source )
|
uint FromString_ReadPartScientific( const char * & source )
|
||||||
{
|
{
|
||||||
int c = 0;
|
uint c = 0;
|
||||||
Big<exp, man> new_exponent, temp;
|
Big<exp, man> new_exponent, temp;
|
||||||
bool was_sign = false;
|
bool was_sign = false;
|
||||||
|
|
||||||
|
@ -2291,7 +2321,7 @@ private:
|
||||||
*/
|
*/
|
||||||
uint FromString_ReadPartScientific_ReadExponent( const char * & source, Big<exp, man> & new_exponent )
|
uint FromString_ReadPartScientific_ReadExponent( const char * & source, Big<exp, man> & new_exponent )
|
||||||
{
|
{
|
||||||
int character;
|
sint character;
|
||||||
Big<exp, man> base, temp;
|
Big<exp, man> base, temp;
|
||||||
|
|
||||||
UInt<man>::SkipWhiteCharacters(source);
|
UInt<man>::SkipWhiteCharacters(source);
|
||||||
|
@ -2320,7 +2350,7 @@ public:
|
||||||
/*!
|
/*!
|
||||||
a method for converting a string into its value
|
a method for converting a string into its value
|
||||||
*/
|
*/
|
||||||
int FromString(const std::string & string, uint base = 10)
|
uint FromString(const std::string & string, uint base = 10)
|
||||||
{
|
{
|
||||||
return FromString( string.c_str(), base );
|
return FromString( string.c_str(), base );
|
||||||
}
|
}
|
||||||
|
@ -2660,7 +2690,7 @@ public:
|
||||||
// exponent >=0 -- the value don't have any fractions
|
// exponent >=0 -- the value don't have any fractions
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if( exponent <= -int(man*TTMATH_BITS_PER_UINT) )
|
if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
|
||||||
{
|
{
|
||||||
// the value is from (-1,1), we return zero
|
// the value is from (-1,1), we return zero
|
||||||
SetZero();
|
SetZero();
|
||||||
|
@ -2668,7 +2698,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
|
// exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
|
||||||
int e = exponent.ToInt();
|
sint e = exponent.ToInt();
|
||||||
|
|
||||||
mantissa.ClearFirstBits( -e );
|
mantissa.ClearFirstBits( -e );
|
||||||
|
|
||||||
|
@ -2698,7 +2728,7 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( exponent <= -int(man*TTMATH_BITS_PER_UINT) )
|
if( exponent <= -sint(man*TTMATH_BITS_PER_UINT) )
|
||||||
{
|
{
|
||||||
// the value is from (-1,1)
|
// the value is from (-1,1)
|
||||||
// we don't make anything with the value
|
// we don't make anything with the value
|
||||||
|
@ -2706,9 +2736,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// e will be from (-man*TTMATH_BITS_PER_UINT, 0)
|
// e will be from (-man*TTMATH_BITS_PER_UINT, 0)
|
||||||
int e = exponent.ToInt();
|
sint e = exponent.ToInt();
|
||||||
|
|
||||||
int how_many_bits_leave = man*TTMATH_BITS_PER_UINT + e; // there'll be a subtraction -- e is negative
|
sint how_many_bits_leave = sint(man*TTMATH_BITS_PER_UINT) + e; // there'll be a subtraction -- e is negative
|
||||||
mantissa.Rcl( how_many_bits_leave, 0);
|
mantissa.Rcl( how_many_bits_leave, 0);
|
||||||
|
|
||||||
// there'll not be a carry because the exponent is too small
|
// there'll not be a carry because the exponent is too small
|
||||||
|
|
|
@ -465,9 +465,9 @@ public:
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method convert an int type to this class
|
this method convert an sint type to this class
|
||||||
*/
|
*/
|
||||||
Int<value_size> & operator=(int i)
|
Int<value_size> & operator=(sint i)
|
||||||
{
|
{
|
||||||
if(i<0)
|
if(i<0)
|
||||||
SetSignOne();
|
SetSignOne();
|
||||||
|
@ -483,7 +483,7 @@ public:
|
||||||
/*!
|
/*!
|
||||||
constructor for converting an uint to this class
|
constructor for converting an uint to this class
|
||||||
*/
|
*/
|
||||||
Int(int i)
|
Int(sint i)
|
||||||
{
|
{
|
||||||
operator=(i);
|
operator=(i);
|
||||||
}
|
}
|
||||||
|
@ -540,11 +540,11 @@ public:
|
||||||
this method returns the lowest value from table with the sign
|
this method returns the lowest value from table with the sign
|
||||||
|
|
||||||
we must be sure when we using this method whether the value
|
we must be sure when we using this method whether the value
|
||||||
will hold in an int type or not (the rest value from table must be zero or -1)
|
will hold in an sint type or not (the rest value from table must be zero or -1)
|
||||||
*/
|
*/
|
||||||
int ToInt() const
|
sint ToInt() const
|
||||||
{
|
{
|
||||||
return int( UInt<value_size>::table[0] );
|
return sint( UInt<value_size>::table[0] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -676,10 +676,10 @@ public:
|
||||||
|
|
||||||
bool operator<(const Int<value_size> & l) const
|
bool operator<(const Int<value_size> & l) const
|
||||||
{
|
{
|
||||||
int i=value_size-1;
|
sint i=value_size-1;
|
||||||
|
|
||||||
int a1 = int(UInt<value_size>::table[i]);
|
sint a1 = sint(UInt<value_size>::table[i]);
|
||||||
int a2 = int(l.table[i]);
|
sint a2 = sint(l.table[i]);
|
||||||
|
|
||||||
if( a1 != a2 )
|
if( a1 != a2 )
|
||||||
return a1 < a2;
|
return a1 < a2;
|
||||||
|
@ -703,11 +703,11 @@ public:
|
||||||
|
|
||||||
bool operator>(const Int<value_size> & l) const
|
bool operator>(const Int<value_size> & l) const
|
||||||
{
|
{
|
||||||
int i=value_size-1;
|
sint i=value_size-1;
|
||||||
|
|
||||||
|
|
||||||
int a1 = int(UInt<value_size>::table[i]);
|
sint a1 = sint(UInt<value_size>::table[i]);
|
||||||
int a2 = int(l.table[i]);
|
sint a2 = sint(l.table[i]);
|
||||||
|
|
||||||
if( a1 != a2 )
|
if( a1 != a2 )
|
||||||
return a1 > a2;
|
return a1 > a2;
|
||||||
|
@ -730,11 +730,11 @@ public:
|
||||||
|
|
||||||
bool operator<=(const Int<value_size> & l) const
|
bool operator<=(const Int<value_size> & l) const
|
||||||
{
|
{
|
||||||
int i=value_size-1;
|
sint i=value_size-1;
|
||||||
|
|
||||||
|
|
||||||
int a1 = int(UInt<value_size>::table[i]);
|
sint a1 = sint(UInt<value_size>::table[i]);
|
||||||
int a2 = int(l.table[i]);
|
sint a2 = sint(l.table[i]);
|
||||||
|
|
||||||
if( a1 != a2 )
|
if( a1 != a2 )
|
||||||
return a1 < a2;
|
return a1 < a2;
|
||||||
|
@ -757,11 +757,11 @@ public:
|
||||||
|
|
||||||
bool operator>=(const Int<value_size> & l) const
|
bool operator>=(const Int<value_size> & l) const
|
||||||
{
|
{
|
||||||
int i=value_size-1;
|
sint i=value_size-1;
|
||||||
|
|
||||||
|
|
||||||
int a1 = int(UInt<value_size>::table[i]);
|
sint a1 = sint(UInt<value_size>::table[i]);
|
||||||
int a2 = int(l.table[i]);
|
sint a2 = sint(l.table[i]);
|
||||||
|
|
||||||
if( a1 != a2 )
|
if( a1 != a2 )
|
||||||
return a1 > a2;
|
return a1 > a2;
|
||||||
|
|
|
@ -1373,9 +1373,14 @@ int index;
|
||||||
// 'index' will be greater than zero
|
// 'index' will be greater than zero
|
||||||
// 'amount_of_parameters' can be zero
|
// 'amount_of_parameters' can be zero
|
||||||
|
|
||||||
|
|
||||||
if( amount_of_parameters==0 && !stack[index-1].function )
|
if( amount_of_parameters==0 && !stack[index-1].function )
|
||||||
Error( err_unexpected_final_bracket );
|
Error( err_unexpected_final_bracket );
|
||||||
|
|
||||||
|
|
||||||
|
bool was_sign = stack[index-1].sign;
|
||||||
|
|
||||||
|
|
||||||
if( stack[index-1].function )
|
if( stack[index-1].function )
|
||||||
{
|
{
|
||||||
// the result of a function will be on 'stack[index-1]'
|
// the result of a function will be on 'stack[index-1]'
|
||||||
|
@ -1402,11 +1407,10 @@ int index;
|
||||||
if there was a '-' character before the first bracket
|
if there was a '-' character before the first bracket
|
||||||
we change the sign of the expression
|
we change the sign of the expression
|
||||||
*/
|
*/
|
||||||
if( stack[index-1].sign )
|
stack[index-1].sign = false;
|
||||||
{
|
|
||||||
|
if( was_sign )
|
||||||
stack[index-1].value.ChangeSign();
|
stack[index-1].value.ChangeSign();
|
||||||
stack[index-1].sign = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
stack[index-1].type = Item::numerical_value;
|
stack[index-1].type = Item::numerical_value;
|
||||||
|
|
||||||
|
@ -1676,7 +1680,7 @@ ErrorCode Parse(const char * str)
|
||||||
|
|
||||||
stack.resize( default_stack_size );
|
stack.resize( default_stack_size );
|
||||||
|
|
||||||
// char buf_temp[] = "1111";
|
// char buf_temp[] = "-(1)";
|
||||||
// pstring = buf_temp;
|
// pstring = buf_temp;
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
*/
|
*/
|
||||||
#define TTMATH_MAJOR_VER 0
|
#define TTMATH_MAJOR_VER 0
|
||||||
#define TTMATH_MINOR_VER 6
|
#define TTMATH_MINOR_VER 6
|
||||||
#define TTMATH_REVISION_VER 3
|
#define TTMATH_REVISION_VER 4
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -86,34 +86,71 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
VC doesn't have these macros
|
||||||
|
#if !defined(__i386__) && !defined(__amd64__)
|
||||||
|
#error "This code is designed only for x86/amd64 platforms (amd64 is very experimental now)"
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
namespace ttmath
|
namespace ttmath
|
||||||
{
|
{
|
||||||
/*!
|
/*!
|
||||||
32 bit integer value without a sign
|
on 32bit platforms one word will be equal 32bits
|
||||||
(on 64bit platforms will be 32bit as well)
|
on 64bit platforms one word will be 64bits
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if !defined _M_X64 && !defined __x86_64__
|
||||||
|
|
||||||
typedef unsigned int uint;
|
typedef unsigned int uint;
|
||||||
|
typedef signed int sint;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
how many bits there are in the uint type
|
||||||
|
*/
|
||||||
|
#define TTMATH_BITS_PER_UINT 32u
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the mask for the highest bit in the unsigned 32bit word (2^31)
|
||||||
|
*/
|
||||||
|
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the max value of the unsigned 32bit word (2^32 - 1)
|
||||||
|
(all bits equal one)
|
||||||
|
*/
|
||||||
|
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef unsigned long uint;
|
||||||
|
typedef signed long sint;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
how many bits there are in the uint type
|
||||||
|
*/
|
||||||
|
#define TTMATH_BITS_PER_UINT 64ul
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the mask for the highest bit in the unsigned 64bit word (2^63)
|
||||||
|
*/
|
||||||
|
#define TTMATH_UINT_HIGHEST_BIT 9223372036854775808ul
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
the max value of the unsigned 64bit word (2^64 - 1)
|
||||||
|
(all bits equal one)
|
||||||
|
*/
|
||||||
|
#define TTMATH_UINT_MAX_VALUE 18446744073709551615ul
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
how many bits there are in the uint type
|
|
||||||
*/
|
|
||||||
#define TTMATH_BITS_PER_UINT 32u
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
the mask for the highest bit in the unsigned 32bit word (2^31)
|
|
||||||
*/
|
|
||||||
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
|
||||||
the max value of the unsigned 32bit word (2^32 - 1)
|
|
||||||
(all bits equal one)
|
|
||||||
*/
|
|
||||||
#define TTMATH_UINT_MAX_VALUE 4294967295u
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
characters which represent the comma operator
|
characters which represent the comma operator
|
||||||
|
@ -304,19 +341,23 @@ namespace ttmath
|
||||||
|
|
||||||
|
|
||||||
#ifdef TTMATH_DEBUG
|
#ifdef TTMATH_DEBUG
|
||||||
#ifdef __GNUC__
|
|
||||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
|
||||||
if( &(expression) == this ) throw ReferenceError(__FILE__, __LINE__);
|
|
||||||
|
|
||||||
#define TTMATH_ASSERT(expression) \
|
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||||
if( !(expression) ) throw RuntimeError(__FILE__, __LINE__);
|
if( &(expression) == this ) throw ttmath::ReferenceError(__FILE__, __LINE__);
|
||||||
#else
|
|
||||||
#define TTMATH_REFERENCE_ASSERT(expression) \
|
|
||||||
if( &(expression) == this ) throw ReferenceError();
|
|
||||||
|
|
||||||
#define TTMATH_ASSERT(expression) \
|
#define TTMATH_ASSERT(expression) \
|
||||||
if( !(expression) ) throw RuntimeError();
|
if( !(expression) ) throw ttmath::RuntimeError(__FILE__, __LINE__);
|
||||||
#endif
|
|
||||||
|
/*
|
||||||
|
if your compiler doesn't support macros __FILE__ and __LINE__
|
||||||
|
you can above asserts change to:
|
||||||
|
|
||||||
|
#define TTMATH_REFERENCE_ASSERT(expression) \
|
||||||
|
if( &(expression) == this ) throw ReferenceError();
|
||||||
|
|
||||||
|
#define TTMATH_ASSERT(expression) \
|
||||||
|
if( !(expression) ) throw RuntimeError();
|
||||||
|
*/
|
||||||
#else
|
#else
|
||||||
#define TTMATH_REFERENCE_ASSERT(expression)
|
#define TTMATH_REFERENCE_ASSERT(expression)
|
||||||
#define TTMATH_ASSERT(expression)
|
#define TTMATH_ASSERT(expression)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,855 @@
|
||||||
|
/*
|
||||||
|
* This file is a part of TTMath Mathematical Library
|
||||||
|
* and is distributed under the (new) BSD licence.
|
||||||
|
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2007, Tomasz Sowa
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* * Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* * Neither the name Tomasz Sowa nor the names of contributors to this
|
||||||
|
* project may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\file ttmathuint.h
|
||||||
|
\brief template class UInt<uint> for 64bit processors
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
namespace ttmath
|
||||||
|
{
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* basic mathematic functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined _M_X64 || defined __x86_64__
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adding ss2 to the this and adding carry if it's defined
|
||||||
|
(this = this + ss2 + c)
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
register uint b = value_size;
|
||||||
|
register uint * p1 = table;
|
||||||
|
register uint * p2 = const_cast<uint*>(ss2.table);
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
/*
|
||||||
|
this part might be compiled with for example visual c
|
||||||
|
*/
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
/*
|
||||||
|
this part should be compiled with gcc
|
||||||
|
*/
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rbx \n"
|
||||||
|
"push %%rcx \n"
|
||||||
|
"push %%rdx \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"subq %%rsi, %%rax \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"movq (%%rbx),%%rax \n"
|
||||||
|
"adcq (%%rdx),%%rax \n"
|
||||||
|
"movq %%rax,(%%rbx) \n"
|
||||||
|
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
|
||||||
|
"loop 1b \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"adcq %%rax,%%rax \n"
|
||||||
|
"movq %%rax, %%rsi \n"
|
||||||
|
|
||||||
|
"pop %%rdx \n"
|
||||||
|
"pop %%rcx \n"
|
||||||
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
: "=S" (c)
|
||||||
|
: "0" (c), "c" (b), "b" (p1), "d" (p2)
|
||||||
|
: "%rax", "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
AddInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 + 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[3] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
register uint b = value_size;
|
||||||
|
register uint * p1 = table;
|
||||||
|
register uint c;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
"push %%rbx \n"
|
||||||
|
"push %%rcx \n"
|
||||||
|
"push %%rdx \n"
|
||||||
|
|
||||||
|
"subq %%rdx, %%rcx \n"
|
||||||
|
|
||||||
|
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
||||||
|
|
||||||
|
"movq %4, %%rdx \n"
|
||||||
|
"clc \n"
|
||||||
|
"1: \n"
|
||||||
|
|
||||||
|
"movq (%%rbx), %%rax \n"
|
||||||
|
"adcq %%rdx, %%rax \n"
|
||||||
|
"movq %%rax, (%%rbx) \n"
|
||||||
|
|
||||||
|
"jnc 2f \n"
|
||||||
|
|
||||||
|
"movq $0, %%rdx \n"
|
||||||
|
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
|
||||||
|
"loop 1b \n"
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"adcq %%rax,%%rax \n"
|
||||||
|
|
||||||
|
"pop %%rdx \n"
|
||||||
|
"pop %%rcx \n"
|
||||||
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
: "=a" (c)
|
||||||
|
: "c" (b), "d" (index), "b" (p1), "q" (value)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method adds only two unsigned words to the existing value
|
||||||
|
and these words begin on the 'index' position
|
||||||
|
(it's used in the multiplication algorithm 2)
|
||||||
|
|
||||||
|
index should be equal or smaller than value_size-2 (index <= value_size-2)
|
||||||
|
x1 - lower word, x2 - higher word
|
||||||
|
|
||||||
|
for example if we've got value_size equal 4 and:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4
|
||||||
|
table[2] = 5
|
||||||
|
table[3] = 6
|
||||||
|
then let
|
||||||
|
x1 = 10
|
||||||
|
x2 = 20
|
||||||
|
and
|
||||||
|
index = 1
|
||||||
|
|
||||||
|
the result of this method will be:
|
||||||
|
table[0] = 3
|
||||||
|
table[1] = 4 + x1 = 14
|
||||||
|
table[2] = 5 + x2 = 25
|
||||||
|
table[3] = 6
|
||||||
|
|
||||||
|
and no carry at the end of table[3]
|
||||||
|
|
||||||
|
(of course if there was a carry in table[2](5+20) then
|
||||||
|
this carry would be passed to the table[3] etc.)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::AddTwoInts(uint index, uint x2, uint x1)
|
||||||
|
{
|
||||||
|
register uint b = value_size;
|
||||||
|
register uint * p1 = table;
|
||||||
|
register uint c;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rbx \n"
|
||||||
|
"push %%rcx \n"
|
||||||
|
"push %%rdx \n"
|
||||||
|
|
||||||
|
"subq %%rdx, %%rcx \n"
|
||||||
|
|
||||||
|
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
||||||
|
|
||||||
|
"movq $0, %%rdx \n"
|
||||||
|
|
||||||
|
"movq (%%rbx), %%rax \n"
|
||||||
|
"addq %4, %%rax \n"
|
||||||
|
"movq %%rax, (%%rbx) \n"
|
||||||
|
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
|
||||||
|
"movq (%%rbx), %%rax \n"
|
||||||
|
"adcq %5, %%rax \n"
|
||||||
|
"movq %%rax, (%%rbx) \n"
|
||||||
|
"jnc 2f \n"
|
||||||
|
|
||||||
|
"dec %%rcx \n"
|
||||||
|
"dec %%rcx \n"
|
||||||
|
"jz 2f \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
|
||||||
|
"movq (%%rbx), %%rax \n"
|
||||||
|
"adcq %%rdx, %%rax \n"
|
||||||
|
"movq %%rax, (%%rbx) \n"
|
||||||
|
|
||||||
|
"jnc 2f \n"
|
||||||
|
|
||||||
|
"loop 1b \n"
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"adcq %%rax,%%rax \n"
|
||||||
|
|
||||||
|
"pop %%rdx \n"
|
||||||
|
"pop %%rcx \n"
|
||||||
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
: "=a" (c)
|
||||||
|
: "c" (b), "d" (index), "b" (p1), "q" (x1), "q" (x2)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method's subtracting ss2 from the 'this' and subtracting
|
||||||
|
carry if it has been defined
|
||||||
|
(this = this - ss2 - c)
|
||||||
|
|
||||||
|
c must be zero or one (might be a bigger value than 1)
|
||||||
|
function returns carry (1) (if it was)
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
|
||||||
|
{
|
||||||
|
register uint b = value_size;
|
||||||
|
register uint * p1 = table;
|
||||||
|
register uint * p2 = const_cast<uint*>(ss2.table);
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rbx \n"
|
||||||
|
"push %%rcx \n"
|
||||||
|
"push %%rdx \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"subq %%rsi, %%rax \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"movq (%%rbx),%%rax \n"
|
||||||
|
"sbbq (%%rdx),%%rax \n"
|
||||||
|
"movq %%rax,(%%rbx) \n"
|
||||||
|
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
"inc %%rdx \n"
|
||||||
|
|
||||||
|
"loop 1b \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"adcq %%rax,%%rax \n"
|
||||||
|
"movq %%rax, %%rsi \n"
|
||||||
|
|
||||||
|
"pop %%rdx \n"
|
||||||
|
"pop %%rcx \n"
|
||||||
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
: "=S" (c)
|
||||||
|
: "0" (c), "c" (b), "b" (p1), "d" (p2)
|
||||||
|
: "%rax", "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method subtracts one word (at a specific position)
|
||||||
|
and returns a carry (if it was)
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
|
||||||
|
if we've got (value_size=3):
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30;
|
||||||
|
table[2] = 5;
|
||||||
|
and we call:
|
||||||
|
SubInt(2,1)
|
||||||
|
then it'll be:
|
||||||
|
table[0] = 10;
|
||||||
|
table[1] = 30 - 2;
|
||||||
|
table[2] = 5;
|
||||||
|
|
||||||
|
of course if there was a carry from table[3] it would be returned
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SubInt(uint value, uint index)
|
||||||
|
{
|
||||||
|
register uint b = value_size;
|
||||||
|
register uint * p1 = table;
|
||||||
|
register uint c;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rbx \n"
|
||||||
|
"push %%rcx \n"
|
||||||
|
"push %%rdx \n"
|
||||||
|
|
||||||
|
"subq %%rdx, %%rcx \n"
|
||||||
|
|
||||||
|
"leaq (%%rbx,%%rdx,8), %%rbx \n"
|
||||||
|
|
||||||
|
"movq %4, %%rdx \n"
|
||||||
|
"clc \n"
|
||||||
|
"1: \n"
|
||||||
|
|
||||||
|
"movq (%%rbx), %%rax \n"
|
||||||
|
"sbbq %%rdx, %%rax \n"
|
||||||
|
"movq %%rax, (%%rbx) \n"
|
||||||
|
|
||||||
|
"jnc 2f \n"
|
||||||
|
|
||||||
|
"movq $0, %%rdx \n"
|
||||||
|
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
|
||||||
|
"loop 1b \n"
|
||||||
|
|
||||||
|
"2: \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"adcq %%rax,%%rax \n"
|
||||||
|
|
||||||
|
"pop %%rdx \n"
|
||||||
|
"pop %%rcx \n"
|
||||||
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
: "=a" (c)
|
||||||
|
: "c" (b), "d" (index), "b" (p1), "q" (value)
|
||||||
|
: "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moving once all bits into the left side
|
||||||
|
return value <- this <- C
|
||||||
|
|
||||||
|
the lowest bit will hold value of 'c' and
|
||||||
|
function returns the highest bit
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcl(uint c)
|
||||||
|
{
|
||||||
|
register sint b = value_size;
|
||||||
|
register uint * p1 = table;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rbx \n"
|
||||||
|
"push %%rcx \n"
|
||||||
|
|
||||||
|
"movq $0,%%rax \n"
|
||||||
|
"subq %%rdx,%%rax \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"rclq $1,(%%rbx) \n"
|
||||||
|
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
"inc %%rbx \n"
|
||||||
|
|
||||||
|
"loop 1b \n"
|
||||||
|
|
||||||
|
"movq $0, %%rdx \n"
|
||||||
|
"adcq %%rdx,%%rdx \n"
|
||||||
|
|
||||||
|
"pop %%rcx \n"
|
||||||
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
: "=d" (c)
|
||||||
|
: "0" (c), "c" (b), "b" (p1)
|
||||||
|
: "%rax", "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method moving once all bits into the right side
|
||||||
|
C -> *this -> return value
|
||||||
|
|
||||||
|
the highest bit will be held value of 'c' and
|
||||||
|
function returns the lowest bit
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::Rcr(uint c)
|
||||||
|
{
|
||||||
|
register sint b = value_size;
|
||||||
|
register uint * p1 = table;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"push %%rbx \n"
|
||||||
|
"push %%rcx \n"
|
||||||
|
|
||||||
|
"leaq (%%rbx,%%rcx,8),%%rbx \n"
|
||||||
|
|
||||||
|
"movq $0, %%rax \n"
|
||||||
|
"subq %%rdx, %%rax \n"
|
||||||
|
|
||||||
|
"1: \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
"dec %%rbx \n"
|
||||||
|
|
||||||
|
"rcrq $1,(%%rbx) \n"
|
||||||
|
|
||||||
|
"loop 1b \n"
|
||||||
|
|
||||||
|
"movq $0, %%rdx \n"
|
||||||
|
"adcq %%rdx,%%rdx \n"
|
||||||
|
|
||||||
|
"pop %%rcx \n"
|
||||||
|
"pop %%rbx \n"
|
||||||
|
|
||||||
|
: "=d" (c)
|
||||||
|
: "0" (c), "c" (b), "b" (p1)
|
||||||
|
: "%rax", "cc", "memory" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
this method returns the number of the highest set bit in one 32-bit word
|
||||||
|
if the 'x' is zero this method returns '-1'
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
sint UInt<value_size>::FindLeadingBitInWord(uint x)
|
||||||
|
{
|
||||||
|
register sint result;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
|
||||||
|
"bsrq %%rbx, %%rax \n"
|
||||||
|
"jnz 1f \n"
|
||||||
|
"movq $-1, %%rax \n"
|
||||||
|
"1: \n"
|
||||||
|
|
||||||
|
: "=a" (result)
|
||||||
|
: "b" (x)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets a special bit in the 'value'
|
||||||
|
and returns the result
|
||||||
|
|
||||||
|
bit is from <0,31>
|
||||||
|
|
||||||
|
e.g.
|
||||||
|
SetBitInWord(0,0) = 1
|
||||||
|
SetBitInWord(0,2) = 4
|
||||||
|
SetBitInWord(10, 8) = 266
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
uint UInt<value_size>::SetBitInWord(uint value, uint bit)
|
||||||
|
{
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"btsq %%rbx,%%rax \n"
|
||||||
|
|
||||||
|
: "=a" (value)
|
||||||
|
: "0" (value), "b" (bit)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Multiplication
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: result2:result1 = a * b
|
||||||
|
result2 - higher word
|
||||||
|
result1 - lower word of the result
|
||||||
|
|
||||||
|
this methos never returns a carry
|
||||||
|
|
||||||
|
it is an auxiliary method for version two of the multiplication algorithm
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result2, uint * result1)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
we must use these temporary variables in order to inform the compilator
|
||||||
|
that value pointed with result1 and result2 has changed
|
||||||
|
|
||||||
|
this has no effect in visual studio but it's usefull when
|
||||||
|
using gcc and options like -O
|
||||||
|
*/
|
||||||
|
register uint result1_;
|
||||||
|
register uint result2_;
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
asm __volatile__(
|
||||||
|
|
||||||
|
"mulq %%rdx \n"
|
||||||
|
|
||||||
|
: "=a" (result1_), "=d" (result2_)
|
||||||
|
: "0" (a), "1" (b)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
*result1 = result1_;
|
||||||
|
*result2 = result2_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
*
|
||||||
|
* Division
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
|
||||||
|
r = a:b / c and rest - remainder
|
||||||
|
|
||||||
|
*
|
||||||
|
* WARNING:
|
||||||
|
* if r (one word) is too small for the result or c is equal zero
|
||||||
|
* there'll be a hardware interruption (0)
|
||||||
|
* and probably the end of your program
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
template<uint value_size>
|
||||||
|
void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest)
|
||||||
|
{
|
||||||
|
register uint r_;
|
||||||
|
register uint rest_;
|
||||||
|
/*
|
||||||
|
these variables have similar meaning like those in
|
||||||
|
the multiplication algorithm MulTwoWords
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
|
||||||
|
#error "another compiler than GCC is currently not supported in 64bit mode"
|
||||||
|
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
|
||||||
|
__asm__ __volatile__(
|
||||||
|
|
||||||
|
"divq %%rcx \n"
|
||||||
|
|
||||||
|
: "=a" (r_), "=d" (rest_)
|
||||||
|
: "d" (a), "a" (b), "c" (c)
|
||||||
|
: "cc" );
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
*r = r_;
|
||||||
|
*rest = rest_;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
Loading…
Reference in New Issue