Sorting.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.numbers.arrays;

  18. import java.util.Arrays;

  19. /**
  20.  * Support class for sorting arrays.
  21.  *
  22.  * <p>Optimal sorting networks are used for small fixed size array sorting.
  23.  *
  24.  * <p>Note: Requires that the floating-point data contains no NaN values; sorting
  25.  * does not respect the order of signed zeros imposed by {@link Double#compare(double, double)}.
  26.  *
  27.  * @see <a href="https://en.wikipedia.org/wiki/Sorting_network">Sorting network (Wikipedia)</a>
  28.  * @see <a href="https://bertdobbelaere.github.io/sorting_networks.html">Sorting Networks (Bert Dobbelaere)</a>
  29.  *
  30.  * @since 1.2
  31.  */
  32. final class Sorting {

  33.     /** No instances. */
  34.     private Sorting() {}

  35.     /**
  36.      * Sorts an array using an insertion sort.
  37.      *
  38.      * @param x Data array.
  39.      * @param left Lower bound (inclusive).
  40.      * @param right Upper bound (inclusive).
  41.      */
  42.     static void sort(double[] x, int left, int right) {
  43.         for (int i = left; ++i <= right;) {
  44.             final double v = x[i];
  45.             // Move preceding higher elements above (if required)
  46.             if (v < x[i - 1]) {
  47.                 int j = i;
  48.                 while (--j >= left && v < x[j]) {
  49.                     x[j + 1] = x[j];
  50.                 }
  51.                 x[j + 1] = v;
  52.             }
  53.         }
  54.     }

  55.     /**
  56.      * Sorts the elements at the given distinct indices in an array.
  57.      *
  58.      * @param x Data array.
  59.      * @param a Index.
  60.      * @param b Index.
  61.      * @param c Index.
  62.      */
  63.     static void sort3(double[] x, int a, int b, int c) {
  64.         // Decision tree avoiding swaps:
  65.         // Order [(0,2)]
  66.         // Move point 1 above point 2 or below point 0
  67.         final double u = x[a];
  68.         final double v = x[b];
  69.         final double w = x[c];
  70.         if (w < u) {
  71.             if (v < w) {
  72.                 x[a] = v;
  73.                 x[b] = w;
  74.                 x[c] = u;
  75.                 return;
  76.             }
  77.             if (u < v) {
  78.                 x[a] = w;
  79.                 x[b] = u;
  80.                 x[c] = v;
  81.                 return;
  82.             }
  83.             // w < v < u
  84.             x[a] = w;
  85.             x[c] = u;
  86.             return;
  87.         }
  88.         if (v < u) {
  89.             // v < u < w
  90.             x[a] = v;
  91.             x[b] = u;
  92.             return;
  93.         }
  94.         if (w < v) {
  95.             // u < w < v
  96.             x[b] = w;
  97.             x[c] = v;
  98.         }
  99.         // u < v < w
  100.     }

  101.     /**
  102.      * Sorts the elements at the given distinct indices in an array.
  103.      *
  104.      * @param x Data array.
  105.      * @param a Index.
  106.      * @param b Index.
  107.      * @param c Index.
  108.      * @param d Index.
  109.      * @param e Index.
  110.      */
  111.     static void sort5(double[] x, int a, int b, int c, int d, int e) {
  112.         // Uses an optimal sorting network from Knuth's Art of Computer Programming.
  113.         // 9 comparisons.
  114.         // Order pairs:
  115.         // [(0,3),(1,4)]
  116.         // [(0,2),(1,3)]
  117.         // [(0,1),(2,4)]
  118.         // [(1,2),(3,4)]
  119.         // [(2,3)]
  120.         if (x[e] < x[b]) {
  121.             final double u = x[e];
  122.             x[e] = x[b];
  123.             x[b] = u;
  124.         }
  125.         if (x[d] < x[a]) {
  126.             final double v = x[d];
  127.             x[d] = x[a];
  128.             x[a] = v;
  129.         }

  130.         if (x[d] < x[b]) {
  131.             final double u = x[d];
  132.             x[d] = x[b];
  133.             x[b] = u;
  134.         }
  135.         if (x[c] < x[a]) {
  136.             final double v = x[c];
  137.             x[c] = x[a];
  138.             x[a] = v;
  139.         }

  140.         if (x[e] < x[c]) {
  141.             final double u = x[e];
  142.             x[e] = x[c];
  143.             x[c] = u;
  144.         }
  145.         if (x[b] < x[a]) {
  146.             final double v = x[b];
  147.             x[b] = x[a];
  148.             x[a] = v;
  149.         }

  150.         if (x[e] < x[d]) {
  151.             final double u = x[e];
  152.             x[e] = x[d];
  153.             x[d] = u;
  154.         }
  155.         if (x[c] < x[b]) {
  156.             final double v = x[c];
  157.             x[c] = x[b];
  158.             x[b] = v;
  159.         }

  160.         if (x[d] < x[c]) {
  161.             final double u = x[d];
  162.             x[d] = x[c];
  163.             x[c] = u;
  164.         }
  165.     }

  166.     /**
  167.      * Place the lower median of 4 elements in {@code b}; the smaller element in
  168.      * {@code a}; and the larger two elements in {@code c, d}.
  169.      *
  170.      * @param x Values
  171.      * @param a Index.
  172.      * @param b Index.
  173.      * @param c Index.
  174.      * @param d Index.
  175.      */
  176.     static void lowerMedian4(double[] x, int a, int b, int c, int d) {
  177.         // 3 to 5 comparisons
  178.         if (x[d] < x[b]) {
  179.             final double u = x[d];
  180.             x[d] = x[b];
  181.             x[b] = u;
  182.         }
  183.         if (x[c] < x[a]) {
  184.             final double v = x[c];
  185.             x[c] = x[a];
  186.             x[a] = v;
  187.         }
  188.         // a--c
  189.         // b--d
  190.         if (x[c] < x[b]) {
  191.             final double u = x[c];
  192.             x[c] = x[b];
  193.             x[b] = u;
  194.         } else if (x[b] < x[a]) {
  195.             //    a--c
  196.             // b--d
  197.             final double xb = x[a];
  198.             x[a] = x[b];
  199.             x[b] = xb;
  200.             //    b--c
  201.             // a--d
  202.             if (x[d] < xb) {
  203.                 x[b] = x[d];
  204.                 // Move a pair to maintain the sorted order
  205.                 x[d] = x[c];
  206.                 x[c] = xb;
  207.             }
  208.         }
  209.     }

  210.     /**
  211.      * Place the upper median of 4 elements in {@code c}; the smaller two elements in
  212.      * {@code a,b}; and the larger element in {@code d}.
  213.      *
  214.      * @param x Values
  215.      * @param a Index.
  216.      * @param b Index.
  217.      * @param c Index.
  218.      * @param d Index.
  219.      */
  220.     static void upperMedian4(double[] x, int a, int b, int c, int d) {
  221.         // 3 to 5 comparisons
  222.         if (x[d] < x[b]) {
  223.             final double u = x[d];
  224.             x[d] = x[b];
  225.             x[b] = u;
  226.         }
  227.         if (x[c] < x[a]) {
  228.             final double v = x[c];
  229.             x[c] = x[a];
  230.             x[a] = v;
  231.         }
  232.         // a--c
  233.         // b--d
  234.         if (x[b] > x[c]) {
  235.             final double u = x[c];
  236.             x[c] = x[b];
  237.             x[b] = u;
  238.         } else if (x[c] > x[d]) {
  239.             //    a--c
  240.             // b--d
  241.             final double xc = x[d];
  242.             x[d] = x[c];
  243.             x[c] = xc;
  244.             //    a--d
  245.             // b--c
  246.             if (x[a] > xc) {
  247.                 x[c] = x[a];
  248.                 // Move a pair to maintain the sorted order
  249.                 x[a] = x[b];
  250.                 x[b] = xc;
  251.             }
  252.         }
  253.     }

  254.     /**
  255.      * Sorts an array using an insertion sort.
  256.      *
  257.      * @param x Data array.
  258.      * @param left Lower bound (inclusive).
  259.      * @param right Upper bound (inclusive).
  260.      */
  261.     static void sort(int[] x, int left, int right) {
  262.         for (int i = left; ++i <= right;) {
  263.             final int v = x[i];
  264.             // Move preceding higher elements above (if required)
  265.             if (v < x[i - 1]) {
  266.                 int j = i;
  267.                 while (--j >= left && v < x[j]) {
  268.                     x[j + 1] = x[j];
  269.                 }
  270.                 x[j + 1] = v;
  271.             }
  272.         }
  273.     }

  274.     /**
  275.      * Sorts the elements at the given distinct indices in an array.
  276.      *
  277.      * @param x Data array.
  278.      * @param a Index.
  279.      * @param b Index.
  280.      * @param c Index.
  281.      */
  282.     static void sort3(int[] x, int a, int b, int c) {
  283.         // Decision tree avoiding swaps:
  284.         // Order [(0,2)]
  285.         // Move point 1 above point 2 or below point 0
  286.         final int u = x[a];
  287.         final int v = x[b];
  288.         final int w = x[c];
  289.         if (w < u) {
  290.             if (v < w) {
  291.                 x[a] = v;
  292.                 x[b] = w;
  293.                 x[c] = u;
  294.                 return;
  295.             }
  296.             if (u < v) {
  297.                 x[a] = w;
  298.                 x[b] = u;
  299.                 x[c] = v;
  300.                 return;
  301.             }
  302.             // w < v < u
  303.             x[a] = w;
  304.             x[c] = u;
  305.             return;
  306.         }
  307.         if (v < u) {
  308.             // v < u < w
  309.             x[a] = v;
  310.             x[b] = u;
  311.             return;
  312.         }
  313.         if (w < v) {
  314.             // u < w < v
  315.             x[b] = w;
  316.             x[c] = v;
  317.         }
  318.         // u < v < w
  319.     }

  320.     /**
  321.      * Sorts the elements at the given distinct indices in an array.
  322.      *
  323.      * @param x Data array.
  324.      * @param a Index.
  325.      * @param b Index.
  326.      * @param c Index.
  327.      * @param d Index.
  328.      * @param e Index.
  329.      */
  330.     static void sort5(int[] x, int a, int b, int c, int d, int e) {
  331.         // Uses an optimal sorting network from Knuth's Art of Computer Programming.
  332.         // 9 comparisons.
  333.         // Order pairs:
  334.         // [(0,3),(1,4)]
  335.         // [(0,2),(1,3)]
  336.         // [(0,1),(2,4)]
  337.         // [(1,2),(3,4)]
  338.         // [(2,3)]
  339.         if (x[e] < x[b]) {
  340.             final int u = x[e];
  341.             x[e] = x[b];
  342.             x[b] = u;
  343.         }
  344.         if (x[d] < x[a]) {
  345.             final int v = x[d];
  346.             x[d] = x[a];
  347.             x[a] = v;
  348.         }

  349.         if (x[d] < x[b]) {
  350.             final int u = x[d];
  351.             x[d] = x[b];
  352.             x[b] = u;
  353.         }
  354.         if (x[c] < x[a]) {
  355.             final int v = x[c];
  356.             x[c] = x[a];
  357.             x[a] = v;
  358.         }

  359.         if (x[e] < x[c]) {
  360.             final int u = x[e];
  361.             x[e] = x[c];
  362.             x[c] = u;
  363.         }
  364.         if (x[b] < x[a]) {
  365.             final int v = x[b];
  366.             x[b] = x[a];
  367.             x[a] = v;
  368.         }

  369.         if (x[e] < x[d]) {
  370.             final int u = x[e];
  371.             x[e] = x[d];
  372.             x[d] = u;
  373.         }
  374.         if (x[c] < x[b]) {
  375.             final int v = x[c];
  376.             x[c] = x[b];
  377.             x[b] = v;
  378.         }

  379.         if (x[d] < x[c]) {
  380.             final int u = x[d];
  381.             x[d] = x[c];
  382.             x[c] = u;
  383.         }
  384.     }

  385.     /**
  386.      * Place the lower median of 4 elements in {@code b}; the smaller element in
  387.      * {@code a}; and the larger two elements in {@code c, d}.
  388.      *
  389.      * @param x Values
  390.      * @param a Index.
  391.      * @param b Index.
  392.      * @param c Index.
  393.      * @param d Index.
  394.      */
  395.     static void lowerMedian4(int[] x, int a, int b, int c, int d) {
  396.         // 3 to 5 comparisons
  397.         if (x[d] < x[b]) {
  398.             final int u = x[d];
  399.             x[d] = x[b];
  400.             x[b] = u;
  401.         }
  402.         if (x[c] < x[a]) {
  403.             final int v = x[c];
  404.             x[c] = x[a];
  405.             x[a] = v;
  406.         }
  407.         // a--c
  408.         // b--d
  409.         if (x[c] < x[b]) {
  410.             final int u = x[c];
  411.             x[c] = x[b];
  412.             x[b] = u;
  413.         } else if (x[b] < x[a]) {
  414.             //    a--c
  415.             // b--d
  416.             final int xb = x[a];
  417.             x[a] = x[b];
  418.             x[b] = xb;
  419.             //    b--c
  420.             // a--d
  421.             if (x[d] < xb) {
  422.                 x[b] = x[d];
  423.                 // Move a pair to maintain the sorted order
  424.                 x[d] = x[c];
  425.                 x[c] = xb;
  426.             }
  427.         }
  428.     }

  429.     /**
  430.      * Place the upper median of 4 elements in {@code c}; the smaller two elements in
  431.      * {@code a,b}; and the larger element in {@code d}.
  432.      *
  433.      * @param x Values
  434.      * @param a Index.
  435.      * @param b Index.
  436.      * @param c Index.
  437.      * @param d Index.
  438.      */
  439.     static void upperMedian4(int[] x, int a, int b, int c, int d) {
  440.         // 3 to 5 comparisons
  441.         if (x[d] < x[b]) {
  442.             final int u = x[d];
  443.             x[d] = x[b];
  444.             x[b] = u;
  445.         }
  446.         if (x[c] < x[a]) {
  447.             final int v = x[c];
  448.             x[c] = x[a];
  449.             x[a] = v;
  450.         }
  451.         // a--c
  452.         // b--d
  453.         if (x[b] > x[c]) {
  454.             final int u = x[c];
  455.             x[c] = x[b];
  456.             x[b] = u;
  457.         } else if (x[c] > x[d]) {
  458.             //    a--c
  459.             // b--d
  460.             final int xc = x[d];
  461.             x[d] = x[c];
  462.             x[c] = xc;
  463.             //    a--d
  464.             // b--c
  465.             if (x[a] > xc) {
  466.                 x[c] = x[a];
  467.                 // Move a pair to maintain the sorted order
  468.                 x[a] = x[b];
  469.                 x[b] = xc;
  470.             }
  471.         }
  472.     }

  473.     /**
  474.      * Sort the unique indices in-place to the start of the array. The number of
  475.      * unique indices is returned.
  476.      *
  477.      * <p>Uses an insertion sort modified to ignore duplicates. Use on small {@code n}.
  478.      *
  479.      * <p>Warning: Requires {@code n > 0}. The array contents after the count of unique
  480.      * indices {@code c} are unchanged (i.e. {@code [c, n)}. This may change the count of
  481.      * each unique index in the entire array.
  482.      *
  483.      * @param x Indices.
  484.      * @param n Number of indices.
  485.      * @return the number of unique indices
  486.      */
  487.     static int insertionSortIndices(int[] x, int n) {
  488.         // Index of last unique value
  489.         int unique = 0;
  490.         // Do an insertion sort but only compare the current set of unique values.
  491.         for (int i = 0; ++i < n;) {
  492.             final int v = x[i];
  493.             int j = unique;
  494.             if (v > x[j]) {
  495.                 // Insert at end
  496.                 x[++unique] = v;
  497.             } else if (v < x[j]) {
  498.                 // Find insertion point in the unique indices
  499.                 do {
  500.                     --j;
  501.                 } while (j >= 0 && v < x[j]);
  502.                 // Insertion point = j + 1
  503.                 // Insert if at start or non-duplicate
  504.                 if (j < 0 || v != x[j]) {
  505.                     // Move (j, unique] to (j+1, unique+1]
  506.                     for (int k = unique; k > j; --k) {
  507.                         x[k + 1] = x[k];
  508.                     }
  509.                     x[j + 1] = v;
  510.                     ++unique;
  511.                 }
  512.             }
  513.         }
  514.         return unique + 1;
  515.     }

  516.     /**
  517.      * Sort the unique indices in-place to the start of the array. The number of
  518.      * unique indices is returned.
  519.      *
  520.      * <p>Uses an Order(1) data structure to ignore duplicates.
  521.      *
  522.      * <p>Warning: Requires {@code n > 0}. The array contents after the count of unique
  523.      * indices {@code c} are unchanged (i.e. {@code [c, n)}. This may change the count of
  524.      * each unique index in the entire array.
  525.      *
  526.      * @param x Indices.
  527.      * @param n Number of indices.
  528.      * @return the number of unique indices
  529.      */
  530.     static int sortIndices(int[] x, int n) {
  531.         // Duplicates are checked using a primitive hash set.
  532.         // Storage (bytes) = 4 * next-power-of-2(n*2) => 2-4 times n
  533.         final HashIndexSet set = HashIndexSet.create(n);
  534.         int i = 0;
  535.         int last = 0;
  536.         set.add(x[0]);
  537.         while (++i < n) {
  538.             final int v = x[i];
  539.             if (set.add(v)) {
  540.                 x[++last] = v;
  541.             }
  542.         }
  543.         Arrays.sort(x, 0, ++last);
  544.         return last;
  545.     }
  546. }