Example #1
0
        public void Evaluate_Function_Log()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("log(10 * 10 * 10 * 10)");
            double result           = ae.Evaluate(double.NaN);

            Assert.AreEqual(4.0, result);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #2
0
        public void Evaluate_SimpleFunction_AutoMultiply()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("5sqrt(x)");
            double result           = ae.Evaluate(16);

            Assert.AreEqual(5.0 * Math.Sqrt(16), result);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #3
0
        public void Evaluate_Precedence()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("1 / (2 * 4) ^ 2");
            double result           = ae.Evaluate(double.NaN);

            Assert.AreEqual(1.0 / Math.Pow(2.0 * 4.0, 2), result);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #4
0
        public void Evaluate_SimpleExpression()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("(2 - 1 + 6) % 5");
            double result           = ae.Evaluate(double.NaN);

            Assert.AreEqual((2 - 1 + 6) % 5, result);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #5
0
        public void Evaluate_Parentheses()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("((( ((( ((( 1 + 2 ))) + 3 ))) + 4 ))) + 5");
            double result           = ae.Evaluate(double.NaN);

            Assert.AreEqual(1 + 2 + 3 + 4 + 5, result);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #6
0
        public void Evaluate_Function_RoundDown()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("round(z)");
            double result           = ae.Evaluate(6.49);

            Assert.AreEqual(6.0, result);
            Assert.AreEqual("z", ae.VariableName);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #7
0
        public void Evaluate_SimpleFunction()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("cos(custom)");
            double result           = ae.Evaluate(0);

            Assert.AreEqual(1.0, result);
            Assert.AreEqual("custom", ae.VariableName);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #8
0
        public void Evaluate_Variable()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("x");
            double result           = ae.Evaluate(-10);

            Assert.AreEqual(-10, result);
            Assert.AreEqual("x", ae.VariableName);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #9
0
        public void Evaluate_Constant_AutoMultiply()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("2pi");
            double result           = ae.Evaluate(double.NaN);

            Assert.AreEqual(2.0 * Math.PI, result);
            Assert.IsNull(ae.VariableName);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #10
0
        public void Evaluate_Constant_3()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("6e-3");
            double result           = ae.Evaluate(double.NaN);

            Assert.AreEqual(0.006, result);
            Assert.IsNull(ae.VariableName);
            Assert.IsTrue(ae.IsSimpleConstantOnly);
        }
Example #11
0
        public void Evaluate_Comment()
        {
            ArithmeticExpression ae = ArithmeticExpression.Parse("1 + 2 + 3 # This is comment!");
            double result           = ae.Evaluate(double.NaN);

            Assert.AreEqual(6, result);
            Assert.IsNull(ae.VariableName);
            Assert.IsFalse(ae.IsSimpleConstantOnly);
        }
Example #12
0
        public void Evaluate_Variable_2()
        {
            ArithmeticExpression ae1 = ArithmeticExpression.Parse("sin(x)");
            double result1           = ae1.Evaluate(10);

            ArithmeticExpression ae2 = ArithmeticExpression.Parse("sin(10)");
            double result2           = ae2.Evaluate(double.NaN);

            Assert.AreEqual(result1, result2);
        }
Example #13
0
        public void Evaluate_KnownConstants()
        {
            ArithmeticExpression ae1 = ArithmeticExpression.Parse("pi");
            double result1           = ae1.Evaluate(double.NaN);

            Assert.AreEqual(Math.PI, result1);

            ArithmeticExpression ae2 = ArithmeticExpression.Parse("e");
            double result2           = ae2.Evaluate(double.NaN);

            Assert.AreEqual(Math.E, result2);
        }
Example #14
0
        public void Evaluate_Callbacks()
        {
            ArithmeticExpression    ae        = ArithmeticExpression.Parse("(+1) * (-2) * 3");
            DotNetOperatorCallbacks callbacks = new DotNetOperatorCallbacks();

            ae.Callbacks = callbacks;

            double result = ae.Evaluate(0);

            Assert.AreEqual((+1) * (-2) * 3, result);
            Assert.AreEqual(callbacks, ae.Callbacks);

            Assert.IsFalse(callbacks.IsDisposed);

            callbacks.Dispose();

            Assert.IsTrue(callbacks.IsDisposed);
        }
Example #15
0
        private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Text")
            {
                ListView.Item item = (ListView.Item)sender;
                if (string.IsNullOrEmpty(item.Text))
                {
                    item.NumericValueSource = null;
                    item.TextDisplay        = "\f[0x999999]" + Tx.T("main.enter expression");
                }
                else
                {
                    try {
                        ArithmeticExpression ae = ArithmeticExpression.Parse(item.Text);
                        ae.Callbacks = item.OperatorCallbacks;

                        item.NumericValueSource = ae;

                        int i = item.Text.IndexOf('#');
                        if (i != -1)
                        {
                            while (i > 0 && item.Text[i - 1] == ' ')
                            {
                                i--;
                            }

                            StringBuilder sb = new StringBuilder();
                            sb.Append(item.Text, 0, i);

                            if (ae.VariableName == null && !ae.IsSimpleConstantOnly)
                            {
                                double result = ae.Evaluate(double.NaN);

                                sb.Append("\f[I]\f[0x999999] = ");
                                sb.Append(result.ToExactString().LimitSize(32));
                                sb.Append(" \f[I]");
                            }

                            sb.Append("\f[0x498E3E]");
                            sb.Append(item.Text, i, item.Text.Length - i);

                            CheckCallbacks(item, sb);

                            item.TextDisplay = sb.ToString();
                        }
                        else
                        {
                            if (ae.VariableName == null && !ae.IsSimpleConstantOnly)
                            {
                                StringBuilder sb = new StringBuilder();
                                sb.Append(item.Text);

                                double result = ae.Evaluate(double.NaN);

                                sb.Append("\f[I]\f[0x999999] = ");
                                if (double.IsPositiveInfinity(result))
                                {
                                    sb.Append("+∞");
                                }
                                else if (double.IsNegativeInfinity(result))
                                {
                                    sb.Append("−∞");
                                }
                                else
                                {
                                    sb.Append(result.ToExactString().LimitSize(32));
                                }
                                sb.Append("\f[I]");

                                CheckCallbacks(item, sb);

                                item.TextDisplay = sb.ToString();
                            }
                            else
                            {
                                StringBuilder sb = new StringBuilder();
                                sb.Append(item.Text);

                                CheckCallbacks(item, sb);

                                item.TextDisplay = sb.ToString();
                            }
                        }
                    } catch (SyntaxException ex) {
                        item.NumericValueSource = null;

                        StringBuilder sb = new StringBuilder();
                        sb.Append("\f[0x8b0000]");

                        int length = ex.Input.IndexOf('#');
                        if (length == -1)
                        {
                            length = ex.Input.Length;
                        }

                        if (length < 3)
                        {
                            sb.Append(ex.Input);
                        }
                        else
                        {
                            if (ex.Index - 1 < 0)
                            {
                                sb.Append("\f[U]");
                            }
                            else
                            {
                                sb.Append(ex.Input, 0, ex.Index - 1);

                                sb.Append("\f[U]\f[0xd00000]");
                                sb.Append(ex.Input[ex.Index - 1]);
                            }

                            sb.Append("\f[0xff0000]");
                            sb.Append(ex.Input[ex.Index]);

                            if (ex.Index + 1 < length)
                            {
                                sb.Append("\f[0xd00000]");
                                sb.Append(ex.Input[ex.Index + 1]);

                                sb.Append("\f[0x8b0000]\f[U]");

                                if (ex.Index + 2 < length)
                                {
                                    sb.Append(ex.Input, ex.Index + 2, length - (ex.Index + 2));
                                }
                            }
                            else
                            {
                                sb.Append("\f[0xd00000] \f[U]");
                            }
                        }

                        switch (ex.ExceptionType)
                        {
                        case SyntaxException.Type.Unknown:
                            break;

                        case SyntaxException.Type.InvalidNumber:
                            sb.Append("      \f[-]\f[image:warning]  \f[0xaa6400]\f[I]");
                            sb.Append(Tx.T("expression.errors.invalid number"));
                            break;

                        case SyntaxException.Type.DistinctVariableCountExceeded:
                            sb.Append("      \f[-]\f[image:warning]  \f[0xaa6400]\f[I]");
                            sb.Append(Tx.T("expression.errors.distinct variable count exceeded"));
                            break;

                        case SyntaxException.Type.ParenthesesCountMismatch:
                            sb.Append("      \f[-]\f[image:warning]  \f[0xaa6400]\f[I]");
                            sb.Append(Tx.T("expression.errors.parentheses count mismatch"));
                            break;

                        default:
                            throw new InvalidEnumArgumentException("ex.ExceptionType", (int)ex.ExceptionType, typeof(SyntaxException.Type));
                        }

                        item.TextDisplay = sb.ToString();
                    } catch (Exception ex) {
                        item.NumericValueSource = null;

                        item.TextDisplay = "\f[0x8b0000]" + item.Text + "      \f[-]\f[image:warning]  \f[0xaa6400]\f[I]" + ex.Message;
                    }
                }

                item.CheckEnabled = (item.NumericValueSource != null);

                RefreshToolStrip();
            }
            else if (e.PropertyName == "OperatorCallbacks")
            {
                ListView.Item        item = (ListView.Item)sender;
                ArithmeticExpression arithmeticExpression = item.NumericValueSource as ArithmeticExpression;
                if (arithmeticExpression != null)
                {
                    arithmeticExpression.Callbacks = item.OperatorCallbacks;

                    OnItemPropertyChanged(item, new PropertyChangedEventArgs("Text"));
                }

                item.Description = item.OperatorCallbacks.ImplementationName;
            }
        }
Example #16
0
        private unsafe void OnExportSelectedButtonClick(object sender, EventArgs e)
        {
            ListView.Item selected = listView.FocusedItem;
            if (selected == null)
            {
                // Nothing to export...
                return;
            }

            ArithmeticExpression ae = selected.NumericValueSource as ArithmeticExpression;

            if (ae == null)
            {
                MessageBox.Show(this, Tx.T("dataset.errors.item not supported"), Tx.T("main.error"), MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            long xFi = 0, xLi = 0, distance = 0;

            if (ae.VariableName != null)
            {
                double xF_ = graph.MinVisibleX;
                double xL_ = graph.MaxVisibleX;

                if (xF_ >= xL_)
                {
                    MessageBox.Show(this, Tx.T("dataset.errors.cannot determine interval"), Tx.T("main.error"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (Math.Sign(xF_) != Math.Sign(xL_))
                {
                    MessageBox.Show(this, Tx.T("dataset.errors.interval with zero"), Tx.T("main.error"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // Swap first and last for negative "x" values
                xFi = *(long *)&xF_;
                xLi = *(long *)&xL_;
                if (xFi > xLi)
                {
                    long swap = xLi;
                    xLi = xFi;
                    xFi = swap;
                }
                distance = (xLi - xFi);

                if (distance < 0)
                {
                    MessageBox.Show(this, Tx.T("dataset.errors.interval too big"), Tx.T("main.error"),
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                if (distance > 10 * 1000 * 1000)
                {
                    long   sizeInMB = (distance * 8 * 2 / 1024 / 1024);
                    string sizeString;
                    if (sizeInMB > 100L * 1024L)
                    {
                        sizeString = Tx.N(sizeInMB / 1024) + " GB";
                    }
                    else
                    {
                        sizeString = Tx.N(sizeInMB) + " MB";
                    }

                    if (MessageBox.Show(this, Tx.T("dataset.errors.file too big", Tx.N(distance), sizeString), Tx.T("main.warning"),
                                        MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                    {
                        return;
                    }
                }
            }

            using (SaveFileDialog dialog = new SaveFileDialog()) {
                const string ext = ".fvis-values";

                dialog.Filter           = Tx.T("dataset.filetype") + " (*" + ext + ")|*" + ext;
                dialog.FilterIndex      = 0;
                dialog.RestoreDirectory = true;
                dialog.Title            = Tx.T("dataset.save");

                string filename     = selected.Text;
                char[] invalidChars = Path.GetInvalidFileNameChars();
                for (int i = 0; i < invalidChars.Length; i++)
                {
                    filename = filename.Replace(invalidChars[i], '_');
                }

                dialog.FileName = filename + ext;

                if (dialog.ShowDialog(this) != DialogResult.OK)
                {
                    return;
                }

                filename = dialog.FileName;

                ProgressDialog progressDialog = new ProgressDialog();
                progressDialog.Text            = Tx.T("dataset.saving.title");
                progressDialog.MainInstruction = Tx.T("dataset.saving.description");
                progressDialog.Line1           = Tx.T("dataset.saving.progress", "0", Tx.N(xLi - xFi));
                progressDialog.Show(this);

                ThreadPool.UnsafeQueueUserWorkItem(delegate {
                    using (FileStream s = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None))
                        using (BinaryWriter bw = new BinaryWriter(s)) {
                            bw.Write(new[] { (byte)'f', (byte)'V', (byte)'i', (byte)'s' });

                            const int flags = 0;
                            bw.Write(flags);

                            string description = selected.Text;
                            bw.Write(description);

                            // Save graph viewport settings
                            long axisX         = graph.AxisX;
                            long axisY         = graph.AxisY;
                            double scaleFactor = graph.ScaleFactor;

                            bw.Write(axisX);
                            bw.Write(axisY);
                            bw.Write(scaleFactor);

                            if (ae.VariableName == null)
                            {
                                // Constant function, save only one value
                                double y = ae.Evaluate(double.NaN);

                                const long count = 2;
                                bw.Write(count);

                                bw.Write(double.MinValue);
                                bw.Write(y);
                                bw.Write(double.MaxValue);
                                bw.Write(y);
                            }
                            else
                            {
                                bw.Write(distance + 1);

                                Stopwatch sw       = Stopwatch.StartNew();
                                long lastProcessed = xFi;

                                for (long xi = xFi; xi <= xLi; xi++)
                                {
                                    double x = *(double *)&xi;
                                    double y = ae.Evaluate(x);

                                    bw.Write(x);
                                    bw.Write(y);

                                    if (sw.ElapsedMilliseconds > 4000)
                                    {
                                        if (progressDialog.IsCancelled)
                                        {
                                            break;
                                        }

                                        sw.Stop();

                                        long delta         = (xi - lastProcessed);
                                        long rate          = delta * 1000 / (long)sw.Elapsed.TotalMilliseconds;
                                        TimeSpan remaining = TimeSpan.FromSeconds((xLi - xi) / rate);

                                        lastProcessed = xi;

                                        BeginInvoke((MethodInvoker) delegate {
                                            progressDialog.Line1    = Tx.T("dataset.saving.progress", Tx.N(lastProcessed - xFi), Tx.N(xLi - xFi));
                                            progressDialog.Line2    = Tx.T("main.remaining time", remaining.ToTextString());
                                            progressDialog.Progress = (int)((lastProcessed - xFi) * 100 / (xLi - xFi));
                                        });

                                        sw.Restart();
                                    }
                                }

                                sw.Stop();
                            }
                        }

                    if (progressDialog.IsCancelled)
                    {
                        try {
                            File.Delete(filename);
                        } catch {
                            // Nothing to do...
                        }
                    }

                    BeginInvoke((MethodInvoker) delegate {
                        progressDialog.TaskCompleted();
                    });
                }, null);
            }
        }