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