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:
parent
ab42f75285
commit
1dabd725cb
10
CHANGELOG
10
CHANGELOG
|
@ -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
4
TODO
|
@ -1,7 +1,5 @@
|
|||
TODO TTMath Library
|
||||
===================
|
||||
|
||||
|
||||
|
||||
|
||||
* add the method Mod (a remainder from a division) for the Big type
|
||||
|
||||
|
|
109
ttmath/ttmath.h
109
ttmath/ttmath.h
|
@ -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() )
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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>
|
||||
*/
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue