fixed: Big::Mod(x) didn't correctly return a carry

and the result was sometimes very big (even greater than x)
fixed:   global function Mod(x) didn't set an ErrorCode object
fixed:   global function Round() didn't test a carry
         now it sets ErrorCode object
changed: function Sin(x) to Sin(x, ErrorCode * err=0)
         when x was very big the function returns zero
         now it sets ErrorCode object to err_overflow
         and the result is undefined
         the same is to Cos() function
changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
         should be a little accurate especially on a very big 'x'



git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@143 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Tomasz Sowa 2009-05-11 01:50:00 +00:00
parent 05b67e7103
commit 939d0f7519
5 changed files with 106 additions and 45 deletions

View File

@ -1,3 +1,17 @@
Version 0.8.5 (2009.05.11):
* fixed: Big::Mod(x) didn't correctly return a carry
and the result was sometimes very big (even greater than x)
* fixed: global function Mod(x) didn't set an ErrorCode object
* fixed: global function Round() didn't test a carry
now it sets ErrorCode object
* changed: function Sin(x) to Sin(x, ErrorCode * err=0)
when x was very big the function returns zero
now it sets ErrorCode object to err_overflow
and the result is undefined
the same is to Cos() function
* changed: PrepareSin(x) is using Big::Mod() now when reducing 2PI period
should be a little accurate especially on a very big 'x'
Version 0.8.4 (2009.05.08):
* fixed: UInt::DivInt() didn't check whether the divisor is zero
there was a hardware interruption when the divisor was zero

View File

@ -94,10 +94,13 @@ namespace ttmath
-2.7 = -3
*/
template<class ValueType>
ValueType Round(const ValueType & x)
ValueType Round(const ValueType & x, ErrorCode * err = 0)
{
ValueType result( x );
result.Round();
uint c = result.Round();
if( err )
*err = c ? err_overflow : err_ok;
return result;
}
@ -295,7 +298,7 @@ namespace ttmath
(you don't have to call this function)
*/
template<class ValueType>
void PrepareSin(ValueType & x, bool & change_sign)
uint PrepareSin(ValueType & x, bool & change_sign)
{
ValueType temp;
@ -311,13 +314,11 @@ namespace ttmath
// we're reducing the period 2*PI
// (for big values there'll always be zero)
temp.Set2Pi();
if( x > temp )
{
x.Div( temp );
x.RemainFraction();
x.Mul( temp );
}
if( x.Mod(temp) )
return 1;
// we're setting 'x' as being in the range of <0, 0.5PI>
temp.SetPi();
@ -337,6 +338,8 @@ namespace ttmath
x.Sub( temp );
x = temp - x;
}
return 0;
}
@ -455,15 +458,28 @@ namespace ttmath
this function calculates the Sine
*/
template<class ValueType>
ValueType Sin(ValueType x)
ValueType Sin(ValueType x, ErrorCode * err = 0)
{
using namespace auxiliaryfunctions;
ValueType one;
ValueType one, result;
bool change_sign;
PrepareSin( x, change_sign );
ValueType result = Sin0pi05( x );
if( err )
*err = err_ok;
if( PrepareSin( x, change_sign ) )
{
// x is too big, we cannnot reduce the 2*PI period
// prior to version 0.8.5 the result was zero
if( err )
*err = err_overflow; // maybe another error code?
return result; // result we remain as undefined
}
result = Sin0pi05( x );
one.SetOne();
@ -488,14 +504,22 @@ namespace ttmath
we're using the formula cos(x) = sin(x + PI/2)
*/
template<class ValueType>
ValueType Cos(ValueType x)
ValueType Cos(ValueType x, ErrorCode * err = 0)
{
ValueType pi05;
pi05.Set05Pi();
x.Add( pi05 );
uint c = x.Add( pi05 );
if( c )
{
if( err )
*err = err_overflow;
return Sin(x);
return ValueType(); // result is undefined
}
return Sin(x, err);
}
@ -512,7 +536,10 @@ namespace ttmath
template<class ValueType>
ValueType Tan(const ValueType & x, ErrorCode * err = 0)
{
ValueType result = Cos(x);
ValueType result = Cos(x, err);
if( err && *err != err_ok )
return result;
if( result.IsZero() )
{
@ -522,10 +549,7 @@ namespace ttmath
return result;
}
if( err )
*err = err_ok;
return Sin(x) / result;
return Sin(x, err) / result;
}
@ -552,7 +576,10 @@ namespace ttmath
template<class ValueType>
ValueType Cot(const ValueType & x, ErrorCode * err = 0)
{
ValueType result = Sin(x);
ValueType result = Sin(x, err);
if( err && *err != err_ok )
return result;
if( result.IsZero() )
{
@ -562,10 +589,7 @@ namespace ttmath
return result;
}
if( err )
*err = err_ok;
return Cos(x) / result;
return Cos(x, err) / result;
}
@ -2007,15 +2031,18 @@ namespace ttmath
the remainder from a division
e.g.
mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6
mod(-12.6 ; 3) = -0.6
mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6
mod(-12.6 ; 3) = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
mod( 12.6 ; -3) = 0.6
mod(-12.6 ; -3) = -0.6
*/
template<class ValueType>
ValueType Mod(ValueType a, const ValueType & b)
ValueType Mod(ValueType a, const ValueType & b, ErrorCode * err = 0)
{
a.Mod(b);
uint c = a.Mod(b);
if( err )
*err = c ? err_overflow : err_ok;
return a;
}

View File

@ -952,7 +952,7 @@ public:
UInt<man*2> man1;
UInt<man*2> man2;
uint i,c;
uint i,c = 0;
if( ss2.IsZero() )
{
@ -976,7 +976,9 @@ public:
i = man1.CompensationToLeft();
c = exponent.Sub(i);
if( i )
c += exponent.Sub(i);
c += exponent.Sub(ss2.exponent);
for(i=0 ; i<man ; ++i)
@ -997,8 +999,8 @@ public:
the remainder from a division
e.g.
12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
-12.6 mod 3 = -0.6
12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6
-12.6 mod 3 = -0.6 bacause -12.6 = 3*(-4) + (-0.6)
12.6 mod -3 = 0.6
-12.6 mod -3 = -0.6
@ -1011,18 +1013,25 @@ public:
uint c = 0;
Big<exp, man> temp(*this);
if( !SmallerWithoutSignThan(ss2) )
{
Big<exp, man> temp(*this);
c += temp.Div(ss2);
temp.SkipFraction();
c += temp.Mul(ss2);
c += Sub(temp);
c = temp.Div(ss2);
temp.SkipFraction();
c += temp.Mul(ss2);
c += Sub(temp);
if( !SmallerWithoutSignThan( ss2 ) )
c += 1;
}
return (c==0)? 0 : 1;
}
/*!
power this = this ^ pow
(pow without a sign)

View File

@ -708,7 +708,11 @@ void Sin(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value) );
ErrorCode err;
result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
}
void Cos(int sindex, int amount_of_args, ValueType & result)
@ -716,7 +720,11 @@ void Cos(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value) );
ErrorCode err;
result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value), &err );
if(err != err_ok)
Error( err );
}
void Tan(int sindex, int amount_of_args, ValueType & result)
@ -757,7 +765,10 @@ void Round(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments );
result = ttmath::Round(stack[sindex].value);
result = stack[sindex].value;
if( result.Round() )
Error( err_overflow );
}

View File

@ -64,8 +64,8 @@
*/
#define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 8
#define TTMATH_REVISION_VER 4
#define TTMATH_PRERELEASE_VER 0
#define TTMATH_REVISION_VER 5
#define TTMATH_PRERELEASE_VER 1
/*!