added: IEEE 754 half-to-even rounding (bankers' rounding) to the following

floating point algorithms:
         Big::Add
         Big::Sub
         Big::Mul
         Big::Div



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@258 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2009-12-06 01:09:55 +00:00
parent 72052420dd
commit 357524ae13
2 changed files with 95 additions and 11 deletions

View File

@ -1,7 +1,13 @@
Version 0.9.1 prerelease (2009.12.05):
Version 0.9.1 prerelease (2009.12.06):
* fixed: the parser didn't use characters for changing the base (# and &)
those characters were skipped
(this bug was introduced in 0.9.0)
* added: IEEE 754 half-to-even rounding (bankers' rounding) to the following
floating point algorithms:
Big::Add
Big::Sub
Big::Mul
Big::Div
* added: to Big::ToString() - additional rounding when conv.base_round is used
if the value is not an integer we calculate how many valid digits there are
after the comma operator (in conv.base radix) and then we skipped the rest

View File

@ -714,7 +714,36 @@ public:
private:
/*!
this method does the half-to-even rounding (banker's rounding)
if is_half is:
true - that means the rest was equal the half (0.5 decimal)
false - that means the rest was greater than a half (greater than 0.5 decimal)
if the rest was less than a half then don't call this method
(the rounding should does nothing then)
*/
uint RoundHalfToEven(bool is_half)
{
uint c = 0;
if( !is_half || mantissa.IsTheLowestBitSet() )
{
if( mantissa.AddOne() )
{
mantissa.Rcr(1, 1);
c = exponent.AddOne();
}
}
return c;
}
public:
/*!
*
@ -772,8 +801,11 @@ public:
// values have the same signs
if( mantissa.Add(ss2.mantissa) )
{
mantissa.Rcr(1,1);
c = exponent.AddOne();
bool is_exact_half = mantissa.Rcr(1,1);
c += exponent.AddOne();
if( is_exact_half )
c += RoundHalfToEven(is_exact_half);
}
}
else
@ -1078,6 +1110,41 @@ public:
}
private:
/*!
this method checks whether a table pointed by 'tab' and 'len'
has the value 0.5 decimal
(it is treated as the comma operator would be before the highest bit)
call this method only if the highest bit is set - you have to test it beforehand
return:
true - tab was equal the half (0.5 decimal)
false - tab was greater than a half (greater than 0.5 decimal)
*/
bool CheckGreaterOrEqualHalf(uint * tab, uint len)
{
uint i;
TTMATH_ASSERT( len>0 && (tab[len-1] & TTMATH_UINT_HIGHEST_BIT)!=0 )
for(i=0 ; i<len-1 ; ++i)
if( tab[i] != 0 )
return false;
if( tab[i] != TTMATH_UINT_HIGHEST_BIT )
return false;
return true;
}
public:
/*!
multiplication this = this * ss2
this method returns a carry
@ -1087,7 +1154,8 @@ public:
TTMATH_REFERENCE_ASSERT( ss2 )
UInt<man*2> man_result;
uint i,c;
uint c = 0;
uint i;
if( IsNan() || ss2.IsNan() )
return CheckCarry(1);
@ -1110,13 +1178,22 @@ public:
// if there is a zero value in man_result the method CompensationToLeft()
// returns 0 but we'll correct this at the end in Standardizing() method)
i = man_result.CompensationToLeft();
uint exp_add = man * TTMATH_BITS_PER_UINT - i;
if( exp_add )
c += exponent.Add( exp_add );
c = exponent.Add( man * TTMATH_BITS_PER_UINT - i );
c += exponent.Add( ss2.exponent );
for(i=0 ; i<man ; ++i)
mantissa.table[i] = man_result.table[i+man];
if( (man_result.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
{
bool is_half = CheckGreaterOrEqualHalf(man_result.table, man);
c += RoundHalfToEven(is_half);
}
if( IsSign() == ss2.IsSign() )
{
// the signs are the same, the result is positive
@ -1187,6 +1264,12 @@ public:
for(i=0 ; i<man ; ++i)
mantissa.table[i] = man1.table[i+man];
if( (man1.table[man-1] & TTMATH_UINT_HIGHEST_BIT) != 0 )
{
bool is_half = CheckGreaterOrEqualHalf(man1.table, man);
c += RoundHalfToEven(is_half);
}
if( IsSign() == ss2.IsSign() )
Abs();
else
@ -4374,11 +4457,6 @@ private:
for( ; true ; ++source, ++index )
{
if( index == 98 )
{
index = 98;
}
if( conv.group!=0 && *source==static_cast<char>(conv.group) )
continue;