Ejemplo n.º 1
0
        public void test_string_split_join()
        {
            const string name      = "Jimmy";
            const string splitname = "J-i-m-m-y";
            var          p         = new ParserX();

            p.DefineVar(nameof(name), new Variable(name));

            p.SetExpr("split(name)");
            var res = p.Eval();

            Assert.IsTrue(res.IsMatrix());
            Matrix m = res.GetArray();

            for (var i = 0; i < name.Length; i++)
            {
                var c = name[i];
                Assert.AreEqual(c, m.At(i));
            }
            p.DefineVar("list", new Variable(m));
            p.SetExpr("join(list, \"-\")");
            res = p.Eval();
            Assert.IsTrue(res.IsString());
            Assert.AreEqual(res.GetString(), splitname);
        }
Ejemplo n.º 2
0
        public override void Eval(ref IValue ret, IValue[] a_pArg)
        {
            string sID = a_pArg[0].GetString();

            ParserX.ResetErrorMessageProvider(sID);

            ret = 0;
        }
Ejemplo n.º 3
0
        public void test_detection_of_undefined_variables()
        {
            var p = new ParserX();

            p.SetExpr("a+b+c+d");
            var expr_var = p.GetExprVar();
            var var      = p.GetVar();

            Assert.AreEqual(4, expr_var.Count);
            Assert.AreEqual(0, var.Count);
        }
Ejemplo n.º 4
0
        public void test_detection_of_auto_created_variables()
        {
            var p = new ParserX();

            p.EnableAutoCreateVar(true);
            p.SetExpr("a+b+c+d");
            var expr_var = p.GetExprVar();
            var var      = p.GetVar();

            Assert.AreEqual(4, expr_var.Count);
            Assert.AreEqual(4, var.Count);
        }
Ejemplo n.º 5
0
        static void Main(string[] args)
        {
            ParserX.AddTask <ArgsDogICME16>(DogICME16, "Dog@ICME16 evaluation");
            ParserX.AddTask <ArgsCelebMM16>(CelebMM16, "Celeb@MM16 evaluation");
            ParserX.AddTask <ArgsCheckLog>(CheckLog, "Check log file");

            if (ParserX.ParseArgumentsWithUsage(args))
            {
                Stopwatch timer = Stopwatch.StartNew();
                ParserX.RunTask();
                timer.Stop();
                Console.WriteLine("Time used: {0}", timer.Elapsed);
            }
        }
Ejemplo n.º 6
0
        static void Main(string[] args)
        {
            ParserX.AddTask <ArgsStart>(Start, "Start a new evaluation");
            ParserX.AddTask <ArgsStart>(Resume, "Resume the last unfinished evaluation");
            ParserX.AddTask <ArgsEval>(Cancel, "Cancel the current evaluation");
            ParserX.AddTask <ArgsEval>(Check, "Check the progress of the current evaluation");
            ParserX.AddTask <ArgsList>(List, "List the progress of all the current evaluations");

            if (ParserX.ParseArgumentsWithUsage(args))
            {
                Stopwatch timer = Stopwatch.StartNew();
                ParserX.RunTask();
                timer.Stop();
                Console.WriteLine("Time used: {0}", timer.Elapsed);
            }
        }
Ejemplo n.º 7
0
        public void test_detection_of_variables()
        {
            var p = new ParserX();

            Value[] vVarVal = { 1.0, 2.0, 3.0, 4.0 };
            p.DefineVar("a", new Variable(vVarVal[0]));
            p.DefineVar("b", new Variable(vVarVal[1]));
            p.DefineVar("c", new Variable(vVarVal[2]));
            p.DefineVar("d", new Variable(vVarVal[3]));

            p.SetExpr("a+b+c+d");
            var expr_var = p.GetExprVar();
            var var      = p.GetVar();

            Assert.AreEqual(4, expr_var.Count);
            Assert.AreEqual(4, var.Count);
        }
Ejemplo n.º 8
0
            private static void ListExprVar(ParserX parser)
            {
                Console.WriteLine($"   Variables found in : \"{parser.GetExpr()}\"");
                Console.WriteLine("   -----------------------------\n");
                // Query the used variables (must be done after calc)
                var vmap = parser.GetExprVar();

                if (!vmap.Any())
                {
                    Console.WriteLine("Expression does not contain variables\n");
                }
                else
                {
                    foreach (var item in vmap)
                    {
                        Console.WriteLine($"      {item.Key} =  {item.Value}");
                    }
                }
                Console.WriteLine();
            }
Ejemplo n.º 9
0
        public void test_variable_remains_unchanged_after_operation()
        {
            var p = new ParserX();

            p.EnableAutoCreateVar(true);

            p.SetExpr("v = 3.14");
            var v = p.Eval();

            Assert.AreEqual('f', v.GetValueType());
            Assert.AreEqual(3.14, v.AsFloat());


            p.SetExpr("v * 2");
            var ans = p.Eval(); // Perform arithmitic operation on variable

            Assert.AreEqual('f', ans.GetValueType());
            Assert.AreEqual(6.28, ans.AsFloat());


            Assert.AreEqual('f', v.GetValueType());
            Assert.AreEqual(3.14, v.AsFloat());
        }
Ejemplo n.º 10
0
        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;
        }
Ejemplo n.º 11
0
            static void Main()
            {
                EnvDTE80.DTE2 vs_env;
                (string file, int line)error = (null, -1);
                var parser = new ParserX(); //EPackages.pckALL_NON_COMPLEX);

                Initialise(parser);
                DrawSplash();
                SelfTest();
                vs_env = (EnvDTE80.DTE2)Marshal.GetActiveObject("VisualStudio.DTE.15.0");
                while (true)
                {
                    try
                    {
                        Console.Write(PROMPT);
                        var inStr = Console.ReadLine();
                        if (string.IsNullOrEmpty(inStr) || CheckKeywords(inStr))
                        {
                            continue;
                        }
                        parser.SetExpr(inStr);
                        var ans = parser.Eval();

                        Console.WriteLine($"Result (type: '{ans.GetValueType()}'):");
                        Console.WriteLine($"ans = {ans.TidyString()}\n");
                        error.line = -1;
                    }
                    catch (ParserError pe)
                    {
                        //if (error.line != -1)
                        //{
                        //    var len = vs_env.Debugger.Breakpoints.Count;
                        //    vs_env.Debugger.Breakpoints.Item(len).Delete();
                        //}
                        //else
                        pe.Print();
                        error = (pe._file, pe._line);
                    }
                }



                bool CheckKeywords(string sLine)
                {
                    if (sLine == "quit" || sLine == "exit")
                    {
                        Environment.Exit(0);
                    }
                    else if (sLine == "exprvar")
                    {
                        ListExprVar(parser);
                        return(true);
                    }
                    else if (sLine == "cls")
                    {
                        Console.Clear();
                        return(true);
                    }
#if DEBUG
                    else if (sLine == "break")
                    {
                        if (error.line != -1)
                        {
                            vs_env.Debugger.Breakpoints.Add(Line: error.line, File: error.file);
                            parser.Eval();
                            var len = vs_env.Debugger.Breakpoints.Count;
                            vs_env.Debugger.Breakpoints.Item(len).Delete();
                            error = ("", -1);
                        }
                        else
                        {
                            Console.WriteLine("  No error to break on!");
                        }
                        return(true);
                    }
#endif
                    else if (sLine == "clear")
                    {
                        Console.Clear();
                        DrawSplash();
                        return(true);
                    }
                    else if (sLine == "rpn")
                    {
                        parser.DumpRPN();
                        return(true);
                    }

                    return(false);
                }
            }
Ejemplo n.º 12
0
            private static void Initialise(ParserX parser)
            {
                // Create an array variable
                Value arr1 = new Value(3, 0);

                arr1[0] = (1.0);
                arr1[1] = 2.0;
                arr1[2] = 3.0;

                Value arr2 = new Value(3, 0);

                arr2[0] = 4.0;
                arr2[1] = 3.0;
                arr2[2] = 2.0;

                Value arr3 = new Value(4, 0);

                arr3[0] = 1.0;
                arr3[1] = 2.0;
                arr3[2] = 3.0;
                arr3[3] = 4.0;

                Value arr4 = new Value(3, 0);

                arr4[0] = 4.0;
                arr4[1] = false;
                arr4[2] = "hallo";

                // Create a 3x3 matrix with zero elements
                Value m1 = new Value(3, 3, 0);

                m1[0, 0] = 1.0;
                m1[1, 1] = 1.0;
                m1[2, 2] = 1.0;

                Value m2 = new Value(3, 3, 0);

                m2[0, 0] = 1.0;
                m2[0, 1] = 2.0;
                m2[0, 2] = 3.0;
                m2[1, 0] = 4.0;
                m2[1, 1] = 5.0;
                m2[1, 2] = 6.0;
                m2[2, 0] = 7.0;
                m2[2, 1] = 8.0;
                m2[2, 2] = 9.0;

                Value[] val = new Value[5];
                val[0] = 1.1;
                val[1] = 1.0;
                val[2] = false;
                val[3] = "Hello";
                val[4] = "World";

                Value[] fVal = new Value[3];
                fVal[0] = 1;
                fVal[1] = 2.22;
                fVal[2] = 3.33;

                Value[] sVal = new Value[3];
                sVal[0] = "hello";
                sVal[1] = "world";
                sVal[2] = "test";

                Value[] cVal = new Value[3];
                cVal[0] = new Complex(1, 1);
                cVal[1] = new Complex(2, 2);
                cVal[2] = new Complex(3, 3);

                var size_3x1 = new Value(1, 2, 0);

                size_3x1.At(0, 0) = 3.0;
                size_3x1.At(0, 1) = 1.0;

                parser.DefineVar("s31", new Variable(size_3x1));
                Value ans = new Value(0);

                parser.DefineVar("ans", new Variable(ans));

                // some tests for vectors
                parser.DefineVar("va", new Variable(arr1));
                parser.DefineVar("vb", new Variable(arr2));
                parser.DefineVar("vc", new Variable(arr3));
                parser.DefineVar("vd", new Variable(arr4));
                parser.DefineVar("m1", new Variable(m1));
                parser.DefineVar("m2", new Variable(m2));

                parser.DefineVar("a", new Variable(fVal[0]));
                parser.DefineVar("b", new Variable(fVal[1]));
                parser.DefineVar("c", new Variable(fVal[2]));

                parser.DefineVar("ca", new Variable(cVal[0]));
                parser.DefineVar("cb", new Variable(cVal[1]));
                parser.DefineVar("cc", new Variable(cVal[2]));

                parser.DefineVar("sa", new Variable(sVal[0]));
                parser.DefineVar("sb", new Variable(sVal[1]));

                // Add functions for inspecting the parser properties
                parser.DefineFun(new FunListVar());
                parser.DefineFun(new FunListFunctions());
                parser.DefineFun(new FunListConst());
                parser.DefineFun(new FunBenchmark());
                parser.DefineFun(new FunEnableOptimizer());
                parser.DefineFun(new FunSelfTest());
                parser.DefineFun(new FunEnableDebugDump());
                parser.DefineFun(new FunTest0());
                parser.DefineFun(new FunPrint());


                parser.DefineFun(new FunLang());
                parser.EnableAutoCreateVar(true);

#if DEBUG
                ParserXBase.EnableDebugDump(bDumpStack: false, bDumpRPN: false);
#endif

                Value x = 1.0;
                Value y = new Complex(0, 1);
                parser.DefineVar("x", new Variable(x));
                parser.DefineVar("y", new Variable(y));
            }
Ejemplo n.º 13
0
        public static void ThrowTest(string a_sExpr, EErrorCodes a_nErrc, int a_nPos = -1, string a_sIdent = null)
        {
            try
            {
                var     p       = new ParserX();
                Value[] vVarVal = { 1, 2, 3, -2 };
                p.DefineVar("a", new Variable(vVarVal[0]));
                p.DefineVar("b", new Variable(vVarVal[1]));
                p.DefineVar("c", new Variable(vVarVal[2]));
                p.DefineVar("d", new Variable(vVarVal[3]));

                // array variables
                Value aVal1 = new Value(3, 0);
                aVal1.At(0) = 1.0;
                aVal1.At(1) = 2.0;
                aVal1.At(2) = 3.0;

                Value aVal2 = new Value(3, 0);
                aVal2.At(0) = 4.0;
                aVal2.At(1) = 3.0;
                aVal2.At(2) = 2.0;

                Value aVal3 = new Value(4, 0);
                aVal3.At(0) = 4.0;
                aVal3.At(1) = 3.0;
                aVal3.At(2) = 2.0;
                aVal3.At(3) = 5.0;

                Value aVal4 = new Value(4, 0);
                aVal4.At(0) = 4.0;
                aVal4.At(1) = false;
                aVal4.At(2) = "hallo";

                // Matrix variables
                Value m1 = new Value(3, 3, 0);
                m1.At(0, 0) = 1.0;
                m1.At(1, 1) = 1.0;
                m1.At(2, 2) = 1.0;

                Value m2 = new Value(3, 3, 0);
                m2.At(0, 0) = 1.0; m2.At(0, 1) = 2.0; m2.At(0, 2) = 3.0;
                m2.At(1, 0) = 4.0; m2.At(1, 1) = 5.0; m2.At(1, 2) = 6.0;
                m2.At(2, 0) = 7.0; m2.At(2, 1) = 8.0; m2.At(2, 2) = 9.0;

                p.DefineVar("m1", new Variable(m1));
                p.DefineVar("m2", new Variable(m2));
                p.DefineVar("va", new Variable(aVal1));
                p.DefineVar("vb", new Variable(aVal2));
                p.DefineVar("vc", new Variable(aVal3));
                p.DefineVar("vd", new Variable(aVal4));

                p.SetExpr(a_sExpr);
                IValue fRes = p.Eval();
                Assert.Fail("Evauluation of '" + a_sExpr + "' diddn't throw expected error: ( " + a_nErrc + " )");
            }
            catch (ParserError p)
            {
                Assert.AreEqual(p.GetCode(), a_nErrc);
                if (a_nPos != -1)
                {
                    Assert.AreEqual(p.GetPos(), a_nPos);
                }
                if (a_sIdent != null)
                {
                    Assert.AreEqual(p.GetToken(), a_sIdent);
                }
            }
        }
Ejemplo n.º 14
0
        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)));
                }
            }
        }