public IValue Middle(IValue before, IValue after) { var beforeType = before.ValueType; var afterType = after.ValueType; if (beforeType == ValueTypes.String || afterType == ValueTypes.String) { return(new Constant(before.GetString() + after.GetString())); } if (beforeType == ValueTypes.Number || afterType == ValueTypes.Number) { return(new Constant(before.GetNumber() + after.GetNumber())); } if (beforeType == ValueTypes.Float || afterType == ValueTypes.Float) { return(new Constant(before.GetFloat() + after.GetFloat())); } if (beforeType == ValueTypes.Integer || afterType == ValueTypes.Integer) { return(new Constant(before.GetInteger() + after.GetInteger())); } throw new Exception(StringHelper.Format("{0} and {1} cannot {2}.", beforeType.ToString(), afterType.ToString(), Code)); }
public override double GetFloat() { try { return(m_pVal.GetFloat()); } catch (ParserError exc) { exc.GetContext().Ident = GetIdent(); throw; } }
public override void Eval(ref IValue ret, IValue[] a_pArg) { Global.MUP_VERIFY(a_pArg.Length == 2); IValue arg1 = a_pArg[0]; IValue arg2 = a_pArg[1]; if (arg1.IsNonComplexScalar() || arg2.IsNonComplexScalar()) { if (!arg1.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg1.GetValueType(), 'f', 1)); } if (!arg2.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg2.GetValueType(), 'f', 2)); } if (arg1.IsInteger() && arg2.IsInteger()) { ret = arg1.GetInteger() - arg2.GetInteger(); } else { ret = arg1.GetFloat() - arg2.GetFloat(); } } else //if (arg1.IsMatrix() && arg2.IsMatrix()) { // Vector + Vector //Matrix a1 = arg1.GetArray(), a2 = arg2.GetArray(); //if (a1.GetRows() != a2.GetRows()) // throw new ParserError(new ErrorContext(EErrorCodes.ecARRAY_SIZE_MISMATCH, -1, GetIdent(), 'm', 'm', 2)); //var rv = new Matrix(a1.GetRows()); //for (int i = 0; i < a1.GetRows(); ++i) //{ // if (!a1.At(i).IsNonComplexScalar()) // throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), a1.At(i).GetValueType(), 'f', 1)); // if (!a2.At(i).IsNonComplexScalar()) // throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), a2.At(i).GetValueType(), 'f', 1)); // if (a1.At(i).IsInteger() && a2.At(i).IsInteger()) // rv.At(i) = a1.At(i).GetInteger() - a2.At(i).GetInteger(); // else // rv.At(i) = a1.At(i).GetFloat() - a2.At(i).GetFloat(); //} ret = arg1 - arg2; } }
public IValue Before(IValue after) { switch (after.ValueType) { case ValueTypes.Integer: return(new Constant(-after.GetInteger())); case ValueTypes.Float: return(new Constant(-after.GetFloat())); case ValueTypes.Number: return(new Constant(-after.GetNumber())); default: throw new Exception("- 无法应用于" + after.ValueType); } }
public override void Eval(ref IValue ret, IValue[] a_pArg) { Global.MUP_VERIFY(a_pArg.Length == 2); IValue arg1 = a_pArg[0]; IValue arg2 = a_pArg[1]; if (!arg1.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg1.GetValueType(), 'f', 1)); } if (!arg2.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg2.GetValueType(), 'f', 2)); } ret = arg1.GetFloat() / arg2.GetFloat(); }
public double GetFloat() { return(value.GetFloat()); }
public override void Eval(ref IValue ret, IValue[] a_pArg) { Global.MUP_VERIFY(a_pArg.Length == 2); IValue arg1 = a_pArg[0]; IValue arg2 = a_pArg[1]; if (!arg1.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg1.GetValueType(), 'f', 1)); } if (!arg2.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), arg2.GetValueType(), 'f', 2)); } if (arg1.IsInteger() && arg2.IsInteger()) { var i1 = arg1.GetInteger(); var i2 = arg2.GetInteger(); switch (i2) { case 1: ret = i1; break; case 2: ret = i1 * i1; break; case 3: ret = i1 * i1 * i1; break; case 4: ret = i1 * i1 * i1 * i1; break; case 5: ret = i1 * i1 * i1 * i1 * i1; break; default: ret = (long)Math.Pow(i1, i2); break; } } else { var i1 = arg1.GetFloat(); var i2 = arg2.GetFloat(); switch (i2) { case 1: ret = i1; break; case 2: ret = i1 * i1; break; case 3: ret = i1 * i1 * i1; break; case 4: ret = i1 * i1 + i1 * i1; break; case 5: ret = i1 * i1 * i1 * i1 * i1; break; default: ret = Math.Pow(i1, i2); break; } } }
public static void EqnTest(string a_str, dynamic d, bool a_fPass, int nExprVar = -1) { IValue[] fVal = new IValue[5]; IValue a_val = d; try { // p1 is a pointer since I'm going to delete it in order to test if // parsers after copy construction still refer to members of the deleted object. // !! If this is the case this function will crash !! ParserX p1 = new ParserX(); // Add variables Value[] vVarVal = { 1, 2, 3, -2, -1 }; // m1 ist die Einheitsmatrix var m1 = new Value(3, 3, 0L); m1.At(0, 0) = 1L; m1.At(1, 1) = 1L; m1.At(2, 2) = 1L; // m2 ist die Einheitsmatrix Value m2 = new Value(3, 3, 0); m2.At(0, 0) = 1; m2.At(0, 1) = 2; m2.At(0, 2) = 3; m2.At(1, 0) = 4; m2.At(1, 1) = 5; m2.At(1, 2) = 6; m2.At(2, 0) = 7; m2.At(2, 1) = 8; m2.At(2, 2) = 9; p1.DefineOprt(new DbgSillyAdd()); p1.DefineFun(new FunTest0()); p1.DefineVar("a", new Variable(vVarVal[0])); p1.DefineVar("b", new Variable(vVarVal[1])); p1.DefineVar("c", new Variable(vVarVal[2])); p1.DefineVar("d", new Variable(vVarVal[3])); p1.DefineVar("f", new Variable(vVarVal[4])); p1.DefineVar("m1", new Variable(m1)); p1.DefineVar("m2", new Variable(m2)); // Add constants p1.DefineConst("const", 1); p1.DefineConst("const1", 2); p1.DefineConst("const2", 3); // some vector variables Value aVal1 = new Value(3, 0); aVal1.At(0) = 1; aVal1.At(1) = 2; aVal1.At(2) = 3; Value aVal2 = new Value(3, 0); aVal2.At(0) = 4; aVal2.At(1) = 3; aVal2.At(2) = 2; p1.DefineVar("va", new Variable(aVal1)); p1.DefineVar("vb", new Variable(aVal2)); // complex variables Value[] cVal = new Value[3]; cVal[0] = new Complex(1, 1); cVal[1] = new Complex(2, 3); cVal[2] = new Complex(3, 4); p1.DefineVar("ca", new Variable(cVal[0])); p1.DefineVar("cb", new Variable(cVal[1])); p1.DefineVar("cc", new Variable(cVal[2])); p1.SetExpr(a_str); fVal[0] = p1.Eval(); p1.DumpRPN(); // Test copy and assignement operators List <ParserX> vParser = new List <ParserX>(); vParser.Add(p1); // Push p1 into the vector ParserX p2 = new ParserX(); // take parser from vector p2.Assign(vParser[0]); // destroy the originals from p2 vParser.Clear(); // delete the vector p1 = null; // delete the original fVal[1] = p2.Eval(); // If copy constructions does not work // we may see a crash here ParserX p3 = new ParserX(p2); fVal[2] = p3.Eval(); // If assignment does not work // we may see a crash here // Calculating a second time will parse from rpn rather than from // string. The result must be the same... fVal[3] = p3.Eval(); // Calculate yet another time. There is the possibility of // changing variables as a side effect of expression // evaluation. So there are really bugs that could make this fail... fVal[4] = p3.Eval(); // Check i number of used variables is correct if (nExprVar != -1) { int n2 = p2.GetExprVar().Count; int n3 = p3.GetExprVar().Count; if (n2 + n3 != 2 * n2 || n2 != nExprVar) { var msg = $"Number of expression variables is incorrect. (expected: {nExprVar}; detected: {n2})"; Assert.Fail(msg); } } // Check the three results // 1.) computed results must have identic type char cType = fVal[0].GetValueType(); bool bStat = cType == fVal[1].GetValueType() && cType == fVal[2].GetValueType() && cType == fVal[3].GetValueType() && cType == fVal[4].GetValueType(); if (!bStat) { var msg = $"{a_str} : inconsistent result type " + $"({fVal[0].GetValueType()}, {fVal[1].GetValueType()}, " + $"{fVal[2].GetValueType()}, {fVal[3].GetValueType()}, {fVal[4].GetValueType()})"; Assert.Fail(msg); } if ((cType == 'x' || a_val.GetValueType() == 'x') && cType != a_val.GetValueType()) { var msg = $"{a_str}: Complex value sliced!"; Assert.Fail(msg); } // Compare the results switch (cType) { case 'i': case 'b': case 's': bStat = (a_val == fVal[0] && a_val == fVal[1] && a_val == fVal[2] && a_val == fVal[3] && a_val == fVal[4]); break; // We need more attention for comaring float values due to floating point // inaccuracies. case 'f': { bStat = true; int num = fVal.Length; for (int i = 0; i < num; ++i) { bStat &= Math.Abs(a_val.GetFloat() - fVal[i].GetFloat()) <= Math.Abs(fVal[i].GetFloat() * 0.0001); } } break; case 'z': { bStat = true; int num = fVal.Length; for (int i = 0; i < num; ++i) { bStat &= Math.Abs(a_val.AsFloat() - fVal[i].AsFloat()) <= Math.Max(1e-15, Math.Abs(fVal[i].AsFloat() * 0.0000001)); bStat &= Math.Abs(a_val.GetImag() - fVal[i].GetImag()) <= Math.Max(1e-15, Math.Abs(fVal[i].GetImag() * 0.0000001)); } } break; case 'm': { bStat = true; int num = fVal.Length; for (int i = 0; i < num; ++i) { bStat = Check(a_val, fVal[i]); if (!bStat) { break; } } } break; default: Assert.Fail($"Parser return value has an unexpected typecode '{cType}'."); break; } Assert.AreEqual(bStat, a_fPass); } catch (ParserError p) { Assert.Fail(p.GetMsg()); } catch (Exception e) { var msg = a_str + ": " + e.Message; Assert.Fail(msg); } bool Check(IValue v1, IValue v2, bool checkType = true) { if (checkType && v1.GetValueType() != v2.GetValueType()) { return(false); } if (v1.GetRows() != v2.GetRows()) { return(false); } if (v1.IsMatrix()) { for (int i = 0; i < v1.GetRows(); ++i) { for (int j = 0; j < v1.GetCols(); ++j) { if (!Check(v1.At(i, j), v2.At(i, j))) { return(false); } } } return(true); } else { return(Math.Abs(v1.GetFloat() - v2.GetFloat()) <= Math.Max(1e-15, Math.Abs(v1.GetFloat() * 0.0000001))); } } }