From 277dd72fb6375a1bb87ba08df6d8fc9628b6b786 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 8 May 2009 18:14:00 +0000 Subject: [PATCH 1/5] fixed: UInt::AddInt() in no-asm code has incorrect assertion changed: UInt::SubInt() in no-asm code is a little faster now changed: small cosmetic changes in commentaries deleted: some debug #ifdef's from UInt::Div() (in no-asm code) git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@136 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 3 +-- README | 4 +-- ttmath/ttmath.h | 2 +- ttmath/ttmathbig.h | 2 +- ttmath/ttmathuint.h | 1 - ttmath/ttmathuint_noasm.h | 52 +++++++++----------------------------- ttmath/ttmathuint_x86.h | 20 +++++++-------- ttmath/ttmathuint_x86_64.h | 21 ++++++++------- 8 files changed, 36 insertions(+), 69 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8e0c110..288300b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Version 0.8.4 prerelease (2009.05.05): +Version 0.8.4 prerelease (2009.05.08): * fixed: UInt::DivInt() didn't check whether the divisor is zero there was a hardware interruption when the divisor was zero (now the method returns one) @@ -25,7 +25,6 @@ Version 0.8.4 prerelease (2009.05.05): (it's used when macro TTMATH_NOASM is defined) The third form can be used on x86 and x86_64 as well and on other platforms with a little effort. - (Temporarily I left there some '#ifdef's for debugging.) Version 0.8.3 (2009.04.06): diff --git a/README b/README index acd597c..8b0c476 100644 --- a/README +++ b/README @@ -21,6 +21,6 @@ This means only C++ developers can use this library and one thing they have to do is to use 'include' directive of the preprocessor. How big the values can be is set directly in the source code by the programmer. -Author: Tomasz Sowa -Project pages: http://ttmath.slimaczek.pl +Author: Tomasz Sowa +Project pages: http://www.ttmath.org http://sourceforge.net/projects/ttmath diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index 6308fad..b326969 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -423,7 +423,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 ) diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index b99bd8b..a71ac32 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -1874,7 +1874,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/ttmathuint.h b/ttmath/ttmathuint.h index 61e773e..ae419ea 100644 --- a/ttmath/ttmathuint.h +++ b/ttmath/ttmathuint.h @@ -2903,7 +2903,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 4ddf437..96e1452 100644 --- a/ttmath/ttmathuint_x86_64.h +++ b/ttmath/ttmathuint_x86_64.h @@ -137,7 +137,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) @@ -339,7 +339,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) @@ -635,7 +635,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*** @@ -723,18 +723,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 @@ -763,8 +762,8 @@ namespace ttmath #endif - *result1 = result1_; - *result2 = result2_; + *result_low = result1_; + *result_high = result2_; } From 1bae0d6cb8f45037138e0e5a7776724f4ef73f11 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 8 May 2009 18:40:32 +0000 Subject: [PATCH 2/5] changed: in ttmathtypes.h 'typedef unsigned long long int ulint' has been put inside '#ifdef TTMATH_NOASM' in order to not confuse a compiler while compiling with strict iso c++ (errors about not defining 'long long' in the c++ standard) git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@137 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmathtypes.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index be98f12..0b9ed76 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -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 /*! how many bits there are in the uint type From 3231780a85c38cbf66a6656b5901f60088b98130 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 8 May 2009 19:13:25 +0000 Subject: [PATCH 3/5] changed: version of the library: 0.8.4 git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@138 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 2 +- ttmath/ttmathtypes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 288300b..7e3b996 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Version 0.8.4 prerelease (2009.05.08): +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 (now the method returns one) diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index 0b9ed76..1a87845 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -65,7 +65,7 @@ #define TTMATH_MAJOR_VER 0 #define TTMATH_MINOR_VER 8 #define TTMATH_REVISION_VER 4 -#define TTMATH_PRERELEASE_VER 1 +#define TTMATH_PRERELEASE_VER 0 /*! From 05b67e71038f9bc5d3226fc12c9b94f58bc3ca36 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Sat, 9 May 2009 01:34:45 +0000 Subject: [PATCH 4/5] changed: corrected spaces in changelog git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@142 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 7e3b996..afeeab5 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -11,7 +11,7 @@ Version 0.8.4 (2009.05.08): (like "m" (mask) constraints in Rcl2 and Rcr2) have also gone away, now the library works well with -O2 and -O3 and the asm code is a little faster - * added: UInt::PrintLog(const char * msg, std::ostream & output) + * added: UInt::PrintLog(const char * msg, std::ostream & output) used (for debugging purposes) by macro TTMATH_LOG(msg) (it is used in nearly all methods in UInt class) * added: macro TTMATH_DEBUG_LOG: when defined then TTMATH_LOG() From 939d0f75195c1d175eac386038d24f6ba512639b Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Mon, 11 May 2009 01:50:00 +0000 Subject: [PATCH 5/5] 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 --- CHANGELOG | 14 +++++++ ttmath/ttmath.h | 89 ++++++++++++++++++++++++++++--------------- ttmath/ttmathbig.h | 27 ++++++++----- ttmath/ttmathparser.h | 17 +++++++-- ttmath/ttmathtypes.h | 4 +- 5 files changed, 106 insertions(+), 45 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index afeeab5..40eed53 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index b326969..4a2f0b4 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -94,10 +94,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; } @@ -295,7 +298,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; @@ -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 - 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 - 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 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 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 - 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 a71ac32..6acf0b3 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -952,7 +952,7 @@ public: UInt man1; UInt 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 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) diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index ac52542..ce4c7f2 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 1a87845..e599d8e 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -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 /*!