From d695785cbbfb19348712daa1c1dc8a18023cd64a Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 27 Mar 2009 22:26:51 +0000 Subject: [PATCH] fixed: in function DegToRad(const ValueType & x, ErrorCode * err = 0) it is better to make division first and then mutliplication -- the result is more accurate especially when x is: 90,180,270 or 360 added: global template functions in ttmath.h: ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) ValueType DegToGrad(const ValueType & d, const ValueType & m, const ValueType & s, ErrorCode * err = 0) ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) added: Parser::SetDegRadGrad(int angle) - 0 deg, 1 rad (default), 2 grad this affects following functions (in the parser only): sin, cos, tan, cot, asin, acos, atan, acot added: functions to the parser: gradtorad(grad), radtograd(rad), degtograd(deg), degtograd(d,m,s), gradtodeg(grad) removed: Big::Ln() and Big::Log() some old info was removed git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@110 e52654a7-88a9-db11-a3e9-0013d4bc506e --- ttmath/ttmath.h | 138 +++++++++++++++++++- ttmath/ttmathbig.h | 15 +-- ttmath/ttmathparser.h | 284 +++++++++++++++++++++++++++++++----------- 3 files changed, 349 insertions(+), 88 deletions(-) diff --git a/ttmath/ttmath.h b/ttmath/ttmath.h index f1e5617..d50e999 100644 --- a/ttmath/ttmath.h +++ b/ttmath/ttmath.h @@ -1347,7 +1347,7 @@ namespace ttmath /* * - * functions for converting between degrees and radians + * functions for converting between degrees, radians and gradians * * */ @@ -1361,14 +1361,18 @@ namespace ttmath template ValueType DegToRad(const ValueType & x, ErrorCode * err = 0) { - ValueType result, delimiter; + ValueType result, temp; uint c = 0; - result.SetPi(); - c += result.Mul(x); + result = x; - delimiter = 180; - c += result.Div(delimiter); + // it is better to make division first and then multiplication + // the result is more accurate especially when x is: 90,180,270 or 360 + temp = 180; + c += result.Div(temp); + + temp.SetPi(); + c += result.Mul(temp); if( err ) *err = c ? err_overflow : err_ok; @@ -1468,6 +1472,128 @@ namespace ttmath } + /*! + this function converts gradians to radians + + it returns: x * pi / 200 + */ + template + ValueType GradToRad(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, temp; + uint c = 0; + + result = x; + + // it is better to make division first and then multiplication + // the result is more accurate especially when x is: 100,200,300 or 400 + temp = 200; + c += result.Div(temp); + + temp.SetPi(); + c += result.Mul(temp); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts radians to gradians + + it returns: x * 200 / pi + */ + template + ValueType RadToGrad(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, delimiter; + uint c = 0; + + result = 200; + c += result.Mul(x); + + delimiter.SetPi(); + c += result.Div(delimiter); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts degrees to gradians + + it returns: x * 200 / 180 + */ + template + ValueType DegToGrad(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, temp; + uint c = 0; + + result = x; + + temp = 200; + c += result.Mul(temp); + + temp = 180; + c += result.Div(temp); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + /*! + this function converts degrees in the long format to gradians + */ + template + ValueType DegToGrad( const ValueType & d, const ValueType & m, const ValueType & s, + ErrorCode * err = 0) + { + ValueType temp_deg = DegToDeg(d,m,s,err); + + if( err && *err!=err_ok ) + return temp_deg; + + return DegToGrad(temp_deg, err); + } + + + /*! + this function converts degrees to gradians + + it returns: x * 180 / 200 + */ + template + ValueType GradToDeg(const ValueType & x, ErrorCode * err = 0) + { + ValueType result, temp; + uint c = 0; + + result = x; + + temp = 180; + c += result.Mul(temp); + + temp = 200; + c += result.Div(temp); + + if( err ) + *err = c ? err_overflow : err_ok; + + return result; + } + + + + /* * * another functions diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 070f98f..7affbdb 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -1003,7 +1003,7 @@ public: -12.6 mod -3 = -0.6 it means: - in other words: this(old) = ss2 * q + this(new)(result) + in other words: this(old) = ss2 * q + this(new -- result) */ uint Mod(const Big & ss2) { @@ -1525,8 +1525,6 @@ public: 0 - ok 1 - overflow 2 - incorrect argument (x<=0) - - parts: look at the LnSurrounding1() method */ uint Ln(const Big & x) { @@ -1558,7 +1556,7 @@ public: /*! - Logarithm with a base 'base' -- this = Log(x) with a base 'base' + Logarithm from 'x' with a 'base' we're using the formula: Log(x) with 'base' = ln(x) / ln(base) @@ -1568,12 +1566,6 @@ public: 1 - overflow 2 - incorrect argument (x<=0) 3 - incorrect base (a<=0 lub a=1) - - - parts: look at the LnSurrounding1() method - we pass this value only into 'ln(x)' method - because if we passed 'parts' into 'ln(base)' as well then - the error (after dividing) would be too great */ uint Log(const Big & x, const Big & base) { @@ -1600,7 +1592,6 @@ public: // there can be only a carry uint c = Ln(x); - // we don't pass the 'parts' here (the error after dividing would be to great) c += denominator.Ln(base); c += Div(denominator); @@ -1612,7 +1603,7 @@ public: /*! * - * convertion methods + * converting methods * */ diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index da51b32..faffc07 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -309,11 +309,21 @@ const char * pstring; /*! - the base of the mathematic system (for example it may be '10') + the base (radix) of the mathematic system (for example it may be '10') */ int base; +/*! + the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot + 0 - deg + 1 - rad (default) + 2 - grad +*/ +int deg_rad_grad; + + + /*! a pointer to an object which tell us whether we should stop calculating or not */ @@ -612,7 +622,53 @@ private: /*! - 'silnia' in polish language + used by: sin,cos,tan,cot +*/ +ValueType ConvertAngleToRad(const ValueType & input) +{ + if( deg_rad_grad == 1 ) // rad + return input; + + ValueType result; + ErrorCode err; + + if( deg_rad_grad == 0 ) // deg + result = ttmath::DegToRad(input, &err); + else // grad + result = ttmath::GradToRad(input, &err); + + if( err != err_ok ) + Error( err ); + +return result; +} + + +/*! + used by: asin,acos,atan,acot +*/ +ValueType ConvertRadToAngle(const ValueType & input) +{ + if( deg_rad_grad == 1 ) // rad + return input; + + ValueType result; + ErrorCode err; + + if( deg_rad_grad == 0 ) // deg + result = ttmath::RadToDeg(input, &err); + else // grad + result = ttmath::RadToGrad(input, &err); + + if( err != err_ok ) + Error( err ); + +return result; +} + + +/*! + factorial result = 1 * 2 * 3 * 4 * .... * x */ void Factorial(int sindex, int amount_of_args, ValueType & result) @@ -645,7 +701,7 @@ void Sin(int sindex, int amount_of_args, ValueType & result) if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); - result = ttmath::Sin(stack[sindex].value); + result = ttmath::Sin( ConvertAngleToRad(stack[sindex].value) ); } void Cos(int sindex, int amount_of_args, ValueType & result) @@ -653,7 +709,7 @@ void Cos(int sindex, int amount_of_args, ValueType & result) if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); - result = ttmath::Cos(stack[sindex].value); + result = ttmath::Cos( ConvertAngleToRad(stack[sindex].value) ); } void Tan(int sindex, int amount_of_args, ValueType & result) @@ -662,7 +718,7 @@ void Tan(int sindex, int amount_of_args, ValueType & result) Error( err_improper_amount_of_arguments ); ErrorCode err; - result = ttmath::Tan(stack[sindex].value, &err); + result = ttmath::Tan(ConvertAngleToRad(stack[sindex].value), &err); if(err != err_ok) Error( err ); @@ -674,7 +730,7 @@ void Cot(int sindex, int amount_of_args, ValueType & result) Error( err_improper_amount_of_arguments ); ErrorCode err; - result = ttmath::Cot(stack[sindex].value, &err); + result = ttmath::Cot(ConvertAngleToRad(stack[sindex].value), &err); if(err != err_ok) Error( err ); @@ -779,10 +835,12 @@ void ASin(int sindex, int amount_of_args, ValueType & result) Error( err_improper_amount_of_arguments ); ErrorCode err; - result = ttmath::ASin(stack[sindex].value, &err); + ValueType temp = ttmath::ASin(stack[sindex].value, &err); if(err != err_ok) Error( err ); + + result = ConvertRadToAngle(temp); } @@ -792,10 +850,12 @@ void ACos(int sindex, int amount_of_args, ValueType & result) Error( err_improper_amount_of_arguments ); ErrorCode err; - result = ttmath::ACos(stack[sindex].value, &err); + ValueType temp = ttmath::ACos(stack[sindex].value, &err); if(err != err_ok) Error( err ); + + result = ConvertRadToAngle(temp); } @@ -804,7 +864,7 @@ void ATan(int sindex, int amount_of_args, ValueType & result) if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); - result = ttmath::ATan(stack[sindex].value); + result = ConvertRadToAngle(ttmath::ATan(stack[sindex].value)); } @@ -813,7 +873,7 @@ void ACot(int sindex, int amount_of_args, ValueType & result) if( amount_of_args != 1 ) Error( err_improper_amount_of_arguments ); - result = ttmath::ACot(stack[sindex].value); + result = ConvertRadToAngle(ttmath::ACot(stack[sindex].value)); } @@ -954,6 +1014,72 @@ void DegToDeg(int sindex, int amount_of_args, ValueType & result) Error( err ); } + +void GradToRad(int sindex, int amount_of_args, ValueType & result) +{ + ErrorCode err; + + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ttmath::GradToRad(stack[sindex].value, &err); + + if( err != err_ok ) + Error( err ); +} + + +void RadToGrad(int sindex, int amount_of_args, ValueType & result) +{ + ErrorCode err; + + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ttmath::RadToGrad(stack[sindex].value, &err); + + if( err != err_ok ) + Error( err ); +} + + +void DegToGrad(int sindex, int amount_of_args, ValueType & result) +{ + ErrorCode err; + + if( amount_of_args == 1 ) + { + result = ttmath::DegToGrad(stack[sindex].value, &err); + } + else + if( amount_of_args == 3 ) + { + result = ttmath::DegToGrad( stack[sindex].value, stack[sindex+2].value, + stack[sindex+4].value, &err); + } + else + Error( err_improper_amount_of_arguments ); + + + if( err != err_ok ) + Error( err ); +} + + +void GradToDeg(int sindex, int amount_of_args, ValueType & result) +{ + ErrorCode err; + + if( amount_of_args != 1 ) + Error( err_improper_amount_of_arguments ); + + result = ttmath::GradToDeg(stack[sindex].value, &err); + + if( err != err_ok ) + Error( err ); +} + + void Ceil(int sindex, int amount_of_args, ValueType & result) { if( amount_of_args != 1 ) @@ -1282,9 +1408,9 @@ void CallFunction(const std::string & function_name, int amount_of_args, int sin function_name - name of the function pf - pointer to the function (to the wrapper) */ -void InsertFunctionToTable(const std::string & function_name, pfunction pf) +void InsertFunctionToTable(const char * function_name, pfunction pf) { - functions_table.insert( std::make_pair(function_name, pf)); + functions_table.insert( std::make_pair(std::string(function_name), pf)); } @@ -1295,9 +1421,9 @@ void InsertFunctionToTable(const std::string & function_name, pfunction pf) variable_name - name of the function pf - pointer to the function */ -void InsertVariableToTable(const std::string & variable_name, pfunction_var pf) +void InsertVariableToTable(const char * variable_name, pfunction_var pf) { - variables_table.insert( std::make_pair(variable_name, pf)); + variables_table.insert( std::make_pair(std::string(variable_name), pf)); } @@ -1309,60 +1435,64 @@ void CreateFunctionsTable() /* names of functions should consist of small letters */ - InsertFunctionToTable(std::string("factorial"), &Parser::Factorial); - InsertFunctionToTable(std::string("abs"), &Parser::Abs); - InsertFunctionToTable(std::string("sin"), &Parser::Sin); - InsertFunctionToTable(std::string("cos"), &Parser::Cos); - InsertFunctionToTable(std::string("tan"), &Parser::Tan); - InsertFunctionToTable(std::string("tg"), &Parser::Tan); - InsertFunctionToTable(std::string("cot"), &Parser::Cot); - InsertFunctionToTable(std::string("ctg"), &Parser::Cot); - InsertFunctionToTable(std::string("int"), &Parser::Int); - InsertFunctionToTable(std::string("round"), &Parser::Round); - InsertFunctionToTable(std::string("ln"), &Parser::Ln); - InsertFunctionToTable(std::string("log"), &Parser::Log); - InsertFunctionToTable(std::string("exp"), &Parser::Exp); - InsertFunctionToTable(std::string("max"), &Parser::Max); - InsertFunctionToTable(std::string("min"), &Parser::Min); - InsertFunctionToTable(std::string("asin"), &Parser::ASin); - InsertFunctionToTable(std::string("acos"), &Parser::ACos); - InsertFunctionToTable(std::string("atan"), &Parser::ATan); - InsertFunctionToTable(std::string("atg"), &Parser::ATan); - InsertFunctionToTable(std::string("acot"), &Parser::ACot); - InsertFunctionToTable(std::string("actg"), &Parser::ACot); - InsertFunctionToTable(std::string("sgn"), &Parser::Sgn); - InsertFunctionToTable(std::string("mod"), &Parser::Mod); - InsertFunctionToTable(std::string("if"), &Parser::If); - InsertFunctionToTable(std::string("or"), &Parser::Or); - InsertFunctionToTable(std::string("and"), &Parser::And); - InsertFunctionToTable(std::string("not"), &Parser::Not); - InsertFunctionToTable(std::string("degtorad"), &Parser::DegToRad); - InsertFunctionToTable(std::string("radtodeg"), &Parser::RadToDeg); - InsertFunctionToTable(std::string("degtodeg"), &Parser::DegToDeg); - InsertFunctionToTable(std::string("ceil"), &Parser::Ceil); - InsertFunctionToTable(std::string("floor"), &Parser::Floor); - InsertFunctionToTable(std::string("sqrt"), &Parser::Sqrt); - InsertFunctionToTable(std::string("sinh"), &Parser::Sinh); - InsertFunctionToTable(std::string("cosh"), &Parser::Cosh); - InsertFunctionToTable(std::string("tanh"), &Parser::Tanh); - InsertFunctionToTable(std::string("tgh"), &Parser::Tanh); - InsertFunctionToTable(std::string("coth"), &Parser::Coth); - InsertFunctionToTable(std::string("ctgh"), &Parser::Coth); - InsertFunctionToTable(std::string("root"), &Parser::Root); - InsertFunctionToTable(std::string("asinh"), &Parser::ASinh); - InsertFunctionToTable(std::string("acosh"), &Parser::ACosh); - InsertFunctionToTable(std::string("atanh"), &Parser::ATanh); - InsertFunctionToTable(std::string("atgh"), &Parser::ATanh); - InsertFunctionToTable(std::string("acoth"), &Parser::ACoth); - InsertFunctionToTable(std::string("actgh"), &Parser::ACoth); - InsertFunctionToTable(std::string("bitand"), &Parser::BitAnd); - InsertFunctionToTable(std::string("bitor"), &Parser::BitOr); - InsertFunctionToTable(std::string("bitxor"), &Parser::BitXor); - InsertFunctionToTable(std::string("band"), &Parser::BitAnd); - InsertFunctionToTable(std::string("bor"), &Parser::BitOr); - InsertFunctionToTable(std::string("bxor"), &Parser::BitXor); - InsertFunctionToTable(std::string("sum"), &Parser::Sum); - InsertFunctionToTable(std::string("avg"), &Parser::Avg); + InsertFunctionToTable("factorial", &Parser::Factorial); + InsertFunctionToTable("abs", &Parser::Abs); + InsertFunctionToTable("sin", &Parser::Sin); + InsertFunctionToTable("cos", &Parser::Cos); + InsertFunctionToTable("tan", &Parser::Tan); + InsertFunctionToTable("tg", &Parser::Tan); + InsertFunctionToTable("cot", &Parser::Cot); + InsertFunctionToTable("ctg", &Parser::Cot); + InsertFunctionToTable("int", &Parser::Int); + InsertFunctionToTable("round", &Parser::Round); + InsertFunctionToTable("ln", &Parser::Ln); + InsertFunctionToTable("log", &Parser::Log); + InsertFunctionToTable("exp", &Parser::Exp); + InsertFunctionToTable("max", &Parser::Max); + InsertFunctionToTable("min", &Parser::Min); + InsertFunctionToTable("asin", &Parser::ASin); + InsertFunctionToTable("acos", &Parser::ACos); + InsertFunctionToTable("atan", &Parser::ATan); + InsertFunctionToTable("atg", &Parser::ATan); + InsertFunctionToTable("acot", &Parser::ACot); + InsertFunctionToTable("actg", &Parser::ACot); + InsertFunctionToTable("sgn", &Parser::Sgn); + InsertFunctionToTable("mod", &Parser::Mod); + InsertFunctionToTable("if", &Parser::If); + InsertFunctionToTable("or", &Parser::Or); + InsertFunctionToTable("and", &Parser::And); + InsertFunctionToTable("not", &Parser::Not); + InsertFunctionToTable("degtorad", &Parser::DegToRad); + InsertFunctionToTable("radtodeg", &Parser::RadToDeg); + InsertFunctionToTable("degtodeg", &Parser::DegToDeg); + InsertFunctionToTable("gradtorad", &Parser::GradToRad); + InsertFunctionToTable("radtograd", &Parser::RadToGrad); + InsertFunctionToTable("degtograd", &Parser::DegToGrad); + InsertFunctionToTable("gradtodeg", &Parser::GradToDeg); + InsertFunctionToTable("ceil", &Parser::Ceil); + InsertFunctionToTable("floor", &Parser::Floor); + InsertFunctionToTable("sqrt", &Parser::Sqrt); + InsertFunctionToTable("sinh", &Parser::Sinh); + InsertFunctionToTable("cosh", &Parser::Cosh); + InsertFunctionToTable("tanh", &Parser::Tanh); + InsertFunctionToTable("tgh", &Parser::Tanh); + InsertFunctionToTable("coth", &Parser::Coth); + InsertFunctionToTable("ctgh", &Parser::Coth); + InsertFunctionToTable("root", &Parser::Root); + InsertFunctionToTable("asinh", &Parser::ASinh); + InsertFunctionToTable("acosh", &Parser::ACosh); + InsertFunctionToTable("atanh", &Parser::ATanh); + InsertFunctionToTable("atgh", &Parser::ATanh); + InsertFunctionToTable("acoth", &Parser::ACoth); + InsertFunctionToTable("actgh", &Parser::ACoth); + InsertFunctionToTable("bitand", &Parser::BitAnd); + InsertFunctionToTable("bitor", &Parser::BitOr); + InsertFunctionToTable("bitxor", &Parser::BitXor); + InsertFunctionToTable("band", &Parser::BitAnd); + InsertFunctionToTable("bor", &Parser::BitOr); + InsertFunctionToTable("bxor", &Parser::BitXor); + InsertFunctionToTable("sum", &Parser::Sum); + InsertFunctionToTable("avg", &Parser::Avg); } @@ -1374,8 +1504,8 @@ void CreateVariablesTable() /* names of variables should consist of small letters */ - InsertVariableToTable(std::string("pi"), &ValueType::SetPi); - InsertVariableToTable(std::string("e"), &ValueType::SetE); + InsertVariableToTable("pi", &ValueType::SetPi); + InsertVariableToTable("e", &ValueType::SetE); } @@ -2218,6 +2348,7 @@ Parser(): default_stack_size(100) puser_functions = 0; pfunction_local_variables = 0; base = 10; + deg_rad_grad = 1; error = err_ok; factorial_max.SetZero(); @@ -2237,6 +2368,7 @@ Parser & operator=(const Parser & p) puser_functions = p.puser_functions; pfunction_local_variables = 0; base = p.base; + deg_rad_grad = p.deg_rad_grad; error = err_ok; factorial_max = p.factorial_max; @@ -2274,6 +2406,18 @@ void SetBase(int b) } +/*! + the unit of angles used in: sin,cos,tan,cot,asin,acos,atan,acot + 0 - deg + 1 - rad (default) + 2 - grad +*/ +void SetDegRadGrad(int angle) +{ + if( angle >= 0 || angle <= 2 ) + deg_rad_grad = angle; +} + /*! this method sets a pointer to the object which tell us whether we should stop calculations