122 m_compare (ascending_compare), m_ms (nullptr)
127 : m_compare (comp), m_ms (nullptr)
141 m_compare = ascending_compare;
143 m_compare = descending_compare;
149template <
typename Comp>
157 for (; start < nel; ++start)
162 T pivot = data[start];
171 if (comp (pivot, data[p]))
186 std::swap (pivot, data[p]);
194template <
typename Comp>
202 for (; start < nel; ++start)
207 T pivot = data[start];
216 if (comp (pivot, data[p]))
231 std::swap (pivot, data[p]);
235 std::swap (ipivot, idx[p]);
261template <
typename Comp>
276 if (comp (*lo, *(lo-1)))
279 for (lo = lo+1; lo < hi; ++lo, ++n)
281 if (comp (*lo, *(lo-1)))
289 for (lo = lo+1; lo < hi; ++lo, ++n)
291 if (comp (*lo, *(lo-1)))
321template <
typename Comp>
342 if (comp (a[ofs], key))
345 ofs = (ofs << 1) + 1;
366 if (comp (*(a-ofs), key))
370 ofs = (ofs << 1) + 1;
378 lastofs = hint - ofs;
388 while (lastofs < ofs)
392 if (comp (a[m], key))
416template <
typename Comp>
437 if (comp (key, *(a-ofs)))
440 ofs = (ofs << 1) + 1;
451 lastofs = hint - ofs;
462 if (comp (key, a[ofs]))
466 ofs = (ofs << 1) + 1;
483 while (lastofs < ofs)
487 if (comp (key, a[m]))
497roundupsize (std::size_t n)
499 unsigned int nbits = 3;
500 std::size_t n2 = n >> 8;
530 std::size_t new_size = ((n >> nbits) + 1) << nbits;
534 >
static_cast<std::size_t
> (std::numeric_limits<octave_idx_type>::max ()))
535 (*current_liboctave_error_handler)
536 (
"unable to allocate sufficient memory for sort");
548 if (need <= m_alloced)
551 need = roundupsize (need);
566 if (m_ia && need <= m_alloced)
569 need = roundupsize (need);
588template <
typename Comp>
601 std::copy (pa, pa + na, m_ms->m_a);
634 if (bcount >= min_gallop)
645 if (acount >= min_gallop)
658 min_gallop -= (min_gallop > 1);
659 m_ms->m_min_gallop = min_gallop;
660 k = gallop_right (*pb, pa, na, 0, comp);
666 dest = std::copy (pa, pa + k, dest);
683 k = gallop_left (*pa, pb, nb, 0, comp);
689 dest = std::copy (pb, pb + k, dest);
700 while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);
703 m_ms->m_min_gallop = min_gallop;
711 std::copy (pa, pa + na, dest);
716 std::copy (pb, pb + nb, dest);
723template <
typename Comp>
737 std::copy (pa, pa + na, m_ms->m_a);
738 std::copy (ipa, ipa + na, m_ms->m_ia);
739 dest = pa; idest = ipa;
740 pa = m_ms->m_a; ipa = m_ms->m_ia;
742 *dest++ = *pb++; *idest++ = *ipb++;
762 *dest++ = *pb++; *idest++ = *ipb++;
768 if (bcount >= min_gallop)
773 *dest++ = *pa++; *idest++ = *ipa++;
779 if (acount >= min_gallop)
792 min_gallop -= (min_gallop > 1);
793 m_ms->m_min_gallop = min_gallop;
794 k = gallop_right (*pb, pa, na, 0, comp);
800 dest = std::copy (pa, pa + k, dest);
801 idest = std::copy (ipa, ipa + k, idest);
813 *dest++ = *pb++; *idest++ = *ipb++;
818 k = gallop_left (*pa, pb, nb, 0, comp);
824 dest = std::copy (pb, pb + k, dest);
825 idest = std::copy (ipb, ipb + k, idest);
831 *dest++ = *pa++; *idest++ = *ipa++;
836 while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);
839 m_ms->m_min_gallop = min_gallop;
848 std::copy (pa, pa + na, dest);
849 std::copy (ipa, ipa + na, idest);
855 std::copy (pb, pb + nb, dest);
856 std::copy (ipb, ipb + nb, idest);
870template <
typename Comp>
885 std::copy (pb, pb + nb, m_ms->m_a);
888 pb = m_ms->m_a + nb - 1;
916 if (acount >= min_gallop)
927 if (bcount >= min_gallop)
940 min_gallop -= (min_gallop > 1);
941 m_ms->m_min_gallop = min_gallop;
942 k = gallop_right (*pb, basea, na, na-1, comp);
949 dest = std::copy_backward (pa+1 - k, pa+1, dest+1) - 1;
960 k = gallop_left (*pa, baseb, nb, nb-1, comp);
969 std::copy (pb+1, pb+1 + k, dest+1);
985 while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);
987 m_ms->m_min_gallop = min_gallop;
995 std::copy (baseb, baseb + nb, dest-(nb-1));
1000 dest = std::copy_backward (pa+1 - na, pa+1, dest+1) - 1;
1007template <
typename T>
1008template <
typename Comp>
1025 idest = ipb + nb - 1;
1026 std::copy (pb, pb + nb, m_ms->m_a);
1027 std::copy (ipb, ipb + nb, m_ms->m_ia);
1029 baseb = m_ms->m_a; ibaseb = m_ms->m_ia;
1030 pb = m_ms->m_a + nb - 1; ipb = m_ms->m_ia + nb - 1;
1031 pa += na - 1; ipa += na - 1;
1033 *dest-- = *pa--; *idest-- = *ipa--;
1050 if (comp (*pb, *pa))
1052 *dest-- = *pa--; *idest-- = *ipa--;
1058 if (acount >= min_gallop)
1063 *dest-- = *pb--; *idest-- = *ipb--;
1069 if (bcount >= min_gallop)
1082 min_gallop -= (min_gallop > 1);
1083 m_ms->m_min_gallop = min_gallop;
1084 k = gallop_right (*pb, basea, na, na-1, comp);
1091 dest = std::copy_backward (pa+1 - k, pa+1, dest+1) - 1;
1092 idest = std::copy_backward (ipa+1 - k, ipa+1, idest+1) - 1;
1098 *dest-- = *pb--; *idest-- = *ipb--;
1103 k = gallop_left (*pa, baseb, nb, nb-1, comp);
1110 dest -= k; idest -= k;
1112 std::copy (pb+1, pb+1 + k, dest+1);
1113 std::copy (ipb+1, ipb+1 + k, idest+1);
1124 *dest-- = *pa--; *idest-- = *ipa--;
1129 while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);
1131 m_ms->m_min_gallop = min_gallop;
1140 std::copy (baseb, baseb + nb, dest-(nb-1));
1141 std::copy (ibaseb, ibaseb + nb, idest-(nb-1));
1147 dest = std::copy_backward (pa+1 - na, pa+1, dest+1) - 1;
1148 idest = std::copy_backward (ipa+1 - na, ipa+1, idest+1) - 1;
1149 pa -= na; ipa -= na;
1150 *dest = *pb; *idest = *ipb;
1158template <
typename T>
1159template <
typename Comp>
1168 pa = data + m_ms->m_pending[i].m_base;
1169 na = m_ms->m_pending[i].m_len;
1170 pb = data + m_ms->m_pending[i+1].m_base;
1171 nb = m_ms->m_pending[i+1].m_len;
1177 m_ms->m_pending[i].m_len = na + nb;
1178 if (i == m_ms->m_n - 3)
1179 m_ms->m_pending[i+1] = m_ms->m_pending[i+2];
1185 k = gallop_right (*pb, pa, na, 0, comp);
1196 nb = gallop_left (pa[na-1], pb, nb, nb-1, comp);
1204 return merge_lo (pa, na, pb, nb, comp);
1206 return merge_hi (pa, na, pb, nb, comp);
1209template <
typename T>
1210template <
typename Comp>
1220 pa = data + m_ms->m_pending[i].m_base;
1221 ipa = idx + m_ms->m_pending[i].m_base;
1222 na = m_ms->m_pending[i].m_len;
1223 pb = data + m_ms->m_pending[i+1].m_base;
1224 ipb = idx + m_ms->m_pending[i+1].m_base;
1225 nb = m_ms->m_pending[i+1].m_len;
1231 m_ms->m_pending[i].m_len = na + nb;
1232 if (i == m_ms->m_n - 3)
1233 m_ms->m_pending[i+1] = m_ms->m_pending[i+2];
1239 k = gallop_right (*pb, pa, na, 0, comp);
1250 nb = gallop_left (pa[na-1], pb, nb, nb-1, comp);
1258 return merge_lo (pa, ipa, na, pb, ipb, nb, comp);
1260 return merge_hi (pa, ipa, na, pb, ipb, nb, comp);
1273template <
typename T>
1274template <
typename Comp>
1278 struct s_slice *p = m_ms->m_pending;
1280 while (m_ms->m_n > 1)
1283 if (n > 0 && p[n-1].m_len <= p[n].m_len + p[n+1].m_len)
1285 if (p[n-1].m_len < p[n+1].m_len)
1287 if (merge_at (n, data, comp) < 0)
1290 else if (p[n].m_len <= p[n+1].m_len)
1292 if (merge_at (n, data, comp) < 0)
1302template <
typename T>
1303template <
typename Comp>
1307 struct s_slice *p = m_ms->m_pending;
1309 while (m_ms->m_n > 1)
1312 if (n > 0 && p[n-1].m_len <= p[n].m_len + p[n+1].m_len)
1314 if (p[n-1].m_len < p[n+1].m_len)
1316 if (merge_at (n, data, idx, comp) < 0)
1319 else if (p[n].m_len <= p[n+1].m_len)
1321 if (merge_at (n, data, idx, comp) < 0)
1336template <
typename T>
1337template <
typename Comp>
1341 struct s_slice *p = m_ms->m_pending;
1343 while (m_ms->m_n > 1)
1346 if (n > 0 && p[n-1].m_len < p[n+1].m_len)
1348 if (merge_at (n, data, comp) < 0)
1355template <
typename T>
1356template <
typename Comp>
1360 struct s_slice *p = m_ms->m_pending;
1362 while (m_ms->m_n > 1)
1365 if (n > 0 && p[n-1].m_len < p[n+1].m_len)
1367 if (merge_at (n, data, idx, comp) < 0)
1384template <
typename T>
1399template <
typename T>
1400template <
typename Comp>
1405 if (! m_ms) m_ms =
new MergeState;
1408 m_ms->getmem (MERGESTATE_TEMP_SIZE);
1425 n = count_run (data + lo, nremaining, descending, comp);
1429 std::reverse (data + lo, data + lo + n);
1435 binarysort (data + lo, force, n, comp);
1440 m_ms->m_pending[m_ms->m_n].m_base = lo;
1441 m_ms->m_pending[m_ms->m_n].m_len = n;
1443 if (merge_collapse (data, comp) < 0)
1451 merge_force_collapse (data, comp);
1455template <
typename T>
1456template <
typename Comp>
1462 if (! m_ms) m_ms =
new MergeState;
1465 m_ms->getmemi (MERGESTATE_TEMP_SIZE);
1482 n = count_run (data + lo, nremaining, descending, comp);
1487 std::reverse (data + lo, data + lo + n);
1488 std::reverse (idx + lo, idx + lo + n);
1495 binarysort (data + lo, idx + lo, force, n, comp);
1500 m_ms->m_pending[m_ms->m_n].m_base = lo;
1501 m_ms->m_pending[m_ms->m_n].m_len = n;
1503 if (merge_collapse (data, idx, comp) < 0)
1511 merge_force_collapse (data, idx, comp);
1515template <
typename T>
1519template <
typename T>
1523#if defined (INLINE_ASCENDING_SORT)
1525 sort (data, nel, std::less<T> ());
1528#if defined (INLINE_DESCENDING_SORT)
1530 sort (data, nel, std::greater<T> ());
1534 sort (data, nel, m_compare);
1537template <
typename T>
1541#if defined (INLINE_ASCENDING_SORT)
1543 sort (data, idx, nel, std::less<T> ());
1546#if defined (INLINE_DESCENDING_SORT)
1548 sort (data, idx, nel, std::greater<T> ());
1552 sort (data, idx, nel, m_compare);
1555template <
typename T>
1556template <
typename Comp>
1560 const T *end = data + nel;
1563 const T *next = data;
1564 while (++next != end)
1566 if (comp (*next, *data))
1576template <
typename T>
1580 bool retval =
false;
1581#if defined (INLINE_ASCENDING_SORT)
1583 retval = issorted (data, nel, std::less<T> ());
1586#if defined (INLINE_DESCENDING_SORT)
1588 retval = issorted (data, nel, std::greater<T> ());
1592 retval = issorted (data, nel, m_compare);
1597struct sortrows_run_t
1601 : col (c), ofs (o), nel (n) { }
1606template <
typename T>
1607template <
typename Comp>
1617 if (cols == 0 || rows <= 1)
1621 typedef sortrows_run_t run_t;
1622 std::stack<run_t> runs;
1624 runs.push (run_t (0, 0, rows));
1626 while (! runs.empty ())
1634 T *lbuf = buf + ofs;
1635 const T *ldata = data + rows*col;
1640 lbuf[i] = ldata[lidx[i]];
1643 sort (lbuf, lidx, nel, comp);
1651 if (comp (lbuf[lst], lbuf[i]))
1654 runs.push (run_t (col+1, ofs + lst, i - lst));
1659 runs.push (run_t (col+1, ofs + lst, nel - lst));
1664template <
typename T>
1669#if defined (INLINE_ASCENDING_SORT)
1671 sort_rows (data, idx, rows, cols, std::less<T> ());
1674#if defined (INLINE_DESCENDING_SORT)
1676 sort_rows (data, idx, rows, cols, std::greater<T> ());
1680 sort_rows (data, idx, rows, cols, m_compare);
1683template <
typename T>
1684template <
typename Comp>
1689 if (rows <= 1 || cols == 0)
1693 const T *lastrow = data + rows*(cols - 1);
1694 typedef std::pair<const T *, octave_idx_type> run_t;
1695 std::stack<run_t> runs;
1698 runs.push (run_t (data, rows));
1699 while (sorted && ! runs.empty ())
1701 const T *lo = runs.top ().first;
1708 const T *hi = lo + n;
1710 for (lo++; lo < hi; lo++)
1712 if (comp (*lst, *lo))
1715 runs.push (run_t (lst + rows, lo - lst));
1718 else if (comp (*lo, *lst))
1725 runs.push (run_t (lst + rows, lo - lst));
1735 sorted = issorted (lo, n, comp);
1741template <
typename T>
1746 bool retval =
false;
1747#if defined (INLINE_ASCENDING_SORT)
1749 retval = is_sorted_rows (data, rows, cols, std::less<T> ());
1752#if defined (INLINE_DESCENDING_SORT)
1754 retval = is_sorted_rows (data, rows, cols, std::greater<T> ());
1758 retval = is_sorted_rows (data, rows, cols, m_compare);
1765template <
typename T>
1766template <
typename Comp>
1769 const T& value, Comp comp)
1777 if (comp (value, data[mid]))
1786template <
typename T>
1792#if defined (INLINE_ASCENDING_SORT)
1794 retval =
lookup (data, nel, value, std::less<T> ());
1797#if defined (INLINE_DESCENDING_SORT)
1799 retval =
lookup (data, nel, value, std::greater<T> ());
1803 retval =
lookup (data, nel, value, m_compare);
1808template <
typename T>
1809template <
typename Comp>
1819 idx[j] =
lookup (data, nel, values[j], comp);
1822template <
typename T>
1828#if defined (INLINE_ASCENDING_SORT)
1830 lookup (data, nel, values, nvalues, idx, std::less<T> ());
1833#if defined (INLINE_DESCENDING_SORT)
1835 lookup (data, nel, values, nvalues, idx, std::greater<T> ());
1839 lookup (data, nel, values, nvalues, idx, m_compare);
1842template <
typename T>
1843template <
typename Comp>
1854 if (nvalues > 0 && nel > 0)
1858 if (comp (values[j], data[i]))
1864 else if (++i == nel)
1877 if (nvalues > 0 && nel > 0)
1881 if (comp (values[j], data[i]))
1887 else if (++i == nel)
1892 for (; j != nvalues; j++)
1897template <
typename T>
1903#if defined (INLINE_ASCENDING_SORT)
1905 lookup_sorted (data, nel, values, nvalues, idx, rev, std::less<T> ());
1908#if defined (INLINE_DESCENDING_SORT)
1910 lookup_sorted (data, nel, values, nvalues, idx, rev, std::greater<T> ());
1914 lookup_sorted (data, nel, values, nvalues, idx, rev, m_compare);
1917template <
typename T>
1918template <
typename Comp>
1927 std::nth_element (data, data + lo, data + nel, comp);
1929 std::partial_sort (data, data + up, data + nel, comp);
1932 std::nth_element (data, data + lo, data + nel, comp);
1936 std::swap (data[lo+1],
1937 *std::min_element (data + lo + 1, data + nel, comp));
1940 std::partial_sort (data + lo + 1, data + up, data + nel, comp);
1944template <
typename T>
1952#if defined (INLINE_ASCENDING_SORT)
1954 nth_element (data, nel, lo, up, std::less<T> ());
1957#if defined (INLINE_DESCENDING_SORT)
1959 nth_element (data, nel, lo, up, std::greater<T> ());
1963 nth_element (data, nel, lo, up, m_compare);
1966template <
typename T>
1974template <
typename T>
octave_idx_type lookup(const T *x, octave_idx_type n, T y)
void set_compare(const compare_fcn_type &comp)
void sort_rows(const T *data, octave_idx_type *idx, octave_idx_type rows, octave_idx_type cols)
static bool descending_compare(typename ref_param< T >::type, typename ref_param< T >::type)
bool issorted(const T *data, octave_idx_type nel)
std::function< bool(typename ref_param< T >::type, typename ref_param< T >::type)> compare_fcn_type
static bool ascending_compare(typename ref_param< T >::type, typename ref_param< T >::type)
octave_idx_type lookup(const T *data, octave_idx_type nel, const T &value)
void sort(T *data, octave_idx_type nel)
void nth_element(T *data, octave_idx_type nel, octave_idx_type lo, octave_idx_type up=-1)
bool is_sorted_rows(const T *data, octave_idx_type rows, octave_idx_type cols)
void lookup_sorted(const T *data, octave_idx_type nel, const T *values, octave_idx_type nvalues, octave_idx_type *idx, bool rev=false)
if_then_else< is_class_type< T >::no, T, Tconst & >::result type
#define liboctave_panic_unless(cond)
F77_RET_T const F77_DBLE * x
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
bool(*)(typename ref_param< T >::type, typename ref_param< T >::type) compare_fcn_ptr