/// <summary>
 /// Recursive method of merge sorting alghorithm
 /// </summary>
 /// <param name="arr">Jagged array who needs to sort</param>
 /// <param name="left">Left bound of sort area</param>
 /// <param name="right">Right bound of sort area</param>
 /// <param name="sorter">Class inmlements IJagSortable interface and allow to sort arrays</param>
 /// <param name="ord">Sort order</param>
 private static void Sort(double[][] arr, int left, int right, IJagSortable sorter, bool ord = true) 
 {
     if (left < right)
     {
         var centr = (left + right) / 2;
         Sort(arr, left, centr, sorter, ord);
         Sort(arr, centr + 1, right, sorter, ord);
         Merge(arr, left, centr, right, sorter, ord);
     }
 }
        /// <summary>
        /// Main sort method
        /// </summary>
        /// <param name="arr">Jagged array who needs to sort</param>
        /// <param name="left">Left bound of sort area</param>
        /// <param name="right">Right bound of sort area</param>
        /// <param name="sorter">Class inmlements IJagSortable interface and allow to sort arrays</param>
        /// <param name="ord">Sort order</param>
        public static void Sorter(double[][] arr, int left, int right, IJagSortable sorter = null, bool ord = true)
        {
            if (right >= arr.Length || right < 0) throw new IndexOutOfRangeException("Wrong right border.");
            if (left >= right || left < 0) throw new IndexOutOfRangeException("Wrong left border.");

            for (int i = 0; i < arr.Length; i++)
                if (arr[i] == null) throw new ArgumentNullException("Array can't contains nulls.");

            if (sorter == null)
                Sort(arr, left, right, new DefaultSorter(), ord);
            else
                Sort(arr, left, right, sorter, ord);
        }
        /// <summary>
        /// Swap by array elements by using sorter class wich implements IJagSortable
        /// with sort method
        /// </summary>
        /// <param name="arr">Jagged array who needs to sort</param>
        /// <param name="left">Left bound of sort area</param>
        /// <param name="centr">Medium element of array</param>
        /// <param name="right">Right bound of sort area</param>
        /// <param name="sorter">Class inmlements IJagSortable interface and allow to sort arrays</param>
        /// <param name="ord">Sort order</param>
        private static void Merge(double[][] arr, int left, int centr, int right, IJagSortable sorter, bool ord = true) 
        {
            long leftSide = left;
            long rightSide = centr + 1;
            long currentPos = 0;

            double[][] temp = new double[right - left + 1][];

            while (leftSide <= centr && rightSide <= right)
            {
                if ((sorter.Sort(arr[leftSide], arr[rightSide]) < 0) == ord)
                    temp[currentPos++] = arr[leftSide++];
                else
                    temp[currentPos++] = arr[rightSide++];
            }

            while (rightSide <= right)
                temp[currentPos++] = arr[rightSide++];
            while (leftSide <= centr)
                temp[currentPos++] = arr[leftSide++];

            for (currentPos = 0; currentPos < right - left + 1; currentPos++)
                arr[left + currentPos] = temp[currentPos];
        }