From 0ada20b4cb8c4a08a96cda2df3be260c1254d1fe Mon Sep 17 00:00:00 2001 From: Tomasz Sowa Date: Fri, 25 Dec 2009 22:06:49 +0000 Subject: [PATCH] fixed: added in the parser: operator's associativity operator ^ (powering) is right-associative: sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24 previously was: 2^3^4 = (2^3)^4 = 4096 git-svn-id: svn://ttmath.org/publicrep/ttmath/trunk@273 e52654a7-88a9-db11-a3e9-0013d4bc506e --- CHANGELOG | 12 ++++++------ ttmath/ttmathbig.h | 2 +- ttmath/ttmathparser.h | 39 ++++++++++++++++++++++++++++----------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index ad45d2c..a689369 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,13 +1,13 @@ -Version 0.9.1 prerelease (2009.12.06): +Version 0.9.1 prerelease (2009.12.25): * fixed: the parser didn't use characters for changing the base (# and &) those characters were skipped (this bug was introduced in 0.9.0) + * fixed: added in the parser: operator's associativity + operator ^ (powering) is right-associative: + sample: 2^3^4 is equal 2^(3^4) and it is: 2.41e+24 + previously was: 2^3^4 = (2^3)^4 = 4096 * added: IEEE 754 half-to-even rounding (bankers' rounding) to the following - floating point algorithms: - Big::Add - Big::Sub - Big::Mul - Big::Div + floating point algorithms: Big::Add, Big::Sub, Big::Mul, Big::Div * added: to Big::ToString() - additional rounding when conv.base_round is used if the value is not an integer we calculate how many valid digits there are after the comma operator (in conv.base radix) and then we skipped the rest diff --git a/ttmath/ttmathbig.h b/ttmath/ttmathbig.h index 9789468..6d46ddd 100644 --- a/ttmath/ttmathbig.h +++ b/ttmath/ttmathbig.h @@ -1575,7 +1575,7 @@ public: if( pow.Mod2() ) c += result.Mul(start); - c += pow.exponent.Sub( e_one ); + c += pow.exponent.Sub( e_one ); // !! may use SubOne() here? if( pow < one ) break; diff --git a/ttmath/ttmathparser.h b/ttmath/ttmathparser.h index 08f7904..e3f18ac 100644 --- a/ttmath/ttmathparser.h +++ b/ttmath/ttmathparser.h @@ -159,14 +159,20 @@ private: none,add,sub,mul,div,pow,lt,gt,let,get,eq,neq,lor,land,shortmul }; + enum Assoc + { + right, // right-associative + non_right // associative or left-associative + }; - Type GetType() const { return type; } - int GetPriority() const { return priority; } - + Type GetType() const { return type; } + int GetPriority() const { return priority; } + Assoc GetAssoc() const { return assoc; } void SetType(Type t) { - type = t; + type = t; + assoc = non_right; switch( type ) { @@ -200,6 +206,7 @@ private: case pow: priority = 14; + assoc = right; break; default: @@ -208,15 +215,15 @@ private: } } - MatOperator(): type(none), priority(0) + MatOperator(): type(none), priority(0), assoc(non_right) { } private: - Type type; - int priority; - + Type type; + int priority; + Assoc assoc; }; // end of MatOperator class @@ -2207,10 +2214,20 @@ void TryRollingUpStackWithOperatorPriority() { while( stack_index>=4 && stack[stack_index-4].type == Item::numerical_value && - stack[stack_index-3].type == Item::mat_operator && + stack[stack_index-3].type == Item::mat_operator && stack[stack_index-2].type == Item::numerical_value && - stack[stack_index-1].type == Item::mat_operator && - stack[stack_index-3].moperator.GetPriority() >= stack[stack_index-1].moperator.GetPriority() + stack[stack_index-1].type == Item::mat_operator && + ( + ( + // the first operator has greater priority + stack[stack_index-3].moperator.GetPriority() > stack[stack_index-1].moperator.GetPriority() + ) || + ( + // or both operators have the same priority and the first operator is not right associative + stack[stack_index-3].moperator.GetPriority() == stack[stack_index-1].moperator.GetPriority() && + stack[stack_index-3].moperator.GetAssoc() == MatOperator::non_right + ) + ) ) { MakeStandardMathematicOperation(stack[stack_index-4].value,