Boost logo

Ublas :

From: Russ (c.r.coggrave_at_[hidden])
Date: 2006-04-24 05:50:36


Michael Stevens <mail <at> michael-stevens.de> writes:

>
> On Tuesday, 18. April 2006 22:58, Russ wrote:
> > 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.
>
> I am wondering if a special IO implmentation just for indirect_array objects
> is the right way to go. range and slice are already defined in the uBLAS
> documentation as models of an STL Revisible Container. I think indirect_array
> would also be modeled as such.
>
> Since Revisible Container provides enough functionality to write generic IO
> functions. One could therefore right a generic formated stream reader and
> writter for these containers and them simply tie them simply provide operator
> << and >> overloads for the types.

I have reimplemented the IO implementation as generic functions for objects that
model the reversible container concept. I would be grateful if you could comment
on whether this is the way in which you were proposing to proceed...

// Output operator for objects that model STL Reversible Container Concept
template<class E, class T, class C>
BOOST_UBLAS_INLINE
std::basic_ostream<E, T> &output_op (std::basic_ostream<E, T> &os, const C &c)
{
        // Check that container C models the Reversible Container Concept
        boost::function_requires< boost::ReversibleContainerConcept< C > >();

        typedef typename C::size_type size_type;
  size_type size = c.size();
  std::basic_ostringstream<E, T, std::allocator<E> > s;
  s.flags (os.flags ());
  s.imbue (os.getloc ());
  s.precision (os.precision ());
        // Output size of container
        s << '[' << size << "](";
        // Initialise iterators
        C::const_iterator it( c.begin () );
        C::const_iterator it_end( c.end() );
        // Output first entry
        if (size > 0) {
      s << *it;
                        ++it;
        }
        // Output comma seperated list of remaining entries
        while (it != it_end) {
      s << ',' << *it;
                        ++it;
        }
  s << ')';
  return os << s.str ().c_str ();
}

// Input operator for indirect_array<A> objects
template<class E, class T, class C>
BOOST_UBLAS_INLINE
std::basic_istream<E, T> &input_op (std::basic_istream<E, T> &is, const C &c)
{
        // Check that container C models the Reversible Container Concept
        boost::function_requires< boost::ReversibleContainerConcept< C > >();

        typedef typename C::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 ()) {
    C s (size);
    if (is >> ch && ch != '(') {
      is.putback (ch);
      is.setstate (std::ios_base::failbit);
    } else if (! is.fail ()) {
                        C::iterator it = s.begin();
                        C::iterator it_end = s.end();
                        size_type i = 0;
                        while (it != it_end) {
        if (is >> *it >> ch && ch != ',') {
          is.putback (ch);
          if (i < size - 1)
            is.setstate (std::ios_base::failbit);
          break;
        }
                                i++;
      }
      if (is >> ch && ch != ')') {
        is.putback (ch);
        is.setstate (std::ios_base::failbit);
      }
    }
    if (! is.fail ())
      c.swap (s);
  }
  return is;
}

// 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
boost::numeric::ublas::indirect_array<A> &ia)
{
        return output_op( os, ia);
}

// 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, const
boost::numeric::ublas::indirect_array<A> &ia)
{
  return input_op( is, ia );
}
 

>
> > 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 think resize() would be nice BUT. To be consistent with people expectations
> it might be good to go all the way and define insert and erase operations.
>
> > 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().
> Sound good.
>
> > 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.
>
> We will need to find a place to but all these non BLAS free functions
>
> Michael

I have added the resize() methods, however, will hold off preparing a patch
until I have had a chance to look at modeling the insert and erase opertions.

Regards,

Russ