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:
parent
72052420dd
commit
357524ae13
|
@ -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 &)
|
* fixed: the parser didn't use characters for changing the base (# and &)
|
||||||
those characters were skipped
|
those characters were skipped
|
||||||
(this bug was introduced in 0.9.0)
|
(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
|
* 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
|
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
|
after the comma operator (in conv.base radix) and then we skipped the rest
|
||||||
|
|
|
@ -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
|
// values have the same signs
|
||||||
if( mantissa.Add(ss2.mantissa) )
|
if( mantissa.Add(ss2.mantissa) )
|
||||||
{
|
{
|
||||||
mantissa.Rcr(1,1);
|
bool is_exact_half = mantissa.Rcr(1,1);
|
||||||
c = exponent.AddOne();
|
c += exponent.AddOne();
|
||||||
|
|
||||||
|
if( is_exact_half )
|
||||||
|
c += RoundHalfToEven(is_exact_half);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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
|
multiplication this = this * ss2
|
||||||
this method returns a carry
|
this method returns a carry
|
||||||
|
@ -1087,7 +1154,8 @@ public:
|
||||||
TTMATH_REFERENCE_ASSERT( ss2 )
|
TTMATH_REFERENCE_ASSERT( ss2 )
|
||||||
|
|
||||||
UInt<man*2> man_result;
|
UInt<man*2> man_result;
|
||||||
uint i,c;
|
uint c = 0;
|
||||||
|
uint i;
|
||||||
|
|
||||||
if( IsNan() || ss2.IsNan() )
|
if( IsNan() || ss2.IsNan() )
|
||||||
return CheckCarry(1);
|
return CheckCarry(1);
|
||||||
|
@ -1110,13 +1178,22 @@ public:
|
||||||
// if there is a zero value in man_result the method CompensationToLeft()
|
// 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)
|
// returns 0 but we'll correct this at the end in Standardizing() method)
|
||||||
i = man_result.CompensationToLeft();
|
i = man_result.CompensationToLeft();
|
||||||
|
uint exp_add = man * TTMATH_BITS_PER_UINT - i;
|
||||||
c = exponent.Add( man * TTMATH_BITS_PER_UINT - i );
|
|
||||||
|
if( exp_add )
|
||||||
|
c += exponent.Add( exp_add );
|
||||||
|
|
||||||
c += exponent.Add( ss2.exponent );
|
c += exponent.Add( ss2.exponent );
|
||||||
|
|
||||||
for(i=0 ; i<man ; ++i)
|
for(i=0 ; i<man ; ++i)
|
||||||
mantissa.table[i] = man_result.table[i+man];
|
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() )
|
if( IsSign() == ss2.IsSign() )
|
||||||
{
|
{
|
||||||
// the signs are the same, the result is positive
|
// the signs are the same, the result is positive
|
||||||
|
@ -1187,6 +1264,12 @@ public:
|
||||||
for(i=0 ; i<man ; ++i)
|
for(i=0 ; i<man ; ++i)
|
||||||
mantissa.table[i] = man1.table[i+man];
|
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() )
|
if( IsSign() == ss2.IsSign() )
|
||||||
Abs();
|
Abs();
|
||||||
else
|
else
|
||||||
|
@ -4374,11 +4457,6 @@ private:
|
||||||
|
|
||||||
for( ; true ; ++source, ++index )
|
for( ; true ; ++source, ++index )
|
||||||
{
|
{
|
||||||
if( index == 98 )
|
|
||||||
{
|
|
||||||
index = 98;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( conv.group!=0 && *source==static_cast<char>(conv.group) )
|
if( conv.group!=0 && *source==static_cast<char>(conv.group) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue