<commit_before>﻿using MathNet.Numerics.LinearAlgebra;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CurveFit
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool PolynomEnabled => UsePolynomCheckBox.IsChecked ?? false;
        private int PolynomDegree => (int) DegreeSlider.Value;

        private bool SinesEnabled => UseSinesCheckBox.IsChecked ?? false;
        private double MinFreq => MinFreqSlider.Value;
        private double StepFreq => StepFreqSlider.Value;
        private double MaxFreq => MaxFreqSlider.Value;

        private bool PlotForAllX => PlotAllXCheckBox.IsChecked ?? false;

        private readonly List<Func<Vector<double>, Matrix<double>>> _availableFunctions;

        public MainWindow()
        {
            InitializeComponent();

            InkCanvas.AddHandler(InkCanvas.MouseDownEvent, new MouseButtonEventHandler(InkCanvas_OnMouseDown), true);

            _availableFunctions = new List<Func<Vector<double>, Matrix<double>>>
            {
                BaselineFunction,
                SineFunction,
                PolynomialFunction
            };
        }

        private IEnumerable<double> XValues()
        {
            if (InkCanvas.Strokes.Count == 0)
                return Enumerable.Empty<double>();
            else
                return InkCanvas.Strokes.Last().StylusPoints.Select(p => p.X);
        }

        private IEnumerable<double> YValues()
        {
            if (InkCanvas.Strokes.Count == 0)
                return Enumerable.Empty<double>();
            else
                return InkCanvas.Strokes.Last().StylusPoints.Select(p => p.Y);
        }

        private Vector<double> Sin(Vector<double> v)
            => v.Map(Math.Sin);

        private IEnumerable<double> Range(double start, double step, double end)
        {
            for (double i = start; i < end; i += step)
            {
                yield return i;
            }
        }

        private Matrix<double> BaselineFunction(Vector<double> input)
        {
            return Vector<double>.Build.Dense(input.Count, 1).ToColumnMatrix();
        }

        private Matrix<double> SineFunction(Vector<double> input)
        {
            if (!SinesEnabled)
                return null;

            var freqRange = Vector<double>.Build.DenseOfEnumerable(Range(MinFreq, StepFreq, MaxFreq))*(Math.PI/1000);
            Matrix<double> result = Matrix<double>.Build.Dense(input.Count, freqRange.Count);
            for (int i = 0; i < freqRange.Count; i++)
            {
                result.SetColumn(i, Sin(freqRange[i] * input));
            }
            return result;
        }

        private Matrix<double> PolynomialFunction(Vector<double> input)
        {
            if (!PolynomEnabled)
                return null;

            Debug.Assert(PolynomDegree > 0);
            Matrix<double> result = Matrix<double>.Build.Dense(input.Count, PolynomDegree);
            for (int i = 0; i < PolynomDegree; i++)
            {
                result.SetColumn(i, input.PointwisePower(i+1));
            }
            return result;
        }

        private Matrix<double> PrepareMatrix(Vector<double> input)
        {
            var matrices = _availableFunctions.Select(func => func(input)).Where(x => x != null);
            return Matrix<double>.Build.DenseOfColumnVectors(matrices.SelectMany(matrix => matrix.EnumerateColumns()));
        }

        private void FitCurve()
        {
            var x = Vector<double>.Build.DenseOfEnumerable(XValues());
            var y = Vector<double>.Build.DenseOfEnumerable(YValues());

            var A = PrepareMatrix(x);

            var parameter = A.PseudoInverse() * y;

            Vector<double> plotX;
            Vector<double> plotY;
            if (PlotForAllX)
            {
                plotX = Vector<double>.Build.DenseOfEnumerable(Range(0, 1, InkCanvas.ActualWidth));
                plotY = PrepareMatrix(plotX)*parameter;
            }<commit_msg>Fixed empty canvas bug if a stroke was removed<commit_after>﻿using MathNet.Numerics.LinearAlgebra;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace CurveFit
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private bool PolynomEnabled => UsePolynomCheckBox.IsChecked ?? false;
        private int PolynomDegree => (int) DegreeSlider.Value;

        private bool SinesEnabled => UseSinesCheckBox.IsChecked ?? false;
        private double MinFreq => MinFreqSlider.Value;
        private double StepFreq => StepFreqSlider.Value;
        private double MaxFreq => MaxFreqSlider.Value;

        private bool PlotForAllX => PlotAllXCheckBox.IsChecked ?? false;

        private readonly List<Func<Vector<double>, Matrix<double>>> _availableFunctions;

        public MainWindow()
        {
            InitializeComponent();

            InkCanvas.AddHandler(InkCanvas.MouseDownEvent, new MouseButtonEventHandler(InkCanvas_OnMouseDown), true);

            _availableFunctions = new List<Func<Vector<double>, Matrix<double>>>
            {
                BaselineFunction,
                SineFunction,
                PolynomialFunction
            };
        }

        private IEnumerable<double> XValues()
        {
            if (InkCanvas.Strokes.Count == 0)
                return Enumerable.Empty<double>();
            else
                return InkCanvas.Strokes.Last().StylusPoints.Select(p => p.X);
        }

        private IEnumerable<double> YValues()
        {
            if (InkCanvas.Strokes.Count == 0)
                return Enumerable.Empty<double>();
            else
                return InkCanvas.Strokes.Last().StylusPoints.Select(p => p.Y);
        }

        private Vector<double> Sin(Vector<double> v)
            => v.Map(Math.Sin);

        private IEnumerable<double> Range(double start, double step, double end)
        {
            for (double i = start; i < end; i += step)
            {
                yield return i;
            }
        }

        private Matrix<double> BaselineFunction(Vector<double> input)
        {
            return Vector<double>.Build.Dense(input.Count, 1).ToColumnMatrix();
        }

        private Matrix<double> SineFunction(Vector<double> input)
        {
            if (!SinesEnabled)
                return null;

            var freqRange = Vector<double>.Build.DenseOfEnumerable(Range(MinFreq, StepFreq, MaxFreq))*(Math.PI/1000);
            Matrix<double> result = Matrix<double>.Build.Dense(input.Count, freqRange.Count);
            for (int i = 0; i < freqRange.Count; i++)
            {
                result.SetColumn(i, Sin(freqRange[i] * input));
            }
            return result;
        }

        private Matrix<double> PolynomialFunction(Vector<double> input)
        {
            if (!PolynomEnabled)
                return null;

            Debug.Assert(PolynomDegree > 0);
            Matrix<double> result = Matrix<double>.Build.Dense(input.Count, PolynomDegree);
            for (int i = 0; i < PolynomDegree; i++)
            {
                result.SetColumn(i, input.PointwisePower(i+1));
            }
            return result;
        }

        private Matrix<double> PrepareMatrix(Vector<double> input)
        {
            var matrices = _availableFunctions.Select(func => func(input)).Where(x => x != null);
            return Matrix<double>.Build.DenseOfColumnVectors(matrices.SelectMany(matrix => matrix.EnumerateColumns()));
        }

        private void FitCurve()
        {
            if (InkCanvas.Strokes.Count == 0)
                return;

            var x = Vector<double>.Build.DenseOfEnumerable(XValues());
            var y = Vector<double>.Build.DenseOfEnumerable(YValues());

            var A = PrepareMatrix(x);

            var parameter = A.PseudoInverse() * y;

            Vector<double> plotX;
            Vector<double> plotY;
            if (PlotForAllX)
            {
                plotX = Vector<double>.Build.DenseOfEnumerable(Range(0, 1, InkCanvas.ActualWidth));
                plotY = PrepareMatrix(plotX)*parameter;
            }
{'fraction_non_alphanumeric': 0.10444347636680462, 'fraction_numerical': 0.0029405358309736443, 'mean_word_length': 2.1330603889457525, 'pattern_counts': {'":': 0, '<': 83, '<?xml version=': 0, '>': 105, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3851158', 'n_tokens_mistral': 2566, 'n_tokens_neox': 2463, 'n_words': 520}