Mercurial > hg > octave-nkf
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. |