Boost logo

Ublas :

From: Russ (c.r.coggrave_at_[hidden])
Date: 2006-04-18 16:58:38


I would like to contribute the following input and output operators for
indirect_array objects (see below). Hopefully this code can be added to io.hpp.

In addition, I would like to ask a quick question...

Background: I am trying to write some code that performs a similar operation to
the Matlab find() function - e.g. returns row and column indices of non-zero
matrix elements. The indirect_array class seems ideal for storing the indices,
since in addition to normal array properties, they can also be used to create a
matrix_vector_indirect proxy object. However, I appreciate that the
indirect_array class is undocumented and its future is unknown.

Is there any reason why there is no resize() method for the indirect_array
templated class? Would anyone mind if I added one? I propose that the size_
attribute is removed, and that the array size is determined as the data_.size().
New resize() methods would call data_.resize().

If the resize() method were added then it would be possible define a free
function that returns info about the non-zero elements as follows:

template< class M, class IA >
void Find( M Matrix, IA &RowIndices, IA &ColIndices )

where IA = indirect_array<>. The Find function could then resize the
indirect_arrays to the number of non-zero elements found in M.

Contributed code...

// Output operator for indirect_array<A> objects
template<class E, class T, class A>
std::basic_ostream<E, T> &operator << (std::basic_ostream<E, T> &os, const
ublas::indirect_array<A> &ia)
{
  typedef typename indirect_array<A>::size_type size_type;
  size_type size = ia.size();
  std::basic_ostringstream<E, T, std::allocator<E> > s;
  s.flags (os.flags ());
  s.imbue (os.getloc ());
  s.precision (os.precision ());
  s << '[' << size << "](";
  if (size > 0)
      s << ia(0);
  for (size_type i = 1; i < size; ++ i)
      s << ',' << ia(i);
  s << ')';
  return os << s.str ().c_str ();
}

// Input operator for indirect_array<A> objects
template<class E, class T, class A>
std::basic_istream<E, T> &operator >> (std::basic_istream<E, T> &is, ublas::
indirect_array<A> &ia)
{
  typedef typename indirect_array<A>::size_type size_type;
  E ch;
  size_type size;
  if (is >> ch && ch != '[') {
    is.putback (ch);
    is.setstate (std::ios_base::failbit);
  } else if (is >> size >> ch && ch != ']') {
    is.putback (ch);
    is.setstate (std::ios_base::failbit);
  } else if (! is.fail ()) {
    indirect_array<A> s (size);
    if (is >> ch && ch != '(') {
      is.putback (ch);
      is.setstate (std::ios_base::failbit);
    } else if (! is.fail ()) {
      for (size_type i = 0; i < size; i ++) {
        if (is >> s (i) >> ch && ch != ',') {
          is.putback (ch);
          if (i < size - 1)
            is.setstate (std::ios_base::failbit);
          break;
        }
      }
      if (is >> ch && ch != ')') {
        is.putback (ch);
        is.setstate (std::ios_base::failbit);
      }
    }
    if (! is.fail ())
      v.swap (s);
  }
  return is;
}