From c97ebf282f3ea548b81ca5d7c1b82acbde32ec89 Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Thu, 5 Apr 2007 19:08:15 +0000 Subject: [PATCH] fixed: Big::PowFrac(..) didn't return a correct error code (when 'this' was negative) added: Root(x; index) (and to the parser as well) added: macro: TTMATH_PRERELEASE_VER (can be either zero or one) git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@32 e52654a7-88a9-db11-a3e9-0013d4bc506e --- README | 2 +- ttmath/ttmath.h | 195 +++++++++++++++++++++++++++++++++++++++++- ttmath/ttmathbig.h | 8 +- ttmath/ttmathparser.h | 13 +++ ttmath/ttmathtypes.h | 6 +- 5 files changed, 220 insertions(+), 4 deletions(-) diff --git a/README b/README index fceebc2..05d91f9 100644 --- a/README +++ b/README @@ -21,4 +21,4 @@ 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 -Home page: http://sourceforge.net/projects/ttmath +Project page: http://sourceforge.net/projects/ttmath diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index 665c928..69d94ca 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -1342,6 +1342,199 @@ namespace ttmath } + + namespace auxiliaryfunctions + { + + template + bool RootCheckIndexSign(ValueType & x, const ValueType & index, ErrorCode * err) + { + if( index.IsSign() ) + { + // index cannot be negative + if( err ) + *err = err_improper_argument; + + return true; + } + + return false; + } + + + template + bool RootCheckIndexZero(ValueType & x, const ValueType & index, ErrorCode * err) + { + if( index.IsZero() ) + { + if( x.IsZero() ) + { + // there isn't root(0;0) + if( err ) + *err = err_improper_argument; + + return true; + } + + // root(x;0) is 1 (if x!=0) + x.SetOne(); + + if( err ) + *err = err_ok; + + return true; + } + + return false; + } + + + template + bool RootCheckIndexOne(ValueType & x, const ValueType & index, ErrorCode * err) + { + ValueType one; + one.SetOne(); + + if( index == one ) + { + //root(x;1) is x + // we do it because if we used the PowFrac function + // we would lose the precision + if( err ) + *err = err_ok; + + return true; + } + + return false; + } + + + template + bool RootCheckIndexFrac(ValueType & x, const ValueType & index, ErrorCode * err) + { + ValueType indexfrac(index); + indexfrac.RemainFraction(); + + if( !indexfrac.IsZero() ) + { + // index must be integer + if( err ) + *err = err_improper_argument; + + return true; + } + + return false; + } + + + template + bool RootCheckXZero(ValueType & x, const ValueType & index, ErrorCode * err) + { + if( x.IsZero() ) + { + // root(0;index) is zero (if index!=0) + x.SetZero(); + + if( err ) + *err = err_ok; + + return true; + } + + return false; + } + + + template + bool RootCheckIndex(ValueType & x, const ValueType & index, ErrorCode * err, bool * change_sign) + { + *change_sign = false; + + if( index.Mod2() ) + { + // index is odd (1,3,5...) + if( x.IsSign() ) + { + *change_sign = true; + x.Abs(); + } + } + else + { + // index is even + // x cannot be negative + if( x.IsSign() ) + { + if( err ) + *err = err_improper_argument; + + return true; + } + } + + return false; + } + + } + + + /*! + indexth Root of x + index must be integer and not negative <0;1;2;3....) + + if index==0 the result is one + if x==0 the result is zero and we assume root(0;0) is not defined + + if index is even (2;4;6...) the result is x^(1/index) and x>0 + if index is odd (1;2;3;...) the result is either + -(abs(x)^(1/index)) if x<0 or + x^(1/index)) if x>0 + + (for index==1 the result is equal x) + */ + template + ValueType Root(ValueType x, const ValueType & index, ErrorCode * err = 0) + { + using namespace auxiliaryfunctions; + + if( RootCheckIndexSign(x, index, err) ) return x; + if( RootCheckIndexZero(x, index, err) ) return x; + if( RootCheckIndexOne (x, index, err) ) return x; + if( RootCheckIndexFrac(x, index, err) ) return x; + if( RootCheckXZero(x, index, err) ) return x; + + // index integer and index!=0 + // x!=0 + + uint c = 0; + bool change_sign; + if( RootCheckIndex(x, index, err, &change_sign ) ) return x; + + ValueType newindex; + newindex.SetOne(); + c += newindex.Div(index); + c += x.PowFrac(newindex); // here can only be a carry + + if( change_sign ) + x.SetSign(); + + if( err ) + *err = c ? err_overflow : err_ok; + + return x; + } + + + + + + + + + + /*! the factorial from given 'x' e.g. @@ -1432,7 +1625,7 @@ namespace ttmath /*! it returns the sign of the value - e.g. -2 = 1 + e.g. -2 = -1 0 = 0 10 = 1 */ diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 6119a17..1fcf6fb 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -450,7 +450,7 @@ public: /*! it remains the 'sign' of the value - e.g. -2 = 1 + e.g. -2 = -1 0 = 0 10 = 1 */ @@ -883,6 +883,7 @@ public: pow can be negative and with fraction return values: + 0 - ok 1 - carry 2 - incorrect argument ('this') */ @@ -892,6 +893,10 @@ public: Big temp; uint c = temp.Ln(*this); + + if( c!= 0 ) + return c; + c += temp.Mul(pow); c += Exp(temp); @@ -904,6 +909,7 @@ public: pow can be negative and with fraction return values: + 0 - ok 1 - carry 2 - incorrect argument ('this' or 'pow') */ diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index 99380d8..51ddfbc 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -1030,6 +1030,18 @@ void Coth(int sindex, int amount_of_args, ValueType & result) } +void Root(int sindex, int amount_of_args, ValueType & result) +{ + if( amount_of_args != 2 ) + Error( err_improper_amount_of_arguments ); + + ErrorCode err; + result = ttmath::Root(stack[sindex].value, stack[sindex+2].value, &err); + + if( err != err_ok ) + Error( err ); +} + /*! this method returns the value from a user-defined function @@ -1178,6 +1190,7 @@ void CreateFunctionsTable() InsertFunctionToTable(std::string("tgh"), &Parser::Tanh); InsertFunctionToTable(std::string("coth"), &Parser::Coth); InsertFunctionToTable(std::string("ctgh"), &Parser::Coth); + InsertFunctionToTable(std::string("root"), &Parser::Root); } diff --git a/ttmath/ttmathtypes.h b/ttmath/ttmathtypes.h index c3bc2e7..2a38b7d 100644 --- a/ttmath/ttmathtypes.h +++ b/ttmath/ttmathtypes.h @@ -58,10 +58,14 @@ /*! the version of the library + + TTMATH_PRERELEASE_VER is either zero or one + if zero that means this is the release version of the library */ #define TTMATH_MAJOR_VER 0 #define TTMATH_MINOR_VER 8 -#define TTMATH_REVISION_VER 0 +#define TTMATH_REVISION_VER 1 +#define TTMATH_PRERELEASE_VER 1 /*!