|
Boost : |
From: Larry Evans (jcampbell3_at_[hidden])
Date: 2001-07-01 11:27:36
Hubert HOLIN wrote:
> Paris (U.E.), le 28/06/2001
>
> --- In boost_at_y..., Larry Evans <jcampbell3_at_p...> wrote:
>
> [SNIP]
>
> > I'm confused by "accessing each index". Do you mean accessing the
> > value corresponding to that index. For example, if the matrix is 'float A[N][M]`
> > and if 'i' is such an iterator, then starting from the initial value of i:
> > *i == A[0][0]
> > *(++i) == A[0][1]
> > ...
> > *(++i) == A[N][M]
> > ?
> > In other words, the iterator produces a 'flattened' version or 'ravel' (apl term)
> > of A, and then access the elements just as a regular stl iterator. Is that
> > what you mean?
>
> Yes.
Attached is code demonstrating an implementation of this. It allows
permuting of the axes, as shown by the last test. Comments welcome.
>
>
> The quirk is that on the one hand the traversal can be somewhat
> more complicated than this (if required by the problem these iterators
> are used for), and on the other hand not every index need be accessed
> but only representatives of certain classes (such as in the case of a
> row index), in which case a further level of iteration is needed after
> dereferencing.
Could you clarify please? I'm guessing that maybe you mean, for rank3 array, A,
A[all][3][all].begin() would be an iterator for a rank 2 array? And by
"further level of iteration" do you mean something like (*i).begin()?
//Purpose:
// Demonstrate section 6.3 "Sequential Access" of
// Budd, Timothy
// _Apl Compiler_
// Springer-Verlag, 1988
//
#include <iostream>
#include <iomanip>
#include <numeric>
#include <vector>
using namespace std;
typedef
int
offset_type
;
template
< offset_type Rank
, typename Elem
>
class
vec_shape
: public vector<Elem>
{
public:
typedef
vector<Elem>
super_type
;
vec_shape(void)
: super_type(Rank)
{}
vec_shape(const Elem x[Rank])
: super_type(Rank)
{ copy(x,x+Rank,begin())
;}
}
;
offset_type const
rank
= 3
;
typedef
vec_shape<rank,offset_type>
index_type
;
typedef
vec_shape<rank+1,offset_type>
evec_type
;
typedef
vector<evec_type>
array_type
;
template
< typename Index
>
ostream&
operator<<(ostream&sout, vector<Index> const& x)
{
; int i=0
; int n=x.size()
; for(;i<n;++i) sout<<x[i]<<endl
; return sout
;}
template
< offset_type Shape
, typename Index
>
ostream&
operator<<(ostream&sout, vec_shape<Shape,Index> const& x)
{
; int i=0
; int n=Shape
; for(;i<n;++i) sout<<setw(2)<<x[i]<<" "
; return sout
;}
class
index_permut
: public index_type
{
public:
index_permut(void)
{ for(unsigned i=0; i<size(); ++i){at(i)=i;}
;}
void
swap(unsigned i, unsigned j)
{ std::swap(at(i),at(j))
;}
}
;//end index_permut class
void
shape2evec
( const index_type&a_shape
, vector<offset_type>::reverse_iterator a_evec
)
{
; partial_sum(a_shape.rbegin(),a_shape.rend(),a_evec,multiplies<offset_type>())
;}
void
shape2evec
( const index_type&a_shape
, evec_type&a_evec
)
{
; a_evec[rank]=1
; shape2evec(a_shape,++a_evec.rbegin())
;}
class
ravel_iter
{
public:
ravel_iter
( const index_permut& a_permut
, const index_type& a_shape
, const array_type& a_array
)
: m_offset_inp(0)
, m_offset_out(0)
, m_array(a_array)
{
; cout<<"ravel_iter:a_permut="<<a_permut<<endl
; evec_type l_evec_inp
; shape2evec(a_shape,l_evec_inp)
; cout<<"ravel_iter:l_evec_inp="<<l_evec_inp<<endl
; index_type l_shape_out
; index_type l_evec_out
; unsigned n = rank()
; int i
; for(i=0; i<n; ++i)
{
; l_shape_out[a_permut[i]] = a_shape[i]
; l_evec_out[a_permut[i]] = l_evec_inp[i+1]
;}
//At this point:
// here [Budd88,sec6.3]
// ---- ---------------
// l_shape_out[i] s[i+1]
// l_evec_out[i] gamma[i+1]
; cout<<"ravel_iter:l_shape_out="<<l_shape_out<<endl
; cout<<"ravel_iter:l_evec_out="<<l_evec_out<<endl
; i = n-1
; m_delta[i] = l_evec_out[i]
; for(--i; -1<i; --i)
{
; m_delta[i] = l_evec_out[i] - l_evec_out[i+1] * l_shape_out[i+1]
;}
; cout<<"ravel_iter:m_delta="<<m_delta<<endl
; shape2evec(l_shape_out,m_evec_out.rbegin())
; cout<<"ravel_iter:m_evec_out="<<m_evec_out<<endl
//At this point:
// here [Budd88,sec6.3]
// ---- ---------------
// m_delta[i] delta[i+1]
// m_evec_out[i] *\s[n-i...1] ( where / here is apl scan op == stl partial_sum )
;}
offset_type
offset(void)const
{ return m_offset_inp
;}
offset_type
inc(void)
//This implements the "Value Phase" algorithm
//in [Budd88,sec6.3], except m_evec_out[i] is used
//instead of s[i] and t to avoid mulitiplications.
{
; ++m_offset_out
; unsigned n = rank()
; int i = n - 1
; for(; -1<i; --i)
{
; m_offset_inp += m_delta[i]
; if(m_offset_out % m_evec_out[i] != 0 ) break
;}
; return m_offset_inp
;}
offset_type
operator++(void)
{ return inc()
;}
evec_type const&
operator()(void)const
{ return m_array[offset()]
;}
unsigned
size(void)const
{ return m_array.size()
;}
unsigned
rank(void)const
{ return m_delta.size()
;}
index_type
indices(void)const
//The following implements [Budd88,p62]
{
; index_type ndx
; unsigned n = rank()
; unsigned i = 0
; unsigned s = 0
; if(1<n)
{ ndx[i] = m_offset_out/m_evec_out[i+1] //a[1] in [Budd88]
; for(++i; i<n-1; ++i)
{ s = m_evec_out[i]/m_evec_out[i+1]
; ndx[i] = ( m_offset_out/m_evec_out[i+1] ) % s //eq(5.7)
;}
;}
; s = m_evec_out[i]
; ndx[i] = m_offset_out % s //a[n] in [Budd88]
; return ndx
;}
private:
index_type
m_evec_out
//This is used in place of s[i] and t in [Budd88,sec6.3]
;
index_type
m_delta
//This is delta in [Budd88,sec6.3]
;
offset_type
m_offset_out
//This is offset (i.e. "output" offset) in [Budd88,sec6.3]
;
offset_type
m_offset_inp
//This is offset' (i.e. "input" offset) in [Budd88,sec6.3]
;
const
array_type&
m_array
;
}
;//end ravel_iter class
ostream&
operator<<
( ostream&sout
, ravel_iter&r_iter
)
{ unsigned n = r_iter.size()
; unsigned i = 0
; for(; i<n; ++i, ++r_iter) sout<<"["<<r_iter.indices()<<"]="<<r_iter()<<endl
; return sout
;}
int
main(void)
{ offset_type ishape[rank]={3,4,2}
; index_type shape(ishape)
; evec_type evec
; shape2evec(shape,evec)
; cout<<"array shape="<<shape<<endl
; cout<<"array evec="<<evec<<endl
; index_type ndx
; int ir=-1
; array_type arr(evec[0])
; array_type::iterator iter(arr.begin())
; for(++ir, ndx[ir]=0; ndx[ir]<shape[ir]; ++ndx[ir])
{ for(++ir, ndx[ir]=0; ndx[ir]<shape[ir]; ++ndx[ir])
{ for(++ir, ndx[ir]=0; ndx[ir]<shape[ir]; ++ndx[ir])
{ evec_type&ev=*iter
; copy(ndx.rbegin(),ndx.rend(),ev.rbegin())
; offset_type off_set =
inner_product
( ndx.rbegin()
, ndx.rend()
, evec.rbegin()
, (offset_type)0
, plus<offset_type>()
, multiplies<offset_type>()
)
; ev[0] = off_set
; ++iter
;}
; --ir
;}
; --ir
;}
; cout<<"arr="<<endl
; cout<<arr<<endl
; {
; cout<<"r_iter w id permut"<<endl
; index_permut ip
; ravel_iter r_iter(ip,shape,arr)
; cout<<"r_iter print:"<<endl
; cout<<r_iter
;}
; {
; cout<<"r_iter w trans permut"<<endl
; index_permut ip
; ip.swap(0,2)
; ravel_iter r_iter(ip,shape,arr)
; cout<<"r_iter print:"<<endl
; cout<<r_iter
;}
; return 0
;}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk