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,9 +1529,76 @@ 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); err_tmp = status==1 ? err_overflow : err_ok;
carry += result.Mul(multipler);
}
err_tmp = carry ? 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;
} }

View File

@ -594,6 +594,73 @@ public:
} }
/*!
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,19 +1342,22 @@ public:
* *
*/ */
/*! /*!
this method sets 'result' as the one word of type sint this method sets 'result' as the one word of type uint
if the value is too big this method returns a carry (1) if the value is too big this method returns a carry (1)
*/ */
uint ToInt(sint & result) const uint ToUInt(uint & result, bool test_sign = true) const
{ {
result = 0; result = 0;
if( IsZero() ) if( IsZero() )
return 0; return 0;
if( test_sign && IsSign() )
// the result should be positive
return 1;
sint maxbit = -sint(man*TTMATH_BITS_PER_UINT); sint maxbit = -sint(man*TTMATH_BITS_PER_UINT);
if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) ) if( exponent > maxbit + sint(TTMATH_BITS_PER_UINT) )
@ -1296,30 +1366,50 @@ public:
return 1; return 1;
if( exponent <= maxbit ) if( exponent <= maxbit )
// our value is from range (-1,1) and we return zero // our value is from the range of (-1,1) and we return zero
return 0; return 0;
UInt<man> mantissa_temp(mantissa); UInt<man> mantissa_temp(mantissa);
// exponent is from a range of (-maxbit,0> // exponent is from a range of (maxbit, maxbit + sint(TTMATH_BITS_PER_UINT) >
sint how_many_bits = exponent.ToInt(); sint how_many_bits = exponent.ToInt();
// how_many_bits is negative, we'll make it positive // how_many_bits is negative, we'll make it positive
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 account only the last word in a mantissa table
mantissa_temp.Rcr( how_many_bits % TTMATH_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 ];
return 0;
}
/*!
this method sets 'result' as the one word of type sint
if the value is too big this method returns a carry (1)
*/
uint ToInt(sint & result) const
{
result = 0;
uint result_uint;
if( ToUInt(result_uint, false) )
return 1;
result = static_cast<sint>( result_uint );
// 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

View File

@ -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();

View File

@ -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