added: UInt::MulInt(int, UInt<int another_size>::&)
added: Big::MulUInt(uint) changed: Big::MulInt(sint) added: Big::ToUInt(uint &) changed: Big::ToInt(sint&) changed: Factorial() it uses Big::MulUInt() at the beginning (faster now especially more on a 32bit platform) git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@33 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
c97ebf282f
commit
e40ed603c6
|
@ -1529,10 +1529,77 @@ namespace ttmath
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace auxiliaryfunctions
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
uint FactorialInt( const ValueType & x, ErrorCode * err,
|
||||||
|
const volatile StopCalculating * stop,
|
||||||
|
ValueType & result)
|
||||||
|
{
|
||||||
|
uint maxvalue = TTMATH_UINT_MAX_VALUE;
|
||||||
|
|
||||||
|
if( x < TTMATH_UINT_MAX_VALUE )
|
||||||
|
x.ToUInt(maxvalue);
|
||||||
|
|
||||||
|
uint multipler = 1;
|
||||||
|
uint carry = 0;
|
||||||
|
|
||||||
|
while( !carry && multipler<maxvalue )
|
||||||
|
{
|
||||||
|
if( stop && stop->WasStopSignal() )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_interrupt;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
++multipler;
|
||||||
|
carry += result.MulUInt(multipler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = carry ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return carry ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class ValueType>
|
||||||
|
int FactorialMore( const ValueType & x, ErrorCode * err,
|
||||||
|
const volatile StopCalculating * stop,
|
||||||
|
ValueType & result)
|
||||||
|
{
|
||||||
|
ValueType multipler(TTMATH_UINT_MAX_VALUE);
|
||||||
|
ValueType one;
|
||||||
|
|
||||||
|
one.SetOne();
|
||||||
|
uint carry = 0;
|
||||||
|
|
||||||
|
while( !carry && multipler < x )
|
||||||
|
{
|
||||||
|
if( stop && stop->WasStopSignal() )
|
||||||
|
{
|
||||||
|
if( err )
|
||||||
|
*err = err_interrupt;
|
||||||
|
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
carry += multipler.Add(one);
|
||||||
|
carry += result.Mul(multipler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( err )
|
||||||
|
*err = carry ? err_overflow : err_ok;
|
||||||
|
|
||||||
|
return carry ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1543,6 +1610,8 @@ namespace ttmath
|
||||||
template<class ValueType>
|
template<class ValueType>
|
||||||
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
|
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
|
||||||
{
|
{
|
||||||
|
using namespace auxiliaryfunctions;
|
||||||
|
|
||||||
static History<ValueType> history;
|
static History<ValueType> history;
|
||||||
ValueType result;
|
ValueType result;
|
||||||
|
|
||||||
|
@ -1577,33 +1646,17 @@ namespace ttmath
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType multipler;
|
uint status = FactorialInt(x, err, stop, result);
|
||||||
ValueType one;
|
if( status == 0 )
|
||||||
uint carry = 0;
|
status = FactorialMore(x, err, stop, result);
|
||||||
|
|
||||||
one = result; // =1
|
|
||||||
multipler = result; // =1
|
|
||||||
|
|
||||||
while( !carry && multipler < x )
|
|
||||||
{
|
|
||||||
if( stop && stop->WasStopSignal() )
|
|
||||||
{
|
|
||||||
if( err )
|
|
||||||
*err = err_interrupt;
|
|
||||||
|
|
||||||
|
if( status == 2 )
|
||||||
|
// the calculation has been interrupted
|
||||||
return result;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
carry += multipler.Add(one);
|
|
||||||
carry += result.Mul(multipler);
|
|
||||||
}
|
|
||||||
|
|
||||||
err_tmp = carry ? err_overflow : err_ok;
|
err_tmp = status==1 ? err_overflow : err_ok;
|
||||||
history.Add(x, result, err_tmp);
|
history.Add(x, result, err_tmp);
|
||||||
|
|
||||||
if( err )
|
|
||||||
*err = carry ? err_overflow : err_ok;
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -593,7 +593,74 @@ public:
|
||||||
return Add(ss2);
|
return Add(ss2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Multiplication this = this * ss2 (ss2 is uint)
|
||||||
|
|
||||||
|
ss2 without a sign
|
||||||
|
*/
|
||||||
|
uint MulUInt(uint ss2)
|
||||||
|
{
|
||||||
|
UInt<man+1> man_result;
|
||||||
|
uint i,c = 0;
|
||||||
|
|
||||||
|
// man_result = mantissa * ss2.mantissa
|
||||||
|
mantissa.MulInt(ss2, man_result);
|
||||||
|
|
||||||
|
int bit = UInt<man>::FindLeadingBitInWord(man_result.table[man]); // man - last word
|
||||||
|
|
||||||
|
if( bit!=-1 && uint(bit) > (TTMATH_BITS_PER_UINT/2) )
|
||||||
|
{
|
||||||
|
// 'i' will be from 0 to TTMATH_BITS_PER_UINT
|
||||||
|
i = man_result.CompensationToLeft();
|
||||||
|
c = exponent.Add( TTMATH_BITS_PER_UINT - i );
|
||||||
|
|
||||||
|
for(i=0 ; i<man ; ++i)
|
||||||
|
mantissa.table[i] = man_result.table[i+1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if( bit != -1 )
|
||||||
|
{
|
||||||
|
man_result.Rcr(bit+1, 0);
|
||||||
|
c += exponent.Add(bit+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0 ; i<man ; ++i)
|
||||||
|
mantissa.table[i] = man_result.table[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
c += Standardizing();
|
||||||
|
|
||||||
|
return (c==0)? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Multiplication this = this * ss2 (ss2 is sint)
|
||||||
|
|
||||||
|
ss2 with a sign
|
||||||
|
*/
|
||||||
|
uint MulInt(sint ss2)
|
||||||
|
{
|
||||||
|
if( IsSign() == (ss2<0) )
|
||||||
|
{
|
||||||
|
// the signs are the same, the result is positive
|
||||||
|
Abs();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// the signs are different, the result is negative
|
||||||
|
SetSign();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( ss2<0 )
|
||||||
|
ss2 = 0 - ss2;
|
||||||
|
|
||||||
|
return MulUInt( uint(ss2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
multiplication this = this * ss2
|
multiplication this = this * ss2
|
||||||
this method returns carry
|
this method returns carry
|
||||||
|
@ -1275,6 +1342,48 @@ public:
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
this method sets 'result' as the one word of type uint
|
||||||
|
|
||||||
|
if the value is too big this method returns a carry (1)
|
||||||
|
*/
|
||||||
|
uint ToUInt(uint & result, bool test_sign = true) const
|
||||||
|
{
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
if( IsZero() )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if( test_sign && IsSign() )
|
||||||
|
// the result should be positive
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
|
||||||
|
|
||||||
|
if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
|
||||||
|
// if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
|
||||||
|
// into the 'sint' type (it's too big)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if( exponent <= maxbit )
|
||||||
|
// our value is from the range of (-1,1) and we return zero
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
UInt<man> mantissa_temp(mantissa);
|
||||||
|
// exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) >
|
||||||
|
sint how_many_bits = exponent.ToInt();
|
||||||
|
|
||||||
|
// how_many_bits is negative, we'll make it positive
|
||||||
|
how_many_bits = -how_many_bits;
|
||||||
|
|
||||||
|
// we're taking into account only the last word in a mantissa table
|
||||||
|
mantissa_temp.Rcr( how_many_bits % TTMATH_BITS_PER_UINT, 0 );
|
||||||
|
result = mantissa_temp.table[ man-1 ];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
this method sets 'result' as the one word of type sint
|
this method sets 'result' as the one word of type sint
|
||||||
|
@ -1284,42 +1393,23 @@ public:
|
||||||
uint ToInt(sint & result) const
|
uint ToInt(sint & result) const
|
||||||
{
|
{
|
||||||
result = 0;
|
result = 0;
|
||||||
|
uint result_uint;
|
||||||
|
|
||||||
if( IsZero() )
|
if( ToUInt(result_uint, false) )
|
||||||
return 0;
|
|
||||||
|
|
||||||
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
|
|
||||||
|
|
||||||
if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
|
|
||||||
// if exponent > (maxbit + sint(TTMATH_BITS_PER_UINT)) the value can't be passed
|
|
||||||
// into the 'sint' type (it's too big)
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( exponent <= maxbit )
|
result = static_cast<sint>( result_uint );
|
||||||
// our value is from range (-1,1) and we return zero
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
UInt<man> mantissa_temp(mantissa);
|
|
||||||
// exponent is from a range of (-maxbit,0>
|
|
||||||
sint how_many_bits = exponent.ToInt();
|
|
||||||
|
|
||||||
// how_many_bits is negative, we'll make it positive
|
|
||||||
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 % TTMATH_BITS_PER_UINT, 0 );
|
|
||||||
result = mantissa_temp.table[ man-1 ];
|
|
||||||
|
|
||||||
// the exception for the minimal value
|
// the exception for the minimal value
|
||||||
if( IsSign() && result == TTMATH_UINT_HIGHEST_BIT )
|
if( IsSign() && result_uint == TTMATH_UINT_HIGHEST_BIT )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
if( (result_uint & TTMATH_UINT_HIGHEST_BIT) != 0 )
|
||||||
// the value is too big
|
// the value is too big
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if( IsSign() )
|
if( IsSign() )
|
||||||
result = -sint(result);
|
result = -result;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1343,7 +1433,6 @@ public:
|
||||||
if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )
|
if( exponent > maxbit + sint(int_size*TTMATH_BITS_PER_UINT) )
|
||||||
// if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
|
// if exponent > (maxbit + sint(int_size*TTMATH_BITS_PER_UINT)) the value can't be passed
|
||||||
// into the 'Int<int_size>' type (it's too big)
|
// into the 'Int<int_size>' type (it's too big)
|
||||||
return 1;
|
|
||||||
|
|
||||||
if( exponent <= maxbit )
|
if( exponent <= maxbit )
|
||||||
// our value is from range (-1,1) and we return zero
|
// our value is from range (-1,1) and we return zero
|
||||||
|
|
|
@ -618,6 +618,7 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
|
||||||
Error( err );
|
Error( err );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Abs(int sindex, int amount_of_args, ValueType & result)
|
void Abs(int sindex, int amount_of_args, ValueType & result)
|
||||||
{
|
{
|
||||||
if( amount_of_args != 1 )
|
if( amount_of_args != 1 )
|
||||||
|
@ -2126,7 +2127,6 @@ ErrorCode Parse(const char * str)
|
||||||
|
|
||||||
stack.resize( default_stack_size );
|
stack.resize( default_stack_size );
|
||||||
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Parse();
|
Parse();
|
||||||
|
|
|
@ -1442,6 +1442,47 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
multiplication: result = this * ss2
|
||||||
|
|
||||||
|
we're using this method only when result_size is greater than value_size
|
||||||
|
if so there will not be a carry
|
||||||
|
*/
|
||||||
|
template<uint result_size>
|
||||||
|
uint MulInt(uint ss2, UInt<result_size> & result)
|
||||||
|
{
|
||||||
|
uint r2,r1;
|
||||||
|
uint x1size=value_size;
|
||||||
|
uint x1start=0;
|
||||||
|
|
||||||
|
if( value_size >= result_size )
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
result.SetZero();
|
||||||
|
|
||||||
|
if( value_size > 2 )
|
||||||
|
{
|
||||||
|
// if the value_size is smaller than or equal to 2
|
||||||
|
// there is no sense to set x1size and x1start to another values
|
||||||
|
|
||||||
|
for(x1size=value_size ; x1size>0 && table[x1size-1]==0 ; --x1size);
|
||||||
|
|
||||||
|
if( x1size==0 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for(x1start=0 ; x1start<x1size && table[x1start]==0 ; ++x1start);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint x1=x1start ; x1<x1size ; ++x1)
|
||||||
|
{
|
||||||
|
MulTwoWords(table[x1], ss2, &r2, &r1 );
|
||||||
|
result.AddTwoInts(r2,r1,x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
the multiplication 'this' = 'this' * ss2
|
the multiplication 'this' = 'this' * ss2
|
||||||
|
|
Loading…
Reference in New Issue