public override INumber Power(RuntimeData runtime, INumber val) { var me = this.Clone() as Number; if (val is Number && (val as Number).Value < 0) { return(new Fraction( Number.New(this.Value).Power(runtime, val.Multiple(runtime, Number.New(-1))), Number.New(1))); } if (val is Number) { if ((val as Number).Value >= 1) { var res = me.Value; for (int i = 0; i < (val as Number).Value - 1; i++) { me.Value *= res; } me.Pow = Number.New(1); return(me); } else if ((val as Number).Value == 0) { return(Number.New(1)); } else { return(new Fraction(me.Power(runtime, Number.New((val as Number).Value * -1)), Number.New(1))); } } me.Pow = val; return(me); }
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)); }
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)); }
public override INumber FinalEval(RuntimeData runtime) { INumber res = Number.New(1); for (int i = 0; i < this.items.Count; i++) { res = res.Multiple(runtime, this.items[i].FinalEval(runtime)); } return(res); }
public override INumber Optimise(RuntimeData runtime) { INumber res = Number.New(1); for (int i = 0; i < this.Count; i++) { res = res.Multiple(runtime, this.items[i]); if (!(res is MultipleFormula)) { res = res.Optimise(runtime); } } //if (!(res is MultipleFormula)) // return res.Optimise(runtime); return(res); }
public override INumber Multiple(RuntimeData runtime, INumber val) { if (val is IConstParameter) { var me = this.Clone() as FloatNumber; me.value *= (val as IConstParameter).ConstValue; return(me); } if (val is InfinityValue) { return(val.Multiple(runtime, this)); } MultipleFormula mf = new MultipleFormula(); mf.AddItem(runtime, val); mf.AddItem(runtime, this); return(mf); }
public INumber Execute(RuntimeData runtime, INumber left, INumber right) { // 意味のない計算はここで弾く if (left is Number && (left as Number).Value == 1) { return(right); } if (right is Number && (right as Number).Value == 1) { return(left); } if ((left is Number && (left as Number).Value == 0) || (right is Number && (right as Number).Value == 0)) { return(Number.New(0)); } if (left is Number && right is Number) { return(Number.New((left as Number).Value * (right as Number).Value)); } return(left.Multiple(runtime, right)); }
public override INumber Eval(RuntimeData runtime) { // 1しかない場合は変数 if (this.items.Count == 1) { if (!(this.items[0] is INumber)) { throw new NotImplementedException("FunctionFormulaに値以外が紛れ込んでいます"); } return((this.items[0] as INumber).Eval(runtime)); } bool nextFlag = false; IExpression func = null; INumber multiple = Number.New(1); for (int i = 0; i < this.items.Count; i++) { IExpression ex = this.items[i]; if (ex is Member && ((nextFlag && func != null) || (!nextFlag && func == null))) { func = FunctionFormula.GetMember(runtime, func, ex as Member); if (func == null) { throw new SyntaxException(string.Format("'{0}'は見つかりませんでした", ex.Token.Text), ex.Token, new KeyNotFoundException()); } if (func is INumber && !(func is IEvalWithParameters)) { multiple = multiple.Multiple(runtime, func as INumber); func = null; } nextFlag = false; continue; } if (ex is Operator && ex.Token.Text == runtime.Setting.Spec.ScopeOperator) { nextFlag = true; continue; } // パラメータ関係 if ((ex is IFormula) && !nextFlag) { if (func == null && multiple is IEvalWithParameters) { func = multiple; multiple = Number.New(1); } if (func != null) { runtime.AddBlock(new BlockData() { MoreScope = true }); runtime.NowBlock.Push(new LineBreak()); (ex as IFormula).ExecuteAsParameter(runtime); IExpression res = null; if (func is INumber && func is IEvalWithParameters) { List <INumber> prm = new List <INumber>(); for (; runtime.NowBlock.Stack.Length != 0;) { var it = runtime.NowBlock.Pop(); if (it is LineBreak) { continue; } if (!(it is INumber)) { throw new RuntimeException("インデックス指定で値型(INumber)以外のパラメータを指定することはできません。", it); } prm.Add(it as INumber); } res = (func as IEvalWithParameters).Execute(runtime, prm.ToArray()) as IExpression; } else { res = ExecuteFunc(runtime, func, multiple); } runtime.PopBlock(); if (res is INumber) { if (multiple is Number && (multiple as Number).Value != 1) { multiple = multiple.Multiple(runtime, res as INumber); } else { multiple = res as INumber; } func = null; } else if (res == null) { func = null; multiple = null; } else { func = res; throw new NotImplementedException("関数の戻り値は現在 '値' しか対応していません"); } continue; } else { if (multiple.Equals(runtime, Number.New(1))) { return(this); // 未解決のメンバーを実行しようとしている式は評価せずに返す } else { var res = (ex as IFormula).Eval(runtime); multiple = multiple.Multiple(runtime, res); } continue; } } throw new NotImplementedException(); } if (func == null && multiple == null) { return(null); } if (func == null) { return(multiple); } if (!(func is INumber)) { throw new RuntimeException("現在、関数の戻り値は値のみに対応しています。関数ポインターを戻り値にすることはできません。", this); } return((func as INumber).Eval(runtime)); }
public override INumber Divide(RuntimeData runtime, INumber val) { if (val is Number) { Fraction me = this.Clone() as Fraction; me.Denominator = me.Denominator.Multiple(runtime, val); if (runtime.Setting.DoOptimize) { return(me.Optimise(runtime)); } else { return(me); } } if (val is Fraction) { var res = new Fraction( this.Denominator.Multiple(runtime, (val as Fraction).Numerator), this.Numerator.Multiple(runtime, (val as Fraction).Denominator)); if (runtime.Setting.DoOptimize) { return(res.Optimise(runtime)); } else { return(res); } } if (this.Denominator is MultipleFormula) { bool mf_res; var dv_res = (this.Denominator as MultipleFormula).TryDivide(runtime, val, out mf_res); if (mf_res) { var me = this.Clone() as Fraction; me.Denominator = dv_res; if (runtime.Setting.DoOptimize) { return(me.Optimise(runtime)); } else { return(me); } } else { var me = this.Clone() as Fraction; me.Denominator = me.Denominator.Multiple(runtime, val); if (runtime.Setting.DoOptimize) { return(me.Optimise(runtime)); } else { return(me); } } } return(val.Multiple(runtime, new Fraction(this.Numerator, this.Denominator))); }
INumber CheckMulti(RuntimeData runtime, string varname, INumber val, out INumber pow) { if (val is IConstParameter) { pow = Number.New(0); return(val); } if (val is Variable) { if ((val as Variable).Name == varname) { pow = val.Pow; return((val as Variable).Multi); } else { pow = Number.New(0); return(val); } } if (val is Member) { if ((val as Member).Text == varname) { pow = val.Pow; return((val as Member).Multi); } else { pow = Number.New(0); return(val); } } if (val is MultipleFormula) { MultipleFormula mf = val as MultipleFormula; INumber res = Number.New(0); INumber pres = Number.New(1); bool flag = false; for (int i = 0; i < mf.Items.Count; i++) { var item = mf.Items[i]; INumber p = null; var r = this.CheckMulti(runtime, varname, item, out p); if (p is Number && (p as Number).Value == 0) { res = res.Multiple(runtime, r); } else { flag = true; pres = pres.Add(runtime, p); res = res.Multiple(runtime, r); } } if (flag) { pow = pres; return(res); } else { pow = Number.New(0); return(res); } } if (val is AdditionFormula) { throw new RuntimeException("バグ: [AF]のアイテム評価関数に[AF]が指定されました。", val); } throw new NotImplementedException("[AF]のアイテム評価関数の未実装"); }
public INumber Execute(RuntimeData runtime, INumber left, INumber right) { return(right.Multiple(runtime, Number.New(-1))); }