changed the sequence of arguments in logarithm functions

changed kind of templates in ttmath.h (template<class ValueType> is now)
added TTMATH_RELEASE macro
added TTMATH_ prefix into macros
changed multiplication in UInt type (now we can use both algorithm in the same time)
added ExceptionInfo, ReferenceError and RuntimeError classes
now TTMATH_ASSERT throws another type of object 
added TTMATH_REFERENCE_ASSERT (it is instead of MATHTT_THIS_ASSERT)



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@3 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2007-01-22 20:25:45 +00:00
parent ab42f75285
commit 1dabd725cb
9 changed files with 585 additions and 485 deletions

View File

@ -1,4 +1,10 @@
Version 0.6.3 (2007.01.22):
* position of arguments (x and base) in logarithm functions are swapped
* it's possible to use any multiplication algorithms in the same time
(macros UINT_MUL_VERSION_'X' have gone)
* added ExceptionInfo, ReferenceError and RuntimeError classes
* the mess in macros has been cleaned up
* added TTMATH_RELEASE macro
Version 0.6.2 (2007.01.10):
* New division algorithm (radix b) where b is 2^32

4
TODO
View File

@ -1,7 +1,5 @@
TODO TTMath Library
===================
* add the method Mod (a remainder from a division) for the Big type

View File

@ -1,5 +1,5 @@
/*
* This file is part of TTMath Mathematical Library
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
@ -59,10 +59,10 @@ namespace ttmath
e.g.
Factorial(4) = 4! = 1*2*3*4
*/
template<int exp,int man>
Big<exp, man> Factorial(const Big<exp, man> & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
template<class ValueType>
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
{
Big<exp, man> result;
ValueType result;
result.SetOne();
@ -76,17 +76,17 @@ namespace ttmath
if( !x.exponent.IsSign() && !x.exponent.IsZero() )
{
// when x>0 there's no sense to calculate the formula
// when x.exponent>0 there's no sense to calculate the formula
// (we can't add one into the x bacause
// we don't have enough bits in our mantissa)
// we don't have enough bits in the mantissa)
if( err )
*err = err_overflow;
return result;
}
Big<exp, man> multipler;
Big<exp, man> one;
ValueType multipler;
ValueType one;
uint carry = 0;
one = result; // =1
@ -124,10 +124,10 @@ namespace ttmath
e.g. -2 = 2
2 = 2
*/
template<int exp,int man>
Big<exp, man> Abs(const Big<exp, man> & x)
template<class ValueType>
ValueType Abs(const ValueType & x)
{
Big<exp, man> result( x );
ValueType result( x );
result.Abs();
return result;
@ -141,10 +141,10 @@ namespace ttmath
-2.2 = 2
-2.7 = 2
*/
template<int exp,int man>
Big<exp, man> SkipFraction(const Big<exp, man> & x)
template<class ValueType>
ValueType SkipFraction(const ValueType & x)
{
Big<exp, man> result( x );
ValueType result( x );
result.SkipFraction();
return result;
@ -158,10 +158,10 @@ namespace ttmath
-2.2 = -2
-2.7 = -3
*/
template<int exp,int man>
Big<exp, man> Round(const Big<exp, man> & x)
template<class ValueType>
ValueType Round(const ValueType & x)
{
Big<exp, man> result( x );
ValueType result( x );
result.Round();
return result;
@ -171,10 +171,10 @@ namespace ttmath
/*!
this method calculates the natural logarithm (logarithm with the base 'e')
*/
template<int exp,int man>
Big<exp, man> Ln(const Big<exp, man> & x, ErrorCode * err = 0)
template<class ValueType>
ValueType Ln(const ValueType & x, ErrorCode * err = 0)
{
Big<exp, man> result;
ValueType result;
uint state = result.Ln(x);
@ -205,12 +205,12 @@ namespace ttmath
/*!
this method calculates the logarithm
*/
template<int exp,int man>
Big<exp, man> Log(const Big<exp, man> & base, const Big<exp, man> & x, ErrorCode * err = 0)
template<class ValueType>
ValueType Log(const ValueType & x, const ValueType & base, ErrorCode * err = 0)
{
Big<exp, man> result;
ValueType result;
uint state = result.Log(base,x);
uint state = result.Log(x, base);
if( err )
{
@ -239,10 +239,10 @@ namespace ttmath
/*!
this method calculates the expression e^x
*/
template<int exp,int man>
Big<exp, man> Exp(const Big<exp, man> & x, ErrorCode * err = 0)
template<class ValueType>
ValueType Exp(const ValueType & x, ErrorCode * err = 0)
{
Big<exp, man> result;
ValueType result;
uint state = result.Exp(x);
@ -267,10 +267,10 @@ namespace ttmath
an auxiliary function for calculating the Sin
(you don't have to call this function)
*/
template<int exp,int man>
void PrepareSin(Big<exp,man> & x, bool & change_sign)
template<class ValueType>
void PrepareSin(ValueType & x, bool & change_sign)
{
Big<exp,man> temp;
ValueType temp;
change_sign = false;
@ -332,13 +332,13 @@ namespace ttmath
and when a=PI/2:
sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ...
*/
template<int exp,int man>
Big<exp,man> Sin0pi05(const Big<exp,man> & x)
template<class ValueType>
ValueType Sin0pi05(const ValueType & x)
{
Big<exp,man> result;
Big<exp,man> numerator, denominator;
Big<exp,man> d_numerator, d_denominator;
Big<exp,man> one, temp, old_result;
ValueType result;
ValueType numerator, denominator;
ValueType d_numerator, d_denominator;
ValueType one, temp, old_result;
// temp = pi/4
temp.Set05Pi();
@ -367,7 +367,7 @@ namespace ttmath
denominator = one;
// d_numerator = (x-pi/2)^2
Big<exp,man> pi05;
ValueType pi05;
pi05.Set05Pi();
temp = x;
@ -382,7 +382,7 @@ namespace ttmath
bool addition = false;
old_result = result;
for(int i=1 ; i<5000 ; ++i)
for(int i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
{
// we're starting from a second part of the formula
c += numerator. Mul( d_numerator );
@ -424,21 +424,24 @@ namespace ttmath
/*!
this function calulates the Sin
*/
template<int exp,int man>
Big<exp,man> Sin(Big<exp,man> x)
template<class ValueType>
ValueType Sin(ValueType x)
{
Big<exp,man> one;
ValueType one;
bool change_sign;
PrepareSin( x, change_sign );
Big<exp,man> result = Sin0pi05( x );
ValueType result = Sin0pi05( x );
one.SetOne();
// after calculations there can be small distortions in the result
if( result > one )
result = one;
else
if( result.IsSign() )
// we've calculated the sin from <0, pi/2> and the result
// should be positive
result.SetZero();
if( change_sign )
@ -452,10 +455,10 @@ namespace ttmath
this function calulates the Cos
we're using the formula cos(x) = sin(x + PI/2)
*/
template<int exp,int man>
Big<exp,man> Cos(Big<exp,man> x)
template<class ValueType>
ValueType Cos(ValueType x)
{
Big<exp,man> pi05;
ValueType pi05;
pi05.Set05Pi();
x.Add( pi05 );
@ -469,15 +472,15 @@ namespace ttmath
we're using the formula tan(x) = sin(x) / cos(x)
it takes more time than calculating the Tan directly
from for example Taylor series but should be a bit precise
from for example Taylor series but should be a bit preciser
because Tan receives its values from -infinity to +infinity
and when we calculate it from any series then we can make
a small mistake than calculating 'sin/cos'
*/
template<int exp,int man>
Big<exp,man> Tan(const Big<exp,man> & x, ErrorCode * err = 0)
template<class ValueType>
ValueType Tan(const ValueType & x, ErrorCode * err = 0)
{
Big<exp,man> result = Cos(x);
ValueType result = Cos(x);
if( result.IsZero() )
{
@ -499,12 +502,12 @@ namespace ttmath
we're using the formula tan(x) = cos(x) / sin(x)
(why do we make it in this way?
look at the info in Tan() function)
look at information in Tan() function)
*/
template<int exp,int man>
Big<exp,man> CTan(const Big<exp,man> & x, ErrorCode * err = 0)
template<class ValueType>
ValueType CTan(const ValueType & x, ErrorCode * err = 0)
{
Big<exp,man> result = Sin(x);
ValueType result = Sin(x);
if( result.IsZero() )
{

View File

@ -1,5 +1,5 @@
/*
* This file is part of TTMath Mathematical Library
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
@ -204,7 +204,7 @@ public:
// (first is the highest word)
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
exponent = -int(man)*int(BITS_PER_UINT) + 2;
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 2;
info = 0;
}
@ -215,7 +215,7 @@ public:
void Set05Pi()
{
SetPi();
exponent = -int(man)*int(BITS_PER_UINT) + 1;
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 1;
}
@ -225,7 +225,7 @@ public:
void Set2Pi()
{
SetPi();
exponent = -int(man)*int(BITS_PER_UINT) + 3;
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 3;
}
@ -249,7 +249,7 @@ public:
};
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
exponent = -int(man)*int(BITS_PER_UINT) + 2;
exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 2;
info = 0;
}
@ -274,7 +274,7 @@ public:
};
mantissa.SetFromTable(temp_table, sizeof(temp_table) / sizeof(uint));
exponent = -int(man)*int(BITS_PER_UINT);
exponent = -int(man)*int(TTMATH_BITS_PER_UINT);
info = 0;
}
@ -394,7 +394,7 @@ public:
uint Add(Big<exp, man> ss2)
{
Int<exp> exp_offset( exponent );
Int<exp> mantissa_size_in_bits( man * BITS_PER_UINT );
Int<exp> mantissa_size_in_bits( man * TTMATH_BITS_PER_UINT );
int c = 0;
exp_offset.Sub( ss2.exponent );
@ -472,22 +472,22 @@ public:
*/
uint Mul(const Big<exp, man> & ss2)
{
MATHTT_THIS_ASSERT( ss2 )
TTMATH_REFERENCE_ASSERT( ss2 )
UInt<man*2> man_result;
int i,c;
// man_result = mantissa * ss2.mantissa
mantissa.Mul(ss2.mantissa, man_result);
mantissa.MulBig(ss2.mantissa, man_result);
// 'i' will be from 0 to man*BITS_PER_UINT
// 'i' will be from 0 to man*TTMATH_BITS_PER_UINT
// because mantissa and ss2.mantissa are standardized
// (the highest bit in man_result is set to 1 or
// if there is a zero value in man_result the method CompensationToLeft()
// returns 0 but we'll correct this at the end in Standardizing() method)
i = man_result.CompensationToLeft();
c = exponent.Add( man * BITS_PER_UINT - i );
c = exponent.Add( man * TTMATH_BITS_PER_UINT - i );
c += exponent.Add( ss2.exponent );
for(i=0 ; i<man ; ++i)
@ -518,7 +518,7 @@ public:
*/
uint Div(const Big<exp, man> & ss2)
{
MATHTT_THIS_ASSERT( ss2 )
TTMATH_REFERENCE_ASSERT( ss2 )
UInt<man*2> man1;
UInt<man*2> man2;
@ -635,15 +635,15 @@ public:
*/
bool Mod2() const
{
if( exponent>int(0) || exponent<=-int(man*BITS_PER_UINT) )
if( exponent>int(0) || exponent<=-int(man*TTMATH_BITS_PER_UINT) )
return false;
int exp_int = exponent.ToInt();
// 'exp_int' is negative (or zero), we set its as positive
exp_int = -exp_int;
int value = mantissa.table[ exp_int / BITS_PER_UINT ];
value >>= (exp_int % BITS_PER_UINT);
int value = mantissa.table[ exp_int / TTMATH_BITS_PER_UINT ];
value >>= (exp_int % TTMATH_BITS_PER_UINT);
return bool(value & 1);
}
@ -696,7 +696,7 @@ public:
*/
uint PowBInt(const Big<exp, man> & pow)
{
MATHTT_THIS_ASSERT( pow )
TTMATH_REFERENCE_ASSERT( pow )
if( !pow.IsSign() )
return PowBUInt(pow);
@ -745,7 +745,7 @@ public:
int Pow(const Big<exp, man> pow)
#endif
{
MATHTT_THIS_ASSERT( pow )
TTMATH_REFERENCE_ASSERT( pow )
if( IsZero() )
{
@ -789,7 +789,7 @@ private:
*/
void ExpSurrounding0(const Big<exp,man> & x)
{
MATHTT_THIS_ASSERT( x )
TTMATH_REFERENCE_ASSERT( x )
Big<exp,man> denominator, denominator_i;
Big<exp,man> one, old_value, next_part;
@ -800,13 +800,12 @@ private:
denominator.SetOne();
denominator_i.SetOne();
// we assume only 'max_loop' iterations of our loop
// every 'step_test' times we make a test
const uint max_loop = 2000;
const uint step_test = 5;
// we begin from 1 in order to not testing at the start
for(uint i=1 ; i<=max_loop ; ++i)
for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
{
bool testing = ((i % step_test) == 0);
@ -870,18 +869,18 @@ public:
// m will be the value of the mantissa in range (-1,1)
Big<exp,man> m(x);
m.exponent = -int(man*BITS_PER_UINT);
m.exponent = -int(man*TTMATH_BITS_PER_UINT);
// 'e_' will be the value of '2^exponent'
// e_.mantissa.table[man-1] = uint_the_highest_bit; and
// e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and
// e_.exponent.Add(1) mean:
// e_.mantissa.table[0] = 1;
// e_.Standardizing();
// e_.exponent.Add(man*BITS_PER_UINT)
// (we must add 'man*BITS_PER_UINT' because we've taken it from the mantissa)
// e_.exponent.Add(man*TTMATH_BITS_PER_UINT)
// (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa)
Big<exp,man> e_(x);
e_.mantissa.SetZero();
e_.mantissa.table[man-1] = uint_the_highest_bit;
e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT;
c += e_.exponent.Add(1);
e_.Abs();
@ -957,13 +956,12 @@ private:
denominator.SetOne();
SetZero();
// we assume only 'max_loop' iterations of our loop
// every 'step_test' times we make a test
const uint max_loop = 2000;
const uint step_test = 5;
// we begin from 1 in order to not testing at the beginning
for(uint i=1 ; i< max_loop+1 ; ++i)
for(uint i=1 ; i<=TTMATH_ARITHMETIC_MAX_LOOP ; ++i)
{
bool testing = ((i % step_test) == 0);
@ -1026,21 +1024,21 @@ public:
*/
uint Ln(const Big<exp,man> & x)
{
MATHTT_THIS_ASSERT( x )
TTMATH_REFERENCE_ASSERT( x )
if( x.IsSign() || x.IsZero() )
return 2;
// m will be the value of the mantissa in range <1,2)
Big<exp,man> m(x);
m.exponent = -int(man*BITS_PER_UINT - 1);
m.exponent = -int(man*TTMATH_BITS_PER_UINT - 1);
LnSurrounding1(m);
Big<exp,man> exponent_temp;
exponent_temp.FromInt( x.exponent );
// we must add 'man*BITS_PER_UINT-1' because we've taken it from the mantissa
uint c = exponent_temp.Add(man*BITS_PER_UINT-1);
// we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa
uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1);
Big<exp,man> ln2;
ln2.SetLn2();
@ -1071,10 +1069,10 @@ public:
because if we passed 'parts' into 'ln(base)' as well then
the error (after dividing) would be too great
*/
uint Log(const Big<exp,man> & base, const Big<exp,man> & x)
uint Log(const Big<exp,man> & x, const Big<exp,man> & base)
{
MATHTT_THIS_ASSERT( base )
MATHTT_THIS_ASSERT( x )
TTMATH_REFERENCE_ASSERT( base )
TTMATH_REFERENCE_ASSERT( x )
if( x.IsSign() || x.IsZero() )
return 2;
@ -1125,10 +1123,10 @@ public:
if( IsZero() )
return 0;
int maxbit = -int(man*BITS_PER_UINT);
int maxbit = -int(man*TTMATH_BITS_PER_UINT);
if( exponent > maxbit + int(BITS_PER_UINT) )
// if exponent > (maxbit + int(BITS_PER_UINT)) the value can't be passed
if( exponent > maxbit + int(TTMATH_BITS_PER_UINT) )
// if exponent > (maxbit + int(TTMATH_BITS_PER_UINT)) the value can't be passed
// into the 'int' type (it's too big)
return 1;
@ -1144,14 +1142,14 @@ public:
how_many_bits = -how_many_bits;
// we're taking into an account only the last word in a mantissa table
mantissa_temp.Rcr( how_many_bits % BITS_PER_UINT, 0 );
mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
result = mantissa_temp.table[ man-1 ];
// the exception for the minimal value
if( IsSign() && result == uint_the_highest_bit )
if( IsSign() && result == TTMATH_UINT_HIGHEST_BIT )
return 0;
if( (result & uint_the_highest_bit) != 0 )
if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
// the value is too big
return 1;
@ -1175,10 +1173,10 @@ public:
if( IsZero() )
return 0;
int maxbit = -int(man*BITS_PER_UINT);
int maxbit = -int(man*TTMATH_BITS_PER_UINT);
if( exponent > maxbit + int(int_size*BITS_PER_UINT) )
// if exponent > (maxbit + int(int_size*BITS_PER_UINT)) the value can't be passed
if( exponent > maxbit + int(int_size*TTMATH_BITS_PER_UINT) )
// if exponent > (maxbit + int(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
// into the 'Int<int_size>' type (it's too big)
return 1;
@ -1192,20 +1190,20 @@ public:
if( how_many_bits < 0 )
{
how_many_bits = -how_many_bits;
uint index = how_many_bits / BITS_PER_UINT;
mantissa_temp.Rcr( how_many_bits % BITS_PER_UINT, 0 );
uint index = how_many_bits / TTMATH_BITS_PER_UINT;
mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
for(uint i=index, a=0 ; i<man ; ++i,++a)
result.table[a] = mantissa_temp.table[i];
}
else
{
uint index = how_many_bits / BITS_PER_UINT;
uint index = how_many_bits / TTMATH_BITS_PER_UINT;
for(uint i=0 ; i<man ; ++i)
result.table[index+i] = mantissa_temp.table[i];
result.Rcl( how_many_bits % BITS_PER_UINT, 0 );
result.Rcl( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
}
// the exception for the minimal value
@ -1218,7 +1216,7 @@ public:
return 0;
}
if( (result.table[int_size-1] & uint_the_highest_bit) != 0 )
if( (result.table[int_size-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
// the value is too big
return 1;
@ -1290,7 +1288,7 @@ public:
uint minimum_size = (int_size < man)? int_size : man;
int compensation = (int)value.CompensationToLeft();
exponent = (int(int_size)-int(man)) * int(BITS_PER_UINT) - compensation;
exponent = (int(int_size)-int(man)) * int(TTMATH_BITS_PER_UINT) - compensation;
// copying the highest words
uint i;
@ -1568,7 +1566,7 @@ private:
// new_exp_ = [log base (2^exponent)] + 1
Big<exp+1,man> new_exp_;
c += new_exp_.ToString_Log(base, temp); // this logarithm isn't very complicated
c += new_exp_.ToString_Log(temp, base); // this logarithm isn't very complicated
new_exp_.SkipFraction();
temp.SetOne();
c += new_exp_.Add( temp );
@ -1628,9 +1626,9 @@ private:
x is greater than 0
base is in <2,16> range
*/
uint ToString_Log(uint base, const Big<exp,man> & x)
uint ToString_Log(const Big<exp,man> & x, uint base)
{
MATHTT_THIS_ASSERT( x )
TTMATH_REFERENCE_ASSERT( x )
Big<exp,man> temp;
temp.SetOne();
@ -1691,13 +1689,13 @@ private:
if( !exponent.IsSign() )
return 1;
if( exponent <= -int(man*BITS_PER_UINT) )
// if 'exponent' is <= than '-int(man*BITS_PER_UINT)'
if( exponent <= -int(man*TTMATH_BITS_PER_UINT) )
// if 'exponent' is <= than '-int(man*TTMATH_BITS_PER_UINT)'
// it means that we must cut the whole mantissa
// (there'll not be any of the valid bits)
return 1;
// e will be from (-man*BITS_PER_UINT, 0>
// e will be from (-man*TTMATH_BITS_PER_UINT, 0>
int e = -( exponent.ToInt() );
mantissa.Rcr(e,0);
@ -1723,9 +1721,9 @@ private:
{
uint value = mantissa.table[i];
for( unsigned int bit=0 ; bit<BITS_PER_UINT ; ++bit )
for( unsigned int bit=0 ; bit<TTMATH_BITS_PER_UINT ; ++bit )
{
if( (value & uint_the_highest_bit) != 0 )
if( (value & TTMATH_UINT_HIGHEST_BIT) != 0 )
new_man += '1';
else
new_man += '0';
@ -1786,7 +1784,7 @@ private:
// we can have the comma as well because
// we're using this method later in ToString_CorrectDigitsAfterComma_Round()
// (we're only ignoring it)
if( new_man[i] == MATHTT_COMMA_CHARACTER_1 )
if( new_man[i] == TTMATH_COMMA_CHARACTER_1 )
continue;
// we're adding one
@ -1898,7 +1896,7 @@ private:
// we're setting the comma within the mantissa
int index = new_man_len - e;
new_man.insert( new_man.begin() + index, MATHTT_COMMA_CHARACTER_1);
new_man.insert( new_man.begin() + index, TTMATH_COMMA_CHARACTER_1);
}
else
{
@ -1907,7 +1905,7 @@ private:
uint how_many = e - new_man_len;
std::string man_temp(how_many+1, '0');
man_temp.insert( man_temp.begin()+1, MATHTT_COMMA_CHARACTER_1);
man_temp.insert( man_temp.begin()+1, TTMATH_COMMA_CHARACTER_1);
new_man.insert(0, man_temp);
}
@ -1926,7 +1924,7 @@ private:
if( new_man.empty() )
return;
new_man.insert( new_man.begin()+1, MATHTT_COMMA_CHARACTER_1 );
new_man.insert( new_man.begin()+1, TTMATH_COMMA_CHARACTER_1 );
ToString_CorrectDigitsAfterComma(new_man, base, max_digit_after_comma);
@ -1996,7 +1994,7 @@ private:
// if directly before the first zero is the comma operator
// we're cutting it as well
if( i>0 && new_man[i]==MATHTT_COMMA_CHARACTER_1 )
if( i>0 && new_man[i]==TTMATH_COMMA_CHARACTER_1 )
--i;
new_man.erase(i+1, new_man.length()-i-1);
@ -2010,7 +2008,7 @@ private:
int max_digit_after_comma) const
{
// first we're looking for the comma operator
std::string::size_type index = new_man.find(MATHTT_COMMA_CHARACTER_1, 0);
std::string::size_type index = new_man.find(TTMATH_COMMA_CHARACTER_1, 0);
if( index == std::string::npos )
// nothing was found (actually there can't be this situation)
@ -2154,8 +2152,8 @@ private:
*/
bool FromString_TestCommaOperator(const char * & source)
{
if( (*source == MATHTT_COMMA_CHARACTER_1) ||
(*source == MATHTT_COMMA_CHARACTER_2 && MATHTT_COMMA_CHARACTER_2 != 0 ) )
if( (*source == TTMATH_COMMA_CHARACTER_1) ||
(*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
{
++source;
@ -2662,14 +2660,14 @@ public:
// exponent >=0 -- the value don't have any fractions
return;
if( exponent <= -int(man*BITS_PER_UINT) )
if( exponent <= -int(man*TTMATH_BITS_PER_UINT) )
{
// the value is from (-1,1), we return zero
SetZero();
return;
}
// exponent is in range (-man*BITS_PER_UINT, 0)
// exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
int e = exponent.ToInt();
mantissa.ClearFirstBits( -e );
@ -2700,17 +2698,17 @@ public:
return;
}
if( exponent <= -int(man*BITS_PER_UINT) )
if( exponent <= -int(man*TTMATH_BITS_PER_UINT) )
{
// the value is from (-1,1)
// we don't make anything with the value
return;
}
// e will be from (-man*BITS_PER_UINT, 0)
// e will be from (-man*TTMATH_BITS_PER_UINT, 0)
int e = exponent.ToInt();
int how_many_bits_leave = man*BITS_PER_UINT + e; // there'll be a subtraction -- e is negative
int how_many_bits_leave = man*TTMATH_BITS_PER_UINT + e; // there'll be a subtraction -- e is negative
mantissa.Rcl( how_many_bits_leave, 0);
// there'll not be a carry because the exponent is too small
@ -2797,10 +2795,10 @@ public:
// we're reading only digits (base=10) and only one comma operator
while( s.good() &&
( UInt<man>::CharToDigit(z, 10)>=0 || (!was_comma && z==MATHTT_COMMA_CHARACTER_1) )
( UInt<man>::CharToDigit(z, 10)>=0 || (!was_comma && z==TTMATH_COMMA_CHARACTER_1) )
)
{
if( z == MATHTT_COMMA_CHARACTER_1 )
if( z == TTMATH_COMMA_CHARACTER_1 )
was_comma = true;
ss += z;

View File

@ -1,5 +1,5 @@
/*
* This file is part of TTMath Mathematical Library
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
@ -69,7 +69,7 @@ public:
void SetMaxValue()
{
UInt<value_size>::SetMaxValue();
UInt<value_size>::table[value_size-1] = ~uint_the_highest_bit;
UInt<value_size>::table[value_size-1] = ~ TTMATH_UINT_HIGHEST_BIT;
}
@ -80,7 +80,7 @@ public:
void SetMinValue()
{
UInt<value_size>::SetZero();
UInt<value_size>::table[value_size-1] = uint_the_highest_bit;
UInt<value_size>::table[value_size-1] = TTMATH_UINT_HIGHEST_BIT;
}
@ -421,14 +421,14 @@ public:
if( i < value_size )
{
uint fill = (p.table[argument_size-1] & uint_the_highest_bit)? uint_max_value : 0;
uint fill = (p.table[argument_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0;
for( ; i<value_size ; ++i)
UInt<value_size>::table[i] = fill;
}
else
{
uint test = (UInt<value_size>::table[value_size-1] & uint_the_highest_bit)? uint_max_value : 0;
uint test = (UInt<value_size>::table[value_size-1] & TTMATH_UINT_HIGHEST_BIT)? TTMATH_UINT_MAX_VALUE : 0;
for( ; i<argument_size ; ++i)
if( p.table[i] != test )

View File

@ -1,5 +1,5 @@
/*
* This file is part of TTMath Mathematical Library
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/

View File

@ -1,5 +1,5 @@
/*
* This file is part of TTMath Mathematical Library
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
@ -81,7 +81,7 @@ namespace ttmath
"1"
"2.1234"
"2,1234" (they are the same, we can either use a comma or a dot in values)
(look at the macro MATHTT_COMMA_CHARACTER_2)
(look at the macro TTMATH_COMMA_CHARACTER_2)
"1 + 2"
"(1 + 2) * 3"
"pi"

View File

@ -1,5 +1,5 @@
/*
* This file is part of TTMath Mathematical Library
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
@ -36,24 +36,24 @@
*/
#ifndef headerfilettmathtypes
#define headerfilettmathtypes
/*!
\file ttmathtypes.h
\brief A Documented file.
\brief constants which are used in the library
Details.
As our library is written in header files (templates) we cannot use
constants like 'const int' etc. because we should have some source files
*.cpp to define this variables. Only what we can have are constants
defined by #define preprocessor macro.
All macros are preceded TTMATH_ part
*/
#include <exception>
#include <string>
#include <iostream>
#include <map>
#include <stdexcept>
#include <sstream>
/*!
@ -61,95 +61,92 @@
*/
#define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 6
#define TTMATH_REVISION_VER 2
#define TTMATH_REVISION_VER 3
/*!
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 macro MATHTT_ASSERT is set as well
and MATHTT_ASSERT can throw an exception if a condition is not fulfilled
(look at the definition of MATHTT_ASSERT)
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)
if you don't want any further testing put two characters '//' before this macro
e.g.
// #define MATHTT_DEBUG
TTMATH_RELEASE
if you are confident that your code is without bugs 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 TTMATH_RELEASE is not set then TTMATH_DEBUG is set
*/
#define MATHTT_DEBUG
#ifndef TTMATH_RELEASE
#define TTMATH_DEBUG
#endif
/*!
32 bit integer value without a sign
(the same on 64 bits platform (amd))
*/
typedef unsigned int uint;
namespace ttmath
{
/*!
32 bit integer value without a sign
(on 64bit platforms will be 32bit as well)
*/
typedef unsigned int uint;
}
/*!
how many bits there are in the uint type
*/
#define BITS_PER_UINT 32u
#define TTMATH_BITS_PER_UINT 32u
/*!
the mask for the highest bit in the unsigned 32bits word (2^31)
the mask for the highest bit in the unsigned 32bit word (2^31)
*/
#define uint_the_highest_bit 2147483648u
#define TTMATH_UINT_HIGHEST_BIT 2147483648u
/*!
the max value of the unsigned 32bits word (2^32 - 1)
the max value of the unsigned 32bit word (2^32 - 1)
(all bits equal one)
*/
#define uint_max_value 4294967295u
/*!
if you define this macro that means the version one of the multiplication algorithm
will be used in the UInt class
*/
//#define UINT_MUL_VERSION_1
/*!
if you define this macro that means the version two of the multiplication algorithm
will be used in the UInt class
this algorithm is much faster than previous
you can't use both these macros together, you must use either UINT_MUL_VERSION_1
or UINT_MUL_VERSION_2
*/
#define UINT_MUL_VERSION_2
#define TTMATH_UINT_MAX_VALUE 4294967295u
/*!
characters which represent the comma operator
MATHTT_COMMA_CHARACTER_1 is used in reading (parsing) and in writing
MATHTT_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
TTMATH_COMMA_CHARACTER_1 is used in reading (parsing) and in writing
TTMATH_COMMA_CHARACTER_2 can be used in reading as an auxiliary comma character
that means you can input values for example 1.2345 and 1,2345 as well
if you don't want it just put 0 there eg.
#define MATHTT_COMMA_CHARACTER_2 0
then only MATHTT_COMMA_CHARACTER_1 will be used
#define TTMATH_COMMA_CHARACTER_2 0
then only TTMATH_COMMA_CHARACTER_1 will be used
don't put here any special character which is used by the parser
(for example a semicolon ';' shouldn't be here)
*/
#define MATHTT_COMMA_CHARACTER_1 '.'
#define MATHTT_COMMA_CHARACTER_2 ','
////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//// odwrocic nazwy ma byc TTMATH
#define TTMATH_COMMA_CHARACTER_1 '.'
#define TTMATH_COMMA_CHARACTER_2 ','
/*!
this variable defines how many iterations are performed
during some kind of calculating when we're making any long formulas
(for example Taylor series)
it's used in ExpSurrounding0(...), LnSurrounding1(...), Sin0pi05(...), etc.
note! there'll not be so many iterations, iterations are stopped when
there is no sense to continue calculating (for example when the result
still remains unchanged after adding next series and we know that the next
series are smaller than previous)
*/
#define TTMATH_ARITHMETIC_MAX_LOOP 5000
@ -162,37 +159,34 @@ namespace ttmath
enum ErrorCode
{
err_ok = 0,
err_nothing_has_read = 1,
err_unknown_character = 2,
err_unexpected_final_bracket = 4,
err_stack_not_clear = 6,
err_unknown_variable = 8,
err_division_by_zero = 9,
err_interrupt = 10,
err_overflow = 11,
err_unknown_function = 12,
err_unexpected_semicolon_operator = 18,
err_improper_amount_of_arguments = 19,
err_improper_argument = 20,
err_unexpected_end = 21,
err_internal_error = 100,
err_nothing_has_read,
err_unknown_character,
err_unexpected_final_bracket,
err_stack_not_clear,
err_unknown_variable,
err_division_by_zero,
err_interrupt,
err_overflow,
err_unknown_function,
err_unexpected_semicolon_operator,
err_improper_amount_of_arguments,
err_improper_argument,
err_unexpected_end,
err_internal_error,
err_incorrect_name,
err_incorrect_value,
err_variable_exists,
err_variable_loop,
err_functions_loop,
err_must_be_only_one_value,
err_object_exists,
err_unknown_object,
err_this_cant_be_used = 200
err_unknown_object
};
/*!
*/
class StopCalculating
{
public:
@ -201,84 +195,135 @@ namespace ttmath
};
/*!
a small class which is useful when compiling with gcc
// moze tutaj z runtime dziedziczyc?
//zmienic nazwe na TTMathError
class MathTTError : public std::exception
object of this type holds the name and the line of a file
in which the macro TTMATH_ASSERT or TTMATH_REFERENCE_ASSERT was used
*/
class ExceptionInfo
{
ErrorCode code;
const char * file;
int line;
public:
MathTTError(ErrorCode c) : code(c) {}
const char* what() const throw()
{
switch( code )
{
case err_this_cant_be_used:
return "You've used 'this' somewhere in your code but you can't use it there";
// dac tu jakis lepszy komunikat w stylu
// 'uzyles referencji do samego siebie ale w tym miejscu nie mozesz tego zrobic'
default:
return ":)"; // temporary
}
ExceptionInfo() : file(0), line(0) {}
ExceptionInfo(const char * f, int l) : file(f), line(l) {}
return "Unnamed";
std::string Where() const
{
if( !file )
return "unknown";
std::ostringstream result;
result << file << ":" << line;
return result.str();
}
};
#ifdef MATHTT_DEBUG
#define MATHTT_ASSERT(expression, c) \
if( !(expression) ) throw MathTTError(c);
/*!
A small class used for reporting 'reference' errors
In the library is used macro TTMATH_REFERENCE_ASSERT which
can throw an exception of this type
If you compile with gcc you can get a small benefit
from using method Where() (it returns std::string with
the name and the line of a file where the macro TTMATH_REFERENCE_ASSERT
was used)
What is it the 'reference' error?
Some kind of methods use a reference as their argument to another object,
and the another object not always can be the same which is calling, e.g.
Big<1,2> foo(10);
foo.Mul(foo); // this is incorrect
above method Mul is making something more with 'this' object and
'this' cannot be passed as the argument because the result will be undefined
macro TTMATH_REFERENCE_ASSERT helps us to solve the above problem
note! some methods can use 'this' object as the argument
for example this code is correct:
UInt<2> foo(10);
foo.Add(foo);
but there are only few methods which can do that
*/
class ReferenceError : public std::logic_error, ExceptionInfo
{
public:
ReferenceError() : std::logic_error ("reference error")
{
}
ReferenceError(const char * f, int l) :
std::logic_error ("reference error"), ExceptionInfo(f,l)
{
}
std::string Where() const
{
return ExceptionInfo::Where();
}
};
/*!
a small class used for reporting errors
in the library is used macro TTMATH_ASSERT which
(if the condition in it is false) throw an exception
of this type
if you compile with gcc you can get a small benefit
from using method Where() (it returns std::string with
the name and the line of a file where the macro TTMATH_ASSERT
was used)
*/
class RuntimeError : public std::runtime_error, ExceptionInfo
{
public:
RuntimeError() : std::runtime_error ("internal error")
{
}
RuntimeError(const char * f, int l) :
std::runtime_error ("internal error"), ExceptionInfo(f,l)
{
}
std::string Where() const
{
return ExceptionInfo::Where();
}
};
#ifdef TTMATH_DEBUG
#ifdef __GNUC__
#define TTMATH_REFERENCE_ASSERT(expression) \
if( &(expression) == this ) throw ReferenceError(__FILE__, __LINE__);
#define TTMATH_ASSERT(expression) \
if( !(expression) ) throw RuntimeError(__FILE__, __LINE__);
#else
#define TTMATH_REFERENCE_ASSERT(expression) \
if( &(expression) == this ) throw ReferenceError();
#define TTMATH_ASSERT(expression) \
if( !(expression) ) throw RuntimeError();
#endif
#else
#define MATHTT_ASSERT(expression, c)
#define TTMATH_REFERENCE_ASSERT(expression)
#define TTMATH_ASSERT(expression)
#endif
#define MATHTT_THIS_ASSERT(expression) \
MATHTT_ASSERT( &expression != this, err_this_cant_be_used)
/*
template<class ValueType>
class ValuesHistory
{
typedef std::map<ValueType, ValueType> buffer_type;
buffer_type buffer;
public:
void AddValue(const ValueType & key, const ValueType & result)
{
buffer.insert( std::make_pair(key, result) );
}
bool GetValue(const ValueType & key, ValueType & result) const
{
buffer_type::iterator i = buffer.find( key );
if( i == buffer.end() )
return false;
result = *i;
return true;
}
uint Size() const
{
return static_cast<uint>( buffer.size() );
}
};
*/
} // namespace
#endif

View File

@ -1,5 +1,5 @@
/*
* This file is part of TTMath Mathematical Library
* This file is a part of TTMath Mathematical Library
* and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/
@ -50,8 +50,6 @@
#define TTMATH_UINT_GUARD 1234567891
// !!!
extern bool bylocos;
namespace ttmath
{
@ -113,7 +111,7 @@ public:
void SetMaxValue()
{
for(uint i=0 ; i<value_size ; ++i)
table[i] = uint_max_value;
table[i] = TTMATH_UINT_MAX_VALUE;
}
@ -153,7 +151,7 @@ public:
// rounding mantissa
if( temp_table_index < temp_table_len )
{
if( (temp_table[temp_table_index] & uint_the_highest_bit) != 0 )
if( (temp_table[temp_table_index] & TTMATH_UINT_HIGHEST_BIT) != 0 )
{
/*
very simply rounding
@ -799,7 +797,7 @@ public:
this method moving all bits into the left side 'bits' times
return value <- this <- C
bits is from a range of <0, man * BITS_PER_UINT>
bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
or it can be even bigger then all bits will be set to 'c'
the value c will be set into the lowest bits
@ -811,10 +809,10 @@ public:
int second;
int last_c = 0;
if( bits > value_size*BITS_PER_UINT )
bits = value_size*BITS_PER_UINT;
if( bits > value_size*TTMATH_BITS_PER_UINT )
bits = value_size*TTMATH_BITS_PER_UINT;
int all_words = int(bits) / int(BITS_PER_UINT);
int all_words = int(bits) / int(TTMATH_BITS_PER_UINT);
if( all_words > 0 )
{
@ -826,12 +824,12 @@ public:
}
// sets the rest bits of value into 'c'
uint mask = (c!=0)? uint_max_value : 0;
uint mask = (c!=0)? TTMATH_UINT_MAX_VALUE : 0;
for( ; first>=0 ; --first )
table[first] = mask;
}
int rest_bits = int(bits) % int(BITS_PER_UINT);
int rest_bits = int(bits) % int(TTMATH_BITS_PER_UINT);
for( ; rest_bits > 0 ; --rest_bits )
last_c = Rcl(c);
@ -843,7 +841,7 @@ public:
this method moving all bits into the right side 'bits' times
c -> this -> return value
bits is from a range of <0, man * BITS_PER_UINT>
bits is from a range of <0, man * TTMATH_BITS_PER_UINT>
or it can be even bigger then all bits will be set to 'c'
the value c will be set into the highest bits
@ -855,17 +853,17 @@ public:
int second;
int last_c = 0;
if( bits > value_size*BITS_PER_UINT )
bits = value_size*BITS_PER_UINT;
if( bits > value_size*TTMATH_BITS_PER_UINT )
bits = value_size*TTMATH_BITS_PER_UINT;
int all_words = int(bits) / int(BITS_PER_UINT);
int all_words = int(bits) / int(TTMATH_BITS_PER_UINT);
if( all_words > 0 )
{
// copying the first part of the value
for(first=0, second=all_words ; second<int(value_size) ; ++first, ++second)
{
last_c = table[first] & uint_the_highest_bit;
last_c = table[first] & TTMATH_UINT_HIGHEST_BIT;
table[first] = table[second];
}
@ -873,12 +871,12 @@ public:
last_c = 1;
// sets the rest bits of value into 'c'
uint mask = (c!=0)? uint_max_value : 0;
uint mask = (c!=0)? TTMATH_UINT_MAX_VALUE : 0;
for( ; first<int(value_size) ; ++first )
table[first] = mask;
}
int rest_bits = int(bits) % int(BITS_PER_UINT);
int rest_bits = int(bits) % int(TTMATH_BITS_PER_UINT);
for( ; rest_bits > 0 ; --rest_bits )
last_c = Rcr(c);
@ -906,7 +904,7 @@ public:
if( a != value_size-1 )
{
moving += ( value_size-1 - a ) * BITS_PER_UINT;
moving += ( value_size-1 - a ) * TTMATH_BITS_PER_UINT;
// moving all words
int i;
@ -918,7 +916,7 @@ public:
table[i] = 0;
}
// moving the rest bits (max BITS_PER_UINT -- only one word)
// moving the rest bits (max TTMATH_BITS_PER_UINT -- only one word)
while( !IsTheHighestBitSet() )
{
Rcl();
@ -1011,11 +1009,11 @@ public:
*/
void SetBit(uint bit_index)
{
uint index = bit_index / BITS_PER_UINT;
uint index = bit_index / TTMATH_BITS_PER_UINT;
if( index >= value_size )
return;
bit_index %= BITS_PER_UINT;
bit_index %= TTMATH_BITS_PER_UINT;
uint result = 1;
if( bit_index > 0 )
@ -1025,75 +1023,14 @@ public:
}
/*!
*
* Multiplication
*
*
*/
#ifdef UINT_MUL_VERSION_1
/*!
the first version of the multiplication algorithm
*/
/*!
multiplication: this = this * ss2
it returns carry if it has been
we can't use a reference to the ss2 because someone can use this
method in this way: mul(*this)
*/
uint Mul(const UInt<value_size> & ss2)
{
MATHTT_THIS_ASSERT( ss2 )
UInt<value_size> ss1( *this );
SetZero();
for(uint i=0; i < value_size*BITS_PER_UINT ; ++i)
{
if( Add(*this) )
return 1;
if( ss1.Rcl() )
if( Add(ss2) )
return 1;
}
return 0;
}
/*!
multiplication: result = this * ss2
result is twice bigger than 'this' and 'ss2'
this method never returns carry
*/
void Mul(const UInt<value_size> & ss2_, UInt<value_size*2> & result)
{
UInt<value_size*2> ss2;
uint i;
// copying *this into result and ss2_ into ss2
for(i=0 ; i<value_size ; ++i)
{
result.table[i] = table[i];
ss2.table[i] = ss2_.table[i];
}
// cleaning the highest bytes in result and ss2
for( ; i < value_size*2 ; ++i)
{
result.table[i] = 0;
ss2.table[i] = 0;
}
// multiply
// (there will not be a carry)
result.Mul( ss2 );
}
#endif
public:
/*!
multiplication: result2:result1 = a * b
@ -1154,113 +1091,222 @@ public:
}
/*!
multiplication: this = this * ss2
it returns carry if it has been
*/
uint MulInt(uint ss2)
{
uint r2,r1;
UInt<value_size> u( *this );
SetZero();
#ifdef UINT_MUL_VERSION_2
/*!
the second version of the multiplication algorithm
this algorithm is similar to the 'schoolbook method' which is done by hand
*/
/*!
multiplication: this = this * ss2
it returns carry if it has been
*/
uint Mul(const UInt<value_size> & ss2)
for(uint x1=0 ; x1<value_size ; ++x1)
{
UInt<value_size*2> result;
uint i;
Mul64(u.table[x1], ss2, &r2, &r1 );
if( x1 <= value_size - 2 )
{
if( AddTwoUints(x1,r2,r1) )
return 1;
}
else
{
// last iteration:
// x1 = value_size - 1;
Mul(ss2, result);
// copying result
for(i=0 ; i<value_size ; ++i)
table[i] = result.table[i];
// testing carry
for( ; i<value_size*2 ; ++i)
if( result.table[i] != 0 )
if( r2 )
return 1;
return 0;
}
table[x1] += r1;
/*!
multiplication: this = this * ss2
it returns carry if it has been
*/
uint MulInt(uint ss2)
{
uint r2,r1;
UInt<value_size> u( *this );
SetZero();
for(uint x1=0 ; x1<value_size ; ++x1)
{
Mul64(u.table[x1], ss2, &r2, &r1 );
if( x1 <= value_size - 2 )
{
if( AddTwoUints(x1,r2,r1) )
return 1;
}
else
{
// last iteration:
// x1 = value_size - 1;
if( r2 )
return 1;
table[x1] += r1;
if( table[x1] < r1 ) // there was a carry
return 1;
}
}
return 0;
}
/*!
multiplication: result = this * ss2
result is twice bigger than this and ss2
this method never returns carry
*/
void Mul(const UInt<value_size> & ss2, UInt<value_size*2> & result)
{
uint r2,r1;
result.SetZero();
for(uint x1=0 ; x1<value_size ; ++x1)
{
for(uint x2=0 ; x2<value_size ; ++x2)
{
Mul64(table[x1], ss2.table[x2], &r2, &r1 );
result.AddTwoUints(x2+x1,r2,r1);
// there will never be a carry
}
if( table[x1] < r1 ) // there was a carry
return 1;
}
}
#endif
return 0;
}
/*!
*/
uint Mul(const UInt<value_size> & ss2, uint algorithm = 2)
{
switch( algorithm )
{
case 1:
return Mul1(ss2);
default:
return Mul2(ss2);
}
}
/*!
*/
void MulBig(const UInt<value_size> & ss2,
UInt<value_size*2> & result,
uint algorithm = 2)
{
switch( algorithm )
{
case 1:
return Mul1Big(ss2, result);
default:
return Mul2Big(ss2, result);
}
}
/*!
the first version of the multiplication algorithm
*/
/*!
multiplication: this = this * ss2
it returns carry if it has been
we can't use a reference to the ss2 because someone can use this
method in this way: mul(*this)
*/
uint Mul1(const UInt<value_size> & ss2)
{
TTMATH_REFERENCE_ASSERT( ss2 )
UInt<value_size> ss1( *this );
SetZero();
for(uint i=0; i < value_size*TTMATH_BITS_PER_UINT ; ++i)
{
if( Add(*this) )
return 1;
if( ss1.Rcl() )
if( Add(ss2) )
return 1;
}
return 0;
}
/*!
multiplication: result = this * ss2
result is twice bigger than 'this' and 'ss2'
this method never returns carry
*/
void Mul1Big(const UInt<value_size> & ss2_, UInt<value_size*2> & result)
{
UInt<value_size*2> ss2;
uint i;
// copying *this into result and ss2_ into ss2
for(i=0 ; i<value_size ; ++i)
{
result.table[i] = table[i];
ss2.table[i] = ss2_.table[i];
}
// cleaning the highest bytes in result and ss2
for( ; i < value_size*2 ; ++i)
{
result.table[i] = 0;
ss2.table[i] = 0;
}
// multiply
// (there will not be a carry)
result.Mul1( ss2 );
}
/*!
the second version of the multiplication algorithm
this algorithm is similar to the 'schoolbook method' which is done by hand
*/
/*!
multiplication: this = this * ss2
it returns carry if it has been
*/
uint Mul2(const UInt<value_size> & ss2)
{
UInt<value_size*2> result;
uint i;
Mul2Big(ss2, result);
// copying result
for(i=0 ; i<value_size ; ++i)
table[i] = result.table[i];
// testing carry
for( ; i<value_size*2 ; ++i)
if( result.table[i] != 0 )
return 1;
return 0;
}
/*!
multiplication: result = this * ss2
result is twice bigger than this and ss2
this method never returns carry
*/
void Mul2Big(const UInt<value_size> & ss2, UInt<value_size*2> & result)
{
uint r2,r1,x1size,x2size,x1start,x2start;
result.SetZero();
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
for(x2size=value_size ; x2size>0 && ss2.table[x2size-1]==0 ; --x2size);
if( x1size==0 || x2size==0 )
return;
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
for(x2start=0 ; x2start<x2size && ss2.table[x2start]==0 ; ++x2start);
for(uint x1=x1start ; x1<x1size ; ++x1)
{
for(uint x2=x2start ; x2<x2size ; ++x2)
{
Mul64(table[x1], ss2.table[x2], &r2, &r1);
result.AddTwoUints(x2+x1,r2,r1);
// there will never be a carry
}
}
}
/*!
*
* Division
*
*
*/
public:
/*!
this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
r = a:b / c and rest - remainder
@ -1370,6 +1416,8 @@ public:
'remainder' - remainder
// !!!!!!!!!!!
it needs a new description
we've got two algorithms:
1. with Log(n) where n is the max value which should be held in this class
(Log(n) will be equal to the number of bits there are in the table)
@ -1530,13 +1578,13 @@ private:
uint Div1_Calculate(const UInt<value_size> & divisor, UInt<value_size> & rest)
{
MATHTT_THIS_ASSERT( divisor )
TTMATH_REFERENCE_ASSERT( divisor )
int loop;
int c;
rest.SetZero();
loop = value_size * BITS_PER_UINT;
loop = value_size * TTMATH_BITS_PER_UINT;
c = 0;
@ -1593,7 +1641,7 @@ public:
*/
uint Div2(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
{
MATHTT_THIS_ASSERT( divisor )
TTMATH_REFERENCE_ASSERT( divisor )
uint bits_diff;
uint status = Div2_Calculate(divisor, remainder, bits_diff);
@ -1692,8 +1740,8 @@ private:
return 0;
}
divisor_index += divisor_table_id * BITS_PER_UINT;
index += table_id * BITS_PER_UINT;
divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT;
index += table_id * TTMATH_BITS_PER_UINT;
if( divisor_table_id == 0 )
{
@ -1790,7 +1838,7 @@ public:
*/
uint Div3(const UInt<value_size> & v, UInt<value_size> * remainder = 0)
{
MATHTT_THIS_ASSERT( v )
TTMATH_REFERENCE_ASSERT( v )
uint m,n, test;
@ -1830,7 +1878,7 @@ private:
void Div3_Division(UInt<value_size> v, UInt<value_size> * remainder, uint m, uint n)
{
MATHTT_ASSERT( n>=2, ttmath::err_internal_error )
TTMATH_ASSERT( n>=2 )
UInt<value_size+1> uu, vv;
UInt<value_size> q;
@ -1931,7 +1979,7 @@ private:
{
uint c = 0;
for( d = 0 ; (v.table[n-1] & uint_the_highest_bit) == 0 ; ++d )
for( d = 0 ; (v.table[n-1] & TTMATH_UINT_HIGHEST_BIT) == 0 ; ++d )
{
// we can move the bits only to the 'n-1' index but at the moment
// we don't have such method
@ -1969,7 +2017,7 @@ private:
u_temp.table[0] = u1;
u_temp.DivInt(v1, &rp);
MATHTT_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1, ttmath::err_internal_error);
TTMATH_ASSERT( u_temp.table[1]==0 || u_temp.table[1]==1 )
do
{
@ -2048,7 +2096,7 @@ public:
*/
void ClearFirstBits(uint n)
{
if( n >= value_size*BITS_PER_UINT )
if( n >= value_size*TTMATH_BITS_PER_UINT )
{
SetZero();
return;
@ -2057,10 +2105,10 @@ public:
uint * p = table;
// first we're clearing the whole words
while( n >= BITS_PER_UINT )
while( n >= TTMATH_BITS_PER_UINT )
{
*p++ = 0;
n -= BITS_PER_UINT;
n -= TTMATH_BITS_PER_UINT;
}
if( n == 0 )
@ -2068,7 +2116,7 @@ public:
// and then we're clearing one word which has left
// mask -- all bits are set to one
uint mask = uint_max_value;
uint mask = TTMATH_UINT_MAX_VALUE;
mask = mask << n;
@ -2081,7 +2129,7 @@ public:
*/
bool IsTheHighestBitSet() const
{
return (table[value_size-1] & uint_the_highest_bit) == uint_the_highest_bit;
return (table[value_size-1] & TTMATH_UINT_HIGHEST_BIT) == TTMATH_UINT_HIGHEST_BIT;
}
@ -2211,8 +2259,10 @@ public:
table[i] = p.table[i];
if( i < value_size )
if( value_size > argument_size )
{
// 'this' is longer than 'p'
for( ; i<value_size ; ++i)
table[i] = 0;
}