|
Boost : |
From: Larry Evans (jcampbell3_at_[hidden])
Date: 2001-03-22 23:33:54
Jeremy Siek wrote:
...skipping
> I've been working with Ron Garcia on the interface for multi-dim arrays
> the last couple days... still have more work to do there. One of the
> trickier parts is deciding on an interface for subarrays and slicing.
> Blitz++ uses the following notation for specifying subarrays and slices:
>
> A(0, Range(1,2), Range(2, 5)) // ranges are specified has closed intervals
>
> However, this interface results in an interface explosion and has a fixed
> limit on the number of dimensions that can be handled.
>
> Blitz++ has an alternate way to specify subarrays using RectDomain, and
> valarray has the gslice interface, however these approaches are not as
> easy to use.
>
> One possibility I'm looking at starts with the std::slice from valarray,
> but allows them to be combined to specify slices for N dimensions.
>
> A[slice(0)(1,2)(2,3)] // slices here are (start,size=1,stride=1)
> // another sensible option would be to
> // specify slices with half-open intervals
> // (start,finish,stride)
>
> If anyone has any good ideas on a nice interface for specifying subarrays,
> feel free to chime in :)
>
I used to be an apl fan, and tried emulating some of apl's interface's with some c++
classes using expansion vectors described in _An APL Compiler_ by
Timothy Budd(1988). Operations on the expansion vector (size = rank) can be used
to take a slice, rotate the axes.
Attached are a test driver _conslivar.c and a header file, varslirnk.h, declaring a
class used to manipulate the expansion vector. You may find the test driver cryptic,
so I'll give some explanation.
; sout<<"===>ConSliOwn CTOR() via SliceOp: From(1)<<UpTo(2)"<<endl
; ConSliOwn<double> ownSl(testArr<<From(1)<<UpTo(2)<<EndSli())
; sout<<ownSl<<endl
I think this takes a slice out of testArr which drops the 1st element in axis 1, and then
takes the 1st 2 elements of axis 2. This is equivlent to the apl:
ownS1 <- 2take[2]1drop[1]testArr
For example if:
testArr =
{{ 11 , 12, 13}
, { 21, 22, 23}
, { 31, 32, 33}
}
then:
ownS1 =
{{ 21, 22}
, { 31, 32}
}
The actual data in the array is stored in a T* for the template arg (e.g. double).
Indexing uses the expansion vector and successive operator[](int) to index into this T*.
I found apl's interface very useful; so, I'm suggesting something similar for boost.
//Modification History:
// 96-09-04.1051 evansl
// WHAT:
// Renamed all to nextAx.
// Appended nextAx() call to all sliceops.
// WHY:
// Required by changes to ConSliOps.h file..
// 96-09-03.1343 evansl
// WHAT:
// Renamed next to all.
// WHY:
// all is more meaningful.
// 96-08-22.1840 evansl
// WHAT:
// Copied from _VarSlRnk.
// WHY:
// -
#include "ConSliVar.h"
#include "OwnArrCon.h"
#include "assign.VarArrCon.h"
#define SLICEOP
#ifdef SLICEOP
#include "ConSliOps.h"
#endif
int
main(void)
{
; IndOstream sout(cout)
; sout<<"===>Normal CTOR"<<endl
; const int rank=3
; const int shapes[rank]={4,4,4}
; OwnArrCon<double> testArr(rank,shapes)
; assign(testArr)
; sout<<"--->begin testArr="<<endl
; sout()<<"---config="<<endl<<testArr.config()<<endl
; sout<<"---contents="<<endl<<testArr<<endl
; {
; sout<<"===>ConSliVar CTOR"<<endl
; ConSliVar<double> varSl(testArr)
; sout<<"--->varSl="<<endl
; sout<<varSl<<endl
; sout<<"--->varSl.from(1)="<<endl
; varSl.from(1).nextAx()
; sout<<varSl<<endl
; sout<<"--->varSl.upto(2)="<<endl
; varSl.upto(2).nextAx()
; sout<<varSl<<endl
; sout<<"--->toConSliOwn="<<endl
; ConSliOwn<double> ownSl(varSl.toConSliOwn())
; sout<<ownSl<<endl
;}
; {
; sout<<"===>ConSliVar CTOR"<<endl
; ConSliVar<double> varSl(testArr)
; sout<<"--->varSl.frto(2,4)="<<endl
; varSl.frto(2,4).nextAx()
; sout<<varSl<<endl
; sout<<"--->varSl.nextAx()="<<endl
; varSl.nextAx()
; sout<<varSl<<endl
; sout<<"--->toConSliOwn="<<endl
; ConSliOwn<double> ownSl(varSl.toConSliOwn())
; sout<<ownSl<<endl
;}
; {
; sout<<"===>ConSliVar CTOR"<<endl
; ConSliVar<double> varSl(testArr)
; sout<<"--->varSl.from(1).upto(1).frto(2,4)="<<endl
; varSl.from(1).nextAx().upto(1).nextAx().frto(2,4).nextAx()
; sout<<varSl<<endl
; sout<<"--->toConSliOwn="<<endl
; ConSliOwn<double> ownSl(varSl.toConSliOwn())
; sout<<ownSl<<endl
;}
; {
; sout<<"===>ConSliVar CTOR"<<endl
; ConSliVar<double> varSl(testArr)
; sout<<"--->varSl.from(1)="<<endl
; varSl.from(1).nextAx()
; sout<<varSl<<endl
; sout<<"--->toConSliOwn="<<endl
; ConSliOwn<double> ownSl(varSl.toConSliOwn())
; sout<<ownSl<<endl
; sout<<"===>ConSliVar CTOR2"<<endl
; ConSliVar<double> varS2(ownSl)
; sout<<"--->varS2.from(1)="<<endl
; varS2.from(1).nextAx()
; sout<<varS2<<endl
; sout<<"--->toConSliOwn="<<endl
; ConSliOwn<double> ownS2(varS2.toConSliOwn())
; sout<<ownS2<<endl
;}
#ifdef SLICEOP
; {
; sout<<"===>ConSliOwn CTOR() via SliceOp: From(1)<<UpTo(2)"<<endl
; ConSliOwn<double> ownSl(testArr<<From(1)<<UpTo(2)<<EndSli())
; sout<<ownSl<<endl
;}
; {
; sout<<"===>ConSliOwn CTOR= via SliceOp: From(1)<<UpTo(2)"<<endl
; ConSliOwn<double> ownSl=testArr<<From(1)<<UpTo(2)<<EndSli()
; sout<<ownSl<<endl
;}
#endif
; sout<<"--->end testArr="<<endl
; sout<<testArr<<endl
; return 0
;}
#ifndef __VarSliRnk_h__
#define __VarSliRnk_h__
//Purpose:
// Provide an intermediate class used to specify the changes to
// a ConEvcRnk or ConSliRnk to produce another ConSliRnk.
// These changes include:
// Taking slices of any axis
// Reversing any axis
// Transposing the axes.
//Modification History:
// 96-10-08.2218 evansl
// WHAT:
// 1.Renamed to VarSliRnk from VarAxsRnk.
// WHY:
// 1.Name more closely reflects purpose.
// 96-09-15.1312 evansl
// WHAT:
// 1.Combined code from VarStpRnk and ConStpPtr.
// WHY:
// 1.Initial version of class def.
#include "ConSliRnk.h"
#include "Permut.h"
class VarSliRnk
: protected ConSliRnk
{
public:
ConSliRnk::rank
;
VarSliRnk&
nextAx
( void
)
{
; assert(_axis<rank())
; _nextAx()
; return *this
;}
VarSliRnk&
setAx
( int axi
)
{
; assert(-1<axi)
; assert(axi<rank())
; _axis=axi
; return *this
;}
VarSliRnk&
from
( int fri
)
{
; assert(_axis<rank())
; _from(fri)
; return *this
;}
VarSliRnk&
upto
( int toi
)
{
; assert(_axis<rank())
; _upto(toi)
; return *this
;}
VarSliRnk&
frto
( int fri
, int toi
)
{
; assert(_axis<rank())
; _frto(fri,toi)
; return *this
;}
VarSliRnk&
trans( void )
{
; _trans()
; return *this
;}
VarSliRnk&
trans( const ExpPerm& p )
{
; assert(p.range() == rank())
; assert(p.OK()==ExpPerm::ALL_OK)
; _trans(p)
; return *this
;}
VarSliRnk&
reverse( void )
{ assert(_axis<rank())
; _reverse()
; return *this
;}
VarSliRnk&
reverse( int ax )
{
; int curAx=slAxis()
; setAx(ax)
; _reverse()
; setAx(curAx)
; return *this
;}
int
slAxis(void)const
{ return _axis
;}
int
slDisp(void)const
{ return _disp
;}
void
print(ostream& sout)const
{ ConSliRnk::print(sout)
; sout<<"axis="<<slAxis()<<endl
; sout<<"disp="<<slDisp()<<endl
;}
VarSliRnk(const ConEvcRnk& evec)
: ConSliRnk(evec, OwnFlag())
, _axVec(_CTORaxes(evec.rank()))
, _axis(0)
, _disp(0)
{
;}
VarSliRnk(const ConSliRnk& evec)
: ConSliRnk(evec, OwnFlag())
, _axVec(_CTORaxes(evec.rank()))
, _axis(0)
, _disp(0)
{
;}
ConSliRnk
toConSliRnk(void)const
{
; return ConSliRnk(rank(),construct_Evec(*this))
;}
~VarSliRnk(void)
{ destruct_ArrCfig()
; delete[] _axVec
;}
int
axis(int i)const
{ return _axVec[i]
;}
private:
static
EvecElement*
construct_Evec(const VarSliRnk& evec)
{ const EvecElement* fr=evec.con_Cptr()
; const r=evec.rank()
; EvecElement* to=construct_ArrCfig(r)
; for(int i=-1; i<r; i++)
{
; to[i]=fr[evec.axis(i)]
;}
; return to
;}
int&
var_axis(int i)
{ return _axVec[i]
;}
void
_upto
( int toi
)
{
; int iax=axis(_axis)
; int ish=shape(_axis)
; assert(toi<=ish)
; EvecElement* eVec=var_Cptr()
; eVec[iax].var_shape()=toi
;}
void
_from
( int fri
)
{
; int iax=axis(_axis)
; int ish=shape(_axis)
; assert(fri<ish)
; EvecElement* eVec=var_Cptr()
; eVec[iax].var_shape()-=fri
; _disp+=fri*stride(iax)
;}
int*
_TRaxes(void)const
{
; int r=rank()
; int* axes = new int[r]
; for(int iax=0; iax<r; ++iax)
{ axes[iax]=axis(iax)
;}
; return axes
;}
void
_trans
( void
)
{
; int* axes=_TRaxes()
; int r=rank()
; int r1=r-1
; for(int iax=0; iax<r; ++iax)
{
; var_axis(iax)=axes[r1-iax]
;}
; delete [] axes
;}
void
_trans
( const ExpPerm& axes
)
{
; int r=rank()
; for(int iax=0; iax<r; ++iax)
{
; var_axis(iax)=axes[iax]
;}
;}
void
_reverse
( void
)
{
; EvecElement* eVec=var_Cptr()
; int iax=axis(_axis)
; int istr=stride(_axis)
; int isha=shape(_axis)
; eVec[iax].var_stride()=-istr
; _disp+=istr*(isha-1)
;}
void
_frto(int fri, int toi)
{
; _from(fri)
; _upto(toi-fri)
;}
void
_nextAx
( void
)
{
; _axis++
;}
static
int *
_CTORaxes(int rank)
{ int* p=new int[rank]
; for(int i=0; i<rank; i++)
{
; p[i]=i
;}
; return p
;}
int*
_axVec
;
int
_axis
;
int
_disp
;
};//end VarSliRnk class
inline
ostream&
operator<<(ostream& sout, const VarSliRnk& x)
{ x.print(sout)
; return sout
;}
#endif
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk