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:
Tomasz Sowa 2007-04-07 22:21:31 +00:00
parent c97ebf282f
commit e40ed603c6
4 changed files with 233 additions and 50 deletions

View File

@ -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>
ValueType Factorial(const ValueType & x, ErrorCode * err = 0, const volatile StopCalculating * stop = 0)
{
using namespace auxiliaryfunctions;
static History<ValueType> history;
ValueType result;
@ -1577,33 +1646,17 @@ namespace ttmath
return result;
}
ValueType multipler;
ValueType one;
uint carry = 0;
one = result; // =1
multipler = result; // =1
while( !carry && multipler < x )
{
if( stop && stop->WasStopSignal() )
{
if( err )
*err = err_interrupt;
uint status = FactorialInt(x, err, stop, result);
if( status == 0 )
status = FactorialMore(x, err, stop, result);
if( status == 2 )
// the calculation has been interrupted
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);
if( err )
*err = carry ? err_overflow : err_ok;
return result;
}

View File

@ -593,7 +593,74 @@ public:
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
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
@ -1284,42 +1393,23 @@ public:
uint ToInt(sint & result) const
{
result = 0;
uint result_uint;
if( IsZero() )
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)
if( ToUInt(result_uint, false) )
return 1;
if( exponent <= maxbit )
// 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 ];
result = static_cast<sint>( result_uint );
// the exception for the minimal value
if( IsSign() && result == TTMATH_UINT_HIGHEST_BIT )
if( IsSign() && result_uint == TTMATH_UINT_HIGHEST_BIT )
return 0;
if( (result & TTMATH_UINT_HIGHEST_BIT) != 0 )
if( (result_uint & TTMATH_UINT_HIGHEST_BIT) != 0 )
// the value is too big
return 1;
if( IsSign() )
result = -sint(result);
result = -result;
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)) the value can't be passed
// into the 'Int<int_size>' type (it's too big)
return 1;
if( exponent <= maxbit )
// our value is from range (-1,1) and we return zero

View File

@ -618,6 +618,7 @@ void Factorial(int sindex, int amount_of_args, ValueType & result)
Error( err );
}
void Abs(int sindex, int amount_of_args, ValueType & result)
{
if( amount_of_args != 1 )
@ -2126,7 +2127,6 @@ ErrorCode Parse(const char * str)
stack.resize( default_stack_size );
try
{
Parse();

View File

@ -1442,6 +1442,47 @@ public:
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