コード例 #1
0
ファイル: Number.cs プロジェクト: takku205/FuncCalc
        public override INumber Subtract(RuntimeData runtime, INumber val)
        {
            var v = val.Eval(runtime);

            if (v is Number)
            {
                if (this.Pow.Equals(runtime, val.Pow))
                {
                    return(Number.New(this.Value - (val as Number).Value));
                }
                else
                {
                    AdditionFormula af = new Expression.AdditionFormula();
                    af.AddItem(runtime, this);
                    af.AddItem(runtime, val.Multiple(runtime, Number.New(-1)));
                    return(af);
                }
            }
            if (v is Fraction)
            {
                return(v.Multiple(runtime, Number.New(-1)).Add(runtime, this));
            }

            return(v.Subtract(runtime, this));
        }
コード例 #2
0
        public INumber Execute(RuntimeData runtime, INumber left, INumber right)
        {
            if (!(left is Variable) && !(left is Member) &&
                !(left is FunctionFormula))
            {
                throw new SyntaxException("代入は変数にのみ行えます。", left);
            }

            Variable v = null;

            if (left is Variable)
            {
                v = left as Variable;
            }
            else if (left is Member)
            {
                v = new Variable((left as Member).Token);
            }
            else if (left is FunctionFormula && (left as FunctionFormula).Count == 1)
            {
                v = new Variable(((left as FunctionFormula).Items[0] as Member).Token);
            }
            else
            {
                throw new NotImplementedException();
            }

            var res = right.Eval(runtime);

            runtime.SetVariable(runtime, v, res);
            return(res);
        }
コード例 #3
0
ファイル: Differential.cs プロジェクト: takku205/FuncCalc
        public static bool IsConstValue(RuntimeData runtime, INumber num)
        {
            var res = num.Eval(runtime);

            if (res is IConstParameter)
            {
                return(true);
            }
            if (res is AdditionFormula || res is MultipleFormula)
            {
                for (int i = 0; i < (res as IFormula).Count; i++)
                {
                    if (!((res as IFormula).Items[i] is IConstParameter))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            if (res is Fraction)
            {
                return
                    (IsConstValue(runtime, (res as Fraction).Denominator) &&
                     IsConstValue(runtime, (res as Fraction).Numerator));
            }

            return(false);
        }
コード例 #4
0
ファイル: Number.cs プロジェクト: takku205/FuncCalc
        public override INumber Multiple(RuntimeData runtime, INumber val)
        {
            if (this.Value == 0)
            {
                return(Number.New(0));
            }

            var v = val.Eval(runtime);

            if (v is Number)
            {
                if (this.Pow.Equals(runtime, val.Pow))
                {
                    return(Number.New(this.Value * (v as Number).Value));
                }
                else
                {
                    MultipleFormula mf = new MultipleFormula();
                    mf.AddItem(runtime, this);
                    mf.AddItem(runtime, val);
                    return(mf);
                }
            }

            return(val.Multiple(runtime, this));
        }
コード例 #5
0
ファイル: Variable.cs プロジェクト: takku205/FuncCalc
        public override INumber Multiple(RuntimeData runtime, INumber val)
        {
            var v = val.Eval(runtime);

            if (v is Variable &&
                (v as Variable).Name == this.Name)
            {
                var me = this.Clone() as Variable;
                me.multi = me.multi.Multiple(runtime, (v as Variable).multi);
                me.Pow   = me.Pow.Add(runtime, (v as Variable).Pow);
                return(me);
            }
            if (v is Number && (v as Number).Value == 1)
            {
                return(this);
            }
            if (v is Number)
            {
                var me = this.Clone() as Variable;
                me.multi = me.multi.Multiple(runtime, v);
                return(me);
            }

            return(v.Multiple(runtime, this));

            MultipleFormula af = new MultipleFormula();

            af.AddItem(runtime, this);
            af.AddItem(runtime, v);
            return(af);
        }
コード例 #6
0
        public INumber Execute(RuntimeData runtime, INumber left, INumber right)
        {
            var r = right.Eval(runtime);

            runtime.Setting.GetOperator("?=", null, true).Execute(runtime, left, r);
            return(r);
        }
コード例 #7
0
ファイル: IncrementRight.cs プロジェクト: takku205/FuncCalc
        public INumber Execute(RuntimeData runtime, INumber left, INumber right)
        {
            var dt = left.Eval(runtime);

            runtime.Setting.Spec.Operations.Where(a => a.Key.GetType() == typeof(Substitution)).First().Key
            .Execute(runtime, left, left.Add(runtime, Number.New(1)));
            return(dt);
        }
コード例 #8
0
ファイル: Number.cs プロジェクト: takku205/FuncCalc
        public override INumber Divide(RuntimeData runtime, INumber val)
        {
            var v = val.Eval(runtime);

            if (val is Number && (val as Number).Value == 0)
            {
                if (this.ValueType == ValueType.Plus)
                {
                    return(InfinityValue.PlusValue);
                }
                else
                {
                    return(InfinityValue.MinusValue);
                }
                // ValueType.Unknownになることはない
            }

            if (v is Number)
            {
                if (this.Pow.Equals(runtime, val.Pow))
                {
                    if (this.Value % (v as Number).Value == 0) // 割り切れるなら数値として返す
                    {
                        return(Number.New(this.Value / (v as Number).Value));
                    }
                    else // 割り切れないなら分数として返す
                    {
                        return(new Fraction(v, this));
                    }
                }
                else
                {
                    return(new Fraction(v, this));
                }
            }

            if (v is Fraction)
            {
                return
                    ((new Fraction((v as Fraction).Numerator, (v as Fraction).Denominator)).Multiple(runtime, this));
            }

            // こちらの方で対応していないものも半ば強引に解決させる
            return(new Fraction(val, this));
        }
コード例 #9
0
        public void AddItem(RuntimeData runtime, INumber val)
        {
            var v = val.Eval(runtime);

            if (v is Number && (val as Number).Value == 0)
            {
            }
            else if (v is AdditionFormula &&
                     (v.Pow is Number && (v.Pow as Number).Value == 1))
            {
                foreach (var item in (val as AdditionFormula).items)
                {
                    this.items.Add(item);
                }
            }
            else
            {
                this.items.Add(v);
            }
        }
コード例 #10
0
ファイル: MultipleFormula.cs プロジェクト: takku205/FuncCalc
        public void AddItem(RuntimeData runtime, INumber val)
        {
            var v = val.Eval(runtime);

            if (v is Number && (v as Number).Value == 1)
            {
                return;
            }

            if (val is AdditionFormula && (val as AdditionFormula).Count == 1)
            {
                this.AddItem(runtime, (val as AdditionFormula).Items[0]);
                return;
            }
            if (val is MultipleFormula)
            {
                foreach (var item in (val as MultipleFormula).items)
                {
                    this.AddItem(runtime, item);
                }
                return;
            }

            for (int i = 0; i < this.items.Count; i++)
            {
                if (runtime.Setting.DoOptimize && (
                        this.items[i].CanJoin(runtime, val) ||
                        val.CanJoin(runtime, this.items[i])))
                {
                    this.items[i] =
                        this.items[i].Multiple(runtime, val);
                    return;
                }
            }

            this.items.Add(v);
        }
コード例 #11
0
        public INumber Eval(RuntimeData runtime)
        {
            BlockData data = runtime.NowBlock;


            for (int i = 0; i < this.Count; i++)
            {
                IExpression exp = this.Items[i];

                if (exp is Operator)
                {
                    INumber  left = null, right = null;
                    Operator op = exp as Operator;

                    if (runtime.Setting.IsDebug)
                    {
                        // Console.Clear();
                        OutputStackData(runtime, exp);
                    }

                    bool willEval = true;
                    // 後ろの方にEvalせずに実行する演算子がある場合、変数を評価しないようにする
                    for (int j = i + 1; j < this.Count; j++)
                    {
                        if (this.items[j] is Operator &&
                            !(this.items[j] as Operator).Evaluator.DoEvaledParam)
                        {
                            willEval = false;
                            runtime.AddBlock(new BlockData()
                            {
                                MoreScope = false
                            });
                            if (runtime.Setting.IsDebug)
                            {
                                Console.WriteLine("AddBlock[MoreScope=false] しました");
                            }
                            break;
                        }
                    }

                    if (op.Evaluator.RequireRightParameter)
                    {
                        var r = data.Pop();
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            r = (r as IEval).Eval(runtime);
                        }
                        if (!op.Evaluator.DoEvaledParam && r is INumber)
                        {
                        }
                        else if (r is Variable || r is Member)
                        {
                        }
                        else if (r is Member)
                        {
                            r = (r as Member).GetVariable(runtime);
                        }
                        else
                        {
                            r = (r as IEval).Eval(runtime);
                        }
                        right = r as INumber;
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            right = right.Eval(runtime);
                        }
                    }
                    if (op.Evaluator.RequireLeftParameter)
                    {
                        var l = data.Pop();
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            l = (l as IEval).Eval(runtime);
                        }
                        if (!op.Evaluator.DoEvaledParam && l is INumber)
                        {
                        }
                        else if (l is Variable)
                        {
                        }
                        else if (l is Member)
                        {
                            l = (l as Member).GetVariable(runtime);
                        }
                        else
                        {
                            l = (l as IEval).Eval(runtime);
                        }

                        left = l as INumber;
                        if (op.Evaluator.DoEvaledParam && willEval)
                        {
                            left = left.Eval(runtime);
                        }
                    }

                    var res = (exp as Operator).Evaluator.Execute(runtime, left as INumber, right as INumber);
                    if (res != null && runtime.Setting.DoOptimize)
                    {
                        res = res.Optimise(runtime);
                    }

                    if (!willEval)
                    {
                        runtime.PopBlock();
                    }

                    data.Push(res);

                    if (runtime.Setting.IsDebug)
                    {
                        // Console.Clear();
                        Console.WriteLine("Eval RPE Formula : ({0})[{1}] {2} ({3})[{4}] => {5}[{6}]",
                                          left != null ? left.ToString() : "null",
                                          left != null ? left.GetType().Name : "",
                                          (exp as Operator).Evaluator.Name,
                                          right != null ? right.ToString() : "null",
                                          right != null ? right.GetType().Name : "",
                                          res != null ? res.ToString() : "null",
                                          res != null ? res.GetType().Name : "");
                        OutputStackData(runtime, null);
                    }
                }
                else
                {
                    if (exp is IEval)
                    {
                        data.Push(exp as IEval);
                    }
                    else
                    {
                        throw new NotImplementedException();
                    }
                }
            }

            if (data.Count == 0)
            {
                return(null);
            }
            else
            {
                var result = data.Pop() as INumber;
                if (result != null && runtime.Setting.DoOptimize)
                {
                    return(result.Optimise(runtime));
                }
                return(result);
            }
        }
コード例 #12
0
ファイル: MultipleFormula.cs プロジェクト: takku205/FuncCalc
        public INumber TryDivide(RuntimeData runtime, INumber val, out bool result)
        {
            // IConstParameterで割ろうとした場合はBase.Divideでも対応できるのでここでは割愛する

            // メンバー(変数)で割ろうとした場合
            Variable v = val as Variable;

            if (v != null || (v = val.Eval(runtime) as Variable) is Variable)
            {
                var me = this.Clone() as MultipleFormula;

                for (int i = 0; i < me.items.Count; i++)
                {
                    var item = me.items[i];
                    if (item is MultipleFormula)
                    {
                        throw new FuncCalcException("MultipleFormulaの中にMultipleFormulaが含まれています。", this);
                    }

                    if (item is Variable)
                    {
                        var res = item.Divide(runtime, v);
                        if (res is Number && (res as Number).Value == 1)
                        {
                            me.items.RemoveAt(i);
                            result = true;
                            return(me);
                        }
                        me.items[i] = res;
                        result      = true;
                        return(me);
                    }
                }
            }
            if (val is MultipleFormula)
            {
                MultipleFormula den  = new Expression.MultipleFormula();
                INumber         num  = this.Clone() as MultipleFormula;
                MultipleFormula f    = val as MultipleFormula;
                bool            flag = false;

                for (int i = 0; i < f.items.Count; i++)
                {
                    var  ex = f.items[i];
                    bool dv_res; INumber res;
                    res = (num as MultipleFormula).TryDivide(runtime, ex, out dv_res);
                    if (dv_res)
                    {
                        flag = true;
                        if (res is MultipleFormula)
                        {
                            num = res as MultipleFormula;
                        }
                        else
                        {
                            num = res;
                            for (int j = i + 1; j < f.items.Count; j++)
                            {
                                den.AddItem(runtime, f.items[j]);
                            }
                            break;
                        }
                    }
                    else
                    {
                        den.AddItem(runtime, ex);
                    }
                }
                if (!flag)
                {
                    result = false; return(null);
                }
                else
                {
                    result = true;

                    // numの条件判定はdenより先に行う
                    if (num is MultipleFormula)
                    {
                        INumber d = den;
                        if (den.items.Count == 0)
                        {
                            return(num);
                        }
                        if (den.items.Count == 1)
                        {
                            d = den.items[0];
                        }

                        if ((num as MultipleFormula).items.Count == 0)
                        {
                            return(new Fraction(d, Number.New(1)));
                        }
                        if ((num as MultipleFormula).items.Count == 1)
                        {
                            return(new Fraction(d, (num as MultipleFormula).items[0]));
                        }
                    }

                    // 最低限の形で返す
                    if (den.items.Count == 0)
                    {
                        return(num);
                    }
                    if (den.items.Count == 1)
                    {
                        var res = new Fraction(den.items[0], num);
                        if (runtime.Setting.DoOptimize)
                        {
                            return(res.Optimise(runtime));
                        }
                        else
                        {
                            return(res);
                        }
                    }

                    return(new Fraction(den, num));
                }
            }

            result = false;
            return(null);
        }