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>
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue