Mercurial > hg > octave-nkf
comparison liboctave/oct-sort.cc @ 8721:e9cb742df9eb
imported patch sort3.diff
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Wed, 11 Feb 2009 15:25:53 +0100 |
parents | 314be237cd5b |
children | d5af326a3ede |
comparison
equal
deleted
inserted
replaced
8720:dda421a1f1e6 | 8721:e9cb742df9eb |
---|---|
95 #endif | 95 #endif |
96 | 96 |
97 #include <cassert> | 97 #include <cassert> |
98 #include <algorithm> | 98 #include <algorithm> |
99 #include <cstring> | 99 #include <cstring> |
100 #include <stack> | |
100 | 101 |
101 #include "lo-mappers.h" | 102 #include "lo-mappers.h" |
102 #include "quit.h" | 103 #include "quit.h" |
103 #include "oct-sort.h" | 104 #include "oct-sort.h" |
105 #include "oct-locbuf.h" | |
104 | 106 |
105 template <class T> | 107 template <class T> |
106 octave_sort<T>::octave_sort (void) : compare (ascending_compare) | 108 octave_sort<T>::octave_sort (void) : compare (ascending_compare) |
107 { | 109 { |
108 merge_init (); | 110 merge_init (); |
109 merge_getmem (1024); | |
110 } | 111 } |
111 | 112 |
112 template <class T> | 113 template <class T> |
113 octave_sort<T>::octave_sort (bool (*comp) (T, T)) : compare (comp) | 114 octave_sort<T>::octave_sort (bool (*comp) (T, T)) : compare (comp) |
114 { | 115 { |
115 merge_init (); | 116 merge_init (); |
116 merge_getmem (1024); | 117 } |
117 } | 118 |
118 | 119 template <class T> |
120 void | |
121 octave_sort<T>::set_compare (sortmode mode) | |
122 { | |
123 if (mode == ASCENDING) | |
124 compare = ascending_compare; | |
125 else if (mode == DESCENDING) | |
126 compare = descending_compare; | |
127 else | |
128 compare = 0; | |
129 } | |
130 | |
119 template <class T> | 131 template <class T> |
120 template <class Comp> | 132 template <class Comp> |
121 void | 133 void |
122 octave_sort<T>::binarysort (T *data, octave_idx_type nel, | 134 octave_sort<T>::binarysort (T *data, octave_idx_type nel, |
123 octave_idx_type start, Comp comp) | 135 octave_idx_type start, Comp comp) |
1506 | 1518 |
1507 template <class T> | 1519 template <class T> |
1508 void | 1520 void |
1509 octave_sort<T>::sort (T *data, octave_idx_type nel) | 1521 octave_sort<T>::sort (T *data, octave_idx_type nel) |
1510 { | 1522 { |
1523 merge_getmem (1024); | |
1511 #ifdef INLINE_ASCENDING_SORT | 1524 #ifdef INLINE_ASCENDING_SORT |
1512 if (compare == ascending_compare) | 1525 if (compare == ascending_compare) |
1513 sort (data, nel, std::less<T> ()); | 1526 sort (data, nel, std::less<T> ()); |
1514 else | 1527 else |
1515 #endif | 1528 #endif |
1516 #ifdef INLINE_DESCENDING_SORT | 1529 #ifdef INLINE_DESCENDING_SORT |
1517 if (compare == descending_compare) | 1530 if (compare == descending_compare) |
1518 sort (data, nel, std::greater<T> ()); | 1531 sort (data, nel, std::greater<T> ()); |
1519 else | 1532 else |
1520 #endif | 1533 #endif |
1521 if (compare) | 1534 if (compare) |
1522 sort (data, nel, compare); | 1535 sort (data, nel, compare); |
1523 } | 1536 } |
1524 | 1537 |
1525 template <class T> | 1538 template <class T> |
1526 void | 1539 void |
1527 octave_sort<T>::sort (T *data, octave_idx_type *idx, octave_idx_type nel) | 1540 octave_sort<T>::sort (T *data, octave_idx_type *idx, octave_idx_type nel) |
1528 { | 1541 { |
1542 merge_getmemi (1024); | |
1529 #ifdef INLINE_ASCENDING_SORT | 1543 #ifdef INLINE_ASCENDING_SORT |
1530 if (compare == ascending_compare) | 1544 if (compare == ascending_compare) |
1531 sort (data, idx, nel, std::less<T> ()); | 1545 sort (data, idx, nel, std::less<T> ()); |
1532 else | 1546 else |
1533 #endif | 1547 #endif |
1534 #ifdef INLINE_DESCENDING_SORT | 1548 #ifdef INLINE_DESCENDING_SORT |
1535 if (compare == descending_compare) | 1549 if (compare == descending_compare) |
1536 sort (data, idx, nel, std::greater<T> ()); | 1550 sort (data, idx, nel, std::greater<T> ()); |
1537 else | 1551 else |
1538 #endif | 1552 #endif |
1539 if (compare) | 1553 if (compare) |
1540 sort (data, idx, nel, compare); | 1554 sort (data, idx, nel, compare); |
1541 } | 1555 } |
1556 | |
1557 template <class T> template <class Comp> | |
1558 bool | |
1559 octave_sort<T>::is_sorted (const T *data, octave_idx_type nel, Comp comp) | |
1560 { | |
1561 const T *end = data + nel; | |
1562 if (data != end) | |
1563 { | |
1564 const T *next = data; | |
1565 while (++next != end) | |
1566 { | |
1567 if (comp (*next, *data)) | |
1568 break; | |
1569 data = next; | |
1570 } | |
1571 data = next; | |
1572 } | |
1573 | |
1574 return data == end; | |
1575 } | |
1576 | |
1577 template <class T> | |
1578 bool | |
1579 octave_sort<T>::is_sorted (const T *data, octave_idx_type nel) | |
1580 { | |
1581 bool retval = false; | |
1582 #ifdef INLINE_ASCENDING_SORT | |
1583 if (compare == ascending_compare) | |
1584 retval = is_sorted (data, nel, std::less<T> ()); | |
1585 else | |
1586 #endif | |
1587 #ifdef INLINE_DESCENDING_SORT | |
1588 if (compare == descending_compare) | |
1589 retval = is_sorted (data, nel, std::greater<T> ()); | |
1590 else | |
1591 #endif | |
1592 if (compare) | |
1593 retval = is_sorted (data, nel, compare); | |
1594 | |
1595 return retval; | |
1596 } | |
1597 | |
1598 // FIXME: is there really no way to make this local to the following function? | |
1599 struct sortrows_run_t | |
1600 { | |
1601 sortrows_run_t (octave_idx_type c, octave_idx_type o, octave_idx_type n) | |
1602 : col (c), ofs (o), nel (n) { } | |
1603 octave_idx_type col, ofs, nel; | |
1604 }; | |
1605 | |
1606 | |
1607 template <class T> template <class Comp> | |
1608 void | |
1609 octave_sort<T>::sort_rows (const T *data, octave_idx_type *idx, | |
1610 octave_idx_type rows, octave_idx_type cols, | |
1611 Comp comp) | |
1612 { | |
1613 OCTAVE_LOCAL_BUFFER (T, buf, rows); | |
1614 for (octave_idx_type i = 0; i < rows; i++) | |
1615 idx[i] = i; | |
1616 | |
1617 if (cols == 0 || rows <= 1) | |
1618 return; | |
1619 | |
1620 | |
1621 // This is a breadth-first traversal. | |
1622 typedef sortrows_run_t run_t; | |
1623 std::stack<run_t> runs; | |
1624 | |
1625 runs.push (run_t (0, 0, rows)); | |
1626 | |
1627 while (! runs.empty ()) | |
1628 { | |
1629 octave_idx_type col = runs.top ().col; | |
1630 octave_idx_type ofs = runs.top ().ofs; | |
1631 octave_idx_type nel = runs.top ().nel; | |
1632 runs.pop (); | |
1633 assert (nel > 1); | |
1634 | |
1635 T *lbuf = buf + ofs; | |
1636 const T *ldata = data + rows*col; | |
1637 octave_idx_type *lidx = idx + ofs; | |
1638 | |
1639 // Gather. | |
1640 for (octave_idx_type i = 0; i < nel; i++) | |
1641 lbuf[i] = ldata[lidx[i]]; | |
1642 | |
1643 // Sort. | |
1644 sort (lbuf, lidx, nel, comp); | |
1645 | |
1646 // Identify constant runs and schedule subsorts. | |
1647 if (col < cols-1) | |
1648 { | |
1649 octave_idx_type lst = 0; | |
1650 for (octave_idx_type i = 0; i < nel; i++) | |
1651 { | |
1652 if (comp (lbuf[lst], lbuf[i])) | |
1653 { | |
1654 if (i > lst + 1) | |
1655 runs.push (run_t (col+1, lst, i - lst)); | |
1656 lst = i; | |
1657 } | |
1658 } | |
1659 if (nel > lst + 1) | |
1660 runs.push (run_t (col+1, lst, nel - lst)); | |
1661 } | |
1662 } | |
1663 } | |
1664 | |
1665 template <class T> | |
1666 void | |
1667 octave_sort<T>::sort_rows (const T *data, octave_idx_type *idx, | |
1668 octave_idx_type rows, octave_idx_type cols) | |
1669 { | |
1670 #ifdef INLINE_ASCENDING_SORT | |
1671 if (compare == ascending_compare) | |
1672 sort_rows (data, idx, rows, cols, std::less<T> ()); | |
1673 else | |
1674 #endif | |
1675 #ifdef INLINE_DESCENDING_SORT | |
1676 if (compare == descending_compare) | |
1677 sort_rows (data, idx, rows, cols, std::greater<T> ()); | |
1678 else | |
1679 #endif | |
1680 if (compare) | |
1681 sort_rows (data, idx, rows, cols, compare); | |
1682 } | |
1683 | |
1684 template <class T> template <class Comp> | |
1685 bool | |
1686 octave_sort<T>::is_sorted_rows (const T *data, octave_idx_type rows, | |
1687 octave_idx_type cols, Comp comp) | |
1688 { | |
1689 if (rows <= 1 || cols == 0) | |
1690 return true; | |
1691 | |
1692 // This is a breadth-first traversal. | |
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; | |
1696 | |
1697 bool sorted = true; | |
1698 runs.push (run_t (data, rows)); | |
1699 while (sorted && ! runs.empty ()) | |
1700 { | |
1701 const T *lo = runs.top ().first; | |
1702 octave_idx_type n = runs.top ().second; | |
1703 runs.pop (); | |
1704 if (lo < lastrow) | |
1705 { | |
1706 // Not the final column. | |
1707 assert (n > 1); | |
1708 const T *hi = lo + n, *lst = lo; | |
1709 for (lo++; lo < hi; lo++) | |
1710 { | |
1711 if (comp (*lst, *lo)) | |
1712 { | |
1713 if (lo > lst + 1) | |
1714 runs.push (run_t (lst + rows, lo - lst)); | |
1715 lst = lo; | |
1716 } | |
1717 else if (comp (*lo, *lst)) | |
1718 break; | |
1719 | |
1720 } | |
1721 if (lo == hi) | |
1722 { | |
1723 if (lo > lst + 1) | |
1724 runs.push (run_t (lst + rows, lo - lst)); | |
1725 } | |
1726 else | |
1727 { | |
1728 sorted = false; | |
1729 break; | |
1730 } | |
1731 } | |
1732 else | |
1733 // The final column - use fast code. | |
1734 sorted = is_sorted (lo, n, comp); | |
1735 } | |
1736 | |
1737 return sorted; | |
1738 } | |
1739 | |
1740 template <class T> | |
1741 bool | |
1742 octave_sort<T>::is_sorted_rows (const T *data, octave_idx_type rows, | |
1743 octave_idx_type cols) | |
1744 { | |
1745 bool retval = false; | |
1746 | |
1747 #ifdef INLINE_ASCENDING_SORT | |
1748 if (compare == ascending_compare) | |
1749 retval = is_sorted_rows (data, rows, cols, std::less<T> ()); | |
1750 else | |
1751 #endif | |
1752 #ifdef INLINE_DESCENDING_SORT | |
1753 if (compare == descending_compare) | |
1754 retval = is_sorted_rows (data, rows, cols, std::greater<T> ()); | |
1755 else | |
1756 #endif | |
1757 if (compare) | |
1758 retval = is_sorted_rows (data, rows, cols, compare); | |
1759 | |
1760 return retval; | |
1761 } | |
1762 | |
1542 | 1763 |
1543 template <class T> | 1764 template <class T> |
1544 bool | 1765 bool |
1545 octave_sort<T>::ascending_compare (T x, T y) | 1766 octave_sort<T>::ascending_compare (T x, T y) |
1546 { | 1767 { |