Пример #1
0
        /// <summary>
        /// Create and return the sub-copy of the current object</summary>
        /// <param name="_from">from index in current object</param>
        /// <param name="_to">to index in current object</param>
        public CBlock Projection(int _from, int _to)
        {
            CBlock block = new CBlock();

            block.Init(m_NumEtalon);
            for (int i = _from; i <= _to; i++)
            {
                if (this[i].IsOperator)
                {
                    block.BaseAdd(null, this[i].Operator);
                }
                else if (this[i].IsNumber)
                {
                    block.BaseAdd(null, this[i].Number);
                }
            }
            return(block);
        }
Пример #2
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        // Find next operator to solve by its priority.
        // And, if available, return it in `_hipos` with valid status,
        // false otherwise
        private bool GetHiPriorityPos(CBlock _blocks, ref int _hipos)
        {
            bool bvalid       = false;
            int  priority     = 0;
            int  testpriority = 0;

            for (int i = 0; i < _blocks.Count; i++)
            {
                if (_blocks[i].IsNumber)
                {
                    continue;
                }
                // here is operator

                testpriority = GetPriority(_blocks[i].Operator);

                // no priority is assigned
                if (!bvalid)
                {
                    priority = testpriority;
                    _hipos   = i;
                    bvalid   = true;
                    continue;
                }

                /** Assign new priority position.
                 * operator (>) or (>=) affects in order of solving operators
                 * with same priority:
                 * (>) - the first operator from the left
                 * (>=)- the last operator from the left
                 * */
                else if (testpriority > priority)
                {
                    priority = testpriority;
                    _hipos   = i;
                }
            }

            return(bvalid);
        }
Пример #3
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>Find end of breace-scope specified by _iStart</summary>
        /// <param name="_blocks">in blocks</param>
        /// <param name="_iStart">at start position</param>
        /// <returns>position of end-brace</returns>
        private int FindEndBrace(CBlock _blocks, int _iStart)
        {
            STUB(_iStart < (_blocks.Count - 1)
                 , "Bad FindEndBrace, index exceed blocks count.");
            STUB((_blocks[_iStart].IsOperator) &&
                 (the(AO.BRBEG) == _blocks[_iStart].Operator)
                 , "Bad FindEndBrace, need operator.");

            int innerBrace = 0;

            for (int i = (_iStart + 1); i < _blocks.Count; i++)
            {
                if (_blocks[i].IsNumber)
                {
                    continue;
                }

                if (the(AO.BRBEG) == _blocks[i].Operator)
                {
                    ++innerBrace;
                }
                else if (the(AO.BREND) == _blocks[i].Operator)
                {
                    if (innerBrace == 0)
                    {
                        return(i);
                    }
                    else
                    {
                        --innerBrace;
                    }
                }
            }
            STUB(false, "End brace not found.");
            return(-1); // unreached code
        }
Пример #4
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Solve unray operator, where operand taken from right of operator
        /// position</summary>
        /// <param name="_blocks">in blocks</param>
        /// <param name="_iHipos">at operator position</param>
        /// <returns>calculation result</returns>
        private CNumber SolveUnary(CBlock _blocks, int _iHipos)
        {
            ASSERT(((_iHipos + 1) < _blocks.Count) && (_blocks[_iHipos + 1].IsNumber)
                   , "Missing argument for >" + _blocks[_iHipos].Operator + '<'
                   , "SolveUnary");

            string  strOperator = _blocks[_iHipos].Operator;
            CNumber number      = _blocks[_iHipos + 1].Number;
            CNumber res;

            STUB(strOperator != null && strOperator != "", "Bad _sOper in SolveUnary");
            STUB(number != null, "Bad _Num in SolveUnary");

            ///-- LOGIC
            if (the(AO.NOT) == strOperator)
            {
                res = CMath.Not(number);
            }
            ///-- ARITHMETIC
            else if (the(AO.MIN) == strOperator)
            {
                res = CMath.Minus(number);
            }
            else if (the(AO.PLS) == strOperator)
            {
                res = CMath.Plus(number);
            }
            else if (the(AO.ROOT) == strOperator)
            { // square root
                res = CMath.Root(number);
            }
            else if (the(AO.ABS) == strOperator)
            {
                res = CMath.Abs(number);
            }
            ///-- THRIGONOMETRY
            else if (the(AO.SIN) == strOperator)
            {
                res = CMath.Sin(number);
            }
            else if (the(AO.COS) == strOperator)
            {
                res = CMath.Cos(number);
            }
            else if (the(AO.EXP) == strOperator)
            {
                res = CMath.Exp(number);
            }
            else if (the(AO.TAN) == strOperator)
            {
                res = CMath.Tan(number);
            }
            ///-- FUNCTION
            else if (the(AO.FACT) == strOperator)
            {
                res = CMath.Factorial(number);
            }
            else if (the(AO.LG) == strOperator)
            {
                res = CMath.Lg(number);
            }
            else if (the(AO.LN) == strOperator)
            {
                res = CMath.Ln(number);
            }
            else if (the(AO.LOG) == strOperator)
            {
                res = CMath.Log(number);
            }
            else
            {
                STUB(false, "[ " + strOperator.ToUpper()
                     + " ] not implemented unary operation!");
                return(null);
            }

            ASSERT(!(double.IsInfinity(res.dValue))
                   , "Result is ±Infinity", "SolveUnary");
            ASSERT(!(double.IsNaN(res.dValue))
                   , "Result is Not a number", "SolveUnary");

            return(res);
        }
Пример #5
0
        /// <summary>
        /// Solve binary operator, where operands taken from right and left
        /// of operator position</summary>
        /// <param name="_blocks">in blocks</param>
        /// <param name="_iHipos">at operator position</param>
        /// <returns>calculation result</returns>
        private CNumber SolveBinary(CBlock _blocks, int _iHipos)
        {
            ASSERT((_blocks.Count >= 3) && (_iHipos > 0) &&
                   ((_iHipos + 1) < _blocks.Count)
                   , "Unrecovered binary operator >" + _blocks[_iHipos].Operator + '<'
                   , "SolveBinary1");
            ASSERT(_blocks[_iHipos - 1].IsNumber && _blocks[_iHipos + 1].IsNumber
                   , "Missing argument for binary operator >" + _blocks[_iHipos].Operator + '<'
                   , "SolveBinary2");

            CNumber nLeft       = _blocks[_iHipos - 1].Number;
            string  strOperator = _blocks[_iHipos].Operator;
            CNumber nRight      = _blocks[_iHipos + 1].Number;
            CNumber res;

            STUB((nLeft != null) && (nRight != null), "Bad _nLeft in SolveBinary.");
            STUB((strOperator != null) && (strOperator != ""), "Bad _sOper in SolveBinary.");

            ///-- ARITHMETIC
            if (the(AO.POW) == strOperator)
            {
                res = CMath.Pow(nLeft, nRight);
            }
            else if (the(AO.MUL) == strOperator)
            {
                res = CMath.Mul(nLeft, nRight);
            }
            else if (the(AO.DIV) == strOperator)
            {
                res = CMath.Div(nLeft, nRight);
            }
            else if (the(AO.MOD) == strOperator)
            {
                res = CMath.Mod(nLeft, nRight);
            }
            else if (the(AO.PLS) == strOperator)
            {
                res = CMath.Plus(nLeft, nRight);
            }
            else if (the(AO.MIN) == strOperator)
            {
                res = CMath.Minus(nLeft, nRight);
            }
            else if (the(AO.ROOT) == strOperator)
            {
                res = CMath.Root(nLeft, nRight);
            }
            ///-- FUNCTION
            else if (the(AO.LOG) == strOperator)
            {
                res = CMath.Log(nLeft, nRight);
            }
            ///-- LOGIC
            else if (the(AO.AND) == strOperator)
            {
                res = CMath.Log(nLeft, nRight);
            }
            else if (the(AO.OR) == strOperator)
            {
                res = CMath.Or(nLeft, nRight);
            }
            else if (the(AO.XOR) == strOperator)
            {
                res = CMath.Xor(nLeft, nRight);
            }
            ///-- BITWISE
            else if (the(AO.SH_LEFT) == strOperator)
            {
                res = CMath.ShiftLeft(nLeft, nRight);
            }
            else if (the(AO.SH_RIGHT) == strOperator)
            {
                res = CMath.ShiftRight(nLeft, nRight);
            }
            else if (the(AO.GCD) == strOperator)
            {
                res = CMath.GCD(nLeft, nRight);
            }
            //-- not implemented
            else
            {
                STUB(false, "[" + strOperator
                     + "] not implemented binary operation!");
                return(null);
            }

            ASSERT(!(double.IsInfinity(res.dValue))
                   , "Result is ±Infinity", "SolveBinary");
            ASSERT(!(double.IsNaN(res.dValue))
                   , "Result is Not a number", "SolveBinary");

            return(res);
        }
Пример #6
0
        //••••••••••••••••••••••••••••••••••••••••••••••••••••••••
        /// <summary>
        /// Solve partitionized expression.
        /// Assume what:
        ///  - created valid partition (Parse_to_Blocks)
        ///  - any registers replaced by value (..)
        ///  - no braces conflicts (..)
        /// Parentheses solved in recursion call, end-condition is
        /// when one part is left, and its a number.</summary>
        /// <param name="_scPart">valid partition</param>
        /// <returns>answer</returns>
        private void Parts_Solve(CBlock _blocks)
        {
            int hipos = 0; // hi priority index
            int brEnd = 0; // index of found `AO.BREND`

            while (1 < _blocks.Count)
            {
                // find hi priority operator index
                if (GetHiPriorityPos(_blocks, ref hipos))
                {
                    // engage braces by self-recursion
                    if (the(AO.BRBEG) == _blocks[hipos].Operator)
                    {
                        // here `hipos` is index of `AO.BRBEG`
                        brEnd = FindEndBrace(_blocks, hipos);
                        // copy sub-expression parts
                        CBlock subBlocks = _blocks.Projection((hipos + 1), (brEnd - 1));

                        Parts_Solve(subBlocks); // enter recursion

                        // RETURN AFTER RECURSIVE CALL WITH ONLY ONE PART
                        ASSERT(1 == subBlocks.Count
                               , "Invalid recursion return"
                               , "Parts_Solve: ret from recursion");

                        _blocks.ReplaceWith(subBlocks[0].Number, hipos, brEnd);
                    }
                    /// engage unary or binary operators by priority
                    /// Check if current operator is a double-sence operator:
                    /// Unary have number from right, binary from both sides.
                    else
                    {
                        bool unary = true; // is unray by default
                        if (IsDoubleSenseAO(_blocks[hipos].Operator))
                        {
                            // check boundaries before accesing by indexes
                            if ((hipos > 0) && ((hipos + 1) < _blocks.Count))
                            {
                                // define from context...
                                unary = (_blocks[hipos - 1].IsOperator ||
                                         _blocks[hipos + 1].IsOperator);
                            }
                        }
                        else
                        {
                            // define from table of unary operators...
                            unary = IsUnaryAO(_blocks[hipos].Operator);
                        }

                        if (unary)
                        {
                            m_result = this.SolveUnary(_blocks, hipos);
                            _blocks.ReplaceWith(m_result, hipos, hipos + 1);
                        }
                        else // binary
                        {
                            m_result = SolveBinary(_blocks, hipos);
                            _blocks.ReplaceWith(m_result, hipos - 1, hipos + 1);
                        }
                    }
                }
                else // priority operator not found
                {
                    ASSERT(false
                           , "Omitted operator found after >" + _blocks[0].Number + '<'
                           , "Parts_Solve: operator not found");
                }
            }

            // End solving with single number
            ASSERT(_blocks.Count == 1, "Nothing to solve", "Parts_Solve: 1-part,1");
            ASSERT(_blocks[0].IsNumber
                   , "Unrecovered >" + _blocks[0].Operator + "< operator"
                   , "Parts_Solve: 1-part,2");
            return;
        }