Mercurial > hg > octave-nkf
comparison liboctave/Sparse.cc @ 10468:197b096001b7
improve sparse 2d indexing (part 3)
author | Jaroslav Hajek <highegg@gmail.com> |
---|---|
date | Fri, 26 Mar 2010 10:41:56 +0100 |
parents | 3011d1765a6e |
children | ded9beac7582 |
comparison
equal
deleted
inserted
replaced
10467:13c1f15c67fa | 10468:197b096001b7 |
---|---|
1823 } | 1823 } |
1824 | 1824 |
1825 return retval; | 1825 return retval; |
1826 } | 1826 } |
1827 | 1827 |
1828 struct | |
1829 idx_node | |
1830 { | |
1831 octave_idx_type i; | |
1832 struct idx_node *next; | |
1833 }; | |
1834 | |
1835 template <class T> | 1828 template <class T> |
1836 Sparse<T> | 1829 Sparse<T> |
1837 Sparse<T>::index (const idx_vector& idx_i, const idx_vector& idx_j, bool resize_ok) const | 1830 Sparse<T>::index (const idx_vector& idx_i, const idx_vector& idx_j, bool resize_ok) const |
1838 { | 1831 { |
1839 Sparse<T> retval; | 1832 Sparse<T> retval; |
1921 retval.xcidx(j+1) = retval.xcidx(j); | 1914 retval.xcidx(j+1) = retval.xcidx(j); |
1922 } | 1915 } |
1923 | 1916 |
1924 retval.change_capacity (retval.xcidx(m)); | 1917 retval.change_capacity (retval.xcidx(m)); |
1925 | 1918 |
1919 // Copy data, adjust row indices. | |
1926 for (octave_idx_type j = 0; j < m; j++) | 1920 for (octave_idx_type j = 0; j < m; j++) |
1927 { | 1921 { |
1928 octave_idx_type i = retval.xcidx(j); | 1922 octave_idx_type i = retval.xcidx(j); |
1929 if (retval.xcidx(j+1) > i) | 1923 if (retval.xcidx(j+1) > i) |
1930 { | 1924 { |
1931 retval.xridx(i) = 0; | 1925 retval.xridx(i) = 0; |
1932 retval.xdata(i) = data(ij[j]); | 1926 retval.xdata(i) = data(ij[j]); |
1933 } | 1927 } |
1934 } | 1928 } |
1935 } | 1929 } |
1930 else if (idx_i.is_cont_range (nr, lb, ub)) | |
1931 { | |
1932 retval = Sparse<T> (n, m); | |
1933 OCTAVE_LOCAL_BUFFER (octave_idx_type, li, m); | |
1934 OCTAVE_LOCAL_BUFFER (octave_idx_type, ui, m); | |
1935 for (octave_idx_type j = 0; j < m; j++) | |
1936 { | |
1937 octave_quit (); | |
1938 octave_idx_type jj = idx_j(j), lj = cidx(jj), nzj = cidx(jj+1) - cidx(jj); | |
1939 octave_idx_type lij, uij; | |
1940 // Lookup indices. | |
1941 li[j] = lij = lblookup (ridx () + lj, nzj, lb) + lj; | |
1942 ui[j] = uij = lblookup (ridx () + lj, nzj, ub) + lj; | |
1943 retval.xcidx(j+1) = retval.xcidx(j) + ui[j] - li[j]; | |
1944 } | |
1945 | |
1946 retval.change_capacity (retval.xcidx(m)); | |
1947 | |
1948 // Copy data, adjust row indices. | |
1949 for (octave_idx_type j = 0, k = 0; j < m; j++) | |
1950 { | |
1951 octave_quit (); | |
1952 for (octave_idx_type i = li[j]; i < ui[j]; i++) | |
1953 { | |
1954 retval.xdata(k) = data(i); | |
1955 retval.xridx(k++) = ridx(i) - lb; | |
1956 } | |
1957 } | |
1958 } | |
1959 else if (idx_i.is_permutation (nr)) | |
1960 { | |
1961 // The columns preserve their length, we just need to renumber and sort them. | |
1962 // Count new nonzero elements. | |
1963 retval = Sparse<T> (nr, m); | |
1964 for (octave_idx_type j = 0; j < m; j++) | |
1965 { | |
1966 octave_idx_type jj = idx_j(j); | |
1967 retval.xcidx(j+1) = retval.xcidx(j) + (cidx(jj+1) - cidx(jj)); | |
1968 } | |
1969 | |
1970 retval.change_capacity (retval.xcidx (m)); | |
1971 | |
1972 octave_quit (); | |
1973 | |
1974 if (idx_i.is_range () && idx_i.increment () == -1) | |
1975 { | |
1976 // It's nr:-1:1. Just flip all columns. | |
1977 for (octave_idx_type j = 0; j < m; j++) | |
1978 { | |
1979 octave_quit (); | |
1980 octave_idx_type jj = idx_j(j), lj = cidx(jj), nzj = cidx(jj+1) - cidx(jj); | |
1981 octave_idx_type li = retval.xcidx(j), uj = lj + nzj - 1; | |
1982 for (octave_idx_type i = 0; i < nzj; i++) | |
1983 { | |
1984 retval.xdata(li + i) = data(uj - i); // Copy in reverse order. | |
1985 retval.xridx(li + i) = nr - 1 - ridx(uj - i); // Ditto with transform. | |
1986 } | |
1987 } | |
1988 } | |
1989 else | |
1990 { | |
1991 // Get inverse permutation. | |
1992 OCTAVE_LOCAL_BUFFER (octave_idx_type, iinv, nr); | |
1993 const Array<octave_idx_type> ia = idx_i.as_array (); | |
1994 for (octave_idx_type i = 0; i < nr; i++) | |
1995 iinv[ia(i)] = i; | |
1996 | |
1997 // Scatter buffer. | |
1998 OCTAVE_LOCAL_BUFFER (T, scb, nr); | |
1999 octave_idx_type *rri = retval.ridx (); | |
2000 | |
2001 for (octave_idx_type j = 0; j < m; j++) | |
2002 { | |
2003 octave_quit (); | |
2004 octave_idx_type jj = idx_j(j), lj = cidx(jj), nzj = cidx(jj+1) - cidx(jj); | |
2005 octave_idx_type li = retval.xcidx(j); | |
2006 // Scatter the column, transform indices. | |
2007 for (octave_idx_type i = 0; i < nzj; i++) | |
2008 scb[rri[li + i] = iinv[ridx(lj + i)]] = data(lj + i); | |
2009 | |
2010 octave_quit (); | |
2011 | |
2012 // Sort them. | |
2013 std::sort (rri + li, rri + li + nzj); | |
2014 | |
2015 // Gather. | |
2016 for (octave_idx_type i = 0; i < nzj; i++) | |
2017 retval.xdata(li + i) = scb[rri[li + i]]; | |
2018 } | |
2019 } | |
2020 | |
2021 } | |
1936 else | 2022 else |
1937 { | 2023 { |
1938 if (n == 0 || m == 0) | 2024 // This is the most general case, where all optimizations failed. |
1939 { | 2025 // I suppose this is a relatively rare case, so it will be done |
1940 retval.resize (n, m); | 2026 // as s(i,j) = ((s(:,j).')(:,i)).' |
1941 } | 2027 // Note that if j is :, the first indexing expr. is a shallow copy. |
1942 else | 2028 retval = index (idx_vector::colon, idx_j).transpose (); |
1943 { | 2029 retval = retval.index (idx_vector::colon, idx_i).transpose (); |
1944 bool idx_i_colon = idx_i.is_colon_equiv (nr); | |
1945 bool idx_j_colon = idx_j.is_colon_equiv (nc); | |
1946 | |
1947 if (idx_i_colon && idx_j_colon) | |
1948 { | |
1949 retval = *this; | |
1950 } | |
1951 else | |
1952 { | |
1953 // Identify if the indices have any repeated values | |
1954 bool permutation = true; | |
1955 | |
1956 OCTAVE_LOCAL_BUFFER (octave_idx_type, itmp, | |
1957 (nr > nc ? nr : nc)); | |
1958 octave_sort<octave_idx_type> lsort; | |
1959 | |
1960 if (n > nr || m > nc) | |
1961 permutation = false; | |
1962 | |
1963 if (permutation && ! idx_i_colon) | |
1964 { | |
1965 // Can't use something like | |
1966 // idx_vector tmp_idx = idx_i; | |
1967 // tmp_idx.sort (true); | |
1968 // if (tmp_idx.length(nr) != n) | |
1969 // permutation = false; | |
1970 // here as there is no make_unique function | |
1971 // for idx_vector type. | |
1972 for (octave_idx_type i = 0; i < n; i++) | |
1973 itmp [i] = idx_i.elem (i); | |
1974 lsort.sort (itmp, n); | |
1975 for (octave_idx_type i = 1; i < n; i++) | |
1976 if (itmp[i-1] == itmp[i]) | |
1977 { | |
1978 permutation = false; | |
1979 break; | |
1980 } | |
1981 } | |
1982 if (permutation && ! idx_j_colon) | |
1983 { | |
1984 for (octave_idx_type i = 0; i < m; i++) | |
1985 itmp [i] = idx_j.elem (i); | |
1986 lsort.sort (itmp, m); | |
1987 for (octave_idx_type i = 1; i < m; i++) | |
1988 if (itmp[i-1] == itmp[i]) | |
1989 { | |
1990 permutation = false; | |
1991 break; | |
1992 } | |
1993 } | |
1994 | |
1995 if (permutation) | |
1996 { | |
1997 // Special case permutation like indexing for speed | |
1998 retval = Sparse<T> (n, m, nnz ()); | |
1999 octave_idx_type *ri = retval.xridx (); | |
2000 | |
2001 std::vector<T> X (n); | |
2002 for (octave_idx_type i = 0; i < nr; i++) | |
2003 itmp [i] = -1; | |
2004 for (octave_idx_type i = 0; i < n; i++) | |
2005 itmp[idx_i.elem(i)] = i; | |
2006 | |
2007 octave_idx_type kk = 0; | |
2008 retval.xcidx(0) = 0; | |
2009 for (octave_idx_type j = 0; j < m; j++) | |
2010 { | |
2011 octave_idx_type jj = idx_j.elem (j); | |
2012 for (octave_idx_type i = cidx(jj); i < cidx(jj+1); i++) | |
2013 { | |
2014 octave_quit (); | |
2015 | |
2016 octave_idx_type ii = itmp [ridx(i)]; | |
2017 if (ii >= 0) | |
2018 { | |
2019 X [ii] = data (i); | |
2020 retval.xridx (kk++) = ii; | |
2021 } | |
2022 } | |
2023 lsort.sort (ri + retval.xcidx (j), kk - retval.xcidx (j)); | |
2024 for (octave_idx_type p = retval.xcidx (j); p < kk; p++) | |
2025 retval.xdata (p) = X [retval.xridx (p)]; | |
2026 retval.xcidx(j+1) = kk; | |
2027 } | |
2028 retval.maybe_compress (); | |
2029 } | |
2030 else | |
2031 { | |
2032 OCTAVE_LOCAL_BUFFER (struct idx_node, nodes, n); | |
2033 OCTAVE_LOCAL_BUFFER (octave_idx_type, start_nodes, nr); | |
2034 | |
2035 for (octave_idx_type i = 0; i < nr; i++) | |
2036 start_nodes[i] = -1; | |
2037 | |
2038 for (octave_idx_type i = 0; i < n; i++) | |
2039 { | |
2040 octave_idx_type ii = idx_i.elem (i); | |
2041 nodes[i].i = i; | |
2042 nodes[i].next = 0; | |
2043 | |
2044 octave_idx_type node = start_nodes[ii]; | |
2045 if (node == -1) | |
2046 start_nodes[ii] = i; | |
2047 else | |
2048 { | |
2049 while (nodes[node].next) | |
2050 node = nodes[node].next->i; | |
2051 nodes[node].next = nodes + i; | |
2052 } | |
2053 } | |
2054 | |
2055 // First count the number of non-zero elements | |
2056 octave_idx_type new_nzmx = 0; | |
2057 for (octave_idx_type j = 0; j < m; j++) | |
2058 { | |
2059 octave_idx_type jj = idx_j.elem (j); | |
2060 | |
2061 if (jj < nc) | |
2062 { | |
2063 for (octave_idx_type i = cidx(jj); | |
2064 i < cidx(jj+1); i++) | |
2065 { | |
2066 octave_quit (); | |
2067 | |
2068 octave_idx_type ii = start_nodes [ridx(i)]; | |
2069 | |
2070 if (ii >= 0) | |
2071 { | |
2072 struct idx_node inode = nodes[ii]; | |
2073 | |
2074 while (true) | |
2075 { | |
2076 if (idx_i.elem (inode.i) < nr) | |
2077 new_nzmx ++; | |
2078 if (inode.next == 0) | |
2079 break; | |
2080 else | |
2081 inode = *inode.next; | |
2082 } | |
2083 } | |
2084 } | |
2085 } | |
2086 } | |
2087 | |
2088 std::vector<T> X (n); | |
2089 retval = Sparse<T> (n, m, new_nzmx); | |
2090 octave_idx_type *ri = retval.xridx (); | |
2091 | |
2092 octave_idx_type kk = 0; | |
2093 retval.xcidx(0) = 0; | |
2094 for (octave_idx_type j = 0; j < m; j++) | |
2095 { | |
2096 octave_idx_type jj = idx_j.elem (j); | |
2097 if (jj < nc) | |
2098 { | |
2099 for (octave_idx_type i = cidx(jj); | |
2100 i < cidx(jj+1); i++) | |
2101 { | |
2102 octave_quit (); | |
2103 | |
2104 octave_idx_type ii = start_nodes [ridx(i)]; | |
2105 | |
2106 if (ii >= 0) | |
2107 { | |
2108 struct idx_node inode = nodes[ii]; | |
2109 | |
2110 while (true) | |
2111 { | |
2112 if (idx_i.elem (inode.i) < nr) | |
2113 { | |
2114 X [inode.i] = data (i); | |
2115 retval.xridx (kk++) = inode.i; | |
2116 } | |
2117 | |
2118 if (inode.next == 0) | |
2119 break; | |
2120 else | |
2121 inode = *inode.next; | |
2122 } | |
2123 } | |
2124 } | |
2125 lsort.sort (ri + retval.xcidx (j), | |
2126 kk - retval.xcidx (j)); | |
2127 for (octave_idx_type p = retval.xcidx (j); | |
2128 p < kk; p++) | |
2129 retval.xdata (p) = X [retval.xridx (p)]; | |
2130 retval.xcidx(j+1) = kk; | |
2131 } | |
2132 } | |
2133 } | |
2134 } | |
2135 } | |
2136 } | 2030 } |
2137 | 2031 |
2138 return retval; | 2032 return retval; |
2139 } | 2033 } |
2140 | 2034 |