comparison liboctave/Sparse.cc @ 10425:0677c5d80b77

rewrite 1D sparse indexing
author Jaroslav Hajek <highegg@gmail.com>
date Fri, 19 Mar 2010 13:00:06 +0100
parents 99e9bae2d81e
children 10207338603a
comparison
equal deleted inserted replaced
10424:0b05b204775b 10425:0677c5d80b77
43 43
44 #include "Sparse.h" 44 #include "Sparse.h"
45 #include "sparse-sort.h" 45 #include "sparse-sort.h"
46 #include "sparse-util.h" 46 #include "sparse-util.h"
47 #include "oct-spparms.h" 47 #include "oct-spparms.h"
48 #include "mx-inlines.cc"
48 49
49 template <class T> 50 template <class T>
50 T& 51 T&
51 Sparse<T>::SparseRep::elem (octave_idx_type _r, octave_idx_type _c) 52 Sparse<T>::SparseRep::elem (octave_idx_type _r, octave_idx_type _c)
52 { 53 {
817 return trans ? this->transpose () : *this; 818 return trans ? this->transpose () : *this;
818 } 819 }
819 820
820 template <class T> 821 template <class T>
821 void 822 void
822 Sparse<T>::resize_no_fill (const dim_vector& dv) 823 Sparse<T>::resize1 (octave_idx_type n)
824 {
825 octave_idx_type nr = rows (), nc = cols ();
826
827 if (nr == 1 || nr == 0)
828 resize (1, n);
829 else if (nc == 1)
830 resize (n, 1);
831 else
832 gripe_invalid_resize ();
833 }
834
835 template <class T>
836 void
837 Sparse<T>::resize (const dim_vector& dv)
823 { 838 {
824 octave_idx_type n = dv.length (); 839 octave_idx_type n = dv.length ();
825 840
826 if (n != 2) 841 if (n != 2)
827 { 842 {
828 (*current_liboctave_error_handler) ("sparse array must be 2-D"); 843 (*current_liboctave_error_handler) ("sparse array must be 2-D");
829 return; 844 return;
830 } 845 }
831 846
832 resize_no_fill (dv(0), dv(1)); 847 resize (dv(0), dv(1));
833 } 848 }
834 849
835 template <class T> 850 template <class T>
836 void 851 void
837 Sparse<T>::resize_no_fill (octave_idx_type r, octave_idx_type c) 852 Sparse<T>::resize (octave_idx_type r, octave_idx_type c)
838 { 853 {
839 if (r < 0 || c < 0) 854 if (r < 0 || c < 0)
840 { 855 {
841 (*current_liboctave_error_handler) 856 (*current_liboctave_error_handler)
842 ("can't resize to negative dimension"); 857 ("can't resize to negative dimension");
1135 // Either A(:) = [] or A(idx) = [] with idx enumerating all 1150 // Either A(:) = [] or A(idx) = [] with idx enumerating all
1136 // elements, so we delete all elements and return [](0x0). To 1151 // elements, so we delete all elements and return [](0x0). To
1137 // preserve the orientation of the vector, you have to use 1152 // preserve the orientation of the vector, you have to use
1138 // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns). 1153 // A(idx,:) = [] (delete rows) or A(:,idx) (delete columns).
1139 1154
1140 resize_no_fill (0, 0); 1155 resize (0, 0);
1141 return; 1156 return;
1142 } 1157 }
1143 1158
1144 idx_arg.sort (true); 1159 idx_arg.sort (true);
1145 1160
1379 if (idx_j.is_colon ()) 1394 if (idx_j.is_colon ())
1380 { 1395 {
1381 // A(:,:) -- We are deleting columns and rows, so the result 1396 // A(:,:) -- We are deleting columns and rows, so the result
1382 // is [](0x0). 1397 // is [](0x0).
1383 1398
1384 resize_no_fill (0, 0); 1399 resize (0, 0);
1385 return; 1400 return;
1386 } 1401 }
1387 1402
1388 if (idx_j.is_colon_equiv (nc, 1)) 1403 if (idx_j.is_colon_equiv (nc, 1))
1389 { 1404 {
1390 // A(:,j) -- We are deleting columns by enumerating them, 1405 // A(:,j) -- We are deleting columns by enumerating them,
1391 // If we enumerate all of them, we should have zero columns 1406 // If we enumerate all of them, we should have zero columns
1392 // with the same number of rows that we started with. 1407 // with the same number of rows that we started with.
1393 1408
1394 resize_no_fill (nr, 0); 1409 resize (nr, 0);
1395 return; 1410 return;
1396 } 1411 }
1397 } 1412 }
1398 1413
1399 if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1)) 1414 if (idx_j.is_colon () && idx_i.is_colon_equiv (nr, 1))
1400 { 1415 {
1401 // A(i,:) -- We are deleting rows by enumerating them. If we 1416 // A(i,:) -- We are deleting rows by enumerating them. If we
1402 // enumerate all of them, we should have zero rows with the 1417 // enumerate all of them, we should have zero rows with the
1403 // same number of columns that we started with. 1418 // same number of columns that we started with.
1404 1419
1405 resize_no_fill (0, nc); 1420 resize (0, nc);
1406 return; 1421 return;
1407 } 1422 }
1408 1423
1409 if (idx_i.is_colon_equiv (nr, 1)) 1424 if (idx_i.is_colon_equiv (nr, 1))
1410 { 1425 {
1411 if (idx_j.is_colon_equiv (nc, 1)) 1426 if (idx_j.is_colon_equiv (nc, 1))
1412 resize_no_fill (0, 0); 1427 resize (0, 0);
1413 else 1428 else
1414 { 1429 {
1415 idx_j.sort (true); 1430 idx_j.sort (true);
1416 1431
1417 octave_idx_type num_to_delete = idx_j.length (nc); 1432 octave_idx_type num_to_delete = idx_j.length (nc);
1418 1433
1419 if (num_to_delete != 0) 1434 if (num_to_delete != 0)
1420 { 1435 {
1421 if (nr == 1 && num_to_delete == nc) 1436 if (nr == 1 && num_to_delete == nc)
1422 resize_no_fill (0, 0); 1437 resize (0, 0);
1423 else 1438 else
1424 { 1439 {
1425 octave_idx_type new_nc = nc; 1440 octave_idx_type new_nc = nc;
1426 octave_idx_type new_nnz = nnz (); 1441 octave_idx_type new_nnz = nnz ();
1427 1442
1482 } 1497 }
1483 } 1498 }
1484 else if (idx_j.is_colon_equiv (nc, 1)) 1499 else if (idx_j.is_colon_equiv (nc, 1))
1485 { 1500 {
1486 if (idx_i.is_colon_equiv (nr, 1)) 1501 if (idx_i.is_colon_equiv (nr, 1))
1487 resize_no_fill (0, 0); 1502 resize (0, 0);
1488 else 1503 else
1489 { 1504 {
1490 idx_i.sort (true); 1505 idx_i.sort (true);
1491 1506
1492 octave_idx_type num_to_delete = idx_i.length (nr); 1507 octave_idx_type num_to_delete = idx_i.length (nr);
1493 1508
1494 if (num_to_delete != 0) 1509 if (num_to_delete != 0)
1495 { 1510 {
1496 if (nc == 1 && num_to_delete == nr) 1511 if (nc == 1 && num_to_delete == nr)
1497 resize_no_fill (0, 0); 1512 resize (0, 0);
1498 else 1513 else
1499 { 1514 {
1500 octave_idx_type new_nr = nr; 1515 octave_idx_type new_nr = nr;
1501 octave_idx_type new_nnz = nnz (); 1516 octave_idx_type new_nnz = nnz ();
1502 1517
1609 return retval; 1624 return retval;
1610 } 1625 }
1611 1626
1612 template <class T> 1627 template <class T>
1613 Sparse<T> 1628 Sparse<T>
1614 Sparse<T>::index (const idx_vector& idx_arg, bool resize_ok) const 1629 Sparse<T>::index (const idx_vector& idx, bool resize_ok) const
1615 { 1630 {
1616 Sparse<T> retval; 1631 Sparse<T> retval;
1617 1632
1618 assert (ndims () == 2); 1633 assert (ndims () == 2);
1634
1635 // FIXME: please don't fix the shadowed member warning yet because
1636 // Sparse<T>::idx will eventually go away.
1619 1637
1620 octave_idx_type nr = dim1 (); 1638 octave_idx_type nr = dim1 ();
1621 octave_idx_type nc = dim2 (); 1639 octave_idx_type nc = dim2 ();
1622 octave_idx_type nz = nnz (); 1640 octave_idx_type nz = nnz ();
1623 1641
1624 // Use safe_numel so that we get an error if the matrix is too big to be indexed. 1642 octave_idx_type nel = numel (); // Can throw.
1625 octave_idx_type orig_len = nr * nc; 1643
1626 1644 const dim_vector idx_dims = idx.orig_dimensions ();
1627 dim_vector idx_orig_dims = idx_arg.orig_dimensions (); 1645
1628 1646 if (idx_dims.length () > 2)
1629 octave_idx_type idx_orig_rows = idx_arg.orig_rows ();
1630 octave_idx_type idx_orig_columns = idx_arg.orig_columns ();
1631
1632 if (idx_orig_dims.length () > 2)
1633 (*current_liboctave_error_handler) 1647 (*current_liboctave_error_handler)
1634 ("cannot index sparse matrix with an N-D Array"); 1648 ("cannot index sparse matrix with an N-D Array");
1635 else if (idx_arg.is_colon ()) 1649 else if (idx.is_colon ())
1636 { 1650 {
1637 // Fast magic colon processing. 1651 // Fast magic colon processing.
1638 retval = Sparse<T> (nr * nc, 1, nz); 1652 retval = Sparse<T> (nel, 1, nz);
1639 1653
1640 for (octave_idx_type i = 0; i < nc; i++) 1654 for (octave_idx_type i = 0; i < nc; i++)
1641 for (octave_idx_type j = cidx(i); j < cidx(i+1); j++) 1655 {
1642 { 1656 for (octave_idx_type j = cidx(i); j < cidx(i+1); j++)
1643 octave_quit (); 1657 {
1644 retval.xdata(j) = data(j); 1658 retval.xdata(j) = data(j);
1645 retval.xridx(j) = ridx(j) + i * nr; 1659 retval.xridx(j) = ridx(j) + i * nr;
1646 } 1660 }
1661 }
1662
1647 retval.xcidx(0) = 0; 1663 retval.xcidx(0) = 0;
1648 retval.xcidx(1) = nz; 1664 retval.xcidx(1) = nz;
1649 } 1665 }
1650 else if (! resize_ok && idx_arg.extent (length ()) > length ()) 1666 else if (idx.extent (nel) > nel)
1651 { 1667 {
1652 gripe_index_out_of_range (1, 1, idx_arg.extent (orig_len), orig_len); 1668 // resize_ok is completely handled here.
1669 if (resize_ok)
1670 {
1671 octave_idx_type ext = idx.extent (nel);
1672 Sparse<T> tmp = *this;
1673 tmp.resize1 (ext);
1674 retval = tmp.index (idx);
1675 }
1676 else
1677 gripe_index_out_of_range (1, 1, idx.extent (nel), nel);
1653 } 1678 }
1654 else if (nr == 1 && nc == 1) 1679 else if (nr == 1 && nc == 1)
1655 { 1680 {
1656 // You have to be pretty sick to get to this bit of code, 1681 // You have to be pretty sick to get to this bit of code,
1657 // since you have a scalar stored as a sparse matrix, and 1682 // since you have a scalar stored as a sparse matrix, and
1658 // then want to make a dense matrix with sparse 1683 // then want to make a dense matrix with sparse
1659 // representation. Ok, we'll do it, but you deserve what 1684 // representation. Ok, we'll do it, but you deserve what
1660 // you get!! 1685 // you get!!
1661 octave_idx_type n = idx_arg.length (length ()); 1686 retval = Sparse<T> (idx_dims(0), idx_dims(1), nz ? data (0) : T ());
1662 if (n == 0) 1687 }
1663 1688 else if (nc == 1)
1664 retval = Sparse<T> (idx_orig_dims); 1689 {
1665 else if (nz < 1) 1690 // Sparse column vector.
1666 if (n >= idx_orig_dims.numel ()) 1691 octave_idx_type lb, ub;
1667 retval = Sparse<T> (idx_orig_dims); 1692 octave_sort<octave_idx_type> isort;
1668 else 1693
1669 retval = Sparse<T> (dim_vector (n, 1)); 1694 if (idx.is_scalar ())
1670 else if (n >= idx_orig_dims.numel ()) 1695 {
1671 { 1696 // Scalar index - just a binary lookup.
1672 T el = elem (0); 1697 octave_idx_type i = isort.lookup (ridx (), nz, idx(0));
1673 octave_idx_type new_nr = idx_orig_rows; 1698 if (i > 0 && ridx(i-1) == idx(0))
1674 octave_idx_type new_nc = idx_orig_columns; 1699 retval = Sparse (1, 1, data (i-1));
1675 for (octave_idx_type i = 2; i < idx_orig_dims.length (); i++) 1700 else
1676 new_nc *= idx_orig_dims (i); 1701 retval = Sparse (1, 1);
1677 1702 }
1678 retval = Sparse<T> (new_nr, new_nc, idx_arg.ones_count ()); 1703 else if (idx.is_cont_range (nel, lb, ub))
1679 1704 {
1680 octave_idx_type ic = 0; 1705 // Special-case a contiguous range.
1681 for (octave_idx_type i = 0; i < n; i++) 1706 // Look-up indices first.
1682 { 1707 octave_idx_type li = isort.lookup (ridx (), nz, lb);
1683 if (i % new_nr == 0) 1708 octave_idx_type ui = isort.lookup (ridx (), nz, ub);
1684 retval.xcidx(i / new_nr) = ic; 1709 // Adjust to lower bounds.
1685 1710 li -= (li > 0 && ridx(li-1) == lb);
1686 octave_idx_type ii = idx_arg.elem (i); 1711 ui -= (ui > 0 && ridx(ui-1) == ub);
1687 if (ii == 0) 1712 // Copy data and adjust indices.
1688 { 1713 octave_idx_type nz_new = ui - li;
1689 octave_quit (); 1714 retval = Sparse<T> (ub - lb, 1, nz_new);
1690 retval.xdata(ic) = el; 1715 copy_or_memcpy (nz_new, data () + li, retval.data ());
1691 retval.xridx(ic++) = i % new_nr; 1716 mx_inline_sub (nz_new, retval.xridx (), ridx () + li, lb);
1692 } 1717 retval.xcidx(1) = nz_new;
1693 }
1694 retval.xcidx (new_nc) = ic;
1695 } 1718 }
1696 else 1719 else
1697 { 1720 {
1698 T el = elem (0); 1721 // If indexing a sparse column vector by a vector, the result is a
1699 retval = Sparse<T> (n, 1, nz); 1722 // sparse column vector, otherwise it inherits the shape of index.
1700 1723 // Vector transpose is cheap, so do it right here.
1701 for (octave_idx_type i = 0; i < nz; i++) 1724 const Array<octave_idx_type> idxa = (idx_dims(0) == 1
1702 { 1725 ? idx.as_array ().transpose ()
1703 octave_quit (); 1726 : idx.as_array ());
1704 retval.xdata(i) = el; 1727
1705 retval.xridx(i) = i; 1728 octave_idx_type new_nr = idxa.rows (), new_nc = idxa.cols ();
1706 } 1729
1707 retval.xcidx(0) = 0; 1730 // Lookup.
1708 retval.xcidx(1) = n; 1731 // FIXME: Could specialize for sorted idx?
1709 } 1732 NoAlias< Array<octave_idx_type> > lidx (new_nr, new_nc);
1710 } 1733 isort.lookup (ridx (), nz, idxa.data (), idxa.numel (), lidx.fortran_vec ());
1711 else if (nr == 1 || nc == 1) 1734
1712 { 1735 // Count matches.
1713 // If indexing a vector with a matrix, return value has same 1736 retval = Sparse<T> (idxa.rows (), idxa.cols ());
1714 // shape as the index. Otherwise, it has same orientation as 1737 for (octave_idx_type j = 0; j < new_nc; j++)
1715 // indexed object. 1738 {
1716 octave_idx_type len = length (); 1739 octave_idx_type nzj = 0;
1717 octave_idx_type n = idx_arg.length (len); 1740 for (octave_idx_type i = 0; i < new_nr; i++)
1718 octave_idx_type l, u; 1741 {
1719 if (n == 0) 1742 octave_idx_type l = lidx(i, j);
1720 if (nr == 1) 1743 if (l > 0 && ridx(l-1) == idxa(i, j))
1721 retval = Sparse<T> (dim_vector (1, 0)); 1744 nzj++;
1722 else 1745 else
1723 retval = Sparse<T> (dim_vector (0, 1)); 1746 lidx(i, j) = 0;
1724 else if (nz < 1) 1747 }
1725 if (idx_orig_rows == 1 || idx_orig_columns == 1) 1748 retval.xcidx(j+1) = retval.xcidx(j) + nzj;
1726 retval = Sparse<T> ((nr == 1 ? 1 : n), (nr == 1 ? n : 1)); 1749 }
1727 else 1750
1728 retval = Sparse<T> (idx_orig_dims); 1751 retval.change_capacity (retval.xcidx(new_nc));
1729 else if (idx_arg.is_range () && idx_arg.is_cont_range (n, l, u)) 1752
1730 { 1753 // Copy data and set row indices.
1731 // Special case of indexing a sparse vector by a continuous range 1754 octave_idx_type k = 0;
1732 if (nr == 1) 1755 for (octave_idx_type j = 0; j < new_nc; j++)
1733 { 1756 for (octave_idx_type i = 0; i < new_nr; i++)
1734 octave_idx_type new_nzmx = cidx(u) - cidx(l); 1757 {
1735 retval = Sparse<T> (1, n, new_nzmx); 1758 octave_idx_type l = lidx(i, j) - 1;
1736 octave_idx_type *iidx = retval.xcidx (); 1759 if (l >= 0)
1737 copy_or_memcpy (n + 1, rep->c + l, iidx); 1760 {
1738 octave_idx_type ii = iidx[0]; 1761 retval.data(k) = data(l);
1739 if (ii != 0) 1762 retval.xridx(k++) = i;
1740 {
1741 for (octave_idx_type i = 0; i < n + 1; i++)
1742 iidx[i] -= ii;
1743 }
1744 copy_or_memcpy (new_nzmx, rep->d + ii, retval.rep->d);
1745 copy_or_memcpy (new_nzmx, rep->r + ii, retval.rep->r);
1746 }
1747 else
1748 {
1749 octave_idx_type j1 = -1;
1750
1751 octave_idx_type new_nzmx = 0;
1752 for (octave_idx_type j = 0; j < nz; j++)
1753 {
1754 octave_idx_type j2 = ridx (j);
1755 if (j2 >= l && j2 < u)
1756 {
1757 new_nzmx++;
1758 if (j1 < 0)
1759 j1 = j;
1760 }
1761 if (j2 >= u)
1762 break;
1763 } 1763 }
1764 1764 }
1765 retval = Sparse<T> (n, 1, new_nzmx); 1765 }
1766 if (new_nzmx > 0) 1766 }
1767 { 1767 else if (nr == 1)
1768 retval.xcidx(0) = 0; 1768 {
1769 retval.xcidx(1) = new_nzmx; 1769 octave_idx_type lb, ub;
1770 copy_or_memcpy (new_nzmx, rep->d + j1, retval.rep->d); 1770 if (idx.is_scalar ())
1771 octave_idx_type *iidx = retval.xridx (); 1771 retval = Sparse<T> (1, 1, elem (0, idx(0)));
1772 copy_or_memcpy (new_nzmx, rep->r + j1, iidx); 1772 else if (idx.is_cont_range (nel, lb, ub))
1773 if (l != 0) 1773 {
1774 { 1774 // Special-case a contiguous range.
1775 for (octave_idx_type i = 0; i < new_nzmx; i++) 1775 octave_idx_type lbi = cidx(lb), ubi = cidx(ub), new_nz = ubi - lbi;
1776 iidx[i] -= l; 1776 retval = Sparse<T> (1, ub - lb, new_nz);
1777 } 1777 copy_or_memcpy (new_nz, data () + lbi, retval.data ());
1778 } 1778 fill_or_memset (new_nz, static_cast<octave_idx_type> (0), retval.ridx ());
1779 } 1779 mx_inline_sub (ub - lb, retval.cidx () + 1, cidx () + lb, lbi);
1780 } 1780 }
1781 else 1781 else
1782 { 1782 {
1783 octave_idx_type new_nzmx = 0; 1783 // Sparse row vectors occupy O(nr) storage anyway, so let's just
1784 if (nr == 1) 1784 // convert the matrix to full, index, and sparsify the result.
1785 for (octave_idx_type i = 0; i < n; i++) 1785 retval = Sparse<T> (array_value ().index (idx));
1786 {
1787 octave_quit ();
1788
1789 octave_idx_type ii = idx_arg.elem (i);
1790 if (ii < len)
1791 if (cidx(ii) != cidx(ii+1))
1792 new_nzmx++;
1793 }
1794 else
1795 for (octave_idx_type i = 0; i < n; i++)
1796 {
1797 octave_idx_type ii = idx_arg.elem (i);
1798 if (ii < len)
1799 for (octave_idx_type j = 0; j < nz; j++)
1800 {
1801 octave_quit ();
1802
1803 if (ridx(j) == ii)
1804 new_nzmx++;
1805 if (ridx(j) >= ii)
1806 break;
1807 }
1808 }
1809
1810 if (idx_orig_rows == 1 || idx_orig_columns == 1)
1811 {
1812 if (nr == 1)
1813 {
1814 retval = Sparse<T> (1, n, new_nzmx);
1815 octave_idx_type jj = 0;
1816 retval.xcidx(0) = 0;
1817 for (octave_idx_type i = 0; i < n; i++)
1818 {
1819 octave_quit ();
1820
1821 octave_idx_type ii = idx_arg.elem (i);
1822 if (ii < len)
1823 if (cidx(ii) != cidx(ii+1))
1824 {
1825 retval.xdata(jj) = data(cidx(ii));
1826 retval.xridx(jj++) = 0;
1827 }
1828 retval.xcidx(i+1) = jj;
1829 }
1830 }
1831 else
1832 {
1833 retval = Sparse<T> (n, 1, new_nzmx);
1834 retval.xcidx(0) = 0;
1835 retval.xcidx(1) = new_nzmx;
1836 octave_idx_type jj = 0;
1837 for (octave_idx_type i = 0; i < n; i++)
1838 {
1839 octave_idx_type ii = idx_arg.elem (i);
1840 if (ii < len)
1841 for (octave_idx_type j = 0; j < nz; j++)
1842 {
1843 octave_quit ();
1844
1845 if (ridx(j) == ii)
1846 {
1847 retval.xdata(jj) = data(j);
1848 retval.xridx(jj++) = i;
1849 }
1850 if (ridx(j) >= ii)
1851 break;
1852 }
1853 }
1854 }
1855 }
1856 else
1857 {
1858 octave_idx_type new_nr;
1859 octave_idx_type new_nc;
1860 if (n >= idx_orig_dims.numel ())
1861 {
1862 new_nr = idx_orig_rows;
1863 new_nc = idx_orig_columns;
1864 }
1865 else
1866 {
1867 new_nr = n;
1868 new_nc = 1;
1869 }
1870
1871 retval = Sparse<T> (new_nr, new_nc, new_nzmx);
1872
1873 if (nr == 1)
1874 {
1875 octave_idx_type jj = 0;
1876 retval.xcidx(0) = 0;
1877 for (octave_idx_type i = 0; i < n; i++)
1878 {
1879 octave_quit ();
1880
1881 octave_idx_type ii = idx_arg.elem (i);
1882 if (ii < len)
1883 if (cidx(ii) != cidx(ii+1))
1884 {
1885 retval.xdata(jj) = data(cidx(ii));
1886 retval.xridx(jj++) = 0;
1887 }
1888 retval.xcidx(i/new_nr+1) = jj;
1889 }
1890 }
1891 else
1892 {
1893 octave_idx_type jj = 0;
1894 retval.xcidx(0) = 0;
1895 for (octave_idx_type i = 0; i < n; i++)
1896 {
1897 octave_idx_type ii = idx_arg.elem (i);
1898 if (ii < len)
1899 for (octave_idx_type j = 0; j < nz; j++)
1900 {
1901 octave_quit ();
1902
1903 if (ridx(j) == ii)
1904 {
1905 retval.xdata(jj) = data(j);
1906 retval.xridx(jj++) = i;
1907 }
1908 if (ridx(j) >= ii)
1909 break;
1910 }
1911 retval.xcidx(i/new_nr+1) = jj;
1912 }
1913 }
1914 }
1915 } 1786 }
1916 } 1787 }
1917 else 1788 else
1918 { 1789 {
1919 (*current_liboctave_warning_with_id_handler) 1790 (*current_liboctave_warning_with_id_handler)
1920 ("Octave:fortran-indexing", "single index used for sparse matrix"); 1791 ("Octave:fortran-indexing", "single index used for sparse matrix");
1921 1792
1922 // This code is only for indexing matrices. The vector 1793 if (nr != 0 && idx.is_scalar ())
1923 // cases are handled above. 1794 retval = Sparse<T> (1, 1, elem (idx(0) % nr, idx(0) / nr));
1924
1925 octave_idx_type result_nr = idx_orig_rows;
1926 octave_idx_type result_nc = idx_orig_columns;
1927
1928 if (nz < 1)
1929 retval = Sparse<T> (result_nr, result_nc);
1930 else 1795 else
1931 { 1796 {
1932 // Count number of non-zero elements 1797 // Indexing a non-vector sparse matrix by linear indexing.
1933 octave_idx_type new_nzmx = 0; 1798 // I suppose this is rare (and it may easily overflow), so let's take the easy way,
1934 octave_idx_type kk = 0; 1799 // and reshape first to column vector, which is already handled above.
1935 for (octave_idx_type j = 0; j < result_nc; j++) 1800 retval = index (idx_vector::colon).index (idx);
1936 { 1801 // In this case we're supposed to always inherit the shape, but column(row) doesn't do
1937 for (octave_idx_type i = 0; i < result_nr; i++) 1802 // it, so we'll do it instead.
1938 { 1803 if (idx_dims (0) == 1 && idx_dims (1) != 1)
1939 octave_quit (); 1804 retval = retval.transpose ();
1940
1941 octave_idx_type ii = idx_arg.elem (kk++);
1942 if (ii < orig_len)
1943 {
1944 octave_idx_type fr = ii % nr;
1945 octave_idx_type fc = (ii - fr) / nr;
1946 for (octave_idx_type k = cidx(fc); k < cidx(fc+1); k++)
1947 {
1948 if (ridx(k) == fr)
1949 new_nzmx++;
1950 if (ridx(k) >= fr)
1951 break;
1952 }
1953 }
1954 }
1955 }
1956
1957 retval = Sparse<T> (result_nr, result_nc, new_nzmx);
1958
1959 kk = 0;
1960 octave_idx_type jj = 0;
1961 retval.xcidx(0) = 0;
1962 for (octave_idx_type j = 0; j < result_nc; j++)
1963 {
1964 for (octave_idx_type i = 0; i < result_nr; i++)
1965 {
1966 octave_quit ();
1967
1968 octave_idx_type ii = idx_arg.elem (kk++);
1969 if (ii < orig_len)
1970 {
1971 octave_idx_type fr = ii % nr;
1972 octave_idx_type fc = (ii - fr) / nr;
1973 for (octave_idx_type k = cidx(fc); k < cidx(fc+1); k++)
1974 {
1975 if (ridx(k) == fr)
1976 {
1977 retval.xdata(jj) = data(k);
1978 retval.xridx(jj++) = i;
1979 }
1980 if (ridx(k) >= fr)
1981 break;
1982 }
1983 }
1984 }
1985 retval.xcidx(j+1) = jj;
1986 }
1987 } 1805 }
1988 } 1806 }
1989 1807
1990 return retval; 1808 return retval;
1991 } 1809 }
2017 gripe_index_out_of_range (2, 2, idx_j.extent (nc), nc); 1835 gripe_index_out_of_range (2, 2, idx_j.extent (nc), nc);
2018 else 1836 else
2019 { 1837 {
2020 if (n == 0 || m == 0) 1838 if (n == 0 || m == 0)
2021 { 1839 {
2022 retval.resize_no_fill (n, m); 1840 retval.resize (n, m);
2023 } 1841 }
2024 else 1842 else
2025 { 1843 {
2026 bool idx_i_colon = idx_i.is_colon_equiv (nr); 1844 bool idx_i_colon = idx_i.is_colon_equiv (nr);
2027 bool idx_j_colon = idx_j.is_colon_equiv (nc); 1845 bool idx_j_colon = idx_j.is_colon_equiv (nc);
2571 } 2389 }
2572 } 2390 }
2573 } 2391 }
2574 2392
2575 return d; 2393 return d;
2394 }
2395
2396 template <class T>
2397 Array<T>
2398 Sparse<T>::array_value () const
2399 {
2400 NoAlias< Array<T> > retval (dims (), T());
2401 if (rows () == 1)
2402 {
2403 octave_idx_type i = 0;
2404 for (octave_idx_type j = 0, nc = cols (); j < nc; j++)
2405 {
2406 if (cidx(j+1) > i)
2407 retval(j) = data (i++);
2408 }
2409 }
2410 else
2411 {
2412 for (octave_idx_type j = 0, nc = cols (); j < nc; j++)
2413 for (octave_idx_type i = cidx(j), iu = cidx(j+1); i < iu; i++)
2414 retval (ridx(i), j) = data (i);
2415 }
2416
2417 return retval;
2576 } 2418 }
2577 2419
2578 // FIXME 2420 // FIXME
2579 // Unfortunately numel can overflow for very large but very sparse matrices. 2421 // Unfortunately numel can overflow for very large but very sparse matrices.
2580 // For now just flag an error when this happens. 2422 // For now just flag an error when this happens.