- merged Tomasz' version 0.8.5

git-svn-id: svn://ttmath.org/publicrep/ttmath/branches/chk@144 e52654a7-88a9-db11-a3e9-0013d4bc506e
This commit is contained in:
Christian Kaiser 2009-05-11 12:25:25 +00:00
parent 00e39d3608
commit cae50cd425
9 changed files with 133 additions and 116 deletions

View File

@ -96,10 +96,13 @@ namespace ttmath
-2.7 = -3 -2.7 = -3
*/ */
template<class ValueType> template<class ValueType>
ValueType Round(const ValueType & x) ValueType Round(const ValueType & x, ErrorCode * err = 0)
{ {
ValueType result( x ); ValueType result( x );
result.Round(); uint c = result.Round();
if( err )
*err = c ? err_overflow : err_ok;
return result; return result;
} }
@ -297,7 +300,7 @@ namespace ttmath
(you don't have to call this function) (you don't have to call this function)
*/ */
template<class ValueType> template<class ValueType>
void PrepareSin(ValueType & x, bool & change_sign) uint PrepareSin(ValueType & x, bool & change_sign)
{ {
ValueType temp; ValueType temp;
@ -313,13 +316,11 @@ namespace ttmath
// we're reducing the period 2*PI // we're reducing the period 2*PI
// (for big values there'll always be zero) // (for big values there'll always be zero)
temp.Set2Pi(); temp.Set2Pi();
if( x > temp )
{ if( x.Mod(temp) )
x.Div( temp ); return 1;
x.RemainFraction();
x.Mul( temp );
}
// we're setting 'x' as being in the range of <0, 0.5PI> // we're setting 'x' as being in the range of <0, 0.5PI>
temp.SetPi(); temp.SetPi();
@ -339,6 +340,8 @@ namespace ttmath
x.Sub( temp ); x.Sub( temp );
x = temp - x; x = temp - x;
} }
return 0;
} }
@ -425,7 +428,7 @@ namespace ttmath
if( c ) if( c )
// Sin is from <-1,1> and cannot make an overflow // Sin is from <-1,1> and cannot make an overflow
// but the carry can be from the Taylor series // but the carry can be from the Taylor series
// (then we only breaks our calculations) // (then we only break our calculations)
break; break;
if( addition ) if( addition )
@ -457,15 +460,28 @@ namespace ttmath
this function calculates the Sine this function calculates the Sine
*/ */
template<class ValueType> template<class ValueType>
ValueType Sin(ValueType x) ValueType Sin(ValueType x, ErrorCode * err = 0)
{ {
using namespace auxiliaryfunctions; using namespace auxiliaryfunctions;
ValueType one; ValueType one, result;
bool change_sign; bool change_sign;
PrepareSin( x, change_sign ); if( err )
ValueType result = Sin0pi05( x ); *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(); one.SetOne();
@ -490,14 +506,22 @@ namespace ttmath
we're using the formula cos(x) = sin(x + PI/2) we're using the formula cos(x) = sin(x + PI/2)
*/ */
template<class ValueType> template<class ValueType>
ValueType Cos(ValueType x) ValueType Cos(ValueType x, ErrorCode * err = 0)
{ {
ValueType pi05; ValueType pi05;
pi05.Set05Pi(); 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);
} }
@ -514,7 +538,10 @@ namespace ttmath
template<class ValueType> template<class ValueType>
ValueType Tan(const ValueType & x, ErrorCode * err = 0) 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() ) if( result.IsZero() )
{ {
@ -524,10 +551,7 @@ namespace ttmath
return result; return result;
} }
if( err ) return Sin(x, err) / result;
*err = err_ok;
return Sin(x) / result;
} }
@ -554,7 +578,10 @@ namespace ttmath
template<class ValueType> template<class ValueType>
ValueType Cot(const ValueType & x, ErrorCode * err = 0) 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() ) if( result.IsZero() )
{ {
@ -564,10 +591,7 @@ namespace ttmath
return result; return result;
} }
if( err ) return Cos(x, err) / result;
*err = err_ok;
return Cos(x) / result;
} }
@ -2011,15 +2035,18 @@ namespace ttmath
the remainder from a division the remainder from a division
e.g. e.g.
mod( 12.6 ; 3) = 0.6 because 12.6 = 3*4 + 0.6 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 bacause -12.6 = 3*(-4) + (-0.6)
mod( 12.6 ; -3) = 0.6 mod( 12.6 ; -3) = 0.6
mod(-12.6 ; -3) = -0.6 mod(-12.6 ; -3) = -0.6
*/ */
template<class ValueType> 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; return a;
} }

View File

@ -954,7 +954,7 @@ public:
UInt<man*2> man1; UInt<man*2> man1;
UInt<man*2> man2; UInt<man*2> man2;
uint i,c; uint i,c = 0;
if( ss2.IsZero() ) if( ss2.IsZero() )
{ {
@ -978,7 +978,9 @@ public:
i = man1.CompensationToLeft(); i = man1.CompensationToLeft();
c = exponent.Sub(i); if( i )
c += exponent.Sub(i);
c += exponent.Sub(ss2.exponent); c += exponent.Sub(ss2.exponent);
for(i=0 ; i<man ; ++i) for(i=0 ; i<man ; ++i)
@ -999,8 +1001,8 @@ public:
the remainder from a division the remainder from a division
e.g. e.g.
12.6 mod 3 = 0.6 because 12.6 = 3*4 + 0.6 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 bacause -12.6 = 3*(-4) + (-0.6)
12.6 mod -3 = 0.6 12.6 mod -3 = 0.6
-12.6 mod -3 = -0.6 -12.6 mod -3 = -0.6
@ -1013,18 +1015,25 @@ public:
uint c = 0; uint c = 0;
Big<exp, man> temp(*this); if( !SmallerWithoutSignThan(ss2) )
{
Big<exp, man> temp(*this);
c += temp.Div(ss2); c = temp.Div(ss2);
temp.SkipFraction(); temp.SkipFraction();
c += temp.Mul(ss2); c += temp.Mul(ss2);
c += Sub(temp); c += Sub(temp);
if( !SmallerWithoutSignThan( ss2 ) )
c += 1;
}
return (c==0)? 0 : 1; return (c==0)? 0 : 1;
} }
/*! /*!
power this = this ^ pow power this = this ^ pow
(pow without a sign) (pow without a sign)
@ -1876,7 +1885,7 @@ public:
// error but I leave it at the moment as is // error but I leave it at the moment as is
TTMATH_ASSERT( sizeof(double) == 8 ) TTMATH_ASSERT( sizeof(double) == 8 )
// I am not sure what will be on a plaltform which has // I am not sure what will be on a platform which has
// a different endianness... but we use this library only // a different endianness... but we use this library only
// on x86 and amd (intel) 64 bits (as there's a lot of assembler code) // on x86 and amd (intel) 64 bits (as there's a lot of assembler code)
union union

View File

@ -87,7 +87,7 @@ namespace ttmath
::LeaveCriticalSection(&_Crit); ::LeaveCriticalSection(&_Crit);
} }
}; };
class clsCritObj class clsCritObj
{ {
private: private:
@ -109,10 +109,10 @@ namespace ttmath
private: \ private: \
clsCrit CritSect; \ clsCrit CritSect; \
public: \ public: \
operator clsCrit&() \ operator clsCrit&() \
{ \ { \
return(CritSect); \ return(CritSect); \
} }
#define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c) #define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c)
#endif #endif
#else // not MS compiler #else // not MS compiler

View File

@ -708,7 +708,11 @@ void Sin(int sindex, int amount_of_args, ValueType & result)
if( amount_of_args != 1 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); 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) 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 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); 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) 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 ) if( amount_of_args != 1 )
Error( err_improper_amount_of_arguments ); 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,7 +64,7 @@
*/ */
#define TTMATH_MAJOR_VER 0 #define TTMATH_MAJOR_VER 0
#define TTMATH_MINOR_VER 8 #define TTMATH_MINOR_VER 8
#define TTMATH_REVISION_VER 4 #define TTMATH_REVISION_VER 5
#define TTMATH_PRERELEASE_VER 1 #define TTMATH_PRERELEASE_VER 1
@ -120,7 +120,6 @@ namespace ttmath
typedef unsigned int uint; typedef unsigned int uint;
typedef signed int sint; typedef signed int sint;
/*! /*!
this type is twice bigger than uint this type is twice bigger than uint
(64bit on a 32bit platforms) (64bit on a 32bit platforms)
@ -129,8 +128,11 @@ namespace ttmath
but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it but it is defined in C99 and in upcoming C++0x /3.9.1 (2)/ and many compilers support it
this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined this type is used in UInt::MulTwoWords and UInt::DivTwoWords when macro TTMATH_NOASM is defined
but only on a 32bit platform
*/ */
typedef unsigned long long int ulint; #ifdef TTMATH_NOASM
typedef unsigned long long int ulint;
#endif
/*! /*!
the mask for the highest bit in the unsigned 32bit word (2^31) the mask for the highest bit in the unsigned 32bit word (2^31)

View File

@ -2905,7 +2905,6 @@ public:
private: private:
public: // !!! chwilowo public
uint Rcl2_one(uint c); uint Rcl2_one(uint c);
uint Rcr2_one(uint c); uint Rcr2_one(uint c);
uint Rcl2(uint bits, uint c); uint Rcl2(uint bits, uint c);

View File

@ -116,7 +116,7 @@ namespace ttmath
table[1] = 30 + 2; table[1] = 30 + 2;
table[2] = 5; table[2] = 5;
of course if there was a carry from table[3] it would be returned of course if there was a carry from table[2] it would be returned
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::AddInt(uint value, uint index) uint UInt<value_size>::AddInt(uint value, uint index)
@ -175,7 +175,7 @@ namespace ttmath
{ {
uint i, c; uint i, c;
TTMATH_ASSERT( index < value_size ) TTMATH_ASSERT( index < value_size - 1 )
c = AddTwoWords(table[index], x1, 0, &table[index]); c = AddTwoWords(table[index], x1, 0, &table[index]);
@ -255,7 +255,7 @@ namespace ttmath
table[1] = 30 - 2; table[1] = 30 - 2;
table[2] = 5; table[2] = 5;
of course if there was a carry from table[3] it would be returned of course if there was a carry from table[2] it would be returned
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::SubInt(uint value, uint index) uint UInt<value_size>::SubInt(uint value, uint index)
@ -473,8 +473,8 @@ namespace ttmath
uint mask = 1; uint mask = 1;
while( bit-- > 0 ) if( bit > 1 )
mask = mask << 1; mask = mask << bit;
uint last = value & mask; uint last = value & mask;
value = value | mask; value = value | mask;
@ -601,7 +601,6 @@ namespace ttmath
*/ */
// !! maybe returns something? a carry? or when c is zero?
/*! /*!
this method calculates 64bits word a:b / 32bits c (a higher, b lower word) this method calculates 64bits word a:b / 32bits c (a higher, b lower word)
r = a:b / c and rest - remainder r = a:b / c and rest - remainder
@ -648,10 +647,6 @@ namespace ttmath
{ {
*r = b / c; *r = b / c;
*rest = b % c; *rest = b % c;
#ifdef TTMATH_WARTOWNIK
++tester_wartownik1; // !!!!! skasowac
#endif
} }
else else
if( c_.u_.high == 0 ) if( c_.u_.high == 0 )
@ -674,10 +669,6 @@ namespace ttmath
*rest = temp2.u % c; *rest = temp2.u % c;
*r = res_.u; *r = res_.u;
#ifdef TTMATH_WARTOWNIK
++tester_wartownik2; // !!!!! skasowac
#endif
} }
else else
{ {
@ -690,6 +681,13 @@ namespace ttmath
#ifdef TTMATH_PLATFORM64 #ifdef TTMATH_PLATFORM64
/*!
this method is available only on 64bit platforms
the same algorithm like the third division algorithm in ttmathuint.h
but now with the radix=2^32
*/
template<uint value_size> template<uint value_size>
void UInt<value_size>::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest) void UInt<value_size>::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest)
{ {
@ -704,7 +702,6 @@ namespace ttmath
c_.u = c; c_.u = c;
// normalizing // normalizing
// a0 will actually not be used
uint d = DivTwoWordsNormalize(a_, b_, c_); uint d = DivTwoWordsNormalize(a_, b_, c_);
// loop from j=1 to j=0 // loop from j=1 to j=0
@ -748,12 +745,7 @@ namespace ttmath
a_.u = a_.u << 1; // carry bits from 'a' are simply skipped a_.u = a_.u << 1; // carry bits from 'a' are simply skipped
if( bc ) if( bc )
{
a_.u = a_.u | 1; a_.u = a_.u | 1;
#ifdef TTMATH_WARTOWNIK
++tester_wartownik3; // !!!!! skasowac
#endif
}
} }
return d; return d;
@ -802,23 +794,11 @@ namespace ttmath
if( decrease ) if( decrease )
{ {
#ifdef TTMATH_WARTOWNIK
++tester_wartownik4; // !!!!! skasowac
#endif
--qp_.u; --qp_.u;
rp_.u += v_.u_.high; rp_.u += v_.u_.high;
if( rp_.u_.high == 0 ) if( rp_.u_.high == 0 )
{
next_test = true; next_test = true;
#ifdef TTMATH_WARTOWNIK
++tester_wartownik5; // !!!!! skasowac
#endif
}
} }
} }
while( next_test ); while( next_test );
@ -849,20 +829,12 @@ namespace ttmath
temp_.u_.low = u_.u_.high; temp_.u_.low = u_.u_.high;
c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u);
#ifdef TTMATH_WARTOWNIK
++tester_wartownik6; // !!!!! skasowac
#endif
if( c ) if( c )
{ {
--q; --q;
c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u); c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.u);
AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u); AddTwoWords(sub_res_high_.u, 0, c, &sub_res_high_.u);
#ifdef TTMATH_WARTOWNIK
++tester_wartownik7; // !!!!! skasowac
#endif
} }
u_.u_.high = sub_res_high_.u_.low; u_.u_.high = sub_res_high_.u_.low;

View File

@ -463,7 +463,6 @@ namespace ttmath
#ifdef __GNUC__ #ifdef __GNUC__
__asm__ __volatile__( __asm__ __volatile__(
"push %%ecx \n" "push %%ecx \n"
"xorl %%eax, %%eax \n" "xorl %%eax, %%eax \n"
@ -515,7 +514,7 @@ namespace ttmath
table[1] = 30 - 2; table[1] = 30 - 2;
table[2] = 5; table[2] = 5;
of course if there was a carry from table[3] it would be returned of course if there was a carry from table[2] it would be returned
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::SubInt(uint value, uint index) uint UInt<value_size>::SubInt(uint value, uint index)
@ -1138,16 +1137,15 @@ namespace ttmath
/*! /*!
multiplication: result2:result1 = a * b multiplication: result_high:result_low = a * b
result2 - higher word result_high - higher word of the result
result1 - lower word of the result result_low - lower word of the result
this method never returns a carry this methos never returns a carry
this method is used in the second version of the multiplication algorithms
it is an auxiliary method for second version of the multiplication algorithm
*/ */
template<uint value_size> template<uint value_size>
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result2, uint * result1) void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
{ {
/* /*
we must use these temporary variables in order to inform the compilator we must use these temporary variables in order to inform the compilator
@ -1192,8 +1190,8 @@ namespace ttmath
#endif #endif
*result1 = result1_; *result_low = result1_;
*result2 = result2_; *result_high = result2_;
} }

View File

@ -158,7 +158,7 @@ namespace ttmath
table[1] = 30 + 2; table[1] = 30 + 2;
table[2] = 5; table[2] = 5;
of course if there was a carry from table[3] it would be returned of course if there was a carry from table[2] it would be returned
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::AddInt(uint value, uint index) uint UInt<value_size>::AddInt(uint value, uint index)
@ -374,7 +374,7 @@ namespace ttmath
table[1] = 30 - 2; table[1] = 30 - 2;
table[2] = 5; table[2] = 5;
of course if there was a carry from table[3] it would be returned of course if there was a carry from table[2] it would be returned
*/ */
template<uint value_size> template<uint value_size>
uint UInt<value_size>::SubInt(uint value, uint index) uint UInt<value_size>::SubInt(uint value, uint index)
@ -695,7 +695,7 @@ namespace ttmath
/* /*
this method returns the number of the highest set bit in one 32-bit word this method returns the number of the highest set bit in one 64-bit word
if the 'x' is zero this method returns '-1' if the 'x' is zero this method returns '-1'
***this method is created only on a 64bit platform*** ***this method is created only on a 64bit platform***
@ -800,18 +800,17 @@ namespace ttmath
/*! /*!
multiplication: result2:result1 = a * b multiplication: result_high:result_low = a * b
result2 - higher word result_high - higher word of the result
result1 - lower word of the result result_low - lower word of the result
this methos never returns a carry this methos never returns a carry
this method is used in the second version of the multiplication algorithms
***this method is created only on a 64bit platform*** ***this method is created only on a 64bit platform***
it is an auxiliary method for version two of the multiplication algorithm
*/ */
template<uint value_size> template<uint value_size>
void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result2, uint * result1) void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
{ {
/* /*
we must use these temporary variables in order to inform the compilator we must use these temporary variables in order to inform the compilator
@ -844,8 +843,8 @@ namespace ttmath
#endif #endif
*result1 = result1_; *result_low = result1_;
*result2 = result2_; *result_high = result2_;
} }