private static void WriteValue(BinaryWriter writer, IValue value) { // Write the value type writer.Write((uint)value.Type); switch (value.Type) { case ValueType.Table: WriteValue(writer, value.AsTable()); break; case ValueType.List: WriteValue(writer, value.AsList()); break; case ValueType.String: WriteValue(writer, value.AsString()); break; case ValueType.Integer: writer.Write(value.AsInteger()); break; case ValueType.Float: writer.Write(value.AsFloat()); break; case ValueType.Boolean: WriteValue(writer, value.AsBoolean()); break; default: throw new InvalidOperationException("Unknown ValueType"); } }
public override void Eval(ref IValue ret, IValue[] a_pArg) { Global.MUP_VERIFY(a_pArg.Length == 2); IValue argMin = a_pArg[0]; IValue argMax = a_pArg[1]; if (!argMin.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), argMin.GetValueType(), 'i', 1)); } if (!argMax.IsNonComplexScalar()) { throw new ParserError(new ErrorContext(EErrorCodes.ecTYPE_CONFLICT_FUN, -1, GetIdent(), argMax.GetValueType(), 'i', 1)); } if (argMax < argMin) { throw new ParserError("Colon operator: Maximum value smaller than Minimum!"); } long n = argMax.AsInteger() - argMin.AsInteger() + 1; var arr = new Matrix(n); for (long i = 0; i < n; ++i) { arr.At(i) = argMin.AsFloat() + i; } ret = arr; }
public override void Eval(ref IValue ret, IValue[] a_pArg) { // Debug.Assert(a_pArg.Length <= 1); StreamWriter pFile = null; bool logToFile = false; int iCount = 400000; if (a_pArg.Length > 0) { if (a_pArg[0].IsInteger()) { iCount = (int)a_pArg[0].GetInteger(); } else { logToFile = a_pArg[0].GetBool(); } } string[] sExpr = { "sin(a)", "cos(a)", "tan(a)", "sqrt(a)", "(a+b)*3", "a^2+b^2", "a^3+b^3", "a^4+b^4", "a^5+b^5", "a*2.43854357347+b*2.43854357347", "-(b^1.1)", "a + b * c", "a * b + c", "a+b*(a+b)", "(1+b)*(-3.43854357347)", "e^log(7.43854357347*a)", "10^log(3+b)", "a+b-e*pi/5^6", "a^b/e*pi-5+6", "sin(a)+sin(b)", "(cos(2.41)/b)", "-(sin(pi+a)+1.43854357347)", "a-(e^(log(7+b)))", "sin(((a-a)+b)+a)", "((0.09/a)+2.58)-1.67", "abs(sin(sqrt(a^2+b^2))*255)", "abs(sin(sqrt(a*a+b*b))*255)", "cos(0.90-((cos(b)/2.89)/e)/a)", "(1*(2*(3*(4*(5*(6*(a+b)))))))", "abs(sin(sqrt(a^2.1+b^2.1))*255)", "(1.43854357347*(2.43854357347*(3.43854357347*(4.43854357347*(5.43854357347*(6.43854357347*(7.43854357347*(a+b))))))))", "1.43854357347/(a*sqrt(2.43854357347*pi))*e^(-0.543854357347*((b-a)/a)^2.43854357347)", "1.43854357347+2.43854357347-3.43854357347*4.43854357347/5.43854357347^6.43854357347*(2.43854357347*(1.43854357347-5.43854357347+(3.43854357347*7.43854357347^9.43854357347)*(4.43854357347+6.43854357347*7.43854357347-3.43854357347)))+12", "1+b-3*4.0/5.43854357347^6*(2*(1.43854357347-5.43854357347+(3.43854357347*7.43854357347^9.43854357347)*(4+6*7-3)))+12.43854357347*a", "(b+1)*(b+2)*(b+3)*(b+4)*(b+5)*(b+6)*(b+7)*(b+8)*(b+9)*(b+10)*(b+11)*(b+12)", "(a/((((b+(((e*(((((pi*((((3.43854357347*((pi+a)+pi))+b)+b)*a))+0.43854357347)+e)+a)/a))+a)+b))+b)*a)-pi))", "(((-9.43854357347))-e/(((((((pi-(((-7.43854357347)+(-3.1238723947329)/4.43897589288/e))))/(((-5.43854357347))-2.43854357347)-((pi+(-0))*(sqrt((e+e))*(-8.43854357347))*(((-pi)+(-pi)-(-9.43854357347)*(6.43854357347*5.43854357347))/(-e)-e))/2.43854357347)/((((sqrt(2.43854357347/(-e)+6.43854357347)-(4.43854357347-2.43854357347))+((5.43854357347/(-2.43854357347))/(1*(-pi)+3.43854357347))/8.43854357347)*pi*((pi/((-2.43854357347)/(-6.43854357347)*1.43854357347*(-1.43854357347))*(-6.43854357347)+(-e)))))/((e+(-2.43854357347)+(-e)*((((-3.43854357347)*9.43854357347+(-e)))+(-9)))))))-((((e-7.43854357347+(((5.43854357347/pi-(3.43854357347/1.43854357347+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-e)*(-e)))-8.43854357347))*(-5.43854357347)/((-e)))*(-6.43854357347)-((((((-2.43854357347)-(-9.43854357347)-(-e)-1)/3))))/(sqrt((8.43854357347+(e-((-6.43854357347))+(9.43854357347*(-9.43854357347))))*(((3.43854357347+2.43854357347-8.43854357347))*(7.43854357347+6.43854357347+(-5.43854357347))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9.43854357347))+((((pi))-8.43854357347+2.43854357347))+pi))/e*4.43854357347)*((-5.43854357347)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4.43854357347+(pi)*(-9.43854357347)))))))+(-pi)" }; #if DEBUG var outstr = $"{Directory.GetCurrentDirectory()}/Result_{DateTime.Now.ToString(CultureInfo.InvariantCulture).Replace(':', '-').Replace(' ', '-').Replace('/', '-')}_debug.txt"; #else var outstr = $"{Directory.GetCurrentDirectory()}/Result_{DateTime.Now.ToString(CultureInfo.InvariantCulture).Replace(':', '-').Replace(' ', '-').Replace('/', '-')}_release.txt"; #endif var parser = new ParserX(EPackages.pckALL_NON_COMPLEX); Value a = new Value(1.0); Value b = new Value(2.0); Value c = new Value(3.0); parser.DefineVar("a", new Variable(a)); parser.DefineVar("b", new Variable(b)); parser.DefineVar("c", new Variable(c)); // parser.DefineConst("pi", 3.14159265); // parser.DefineConst("e", 2.718281828459); var timer = new Timer(); #if DEBUG string sMode = "# debug mode\n"; #else string sMode = "# release mode\n"; #endif if (logToFile) { pFile = new StreamWriter(outstr); pFile.Write("{0}; muParserX V{1}\n", sMode, ParserXBase.GetVersion()); pFile.Write("\"Eqn no.\", \"number\", \"result\", \"time in ms\", \"eval per second\", \"expr\"\n"); } Console.Write(sMode); Console.Write("\"Eqn no.\", \"number\", \"result\", \"time in ms\", \"eval per second\", \"expr\"\n"); double avgEvalPerSec = 0; int ct = 0; for (int i = 0; i < sExpr.Length; ++i) { ct++; timer.Start(); IValue value = 0; parser.SetExpr(sExpr[i]); // implicitely create reverse polish notation parser.Eval(); for (int n = 0; n < iCount; ++n) { value = parser.Eval(); } timer.Stop(); double diff = (double)timer.Duration(iCount); double evalPerSec = iCount * 1000.0 / diff; avgEvalPerSec += evalPerSec; if (logToFile) { pFile.Write("Eqn_{0}, {1:n}, {2,-5:n}, {3,-10:n}, {4,-10:n}, {5}\n", i, iCount, value.AsFloat(), diff, evalPerSec, sExpr[i]); } Console.Write("Eqn_{0}, {1:n}, {2,-5:n}, {3,-10:n}, {4,-10:n}, {5}\n", i, iCount, value.AsFloat(), diff, evalPerSec, sExpr[i]); } avgEvalPerSec /= ct; if (logToFile) { pFile.Write("# Eval per s: {0}", (long)avgEvalPerSec); } Console.WriteLine("# Eval per s: {0}", (long)avgEvalPerSec); if (logToFile) { pFile.Flush(); pFile.Close(); } ret = avgEvalPerSec; }
public override double AsFloat() { return(m_pVal.AsFloat()); }
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))); } } }