added: Int::DivInt(int divisor, int * remainder)
changed: added specializations to Big::ToString() when the base is equal 4, 8 or 16 the previous version was not accurate on some last digits (after the comma operator) consider this binary value (32 bit mantissa): base 2: 1.1111 1111 1111 1111 1111 1111 1110 101 previous ToString() gave: base 4: 1.33333333333332 base 8: 1.777777777 base 16: 1.FFFFFF now we have: base 4: 1.3333333333333222 base 8: 1.77777777724 base 16: 1.FFFFFFEA git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@238 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
parent
4b4b30392a
commit
0d1a57bdb4
15
CHANGELOG
15
CHANGELOG
|
@ -1,4 +1,4 @@
|
|||
Version 0.9.0 prerelease (2009.11.01):
|
||||
Version 0.9.0 prerelease (2009.11.09):
|
||||
* added: support for wide characters (wchar_t, std::wstring)
|
||||
* added: Big::IsInteger()
|
||||
returns true if the value is integer (without fraction)
|
||||
|
@ -47,6 +47,7 @@ Version 0.9.0 prerelease (2009.11.01):
|
|||
* added: UInt::Sqrt() - a new algorithm for calculating the square root
|
||||
* added: to the parser: function frac() - returns a value without the integer part
|
||||
(only fraction remains)
|
||||
* added: Int::DivInt(int divisor, int * remainder)
|
||||
* changed: Factorial() is using the Gamma() function now
|
||||
* changed: Big::Div(ss2)
|
||||
Big::Mod(ss2)
|
||||
|
@ -55,6 +56,18 @@ Version 0.9.0 prerelease (2009.11.01):
|
|||
* changed: algorithms in Big::Sqrt() and ttmath::Root(x ; n)
|
||||
they were not too much accurate for some integers
|
||||
e.g. Root(16;4) returned a value very closed to 2 (not exactly 2)
|
||||
* changed: added specializations to Big::ToString() when the base is equal 4, 8 or 16
|
||||
the previous version was not accurate on some last digits (after the comma operator)
|
||||
consider this binary value (32 bit mantissa):
|
||||
base 2: 1.1111 1111 1111 1111 1111 1111 1110 101
|
||||
previous ToString() gave:
|
||||
base 4: 1.33333333333332
|
||||
base 8: 1.777777777
|
||||
base 16: 1.FFFFFF
|
||||
now we have:
|
||||
base 4: 1.3333333333333222
|
||||
base 8: 1.77777777724
|
||||
base 16: 1.FFFFFFEA
|
||||
* removed: Parser<>::SetFactorialMax() method
|
||||
the factorial() is such a fast now that we don't need the method longer
|
||||
* removed: ErrorCode::err_too_big_factorial
|
||||
|
|
|
@ -3119,6 +3119,19 @@ private:
|
|||
if( conv.base == 2 )
|
||||
return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp);
|
||||
|
||||
// the speciality for base equal 4
|
||||
if( conv.base == 4 )
|
||||
return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 2);
|
||||
|
||||
// the speciality for base equal 8
|
||||
if( conv.base == 8 )
|
||||
return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 3);
|
||||
|
||||
// the speciality for base equal 16
|
||||
if( conv.base == 16 )
|
||||
return ToString_CreateNewMantissaAndExponent_BasePow2(new_man, new_exp, 4);
|
||||
|
||||
|
||||
// this = mantissa * 2^exponent
|
||||
|
||||
// temp = +1 * 2^exponent
|
||||
|
@ -3348,9 +3361,6 @@ private:
|
|||
we use it because if base is equal 2 we don't have to make those
|
||||
complicated calculations and the output is directly from the source
|
||||
(there will not be any small distortions)
|
||||
|
||||
(we can make that speciality when the base is 4,8 or 16 as well
|
||||
but maybe in further time)
|
||||
*/
|
||||
template<class string_type>
|
||||
uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man,
|
||||
|
@ -3377,6 +3387,135 @@ private:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
a special method used to calculate the new mantissa and exponent
|
||||
when the 'base' is equal 4, 8 or 16
|
||||
|
||||
when base is 4 then bits is 2
|
||||
when base is 8 then bits is 3
|
||||
when base is 16 then bits is 4
|
||||
(and the algorithm can be used with a base greater than 16)
|
||||
*/
|
||||
template<class string_type>
|
||||
uint ToString_CreateNewMantissaAndExponent_BasePow2( string_type & new_man,
|
||||
Int<exp+1> & new_exp,
|
||||
uint bits) const
|
||||
{
|
||||
int move; // how many times move the mantissa
|
||||
UInt<man+1> man_temp(mantissa); // man+1 for moving
|
||||
new_exp = exponent;
|
||||
new_exp.DivInt((int)bits, move);
|
||||
|
||||
if( move != 0 )
|
||||
{
|
||||
// we're moving the man_temp to left-hand side
|
||||
if( move < 0 )
|
||||
{
|
||||
move = bits + move;
|
||||
new_exp.SubOne(); // when move is < than 0 then new_exp is < 0 too
|
||||
}
|
||||
|
||||
man_temp.Rcl(move);
|
||||
}
|
||||
|
||||
|
||||
if( bits == 3 )
|
||||
{
|
||||
// base 8
|
||||
// now 'move' is greater than or equal 0
|
||||
uint len = man*TTMATH_BITS_PER_UINT + move;
|
||||
return ToString_CreateNewMantissaAndExponent_Base8(new_man, man_temp, len, bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
// base 4 or 16
|
||||
return ToString_CreateNewMantissaAndExponent_Base4or16(new_man, man_temp, bits);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a special method used to calculate the new mantissa
|
||||
when the 'base' is equal 8
|
||||
|
||||
bits is always 3
|
||||
|
||||
we can use this algorithm when the base is 4 or 16 too
|
||||
but we have a faster method ToString_CreateNewMantissaAndExponent_Base4or16()
|
||||
*/
|
||||
template<class string_type>
|
||||
uint ToString_CreateNewMantissaAndExponent_Base8( string_type & new_man,
|
||||
UInt<man+1> & man_temp,
|
||||
uint len,
|
||||
uint bits) const
|
||||
{
|
||||
uint shift = TTMATH_BITS_PER_UINT - bits;
|
||||
uint mask = TTMATH_UINT_MAX_VALUE >> shift;
|
||||
uint i;
|
||||
|
||||
for( i=0 ; i<len ; i+=bits )
|
||||
{
|
||||
uint digit = man_temp.table[0] & mask;
|
||||
new_man.insert(new_man.begin(), static_cast<char>(Misc::DigitToChar(digit)));
|
||||
|
||||
man_temp.Rcr(bits);
|
||||
}
|
||||
|
||||
TTMATH_ASSERT( man_temp.IsZero() )
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
a special method used to calculate the new mantissa
|
||||
when the 'base' is equal 4 or 16
|
||||
|
||||
when the base is equal 4 or 16 the bits is 2 or 4
|
||||
and because TTMATH_BITS_PER_UINT (32 or 64) is divisible by 2 (or 4)
|
||||
then we can get digits from the end of our mantissa
|
||||
*/
|
||||
template<class string_type>
|
||||
uint ToString_CreateNewMantissaAndExponent_Base4or16( string_type & new_man,
|
||||
UInt<man+1> & man_temp,
|
||||
uint bits) const
|
||||
{
|
||||
TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 2 == 0 )
|
||||
TTMATH_ASSERT( TTMATH_BITS_PER_UINT % 4 == 0 )
|
||||
|
||||
uint shift = TTMATH_BITS_PER_UINT - bits;
|
||||
uint mask = TTMATH_UINT_MAX_VALUE << shift;
|
||||
uint digit;
|
||||
|
||||
// table[man] - last word - is different from zero if we moved man_temp
|
||||
digit = man_temp.table[man];
|
||||
|
||||
if( digit != 0 )
|
||||
new_man += static_cast<char>(Misc::DigitToChar(digit));
|
||||
|
||||
|
||||
for( int i=man-1 ; i>=0 ; --i )
|
||||
{
|
||||
uint shift_local = shift;
|
||||
uint mask_local = mask;
|
||||
|
||||
while( mask_local != 0 )
|
||||
{
|
||||
digit = man_temp.table[i] & mask_local;
|
||||
|
||||
if( shift_local != 0 )
|
||||
digit = digit >> shift_local;
|
||||
|
||||
new_man += static_cast<char>(Misc::DigitToChar(digit));
|
||||
mask_local = mask_local >> bits;
|
||||
shift_local = shift_local - bits;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
an auxiliary method for converting into the string
|
||||
|
||||
|
|
|
@ -468,6 +468,64 @@ public:
|
|||
}
|
||||
|
||||
|
||||
/*!
|
||||
division this = this / ss2 (ss2 is int)
|
||||
returned values:
|
||||
0 - ok
|
||||
1 - division by zero
|
||||
|
||||
for example: (result means 'this')
|
||||
20 / 3 --> result: 6 remainder: 2
|
||||
-20 / 3 --> result: -6 remainder: -2
|
||||
20 / -3 --> result: -6 remainder: 2
|
||||
-20 / -3 --> result: 6 remainder: -2
|
||||
|
||||
in other words: this(old) = ss2 * this(new)(result) + remainder
|
||||
*/
|
||||
uint DivInt(int ss2, int * remainder = 0)
|
||||
{
|
||||
bool ss1_is_sign, ss2_is_sign;
|
||||
|
||||
ss1_is_sign = IsSign();
|
||||
|
||||
/*
|
||||
we don't have to test the carry from Abs as well as in Mul
|
||||
*/
|
||||
Abs();
|
||||
|
||||
if( ss2 < 0 )
|
||||
{
|
||||
ss2 = -ss2;
|
||||
ss2_is_sign = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
ss2_is_sign = false;
|
||||
}
|
||||
|
||||
uint rem;
|
||||
uint c = UInt<value_size>::DivInt((uint)ss2, &rem);
|
||||
|
||||
if( ss1_is_sign != ss2_is_sign )
|
||||
SetSign();
|
||||
|
||||
if( remainder )
|
||||
{
|
||||
if( ss1_is_sign )
|
||||
*remainder = -int(rem);
|
||||
else
|
||||
*remainder = int(rem);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
uint DivInt(int ss2, int & remainder)
|
||||
{
|
||||
return DivInt(ss2, &remainder);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
|
Loading…
Reference in New Issue