예제 #1
0
        //Exp( p ) is
        //    var t : Tree
        //    t := P
        //    while next is a binary operator and prec(binary(next)) >= p
        //       const op := binary(next)
        //       consume
        //       const q := case associativity(op)
        //                  of Right: prec( op )
        //                     Left:  1+prec( op )
        //       const t1 := Exp( q )
        //       t := mkNode( op, t, t1)
        //    return t
        private Expression Exp(int p)
        {
            Expression l = P();

            Operator op = new Operator();

            while (true)
            {
                if (IsBinaryOperator(tokens.Tok, ref op) && Precedence(op) >= p)
                {
                    tokens.Consume();

                    int        q = Precedence(op) + (IsLeftAssociative(op) ? 1 : 0);
                    Expression r = Exp(q);
                    l = Binary.New(op, l, r);
                }
                else if (IsUnaryPostOperator(tokens.Tok, ref op) && Precedence(op) >= p)
                {
                    tokens.Consume();
                    l = Unary.New(op, l);
                }
                else
                {
                    break;
                }
            }
            return(l);
        }
예제 #2
0
        private static Expression Split(Expression P)
        {
            int child = 0;

            if (P is Sum)
            {
                return(ComputerAlgebra.Sum.New(((ComputerAlgebra.Sum)P).Terms.Select(i => ChildPattern(ref child))));
            }
            if (P is Product)
            {
                return(Product.New(((Product)P).Terms.Select(i => ChildPattern(ref child))));
            }
            if (P is Binary)
            {
                return(Binary.New(((Binary)P).Operator, ChildPattern(ref child), ChildPattern(ref child)));
            }
            if (P is Unary)
            {
                return(Unary.New(((Unary)P).Operator, ChildPattern(ref child)));
            }
            if (P is Call)
            {
                return(Call.New(((Call)P).Target, ((Call)P).Arguments.Select(i => ChildPattern(ref child))));
            }
            return(null);
        }
예제 #3
0
        /// <summary>
        /// Distribute products across sums, using partial fractions if necessary.
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public static Expression Expand(this Expression f, Expression x)
        {
            if (f is Product)
            {
                return(ExpandMultiply(f, x));
            }
            else if (f is Sum)
            {
                return(Sum.New(((Sum)f).Terms.Select(i => i.Expand(x))));
            }
            else if (f is Power)
            {
                return(ExpandPower((Power)f, x));
            }
            else if (f is Binary)
            {
                return(Binary.New(((Binary)f).Operator, ((Binary)f).Left.Expand(), ((Binary)f).Right.Expand()));
            }
            else if (f is Unary)
            {
                return(Unary.New(((Unary)f).Operator, ((Unary)f).Operand.Expand()));
            }

            return(f);
        }
예제 #4
0
        /// <summary>
        /// Distribute products across sums, using partial fractions if necessary.
        /// </summary>
        /// <param name="x"></param>
        /// <returns></returns>
        public static Expression Expand(this Expression f, Expression x)
        {
            if (f is Product)
            {
                return(ExpandMultiply(f, x));
            }
            else if (f is Sum sum)
            {
                return(Sum.New(sum.Terms.Select(i => i.Expand(x))));
            }
            else if (f is Power power)
            {
                return(ExpandPower(power, x));
            }
            else if (f is Binary binary)
            {
                return(Binary.New(binary.Operator, binary.Left.Expand(x), binary.Right.Expand(x)));
            }
            else if (f is Unary unary)
            {
                return(Unary.New(unary.Operator, unary.Operand.Expand()));
            }

            return(f);
        }
예제 #5
0
        protected override Expression VisitBinary(Binary B)
        {
            Expression L = Visit(B.Left);
            Expression R = Visit(B.Right);

            if (ReferenceEquals(L, null) || ReferenceEquals(R, null))
            {
                return(null);
            }

            if (ReferenceEquals(L, B.Left) && ReferenceEquals(R, B.Right))
            {
                return(B);
            }
            else
            {
                return(Binary.New(B.Operator, L, R));
            }
        }
예제 #6
0
        protected override Expression VisitBinary(Binary B)
        {
            Expression L = Visit(B.Left);
            Expression R = Visit(B.Right);

            // Evaluate substitution operators.
            if (B is Substitute)
            {
                return(Visit(L.Substitute(Set.MembersOf(R).Cast <Arrow>())));
            }

            Real?LR = AsReal(L);
            Real?RR = AsReal(R);

            // Evaluate relational operators on constants.
            if (LR != null && RR != null)
            {
                switch (B.Operator)
                {
                case Operator.Equal: return(Constant.New(LR.Value == RR.Value));

                case Operator.NotEqual: return(Constant.New(LR.Value != RR.Value));

                case Operator.Less: return(Constant.New(LR.Value < RR.Value));

                case Operator.Greater: return(Constant.New(LR.Value <= RR.Value));

                case Operator.LessEqual: return(Constant.New(LR.Value > RR.Value));

                case Operator.GreaterEqual: return(Constant.New(LR.Value >= RR.Value));

                case Operator.ApproxEqual: return(Constant.New(
                                                      LR.Value == RR.Value ||
                                                      Real.Abs(LR.Value - RR.Value) < 1e-12 * Real.Max(Real.Abs(LR.Value), Real.Abs(RR.Value))));
                }
            }

            // Evaluate boolean operators if possible.
            switch (B.Operator)
            {
            case Operator.And:
                if (IsFalse(LR) || IsFalse(RR))
                {
                    return(Constant.New(false));
                }
                else if (IsTrue(LR) && IsTrue(RR))
                {
                    return(Constant.New(true));
                }
                break;

            case Operator.Or:
                if (IsTrue(LR) || IsTrue(RR))
                {
                    return(Constant.New(true));
                }
                else if (IsFalse(LR) && IsFalse(RR))
                {
                    return(Constant.New(false));
                }
                break;

            case Operator.Equal:
            case Operator.ApproxEqual:
                if (L.Equals(R))
                {
                    return(Constant.New(true));
                }
                break;

            case Operator.NotEqual:
                if (L.Equals(R))
                {
                    return(Constant.New(false));
                }
                break;
            }

            return(Binary.New(B.Operator, L, R));
        }