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): Version 0.6.2 (2007.01.10):
* New division algorithm (radix b) where b is 2^32 * New division algorithm (radix b) where b is 2^32

4
TODO
View File

@ -1,7 +1,5 @@
TODO TTMath Library 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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/ */
@ -59,10 +59,10 @@ namespace ttmath
e.g. e.g.
Factorial(4) = 4! = 1*2*3*4 Factorial(4) = 4! = 1*2*3*4
*/ */
template<int exp,int man> template<class ValueType>
Big<exp, man> Factorial(const Big<exp, man> & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0) ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
{ {
Big<exp, man> result; ValueType result;
result.SetOne(); result.SetOne();
@ -76,17 +76,17 @@ namespace ttmath
if( !x.exponent.IsSign() && !x.exponent.IsZero() ) 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 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 ) if( err )
*err = err_overflow; *err = err_overflow;
return result; return result;
} }
Big<exp, man> multipler; ValueType multipler;
Big<exp, man> one; ValueType one;
uint carry = 0; uint carry = 0;
one = result; // =1 one = result; // =1
@ -124,10 +124,10 @@ namespace ttmath
e.g. -2 = 2 e.g. -2 = 2
2 = 2 2 = 2
*/ */
template<int exp,int man> template<class ValueType>
Big<exp, man> Abs(const Big<exp, man> & x) ValueType Abs(const ValueType & x)
{ {
Big<exp, man> result( x ); ValueType result( x );
result.Abs(); result.Abs();
return result; return result;
@ -141,10 +141,10 @@ namespace ttmath
-2.2 = 2 -2.2 = 2
-2.7 = 2 -2.7 = 2
*/ */
template<int exp,int man> template<class ValueType>
Big<exp, man> SkipFraction(const Big<exp, man> & x) ValueType SkipFraction(const ValueType & x)
{ {
Big<exp, man> result( x ); ValueType result( x );
result.SkipFraction(); result.SkipFraction();
return result; return result;
@ -158,10 +158,10 @@ namespace ttmath
-2.2 = -2 -2.2 = -2
-2.7 = -3 -2.7 = -3
*/ */
template<int exp,int man> template<class ValueType>
Big<exp, man> Round(const Big<exp, man> & x) ValueType Round(const ValueType & x)
{ {
Big<exp, man> result( x ); ValueType result( x );
result.Round(); result.Round();
return result; return result;
@ -171,10 +171,10 @@ namespace ttmath
/*! /*!
this method calculates the natural logarithm (logarithm with the base 'e') this method calculates the natural logarithm (logarithm with the base 'e')
*/ */
template<int exp,int man> template<class ValueType>
Big<exp, man> Ln(const Big<exp, man> & x, ErrorCode * err = 0) ValueType Ln(const ValueType & x, ErrorCode * err = 0)
{ {
Big<exp, man> result; ValueType result;
uint state = result.Ln(x); uint state = result.Ln(x);
@ -205,12 +205,12 @@ namespace ttmath
/*! /*!
this method calculates the logarithm this method calculates the logarithm
*/ */
template<int exp,int man> template<class ValueType>
Big<exp, man> Log(const Big<exp, man> & base, const Big<exp, man> & x, ErrorCode * err = 0) 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 ) if( err )
{ {
@ -239,10 +239,10 @@ namespace ttmath
/*! /*!
this method calculates the expression e^x this method calculates the expression e^x
*/ */
template<int exp,int man> template<class ValueType>
Big<exp, man> Exp(const Big<exp, man> & x, ErrorCode * err = 0) ValueType Exp(const ValueType & x, ErrorCode * err = 0)
{ {
Big<exp, man> result; ValueType result;
uint state = result.Exp(x); uint state = result.Exp(x);
@ -267,10 +267,10 @@ namespace ttmath
an auxiliary function for calculating the Sin an auxiliary function for calculating the Sin
(you don't have to call this function) (you don't have to call this function)
*/ */
template<int exp,int man> template<class ValueType>
void PrepareSin(Big<exp,man> & x, bool & change_sign) void PrepareSin(ValueType & x, bool & change_sign)
{ {
Big<exp,man> temp; ValueType temp;
change_sign = false; change_sign = false;
@ -332,13 +332,13 @@ namespace ttmath
and when a=PI/2: and when a=PI/2:
sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ... sin(x) = 1 - ((x-PI/2)^2)/(2!) + ((x-PI/2)^4)/(4!) - ((x-PI/2)^6)/(6!) ...
*/ */
template<int exp,int man> template<class ValueType>
Big<exp,man> Sin0pi05(const Big<exp,man> & x) ValueType Sin0pi05(const ValueType & x)
{ {
Big<exp,man> result; ValueType result;
Big<exp,man> numerator, denominator; ValueType numerator, denominator;
Big<exp,man> d_numerator, d_denominator; ValueType d_numerator, d_denominator;
Big<exp,man> one, temp, old_result; ValueType one, temp, old_result;
// temp = pi/4 // temp = pi/4
temp.Set05Pi(); temp.Set05Pi();
@ -367,7 +367,7 @@ namespace ttmath
denominator = one; denominator = one;
// d_numerator = (x-pi/2)^2 // d_numerator = (x-pi/2)^2
Big<exp,man> pi05; ValueType pi05;
pi05.Set05Pi(); pi05.Set05Pi();
temp = x; temp = x;
@ -382,7 +382,7 @@ namespace ttmath
bool addition = false; bool addition = false;
old_result = result; 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 // we're starting from a second part of the formula
c += numerator. Mul( d_numerator ); c += numerator. Mul( d_numerator );
@ -424,21 +424,24 @@ namespace ttmath
/*! /*!
this function calulates the Sin this function calulates the Sin
*/ */
template<int exp,int man> template<class ValueType>
Big<exp,man> Sin(Big<exp,man> x) ValueType Sin(ValueType x)
{ {
Big<exp,man> one; ValueType one;
bool change_sign; bool change_sign;
PrepareSin( x, change_sign ); PrepareSin( x, change_sign );
Big<exp,man> result = Sin0pi05( x ); ValueType result = Sin0pi05( x );
one.SetOne(); one.SetOne();
// after calculations there can be small distortions in the result
if( result > one ) if( result > one )
result = one; result = one;
else else
if( result.IsSign() ) if( result.IsSign() )
// we've calculated the sin from <0, pi/2> and the result
// should be positive
result.SetZero(); result.SetZero();
if( change_sign ) if( change_sign )
@ -452,10 +455,10 @@ namespace ttmath
this function calulates the Cos this function calulates the Cos
we're using the formula cos(x) = sin(x + PI/2) we're using the formula cos(x) = sin(x + PI/2)
*/ */
template<int exp,int man> template<class ValueType>
Big<exp,man> Cos(Big<exp,man> x) ValueType Cos(ValueType x)
{ {
Big<exp,man> pi05; ValueType pi05;
pi05.Set05Pi(); pi05.Set05Pi();
x.Add( pi05 ); x.Add( pi05 );
@ -469,15 +472,15 @@ namespace ttmath
we're using the formula tan(x) = sin(x) / cos(x) we're using the formula tan(x) = sin(x) / cos(x)
it takes more time than calculating the Tan directly 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 because Tan receives its values from -infinity to +infinity
and when we calculate it from any series then we can make and when we calculate it from any series then we can make
a small mistake than calculating 'sin/cos' a small mistake than calculating 'sin/cos'
*/ */
template<int exp,int man> template<class ValueType>
Big<exp,man> Tan(const Big<exp,man> & x, ErrorCode * err = 0) ValueType Tan(const ValueType & x, ErrorCode * err = 0)
{ {
Big<exp,man> result = Cos(x); ValueType result = Cos(x);
if( result.IsZero() ) if( result.IsZero() )
{ {
@ -499,12 +502,12 @@ namespace ttmath
we're using the formula tan(x) = cos(x) / sin(x) we're using the formula tan(x) = cos(x) / sin(x)
(why do we make it in this way? (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> template<class ValueType>
Big<exp,man> CTan(const Big<exp,man> & x, ErrorCode * err = 0) ValueType CTan(const ValueType & x, ErrorCode * err = 0)
{ {
Big<exp,man> result = Sin(x); ValueType result = Sin(x);
if( result.IsZero() ) 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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/ */
@ -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(BITS_PER_UINT) + 2; exponent = -int(man)*int(TTMATH_BITS_PER_UINT) + 2;
info = 0; info = 0;
} }
@ -215,7 +215,7 @@ public:
void Set05Pi() void Set05Pi()
{ {
SetPi(); 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() void Set2Pi()
{ {
SetPi(); 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)); 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; 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(BITS_PER_UINT); exponent = -int(man)*int(TTMATH_BITS_PER_UINT);
info = 0; info = 0;
} }
@ -394,7 +394,7 @@ public:
uint Add(Big<exp, man> ss2) uint Add(Big<exp, man> ss2)
{ {
Int<exp> exp_offset( exponent ); 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; int c = 0;
exp_offset.Sub( ss2.exponent ); exp_offset.Sub( ss2.exponent );
@ -472,22 +472,22 @@ public:
*/ */
uint Mul(const Big<exp, man> & ss2) uint Mul(const Big<exp, man> & ss2)
{ {
MATHTT_THIS_ASSERT( ss2 ) TTMATH_REFERENCE_ASSERT( ss2 )
UInt<man*2> man_result; UInt<man*2> man_result;
int i,c; int i,c;
// man_result = mantissa * ss2.mantissa // 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 // because mantissa and ss2.mantissa are standardized
// (the highest bit in man_result is set to 1 or // (the highest bit in man_result is set to 1 or
// if there is a zero value in man_result the method CompensationToLeft() // 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) // returns 0 but we'll correct this at the end in Standardizing() method)
i = man_result.CompensationToLeft(); 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 ); c += exponent.Add( ss2.exponent );
for(i=0 ; i<man ; ++i) for(i=0 ; i<man ; ++i)
@ -518,7 +518,7 @@ public:
*/ */
uint Div(const Big<exp, man> & ss2) uint Div(const Big<exp, man> & ss2)
{ {
MATHTT_THIS_ASSERT( ss2 ) TTMATH_REFERENCE_ASSERT( ss2 )
UInt<man*2> man1; UInt<man*2> man1;
UInt<man*2> man2; UInt<man*2> man2;
@ -635,15 +635,15 @@ public:
*/ */
bool Mod2() const 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; return false;
int exp_int = exponent.ToInt(); int 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 / BITS_PER_UINT ]; int value = mantissa.table[ exp_int / TTMATH_BITS_PER_UINT ];
value >>= (exp_int % BITS_PER_UINT); value >>= (exp_int % TTMATH_BITS_PER_UINT);
return bool(value & 1); return bool(value & 1);
} }
@ -696,7 +696,7 @@ public:
*/ */
uint PowBInt(const Big<exp, man> & pow) uint PowBInt(const Big<exp, man> & pow)
{ {
MATHTT_THIS_ASSERT( pow ) TTMATH_REFERENCE_ASSERT( pow )
if( !pow.IsSign() ) if( !pow.IsSign() )
return PowBUInt(pow); return PowBUInt(pow);
@ -745,7 +745,7 @@ public:
int Pow(const Big<exp, man> pow) int Pow(const Big<exp, man> pow)
#endif #endif
{ {
MATHTT_THIS_ASSERT( pow ) TTMATH_REFERENCE_ASSERT( pow )
if( IsZero() ) if( IsZero() )
{ {
@ -789,7 +789,7 @@ private:
*/ */
void ExpSurrounding0(const Big<exp,man> & x) void ExpSurrounding0(const Big<exp,man> & x)
{ {
MATHTT_THIS_ASSERT( x ) TTMATH_REFERENCE_ASSERT( x )
Big<exp,man> denominator, denominator_i; Big<exp,man> denominator, denominator_i;
Big<exp,man> one, old_value, next_part; Big<exp,man> one, old_value, next_part;
@ -800,13 +800,12 @@ private:
denominator.SetOne(); denominator.SetOne();
denominator_i.SetOne(); denominator_i.SetOne();
// we assume only 'max_loop' iterations of our loop
// every 'step_test' times we make a test // every 'step_test' times we make a test
const uint max_loop = 2000;
const uint step_test = 5; const uint step_test = 5;
// we begin from 1 in order to not testing at the start // 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); bool testing = ((i % step_test) == 0);
@ -870,18 +869,18 @@ 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*BITS_PER_UINT); m.exponent = -int(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] = uint_the_highest_bit; and // e_.mantissa.table[man-1] = TTMATH_UINT_HIGHEST_BIT; and
// e_.exponent.Add(1) mean: // e_.exponent.Add(1) mean:
// e_.mantissa.table[0] = 1; // e_.mantissa.table[0] = 1;
// e_.Standardizing(); // e_.Standardizing();
// e_.exponent.Add(man*BITS_PER_UINT) // e_.exponent.Add(man*TTMATH_BITS_PER_UINT)
// (we must add 'man*BITS_PER_UINT' because we've taken it from the mantissa) // (we must add 'man*TTMATH_BITS_PER_UINT' because we've taken it from the mantissa)
Big<exp,man> e_(x); Big<exp,man> e_(x);
e_.mantissa.SetZero(); 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); c += e_.exponent.Add(1);
e_.Abs(); e_.Abs();
@ -957,13 +956,12 @@ private:
denominator.SetOne(); denominator.SetOne();
SetZero(); SetZero();
// we assume only 'max_loop' iterations of our loop
// every 'step_test' times we make a test // every 'step_test' times we make a test
const uint max_loop = 2000;
const uint step_test = 5; const uint step_test = 5;
// we begin from 1 in order to not testing at the beginning // 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); bool testing = ((i % step_test) == 0);
@ -1026,21 +1024,21 @@ public:
*/ */
uint Ln(const Big<exp,man> & x) uint Ln(const Big<exp,man> & x)
{ {
MATHTT_THIS_ASSERT( x ) TTMATH_REFERENCE_ASSERT( x )
if( x.IsSign() || x.IsZero() ) if( x.IsSign() || x.IsZero() )
return 2; return 2;
// 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*BITS_PER_UINT - 1); m.exponent = -int(man*TTMATH_BITS_PER_UINT - 1);
LnSurrounding1(m); LnSurrounding1(m);
Big<exp,man> exponent_temp; Big<exp,man> exponent_temp;
exponent_temp.FromInt( x.exponent ); exponent_temp.FromInt( x.exponent );
// we must add 'man*BITS_PER_UINT-1' because we've taken it from the mantissa // we must add 'man*TTMATH_BITS_PER_UINT-1' because we've taken it from the mantissa
uint c = exponent_temp.Add(man*BITS_PER_UINT-1); uint c = exponent_temp.Add(man*TTMATH_BITS_PER_UINT-1);
Big<exp,man> ln2; Big<exp,man> ln2;
ln2.SetLn2(); ln2.SetLn2();
@ -1071,10 +1069,10 @@ public:
because if we passed 'parts' into 'ln(base)' as well then because if we passed 'parts' into 'ln(base)' as well then
the error (after dividing) would be too great 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 ) TTMATH_REFERENCE_ASSERT( base )
MATHTT_THIS_ASSERT( x ) TTMATH_REFERENCE_ASSERT( x )
if( x.IsSign() || x.IsZero() ) if( x.IsSign() || x.IsZero() )
return 2; return 2;
@ -1125,10 +1123,10 @@ public:
if( IsZero() ) if( IsZero() )
return 0; 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(TTMATH_BITS_PER_UINT) )
// if exponent > (maxbit + int(BITS_PER_UINT)) the value can't be passed // if exponent > (maxbit + int(TTMATH_BITS_PER_UINT)) the value can't be passed
// into the 'int' type (it's too big) // into the 'int' type (it's too big)
return 1; return 1;
@ -1144,14 +1142,14 @@ public:
how_many_bits = -how_many_bits; how_many_bits = -how_many_bits;
// we're taking into an account only the last word in a mantissa table // 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 ]; result = mantissa_temp.table[ man-1 ];
// the exception for the minimal value // the exception for the minimal value
if( IsSign() && result == uint_the_highest_bit ) if( IsSign() && result == TTMATH_UINT_HIGHEST_BIT )
return 0; return 0;
if( (result & uint_the_highest_bit) != 0 ) if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
// the value is too big // the value is too big
return 1; return 1;
@ -1175,10 +1173,10 @@ public:
if( IsZero() ) if( IsZero() )
return 0; 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*TTMATH_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)) 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;
@ -1192,20 +1190,20 @@ public:
if( how_many_bits < 0 ) if( how_many_bits < 0 )
{ {
how_many_bits = -how_many_bits; how_many_bits = -how_many_bits;
uint index = how_many_bits / BITS_PER_UINT; uint index = how_many_bits / TTMATH_BITS_PER_UINT;
mantissa_temp.Rcr( how_many_bits % BITS_PER_UINT, 0 ); mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
for(uint i=index, a=0 ; i<man ; ++i,++a) for(uint i=index, a=0 ; i<man ; ++i,++a)
result.table[a] = mantissa_temp.table[i]; result.table[a] = mantissa_temp.table[i];
} }
else 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) for(uint i=0 ; i<man ; ++i)
result.table[index+i] = mantissa_temp.table[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 // the exception for the minimal value
@ -1218,7 +1216,7 @@ public:
return 0; 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 // the value is too big
return 1; return 1;
@ -1290,7 +1288,7 @@ public:
uint minimum_size = (int_size < man)? int_size : man; uint minimum_size = (int_size < man)? int_size : man;
int compensation = (int)value.CompensationToLeft(); 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 // copying the highest words
uint i; uint i;
@ -1568,7 +1566,7 @@ private:
// new_exp_ = [log base (2^exponent)] + 1 // new_exp_ = [log base (2^exponent)] + 1
Big<exp+1,man> new_exp_; 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(); new_exp_.SkipFraction();
temp.SetOne(); temp.SetOne();
c += new_exp_.Add( temp ); c += new_exp_.Add( temp );
@ -1628,9 +1626,9 @@ private:
x is greater than 0 x is greater than 0
base is in <2,16> range 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; Big<exp,man> temp;
temp.SetOne(); temp.SetOne();
@ -1691,13 +1689,13 @@ private:
if( !exponent.IsSign() ) if( !exponent.IsSign() )
return 1; return 1;
if( exponent <= -int(man*BITS_PER_UINT) ) if( exponent <= -int(man*TTMATH_BITS_PER_UINT) )
// if 'exponent' is <= than '-int(man*BITS_PER_UINT)' // if 'exponent' is <= than '-int(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*BITS_PER_UINT, 0> // e will be from (-man*TTMATH_BITS_PER_UINT, 0>
int e = -( exponent.ToInt() ); int e = -( exponent.ToInt() );
mantissa.Rcr(e,0); mantissa.Rcr(e,0);
@ -1723,9 +1721,9 @@ private:
{ {
uint value = mantissa.table[i]; 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'; new_man += '1';
else else
new_man += '0'; new_man += '0';
@ -1786,7 +1784,7 @@ private:
// we can have the comma as well because // we can have the comma as well because
// we're using this method later in ToString_CorrectDigitsAfterComma_Round() // we're using this method later in ToString_CorrectDigitsAfterComma_Round()
// (we're only ignoring it) // (we're only ignoring it)
if( new_man[i] == MATHTT_COMMA_CHARACTER_1 ) if( new_man[i] == TTMATH_COMMA_CHARACTER_1 )
continue; continue;
// we're adding one // we're adding one
@ -1898,7 +1896,7 @@ private:
// we're setting the comma within the mantissa // we're setting the comma within the mantissa
int index = new_man_len - e; 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 else
{ {
@ -1907,7 +1905,7 @@ private:
uint how_many = e - new_man_len; uint how_many = e - new_man_len;
std::string man_temp(how_many+1, '0'); 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); new_man.insert(0, man_temp);
} }
@ -1926,7 +1924,7 @@ private:
if( new_man.empty() ) if( new_man.empty() )
return; 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); ToString_CorrectDigitsAfterComma(new_man, base, max_digit_after_comma);
@ -1996,7 +1994,7 @@ private:
// if directly before the first zero is the comma operator // if directly before the first zero is the comma operator
// we're cutting it as well // 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; --i;
new_man.erase(i+1, new_man.length()-i-1); new_man.erase(i+1, new_man.length()-i-1);
@ -2010,7 +2008,7 @@ private:
int max_digit_after_comma) const int 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(MATHTT_COMMA_CHARACTER_1, 0); std::string::size_type index = new_man.find(TTMATH_COMMA_CHARACTER_1, 0);
if( index == std::string::npos ) if( index == std::string::npos )
// nothing was found (actually there can't be this situation) // nothing was found (actually there can't be this situation)
@ -2154,8 +2152,8 @@ private:
*/ */
bool FromString_TestCommaOperator(const char * & source) bool FromString_TestCommaOperator(const char * & source)
{ {
if( (*source == MATHTT_COMMA_CHARACTER_1) || if( (*source == TTMATH_COMMA_CHARACTER_1) ||
(*source == MATHTT_COMMA_CHARACTER_2 && MATHTT_COMMA_CHARACTER_2 != 0 ) ) (*source == TTMATH_COMMA_CHARACTER_2 && TTMATH_COMMA_CHARACTER_2 != 0 ) )
{ {
++source; ++source;
@ -2662,14 +2660,14 @@ 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*BITS_PER_UINT) ) if( exponent <= -int(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();
return; return;
} }
// exponent is in range (-man*BITS_PER_UINT, 0) // exponent is in range (-man*TTMATH_BITS_PER_UINT, 0)
int e = exponent.ToInt(); int e = exponent.ToInt();
mantissa.ClearFirstBits( -e ); mantissa.ClearFirstBits( -e );
@ -2700,17 +2698,17 @@ public:
return; return;
} }
if( exponent <= -int(man*BITS_PER_UINT) ) if( exponent <= -int(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
return; 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 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); 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
@ -2797,10 +2795,10 @@ public:
// we're reading only digits (base=10) and only one comma operator // we're reading only digits (base=10) and only one comma operator
while( s.good() && 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; was_comma = true;
ss += z; 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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/ */
@ -69,7 +69,7 @@ public:
void SetMaxValue() void SetMaxValue()
{ {
UInt<value_size>::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() void SetMinValue()
{ {
UInt<value_size>::SetZero(); 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 ) 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) for( ; i<value_size ; ++i)
UInt<value_size>::table[i] = fill; UInt<value_size>::table[i] = fill;
} }
else 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) for( ; i<argument_size ; ++i)
if( p.table[i] != test ) 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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * 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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/ */
@ -81,7 +81,7 @@ namespace ttmath
"1" "1"
"2.1234" "2.1234"
"2,1234" (they are the same, we can either use a comma or a dot in values) "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"
"(1 + 2) * 3" "(1 + 2) * 3"
"pi" "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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/ */
@ -36,24 +36,24 @@
*/ */
#ifndef headerfilettmathtypes #ifndef headerfilettmathtypes
#define headerfilettmathtypes #define headerfilettmathtypes
/*! /*!
\file ttmathtypes.h \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 <stdexcept>
#include <string> #include <sstream>
#include <iostream>
#include <map>
/*! /*!
@ -61,95 +61,92 @@
*/ */
#define TTMATH_MAJOR_VER 0 #define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 6 #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 this macro enables further testing during writing your code
you don't have to define it in a release mode you don't have to define it in a release mode
if this macro is set then macro MATHTT_ASSERT is set as well if this macro is set then macros TTMATH_ASSERT and TTMATH_REFERENCE_ASSERT
and MATHTT_ASSERT can throw an exception if a condition is not fulfilled are set as well and these macros can throw an exception if a condition in it
(look at the definition of MATHTT_ASSERT) 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 TTMATH_RELEASE
e.g. if you are confident that your code is without bugs you can define TTMATH_RELEASE
// #define MATHTT_DEBUG 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
/*! namespace ttmath
32 bit integer value without a sign {
(the same on 64 bits platform (amd)) /*!
*/ 32 bit integer value without a sign
typedef unsigned int uint; (on 64bit platforms will be 32bit as well)
*/
typedef unsigned int uint;
}
/*! /*!
how many bits there are in the uint type 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) (all bits equal one)
*/ */
#define uint_max_value 4294967295u #define TTMATH_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
/*! /*!
characters which represent the comma operator characters which represent the comma operator
MATHTT_COMMA_CHARACTER_1 is used in reading (parsing) and in writing TTMATH_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_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 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. if you don't want it just put 0 there eg.
#define MATHTT_COMMA_CHARACTER_2 0 #define TTMATH_COMMA_CHARACTER_2 0
then only MATHTT_COMMA_CHARACTER_1 will be used then only TTMATH_COMMA_CHARACTER_1 will be used
don't put here any special character which is used by the parser don't put here any special character which is used by the parser
(for example a semicolon ';' shouldn't be here) (for example a semicolon ';' shouldn't be here)
*/ */
#define MATHTT_COMMA_CHARACTER_1 '.' #define TTMATH_COMMA_CHARACTER_1 '.'
#define MATHTT_COMMA_CHARACTER_2 ',' #define TTMATH_COMMA_CHARACTER_2 ','
////!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//// odwrocic nazwy ma byc TTMATH
/*!
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 enum ErrorCode
{ {
err_ok = 0, err_ok = 0,
err_nothing_has_read = 1, err_nothing_has_read,
err_unknown_character = 2, err_unknown_character,
err_unexpected_final_bracket = 4, err_unexpected_final_bracket,
err_stack_not_clear = 6, err_stack_not_clear,
err_unknown_variable = 8, err_unknown_variable,
err_division_by_zero = 9, err_division_by_zero,
err_interrupt = 10, err_interrupt,
err_overflow = 11, err_overflow,
err_unknown_function = 12, err_unknown_function,
err_unexpected_semicolon_operator = 18, err_unexpected_semicolon_operator,
err_improper_amount_of_arguments = 19, err_improper_amount_of_arguments,
err_improper_argument = 20, err_improper_argument,
err_unexpected_end = 21, err_unexpected_end,
err_internal_error = 100, err_internal_error,
err_incorrect_name, err_incorrect_name,
err_incorrect_value, err_incorrect_value,
err_variable_exists, err_variable_exists,
err_variable_loop, err_variable_loop,
err_functions_loop, err_functions_loop,
err_must_be_only_one_value, err_must_be_only_one_value,
err_object_exists, err_object_exists,
err_unknown_object, err_unknown_object
err_this_cant_be_used = 200
}; };
/*!
*/
class StopCalculating class StopCalculating
{ {
public: public:
@ -201,84 +195,135 @@ namespace ttmath
}; };
/*!
a small class which is useful when compiling with gcc
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
// moze tutaj z runtime dziedziczyc?
//zmienic nazwe na TTMathError
class MathTTError : public std::exception
{ {
ErrorCode code; const char * file;
int line;
public: public:
MathTTError(ErrorCode c) : code(c) {} ExceptionInfo() : file(0), line(0) {}
const char* what() const throw() ExceptionInfo(const char * f, int l) : file(f), line(l) {}
{
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
}
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 #else
#define MATHTT_ASSERT(expression, c) #define TTMATH_REFERENCE_ASSERT(expression)
#define TTMATH_ASSERT(expression)
#endif #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 } // namespace
#endif #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. * and is distributed under the (new) BSD licence.
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> * Author: Tomasz Sowa <t.sowa@slimaczek.pl>
*/ */
@ -50,8 +50,6 @@
#define TTMATH_UINT_GUARD 1234567891 #define TTMATH_UINT_GUARD 1234567891
// !!!
extern bool bylocos;
namespace ttmath namespace ttmath
{ {
@ -113,7 +111,7 @@ public:
void SetMaxValue() void SetMaxValue()
{ {
for(uint i=0 ; i<value_size ; ++i) 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 // rounding mantissa
if( temp_table_index < temp_table_len ) 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 very simply rounding
@ -799,7 +797,7 @@ public:
this method moving all bits into the left side 'bits' times this method moving all bits into the left side 'bits' times
return value <- this <- C 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' or it can be even bigger then all bits will be set to 'c'
the value c will be set into the lowest bits the value c will be set into the lowest bits
@ -811,10 +809,10 @@ public:
int second; int second;
int last_c = 0; int last_c = 0;
if( bits > value_size*BITS_PER_UINT ) if( bits > value_size*TTMATH_BITS_PER_UINT )
bits = value_size*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 ) if( all_words > 0 )
{ {
@ -826,12 +824,12 @@ public:
} }
// sets the rest bits of value into 'c' // 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 ) for( ; first>=0 ; --first )
table[first] = mask; 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 ) for( ; rest_bits > 0 ; --rest_bits )
last_c = Rcl(c); last_c = Rcl(c);
@ -843,7 +841,7 @@ public:
this method moving all bits into the right side 'bits' times this method moving all bits into the right side 'bits' times
c -> this -> return value 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' or it can be even bigger then all bits will be set to 'c'
the value c will be set into the highest bits the value c will be set into the highest bits
@ -855,17 +853,17 @@ public:
int second; int second;
int last_c = 0; int last_c = 0;
if( bits > value_size*BITS_PER_UINT ) if( bits > value_size*TTMATH_BITS_PER_UINT )
bits = value_size*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 ) if( all_words > 0 )
{ {
// copying the first part of the value // copying the first part of the value
for(first=0, second=all_words ; second<int(value_size) ; ++first, ++second) 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]; table[first] = table[second];
} }
@ -873,12 +871,12 @@ public:
last_c = 1; last_c = 1;
// sets the rest bits of value into 'c' // 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 ) for( ; first<int(value_size) ; ++first )
table[first] = mask; 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 ) for( ; rest_bits > 0 ; --rest_bits )
last_c = Rcr(c); last_c = Rcr(c);
@ -906,7 +904,7 @@ public:
if( a != value_size-1 ) 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 // moving all words
int i; int i;
@ -918,7 +916,7 @@ public:
table[i] = 0; 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() ) while( !IsTheHighestBitSet() )
{ {
Rcl(); Rcl();
@ -1011,11 +1009,11 @@ public:
*/ */
void SetBit(uint bit_index) void SetBit(uint bit_index)
{ {
uint index = bit_index / BITS_PER_UINT; uint index = bit_index / TTMATH_BITS_PER_UINT;
if( index >= value_size ) if( index >= value_size )
return; return;
bit_index %= BITS_PER_UINT; bit_index %= TTMATH_BITS_PER_UINT;
uint result = 1; uint result = 1;
if( bit_index > 0 ) if( bit_index > 0 )
@ -1025,75 +1023,14 @@ public:
} }
/*!
*
* Multiplication
*
*
*/
#ifdef UINT_MUL_VERSION_1 public:
/*!
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
/*! /*!
multiplication: result2:result1 = a * b 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();
for(uint x1=0 ; x1<value_size ; ++x1)
#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)
{ {
UInt<value_size*2> result; Mul64(u.table[x1], ss2, &r2, &r1 );
uint i;
if( x1 <= value_size - 2 )
{
if( AddTwoUints(x1,r2,r1) )
return 1;
}
else
{
// last iteration:
// x1 = value_size - 1;
Mul(ss2, result); if( r2 )
// 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 1;
return 0; table[x1] += r1;
}
if( table[x1] < r1 ) // there was a carry
/*! return 1;
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
}
} }
} }
#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: public:
/*! /*!
this method calculates 64bits word a:b / 32bits c (a higher, b lower word) this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
r = a:b / c and rest - remainder r = a:b / c and rest - remainder
@ -1370,6 +1416,8 @@ public:
'remainder' - remainder 'remainder' - remainder
// !!!!!!!!!!! // !!!!!!!!!!!
it needs a new description
we've got two algorithms: we've got two algorithms:
1. with Log(n) where n is the max value which should be held in this class 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) (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) uint Div1_Calculate(const UInt<value_size> & divisor, UInt<value_size> & rest)
{ {
MATHTT_THIS_ASSERT( divisor ) TTMATH_REFERENCE_ASSERT( divisor )
int loop; int loop;
int c; int c;
rest.SetZero(); rest.SetZero();
loop = value_size * BITS_PER_UINT; loop = value_size * TTMATH_BITS_PER_UINT;
c = 0; c = 0;
@ -1593,7 +1641,7 @@ public:
*/ */
uint Div2(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0) uint Div2(const UInt<value_size> & divisor, UInt<value_size> * remainder = 0)
{ {
MATHTT_THIS_ASSERT( divisor ) TTMATH_REFERENCE_ASSERT( divisor )
uint bits_diff; uint bits_diff;
uint status = Div2_Calculate(divisor, remainder, bits_diff); uint status = Div2_Calculate(divisor, remainder, bits_diff);
@ -1692,8 +1740,8 @@ private:
return 0; return 0;
} }
divisor_index += divisor_table_id * BITS_PER_UINT; divisor_index += divisor_table_id * TTMATH_BITS_PER_UINT;
index += table_id * BITS_PER_UINT; index += table_id * TTMATH_BITS_PER_UINT;
if( divisor_table_id == 0 ) if( divisor_table_id == 0 )
{ {
@ -1790,7 +1838,7 @@ public:
*/ */
uint Div3(const UInt<value_size> & v, UInt<value_size> * remainder = 0) uint Div3(const UInt<value_size> & v, UInt<value_size> * remainder = 0)
{ {
MATHTT_THIS_ASSERT( v ) TTMATH_REFERENCE_ASSERT( v )
uint m,n, test; uint m,n, test;
@ -1830,7 +1878,7 @@ private:
void Div3_Division(UInt<value_size> v, UInt<value_size> * remainder, uint m, uint n) 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+1> uu, vv;
UInt<value_size> q; UInt<value_size> q;
@ -1931,7 +1979,7 @@ private:
{ {
uint c = 0; 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 can move the bits only to the 'n-1' index but at the moment
// we don't have such method // we don't have such method
@ -1969,7 +2017,7 @@ private:
u_temp.table[0] = u1; u_temp.table[0] = u1;
u_temp.DivInt(v1, &rp); 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 do
{ {
@ -2048,7 +2096,7 @@ public:
*/ */
void ClearFirstBits(uint n) void ClearFirstBits(uint n)
{ {
if( n >= value_size*BITS_PER_UINT ) if( n >= value_size*TTMATH_BITS_PER_UINT )
{ {
SetZero(); SetZero();
return; return;
@ -2057,10 +2105,10 @@ public:
uint * p = table; uint * p = table;
// first we're clearing the whole words // first we're clearing the whole words
while( n >= BITS_PER_UINT ) while( n >= TTMATH_BITS_PER_UINT )
{ {
*p++ = 0; *p++ = 0;
n -= BITS_PER_UINT; n -= TTMATH_BITS_PER_UINT;
} }
if( n == 0 ) if( n == 0 )
@ -2068,7 +2116,7 @@ public:
// and then we're clearing one word which has left // and then we're clearing one word which has left
// mask -- all bits are set to one // mask -- all bits are set to one
uint mask = uint_max_value; uint mask = TTMATH_UINT_MAX_VALUE;
mask = mask << n; mask = mask << n;
@ -2081,7 +2129,7 @@ public:
*/ */
bool IsTheHighestBitSet() const 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]; table[i] = p.table[i];
if( i < value_size ) if( value_size > argument_size )
{ {
// 'this' is longer than 'p'
for( ; i<value_size ; ++i) for( ; i<value_size ; ++i)
table[i] = 0; table[i] = 0;
} }