Commit 9eac72a6 authored by thomas.forbriger's avatar thomas.forbriger Committed by thomas.forbriger
Browse files

replicated base enables use of slice and subarray for ConstArray

This is a legacy commit from before 2015-03-01.
It may be incomplete as well as inconsistent.
See COPYING.legacy and README.history for details.


SVN Path:     http://gpitrsvn.gpi.uni-karlsruhe.de/repos/TFSoftware/trunk
SVN Revision: 1243
SVN UUID:     67feda4a-a26e-11df-9d6e-31afc202ad0c
parent 08872ad7
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: README,v 1.14 2002-12-29 00:09:05 forbrig Exp $
* $Id: README,v 1.15 2002-12-29 16:57:27 forbrig Exp $
*
* Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
*
......@@ -30,6 +30,13 @@
* - added documentation regarding the concept of
* const correctness
* - added documentation regarding member typedefs
* - 29/12/2002 V1.3 (thof)
* - added section about replicated shared heap base
* class (\ref sec_design_replicated)
* - added section about sparse interface
* (\ref sec_design_interface_sparse)
* - added section about accessing internals
* (\ref sec_design_interface_internals)
*
* ============================================================================
*/
......@@ -55,7 +62,7 @@ namespace aff {
\since December 2002
\date December 2002
\version V1.0
$Id: README,v 1.14 2002-12-29 00:09:05 forbrig Exp $
$Id: README,v 1.15 2002-12-29 16:57:27 forbrig Exp $
Contents of this page:
- \ref sec_main_aims
......@@ -191,13 +198,30 @@ See also "\ref sec_design_multidimensional".
Contents of this page:
- \ref sec_design_interface
- \ref sec_design_replicated
- \ref sec_design_copy
- \ref sec_design_namespaces
- \ref sec_design_binary
- \ref sec_design_multidimensional
- \ref sec_design_const
\section sec_design_interface Common interface elements
\section sec_design_interface Common interface concepts
\subsection sec_design_interface_sparse Sparse interfaces
The class library is intended to be a light-weight library. This means it
should offer basic functionality in terms of multidimensional containers
with counted references (and not more in first place). We do not like to
include a tremendous amount of code for specialized concepts (like subranges
or expression templates in Blitz++) each time we just need a small array.
Thus the header files providing array declarations (aff/array.h and the
files included therein) should be as sparse as possible. All extra
functionality like iterators (aff::Iterator presented in aff/iterator.h) or
slices (aff::Slice presented in aff/slice.h) should be external to the
aff::Array class. This allows us to load their definitions only where
needed. However, this approach requires that the internals of aff::Array are
exposed to the outside through appropriate functions (see "\ref
sec_design_interface_internals").
\subsection sec_design_interface_typedef Member typedefs
......@@ -254,8 +278,133 @@ See also "\ref sec_design_multidimensional".
need not modify all your shell scripts. Now consider one day your shape
class might be renamed...
\subsection sec_design_interface_internals Accessing internals
Providing extended functionality outside of aff::Array (see
"\ref sec_design_interface_sparse") requires, that aff::Array,
aff::ConstArray, aff::Series, and aff::ConstSeries expose some of their
internals. This concerns the underlying shape as well as the represented
data.
aff::ConstArray and aff::ConstSeries provide a read-only reference to the
data (i.e. an aff::ConstSharedHeap object) through their member-functions
aff::ConstArray::representation and
aff::ConstSeries::representation, respectively.
In the same way aff::Array and aff::Series return an aff::SharedHeap through
their representation member function.
All of them return a copy of their shape through the member functions
aff::Array::shape, aff::ConstArray::shape, aff::Series::shape, and
aff::ConstSeries::shape, respectively. The type of the appropriate shape is
available through a member typedef (
see "\ref sec_design_interface_typedef").
In return all containers provide a constructor that takes a representation
and a shape object and checks for their consistency.
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_replicated Replicated ConstSharedHeap base
\subsection sec_design_replicated_fact Design decision
aff::Array inherits from aff::SharedHeap (which is exposed to the outside
through aff::Array::representation), which itself inherits from
aff::ConstSharedHeap. At the same time aff::ConstArray is a base of
aff::Array and inherits itself from aff::ConstSharedHeap (which is exposed
to the outside through aff::ConstArray::representation). Thus the base class
aff::ConstSharedHeap is replicated in aff::Array and it is not declared a
virtual base class.
The same applies to aff::Series and aff::ConstSeries.
\subsection sec_design_replicated_problem Where is the problem?
Having an array object \c a declared
\code aff::Array<T> a; \endcode where \c T is any type, we want to pass this
object to a function that promises constness of the elements (see
"\ref sec_design_const"). The function is thus declared
\code void func(const aff::ConstArray<T>&); \endcode
and we want to use it like
\code func(a) \endcode
Consequently we must offer a way to convert an
\code aff::Array<T>& \endcode
to an
\code aff::ConstArray<T>& \endcode
implicitely.
This is done by deriving aff::Array<T> publicly from aff::ConstArray<T>.
The memory representation is needed by both, aff::Array<T> and its base
class. Hence aff::ConstArray<T> has to inherit from the representation. It
would be natural for aff::ConstArray<T> to inherit from aff::ConstSharedHeap
only. However, since the derived aff::Array<T> needs full access to an
aff::SharedHeap<T> (to expose the representation to the outside), we might
tend to derive aff::ConstArray<T> from aff::SharedHeap<T> privately,
allowing only read access and conversion to aff::ConstSharedHeap.
Why is this a problem?
Consider the inside of the above function. We might know, that the columns
of the passed array contain seismogram waveforms. And we might like to
access them in an appropriate way (i.e. through an interface that provides
waveform operations), though just reading - not modifying - the data. Then
we would like to code something like
\code
template<class T>
void func(const aff::ConstArray<T>& a)
{
// cycle all seismograms
for (Tsubscript iseis=a.f(1); iseis<=a.l(1); iseis++)
{
// extract shape
aff::Strided shape(a.shape());
// collapse to waveform iseis
shape.collapse(1,iseis);
// create a time series
aff::ConstSeries<T> waveform(a.representation(),
shape.size(), shape.first_offset());
// operate on time series (e.g. recursive filter)
some_waveform_operation(waveform);
}
}
\endcode
The above example requires that we can construct an aff::ConstSeries<T> from
an aff::ConstSharedHeap<T> (which is returned by
aff::ConstArray::representation). The same problem appears together with
aff::ConstArray, when creating a subarray or slice from an aff::ConstArray
with aff::Subarray or aff::Slice and aff::ConstArray itself knowing nothing
about slices, etc.
Constructing aff::ConstArray from an aff::ConstSharedHeap sounds a natural
operation. However, aff::ConstArray will ask for an aff::SharedHeap, if we
derive from aff::SharedHeap (as sketched above). Conclusion: aff::ConstArray
must inherit from aff::ConstSharedHeap only. At the same time we must hold
the full aff::SharedHeap together with the aff::Array object, since they must
return an aff::SharedHeap through aff::Array::representation to allow the
above operation (accessing data through aff::Series or constructing a
slice - see "\ref sec_design_interface_sparse").
\subsection sec_design_replicated_solution Solution
The most convincing solution (IMHO) to this problem is to derive
aff::Array<T> from aff::SharedHeap<T> additionally to aff::ConstArray<T>.
In consequence aff::ConstSharedHeap<T> is then a replicated base of
aff::Array<T>. For a proper design we might consider to make
aff::ConstSharedHeap a virtual base, thus avoiding member data duplication.
This would, however, introduce an extra level of indirection (additional to
the indirection when accessing the heap data through the pointer to the
aff::util::SHeap struct in aff::ConstSharedHeap). On the other hand, fully
replicating the base aff::ConstSharedHeap just adds one member data pointer
(the pointer to the aff::util::SHeap struct) to the data block in aff::Array
(which already contains many bytes from the aff::Strided base). This
overhead is not considered significant.
\b But \b notice: We now must take care to synchronize the aff::SharedHeap
base of aff::Array and the aff::ConstSharedHeap base of aff::ConstArray
during construction. This is no major concern, but it is error-prone to some
degree.
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_copy Copy constructor and copy operator
Usually we would expect the copy operator and the copy constructor to have
......@@ -299,6 +448,7 @@ See also "\ref sec_design_multidimensional".
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_namespaces Namespaces
We group all code in two namespaces. Major modules which will be accessed by
......@@ -316,6 +466,7 @@ See also "\ref sec_design_multidimensional".
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_binary Binary library
We provide a binary version of the library. It contains a set of prebuilt
......@@ -351,6 +502,7 @@ in the structure of header files and may be activated in the future.
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_multidimensional Multidimensional arrays
\todo
......@@ -358,6 +510,7 @@ in the structure of header files and may be activated in the future.
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_const Notes on the const-correctness of arrays
\subsection sec_design_const_problem Where is the problem?
......@@ -457,7 +610,7 @@ in the structure of header files and may be activated in the future.
Additionally both would offer name commonality for containers of non-const
elements and containers of const elements.
\par Using arrays with element type \c const \c T
\par Using arrays with element type const T
A rather straight approach is to use the element type \c const \c T
where an array of elements of type \c T should be used, that we do not allow
to be changed. This design concept can be accomplished with a special traits
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: README.changelog,v 1.24 2002-12-29 00:09:05 forbrig Exp $
* $Id: README.changelog,v 1.25 2002-12-29 16:57:27 forbrig Exp $
*
* Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
*
......@@ -21,12 +21,24 @@
/*! \page page_changelog ChangeLog (AFF)
$Id: README.changelog,v 1.24 2002-12-29 00:09:05 forbrig Exp $
$Id: README.changelog,v 1.25 2002-12-29 16:57:27 forbrig Exp $
\sa \ref page_project_status
Major changes in the interface of the library are marked by \b !!.
- \b 29/12/2002 (thof)
- aff::ConstArray and aff::ConstSeries now inherit from
aff::ConstSharedHeap. See "\ref sec_design_replicated".
- added section about sparse interface
(\ref sec_design_interface_sparse)
- added section about accessing internals
(\ref sec_design_interface_internals)
- \b !! reworked class aff::util::Subarray and introduced
aff::subarray
- \b !! reworked class aff::util::Slice and introduced
aff::slice
- \b 28/12/2002 (thof)
- \b !! Wolfgang pointed out a fundamental design error: Classes
aff::Array, aff::Series and aff::SharedHeap used a specialization of
......@@ -111,7 +123,7 @@
/*! \page page_project_status Project status (AFF)
$Id: README.changelog,v 1.24 2002-12-29 00:09:05 forbrig Exp $
$Id: README.changelog,v 1.25 2002-12-29 16:57:27 forbrig Exp $
\sa \ref page_changelog
......@@ -147,10 +159,10 @@
<TD>19/12/2002</TD><TD>20/12/2002</TD><TD> </TD><TD> </TD>
</TR>
<TR><TD>libaff/fortranshape.cc</TD>
<TD>23/12/02</TD><TD> </TD><TD> </TD><TD> </TD>
<TD>23/12/02</TD><TD> </TD><TD>23/12/02</TD><TD> </TD>
</TR>
<TR><TD>libaff/fortranshape.h</TD>
<TD>23/12/02</TD><TD> </TD><TD> </TD><TD> </TD>
<TD>23/12/02</TD><TD> </TD><TD>23/12/02</TD><TD> </TD>
</TR>
<TR><TD>libaff/iterator.h</TD>
<TD>20/12/2002</TD><TD> </TD><TD>23/12/02</TD><TD> </TD>
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: array_dec.h,v 1.17 2002-12-29 00:09:05 forbrig Exp $
* $Id: array_dec.h,v 1.18 2002-12-29 16:57:28 forbrig Exp $
* \author Thomas Forbriger
* \since 08/12/2002
*
......@@ -11,7 +11,7 @@
*
* \note
* This should never be included directly. Use array.h or binarray.h instead.
*
*
* Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
*
* REVISIONS and CHANGES
......@@ -39,6 +39,9 @@
* - 28/12/2002 V1.6 (thof)
* - changed base class from specialization to
* independent class template
* - 29/12/2002 V1.7 (thof)
* - ConstArray now inherits from ConstSharedHeap
* (see "\ref sec_design_replicated")
*
* ============================================================================
*/
......@@ -47,9 +50,9 @@
#ifndef AFF_ARRAY_DEC_H_VERSION
#define AFF_ARRAY_DEC_H_VERSION \
"AFF_ARRAY_DEC_H V1.6"
"AFF_ARRAY_DEC_H V1.7"
#define AFF_ARRAY_DEC_H_CVSID \
"$Id: array_dec.h,v 1.17 2002-12-29 00:09:05 forbrig Exp $"
"$Id: array_dec.h,v 1.18 2002-12-29 16:57:28 forbrig Exp $"
#include <aff/lib/sharedheap.h>
#include <aff/lib/strided.h>
......@@ -70,6 +73,7 @@ namespace prebuilt {
* \sa \ref sec_design_interface
* \sa \ref sec_design_const
* \sa \ref page_representation
* \sa \ref sec_design_replicated
* \sa aff::Strided
* \sa aff::SharedHeap
* \sa tests/arraytest.cc
......@@ -78,7 +82,7 @@ namespace prebuilt {
*/
template<class T>
class ConstArray:
private aff::Strided, private aff::SharedHeap<T>
private aff::Strided, private aff::ConstSharedHeap<T>
{
public:
/*! \name Various types
......@@ -98,8 +102,6 @@ namespace prebuilt {
*/
//@{
//! Type of representation
typedef aff::SharedHeap<T> Tmutable_representation;
//! Type of representation
typedef aff::ConstSharedHeap<T> Trepresentation;
//! Type of shape
typedef aff::Strided Tshape;
......@@ -140,7 +142,7 @@ namespace prebuilt {
ConstArray() { }
//! construct from shape and representation
ConstArray(const Tshape& shape,
const Tmutable_representation& representation);
const Trepresentation& representation);
//! construct from shape (defines size and layout)
explicit ConstArray(const Tshape& shape);
//! construct from index range limits
......@@ -267,36 +269,30 @@ namespace prebuilt {
//! full dimensionality access
T& operator()(const TIndexVec& index)
{ return(this->Tmutable_representation::operator[](
{ return(this->Trepresentation::operator[](
this->Tshape::offset(index))); }
//! access from 1 index value
T& operator()(const Tsubscript& i0)
{ return(this->Tmutable_representation::operator[](
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0))); }
//! access from 2 index values
T& operator()(const Tsubscript& i0,
const Tsubscript& i1)
{ return(this->Tmutable_representation::operator[](
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0, i1))); }
//! access from 3 index values
T& operator()(const Tsubscript& i0,
const Tsubscript& i1,
const Tsubscript& i2)
{ return(this->Tmutable_representation::operator[](
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0, i1, i2))); }
//! access from 4 index values
T& operator()(const Tsubscript& i0,
const Tsubscript& i1,
const Tsubscript& i2,
const Tsubscript& i3)
{ return(this->Tmutable_representation::operator[](
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0, i1, i2, i3))); }
/*-----------------------------------------------------------------*/
//! return full access representation
const Tmutable_representation& mutable_representation()
{ return (*this); }
//@}
}; // class ConstArray
......@@ -312,9 +308,22 @@ namespace prebuilt {
*
* \sa aff::ConstArray
* \sa \ref sec_design_const
* \sa \ref sec_design_replicated
*
* \todo
* Some of the constructors use too many temporaries to be really efficient.
*
* \todo
* Using data modification operators through the ConstArray base looks like
* improper design. This is done, because only the base knows about the
* shape. But the shape could be protected rather than private in the base
* class. On the other hand, implementing access operators here, would
* probably override access declaration, thus we would have to reimplement
* the const access operators too.
*/
template<class T>
class Array:
private aff::SharedHeap<T>,
public ConstArray<T>
{
public:
......@@ -331,7 +340,7 @@ namespace prebuilt {
//! Type of this array
typedef Array<T> Tcontainer;
//! base is container of const (see specialization below)
typedef ConstArray<T> Tbase;
typedef aff::ConstArray<T> Tbase;
//! Type of the array of const values
typedef Tbase Tcontainer_of_const;
/*! \brief short for Tcontainer_of_const
......@@ -356,9 +365,9 @@ namespace prebuilt {
*/
typedef Tbase Tcoc;
//! Type of representation
typedef SharedHeap<T> Trepresentation;
typedef aff::SharedHeap<T> Trepresentation;
//! Type of subscriptor
typedef Strided Tshape;
typedef aff::Strided Tshape;
//! Element type
typedef T Tvalue;
//! Type of pointer to element
......@@ -391,14 +400,13 @@ namespace prebuilt {
//! construct from shape and representation
Array(const Tshape& shape,
const Trepresentation& representation):
Trepresentation(representation),
Tbase(shape, representation) { }
//! construct from shape (defines size and layout)
explicit Array(const Tshape& shape):
Tbase(shape) { }
explicit Array(const Tshape& shape);
//! construct from index range limits
explicit Array(const Tsize& s0, const Tsize& s1=1,
const Tsize& s2=1, const Tsize& s3=1):
Tbase(s0, s1, s2, s3) { }
const Tsize& s2=1, const Tsize& s3=1);
//@}
/*-----------------------------------------------------------------*/
......@@ -458,7 +466,7 @@ namespace prebuilt {
//! return full access representation
const Trepresentation& representation()
{ return (this->Tbase::mutable_representation()); }
{ return (*this); }
private:
//! reimplement copy operator for base class to override access
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: array_def.h,v 1.13 2002-12-29 00:09:06 forbrig Exp $
* $Id: array_def.h,v 1.14 2002-12-29 16:57:28 forbrig Exp $
* \author Thomas Forbriger
* \since 08/12/2002
*
......@@ -50,7 +50,7 @@
#define AFF_ARRAY_DEF_H_VERSION \
"AFF_ARRAY_DEF_H V1.5"
#define AFF_ARRAY_DEF_H_CVSID \
"$Id: array_def.h,v 1.13 2002-12-29 00:09:06 forbrig Exp $"
"$Id: array_def.h,v 1.14 2002-12-29 16:57:28 forbrig Exp $"
#include<aff/lib/error.h>
#include<aff/lib/stridedstepper.h>
......@@ -82,8 +82,8 @@ namespace prebuilt {
size[2]=s2;
size[3]=s3;
this->Tshape::operator=(Tshape(size));
this->Tmutable_representation::operator=(
Tmutable_representation(this->Tshape::memory_size()));
this->Trepresentation::operator=(
Trepresentation(this->Tshape::memory_size()));
}
/*----------------------------------------------------------------------*/
......@@ -91,14 +91,14 @@ namespace prebuilt {
//! construct array from shape and representation
template<class T>
ConstArray<T>::ConstArray(const Tshape& shape,
const Tmutable_representation& representation)
const Trepresentation& representation)
{
AFF_assert((shape.first_offset()>=0),
"ERROR (Array): invalid shape in constructor");
AFF_assert((shape.last_offset()<Tsubscript(representation.size())),
"ERROR (Array): shape and representation are inconsistent");
this->Tshape::operator=(shape);
this->Tmutable_representation::operator=(representation);
this->Trepresentation::operator=(representation);
}
/*----------------------------------------------------------------------*/
......@@ -107,8 +107,8 @@ namespace prebuilt {
template<class T>
ConstArray<T>::ConstArray(const Tshape& shape): Tshape(shape)
{
this->Tmutable_representation::operator=(
Tmutable_representation(this->Tshape::memory_size()));
this->Trepresentation::operator=(
Trepresentation(this->Tshape::memory_size()));
}
/*----------------------------------------------------------------------*/
......@@ -119,7 +119,7 @@ namespace prebuilt {
{
aff::util::StridedStepper st(*this);
for(st.tofirst(); st.valid(); st.incr())
{ this->Tmutable_representation::operator[](st.current())=value; }
{ this->Trepresentation::operator[](st.current())=value; }
return(*this);
}
......@@ -138,7 +138,7 @@ namespace prebuilt {
stm.tofirst();
while (sta.valid() && stm.valid())
{
this->Tmutable_representation::operator[](stm.current())=
this->Trepresentation::operator[](stm.current())=
a.representation()[sta.current()];
stm.incr();
sta.incr();
......@@ -146,6 +146,37 @@ namespace prebuilt {
return(*this);
}
/*======================================================================*/
//! construct array from shape
template<class T>
Array<T>::Array(const Tshape& shape)
{
this->Trepresentation::operator=(
Trepresentation(shape.memory_size()));
this->Tbase::operator=(Tbase(shape, Trepresentation(*this)));
}
/*----------------------------------------------------------------------*/
//! construct array from given dimension sizes
template<class T>
Array<T>::Array(const Tsize& s0,
const Tsize& s1,
const Tsize& s2,
const Tsize& s3)
{
Tshape::TSizeVec size;
size[0]=s0;
size[1]=s1;
size[2]=s2;
size[3]=s3;
Tshape shape(size);
this->Trepresentation::operator=(
Trepresentation(shape.memory_size()));
this->Tbase::operator=(Tbase(shape, Trepresentation(*this)));
}
#ifdef AFF_PREBUILT
} // namespace prebuilt
#endif
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: series.h,v 1.7 2002-12-29 00:09:06 forbrig Exp $
* $Id: series.h,v 1.8 2002-12-29 16:57:28 forbrig Exp $
* \author Thomas Forbriger
* \date 17/12/2002
*
......@@ -22,6 +22,9 @@
* independent class template
* - transformed conversion operator into memeber
* function representation()
* - 29/12/2002 V1.3 (thof)
* - ConstSeries now inherits from ConstSharedHeap
* (see "\ref sec_design_replicated")
*
* ============================================================================
*/
......@@ -30,9 +33,9 @@
#ifndef AFF_SERIES_H_VERSION
#define AFF_SERIES_H_VERSION \
"AFF_SERIES_H V1.2"
"AFF_SERIES_H V1.3"
#define AFF_SERIES_H_CVSID \
"$Id: series.h,v 1.7 2002-12-29 00:09:06 forbrig Exp $"
"$Id: series.h,v 1.8 2002-12-29 16:57:28 forbrig Exp $"
#include<aff/lib/sharedheap.h>
#include<aff/lib/error.h>
......@@ -78,10 +81,17 @@ namespace aff {
/*======================================================================*/
/*! \brief base class
*
* \sa \ref sec_design_interface
* \sa \ref sec_design_const
* \sa \ref page_representation
* \sa \ref sec_design_replicated
* \sa aff::LinearShape
* \sa aff::SharedHeap
*/
template<class T>
class ConstSeries:
private aff::LinearShape, private aff::SharedHeap<T>
private aff::LinearShape, private aff::ConstSharedHeap<T>
{
public:
/*! \name Various types
......@@ -94,8 +104,6 @@ namespace aff {
*/
//@{
//! Type of representation
typedef aff::SharedHeap<T> Tmutable_representation;
//! Type of representation
typedef aff::ConstSharedHeap<T> Trepresentation;
//! Type of shape
typedef aff::LinearShape Tshape;
......@@ -146,11 +154,15 @@ namespace aff {
//! construct from nothing (empty)
ConstSeries(): Tshape(), Trepresentation(this->Tshape::size()) { }
//! construct from shape and representation
ConstSeries(const Tshape& shape,