diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index e24e2d7..b6c8286 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -96,10 +96,13 @@ namespace ttmath -2.7 = -3 */ template - 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; } @@ -297,7 +300,7 @@ namespace ttmath (you don't have to call this function) */ template - void PrepareSin(ValueType & x, bool & change_sign) + uint PrepareSin(ValueType & x, bool & change_sign) { ValueType temp; @@ -313,13 +316,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(); @@ -339,6 +340,8 @@ namespace ttmath x.Sub( temp ); x = temp - x; } + + return 0; } @@ -425,7 +428,7 @@ namespace ttmath if( c ) // Sin is from <-1,1> and cannot make an overflow // but the carry can be from the Taylor series - // (then we only breaks our calculations) + // (then we only break our calculations) break; if( addition ) @@ -457,15 +460,28 @@ namespace ttmath this function calculates the Sine */ template - 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(); @@ -490,14 +506,22 @@ namespace ttmath we're using the formula cos(x) = sin(x + PI/2) */ template - 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); } @@ -514,7 +538,10 @@ namespace ttmath template 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() ) { @@ -524,10 +551,7 @@ namespace ttmath return result; } - if( err ) - *err = err_ok; - - return Sin(x) / result; + return Sin(x, err) / result; } @@ -554,7 +578,10 @@ namespace ttmath template 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() ) { @@ -564,10 +591,7 @@ namespace ttmath return result; } - if( err ) - *err = err_ok; - - return Cos(x) / result; + return Cos(x, err) / result; } @@ -2011,15 +2035,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 - 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; } diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 4a7fff2..65b7ce8 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -954,7 +954,7 @@ public: UInt man1; UInt man2; - uint i,c; + uint i,c = 0; if( ss2.IsZero() ) { @@ -978,7 +978,9 @@ public: i = man1.CompensationToLeft(); - c = exponent.Sub(i); + if( i ) + c += exponent.Sub(i); + c += exponent.Sub(ss2.exponent); for(i=0 ; i temp(*this); + if( !SmallerWithoutSignThan(ss2) ) + { + Big 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) @@ -1876,7 +1885,7 @@ public: // error but I leave it at the moment as is 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 // on x86 and amd (intel) 64 bits (as there's a lot of assembler code) union diff --git a/ttmath/ttmathconfig.h b/ttmath/ttmathconfig.h index ec9a341..785bc8e 100644 --- a/ttmath/ttmathconfig.h +++ b/ttmath/ttmathconfig.h @@ -87,7 +87,7 @@ namespace ttmath ::LeaveCriticalSection(&_Crit); } }; - + class clsCritObj { private: @@ -109,10 +109,10 @@ namespace ttmath private: \ clsCrit CritSect; \ public: \ - operator clsCrit&() \ - { \ - return(CritSect); \ - } + operator clsCrit&() \ + { \ + return(CritSect); \ + } #define TTMATH_USE_THREADSAFE_OBJ(c) clsCritObj lock(c) #endif #else // not MS compiler diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index e7505bf..a8690f5 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -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 ); } diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index 72d54ec..6a6a240 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -64,7 +64,7 @@ */ #define TTMATH_MAJOR_VER 0 #define TTMATH_MINOR_VER 8 -#define TTMATH_REVISION_VER 4 +#define TTMATH_REVISION_VER 5 #define TTMATH_PRERELEASE_VER 1 @@ -120,7 +120,6 @@ namespace ttmath typedef unsigned int uint; typedef signed int sint; - /*! this type is twice bigger than uint (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 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) diff --git a/ttmath/ttmathuint.h b/ttmath/ttmathuint.h index e9f1f7d..84c1816 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -2905,7 +2905,6 @@ public: private: -public: // !!! chwilowo public uint Rcl2_one(uint c); uint Rcr2_one(uint c); uint Rcl2(uint bits, uint c); diff --git a/ttmath/ttmathuint_noasm.h b/ttmath/ttmathuint_noasm.h index e84f837..4d1fa67 100644 --- a/ttmath/ttmathuint_noasm.h +++ b/ttmath/ttmathuint_noasm.h @@ -116,7 +116,7 @@ namespace ttmath table[1] = 30 + 2; 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 UInt::AddInt(uint value, uint index) @@ -175,7 +175,7 @@ namespace ttmath { uint i, c; - TTMATH_ASSERT( index < value_size ) + TTMATH_ASSERT( index < value_size - 1 ) c = AddTwoWords(table[index], x1, 0, &table[index]); @@ -255,7 +255,7 @@ namespace ttmath table[1] = 30 - 2; 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 UInt::SubInt(uint value, uint index) @@ -473,8 +473,8 @@ namespace ttmath uint mask = 1; - while( bit-- > 0 ) - mask = mask << 1; + if( bit > 1 ) + mask = mask << bit; uint last = 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) r = a:b / c and rest - remainder @@ -648,10 +647,6 @@ namespace ttmath { *r = b / c; *rest = b % c; - -#ifdef TTMATH_WARTOWNIK - ++tester_wartownik1; // !!!!! skasowac -#endif } else if( c_.u_.high == 0 ) @@ -674,10 +669,6 @@ namespace ttmath *rest = temp2.u % c; *r = res_.u; -#ifdef TTMATH_WARTOWNIK - ++tester_wartownik2; // !!!!! skasowac -#endif - } else { @@ -690,6 +681,13 @@ namespace ttmath #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 void UInt::DivTwoWords2(uint a, uint b, uint c, uint * r, uint * rest) { @@ -704,7 +702,6 @@ namespace ttmath c_.u = c; // normalizing - // a0 will actually not be used uint d = DivTwoWordsNormalize(a_, b_, c_); // 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 if( bc ) - { a_.u = a_.u | 1; - #ifdef TTMATH_WARTOWNIK - ++tester_wartownik3; // !!!!! skasowac - #endif - } } return d; @@ -802,23 +794,11 @@ namespace ttmath if( decrease ) { - #ifdef TTMATH_WARTOWNIK - ++tester_wartownik4; // !!!!! skasowac - #endif - --qp_.u; rp_.u += v_.u_.high; if( rp_.u_.high == 0 ) - { next_test = true; - - #ifdef TTMATH_WARTOWNIK - ++tester_wartownik5; // !!!!! skasowac - #endif - } - - } } while( next_test ); @@ -849,20 +829,12 @@ namespace ttmath temp_.u_.low = u_.u_.high; c = SubTwoWords(temp_.u, res_high, c, &sub_res_high_.u); -#ifdef TTMATH_WARTOWNIK - ++tester_wartownik6; // !!!!! skasowac -#endif - if( c ) { --q; c = AddTwoWords(sub_res_low_.u, v_.u, 0, &sub_res_low_.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; diff --git a/ttmath/ttmathuint_x86.h b/ttmath/ttmathuint_x86.h index d5bb4a3..3714708 100644 --- a/ttmath/ttmathuint_x86.h +++ b/ttmath/ttmathuint_x86.h @@ -463,7 +463,6 @@ namespace ttmath #ifdef __GNUC__ __asm__ __volatile__( - "push %%ecx \n" "xorl %%eax, %%eax \n" @@ -515,7 +514,7 @@ namespace ttmath table[1] = 30 - 2; 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 UInt::SubInt(uint value, uint index) @@ -1138,16 +1137,15 @@ namespace ttmath /*! - multiplication: result2:result1 = a * b - result2 - higher word - result1 - lower word of the result + multiplication: result_high:result_low = a * b + result_high - higher word of the result + result_low - lower word of the result - this method never returns a carry - - it is an auxiliary method for second version of the multiplication algorithm + this methos never returns a carry + this method is used in the second version of the multiplication algorithms */ template - void UInt::MulTwoWords(uint a, uint b, uint * result2, uint * result1) + void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) { /* we must use these temporary variables in order to inform the compilator @@ -1192,8 +1190,8 @@ namespace ttmath #endif - *result1 = result1_; - *result2 = result2_; + *result_low = result1_; + *result_high = result2_; } diff --git a/ttmath/ttmathuint_x86_64.h b/ttmath/ttmathuint_x86_64.h index e52c96a..9e6603f 100644 --- a/ttmath/ttmathuint_x86_64.h +++ b/ttmath/ttmathuint_x86_64.h @@ -158,7 +158,7 @@ namespace ttmath table[1] = 30 + 2; 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 UInt::AddInt(uint value, uint index) @@ -374,7 +374,7 @@ namespace ttmath table[1] = 30 - 2; 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 UInt::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' ***this method is created only on a 64bit platform*** @@ -800,18 +800,17 @@ namespace ttmath /*! - multiplication: result2:result1 = a * b - result2 - higher word - result1 - lower word of the result + multiplication: result_high:result_low = a * b + result_high - higher word of the result + result_low - lower word of the result 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*** - - it is an auxiliary method for version two of the multiplication algorithm */ template - void UInt::MulTwoWords(uint a, uint b, uint * result2, uint * result1) + void UInt::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low) { /* we must use these temporary variables in order to inform the compilator @@ -844,8 +843,8 @@ namespace ttmath #endif - *result1 = result1_; - *result2 = result2_; + *result_low = result1_; + *result_high = result2_; }