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: support for wide characters (wchar_t, std::wstring)
|
||||||
* added: Big::IsInteger()
|
* added: Big::IsInteger()
|
||||||
returns true if the value is integer (without fraction)
|
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: UInt::Sqrt() - a new algorithm for calculating the square root
|
||||||
* added: to the parser: function frac() - returns a value without the integer part
|
* added: to the parser: function frac() - returns a value without the integer part
|
||||||
(only fraction remains)
|
(only fraction remains)
|
||||||
|
* added: Int::DivInt(int divisor, int * remainder)
|
||||||
* changed: Factorial() is using the Gamma() function now
|
* changed: Factorial() is using the Gamma() function now
|
||||||
* changed: Big::Div(ss2)
|
* changed: Big::Div(ss2)
|
||||||
Big::Mod(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)
|
* changed: algorithms in Big::Sqrt() and ttmath::Root(x ; n)
|
||||||
they were not too much accurate for some integers
|
they were not too much accurate for some integers
|
||||||
e.g. Root(16;4) returned a value very closed to 2 (not exactly 2)
|
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
|
* removed: Parser<>::SetFactorialMax() method
|
||||||
the factorial() is such a fast now that we don't need the method longer
|
the factorial() is such a fast now that we don't need the method longer
|
||||||
* removed: ErrorCode::err_too_big_factorial
|
* removed: ErrorCode::err_too_big_factorial
|
||||||
|
|
|
@ -3119,6 +3119,19 @@ private:
|
||||||
if( conv.base == 2 )
|
if( conv.base == 2 )
|
||||||
return ToString_CreateNewMantissaAndExponent_Base2(new_man, new_exp);
|
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
|
// this = mantissa * 2^exponent
|
||||||
|
|
||||||
// temp = +1 * 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
|
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
|
complicated calculations and the output is directly from the source
|
||||||
(there will not be any small distortions)
|
(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>
|
template<class string_type>
|
||||||
uint ToString_CreateNewMantissaAndExponent_Base2( string_type & new_man,
|
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
|
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:
|
private:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue