Commit 97c9767b authored by thomas.forbriger's avatar thomas.forbriger Committed by thomas.forbriger
Browse files

some many improvements... :-)

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: 1245
SVN UUID:     67feda4a-a26e-11df-9d6e-31afc202ad0c
parent bda2450b
# this is <Makefile>
# ----------------------------------------------------------------------------
# $Id: Makefile,v 1.15 2002-12-29 00:09:05 forbrig Exp $
# $Id: Makefile,v 1.16 2002-12-29 23:02:15 forbrig Exp $
#
# Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
#
......@@ -319,4 +319,12 @@ tests/%.run: tests/%
$< $(ARG)
/bin/rm -fv $< $<.o
# after each modification to the library this target should be used
compile-tests: \
tests/shapetest.run \
tests/reprtest.run \
tests/arraytest.run \
tests/helpertest.run \
tests/f77test.run
# ----- END OF Makefile -----
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: README,v 1.15 2002-12-29 16:57:27 forbrig Exp $
* $Id: README,v 1.16 2002-12-29 23:02:15 forbrig Exp $
*
* Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
*
......@@ -37,6 +37,9 @@
* (\ref sec_design_interface_sparse)
* - added section about accessing internals
* (\ref sec_design_interface_internals)
* - reflect changes to Subarray and Slice
* - tell about class hierarchies and member data vs.
* inheritance
*
* ============================================================================
*/
......@@ -62,7 +65,7 @@ namespace aff {
\since December 2002
\date December 2002
\version V1.0
$Id: README,v 1.15 2002-12-29 16:57:27 forbrig Exp $
$Id: README,v 1.16 2002-12-29 23:02:15 forbrig Exp $
Contents of this page:
- \ref sec_main_aims
......@@ -147,10 +150,10 @@ $Id: README,v 1.15 2002-12-29 16:57:27 forbrig Exp $
-# aff::Range presented in aff/lib/range.h which is usefull where ever you
need to deal with numerical ranges (calculate with them, find
the smallest in a set, etc.).
-# aff::Subarray presented in aff/subarray.h to conveniently create
-# aff::subarray presented in aff/subarray.h to conveniently create
subarrays from aff::Array objects (see example
tests/helpertest.cc).
-# aff::Slice presented in aff/slice.h to conveniently create
-# aff::slice presented in aff/slice.h to conveniently create
slices from aff::Array objects (see example
tests/helpertest.cc).
-# aff::FortranArray and its associate aff::util::FortranShape are presented
......@@ -198,12 +201,23 @@ See also "\ref sec_design_multidimensional".
Contents of this page:
- \ref sec_design_interface
- \ref sec_design_interface_sparse
- \ref sec_design_interface_typedef
- \ref sec_design_interface_internals
- \ref sec_design_hierarchy
- \ref sec_design_replicated
- \ref sec_design_replicated_fact
- \ref sec_design_replicated_problem
- \ref sec_design_replicated_solution
- \ref sec_design_copy
- \ref sec_design_namespaces
- \ref sec_design_binary
- \ref sec_design_multidimensional
- \ref sec_design_const
- \ref sec_design_const_problem
- \ref sec_design_const_approach
- \ref sec_design_const_alternatives
- \ref sec_design_const_general
\section sec_design_interface Common interface concepts
......@@ -305,16 +319,54 @@ See also "\ref sec_design_multidimensional".
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_replicated Replicated ConstSharedHeap base
\section sec_design_hierarchy Class hierarchy: member data vs. inheritance
Containers like aff::Array rely on functionality provided by other classes.
They are shapes like aff::Strided and memory representations like
aff::SharedHeap (see "\ref page_representation").
\par An array isn't a shape.
Thus it would look like better design to use shapes as member data.
We prefer, \b however, to derive privately from the shape classes.
This hides them from the outside (apart from explicit access -
see "\ref sec_design_interface_internals").
At the same time we make use of using declarations to provide access to
member functions like aff::Strided::size() that make also sense as a member
of aff::Array.
\par An array is some kind of memory representation.
Thus it would look like proper design to derive an array from a
representation class.
We prefer, \b however, to use the memory representation as a private
member.
We think of the representation as an individual and independent object
that can be passed (e.g.) from an aff::Array to and aff::Series.
Also due to the replication of the representation in aff::Array
(see "\ref sec_design_replicated") and the distinction between containers
that allow data modification and containers that allow only read access
this leads to a clearer design.
This is reflected by the conciseness of the array constructors.
Use the representation class as member data should introduce no runtime
overhead.
The full class specification including member data is available at
compile-time.
This should enable compilers to do excessive inlining.
/*----------------------------------------------------------------------*/
<HR>
\section sec_design_replicated Replicated ConstSharedHeap
\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.
aff::Array has a member of type aff::SharedHeap (which is exposed to the
outside through aff::Array::representation), which itself inherits from
aff::ConstSharedHeap.
At the same time aff::ConstArray has a member of type aff::Array and
inherits itself from aff::ConstSharedHeap (which is exposed to the outside
through aff::ConstArray::representation).
Thus the class aff::ConstSharedHeap is replicated in aff::Array and it
is not replicated by deriving from virtual base classes a virtual base
class.
The same applies to aff::Series and aff::ConstSeries.
......@@ -377,16 +429,17 @@ See also "\ref sec_design_multidimensional".
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
must use an aff::ConstSharedHeap only. At the same time we must hold
the full aff::SharedHeap together with the aff::Array object, since this 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
The most convincing solution (IMHO) to this problem is to use an
(additional) member of type aff::SharedHeap<T> in aff::Array<T> which
derives aff::ConstArray<T>.
In consequence aff::ConstSharedHeap<T> is then a replicated within
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
......@@ -400,7 +453,8 @@ See also "\ref sec_design_multidimensional".
\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.
degree. It is, however, much easier to keep them synchronous when using
member data instead if inheritance.
/*----------------------------------------------------------------------*/
......@@ -441,6 +495,8 @@ See also "\ref sec_design_multidimensional".
\par Design decision
The classes aff::Array and aff::Series provide copy (assignment) operators
with shallow copy semantics.
The automatically created copy constructor and copy operator do just right
for this.
This is sensible, because we are not offering mathematical array operations.
This operations may be delegated to a wrapper class in the future, which
then also may provide expression templates and an appropriate assignment
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: README.changelog,v 1.26 2002-12-29 17:00:36 forbrig Exp $
* $Id: README.changelog,v 1.27 2002-12-29 23:02:15 forbrig Exp $
*
* Copyright (c) 2002 by Thomas Forbriger (IMG Frankfurt)
*
......@@ -21,7 +21,7 @@
/*! \page page_changelog ChangeLog (AFF)
$Id: README.changelog,v 1.26 2002-12-29 17:00:36 forbrig Exp $
$Id: README.changelog,v 1.27 2002-12-29 23:02:15 forbrig Exp $
\sa \ref page_project_status
......@@ -38,6 +38,20 @@
aff::subarray
- \b !! reworked class aff::util::Slice and introduced
aff::slice
- use "using" syntax for access declarations
- overloaded, protected versions of write-access operators lead to
conflicts in derived classes. Resolved that conflicts and made shared
heap objects data members in container classes.
- aff::Strided now provides Fortran style constructor
- reworked array classes to use shared heap member data and correct set of
access operators - looks much more natural now
- explain concept of member data representation
(\ref sec_design_hierarchy)
- reworked series classes in the same way as array classes
- introduced lib/deepcopy.h
- factored out common code in copyin functions to aff::util::deepcopy
- now and aff::Array should be able to copy in the values of an
aff::Series
- \b 28/12/2002 (thof)
- \b !! Wolfgang pointed out a fundamental design error: Classes
......@@ -123,7 +137,7 @@
/*! \page page_project_status Project status (AFF)
$Id: README.changelog,v 1.26 2002-12-29 17:00:36 forbrig Exp $
$Id: README.changelog,v 1.27 2002-12-29 23:02:15 forbrig Exp $
\sa \ref page_changelog
......@@ -166,8 +180,7 @@
</TR>
<TR><TD>libaff/iterator.h</TD>
<TD>20/12/2002</TD><TD> </TD><TD>23/12/02</TD>
<TD>does not work with ConstArray due to wrong resolution of access
operator in ConstSharedHeap </TD>
<TD> </TD>
</TR>
<TR><TD>libaff/series.h</TD>
<TD>17/12/02</TD><TD> </TD><TD> </TD><TD> </TD>
......@@ -188,6 +201,9 @@
<TR><TD>libaff/lib/README</TD>
<TD>has no code</TD><TD>20/12/02</TD><TD>has no code</TD><TD> </TD>
</TR>
<TR><TD>libaff/lib/deepcopy.h</TD>
<TD>29/12/02</TD><TD>29/12/2002</TD><TD>29/12/02</TD><TD> </TD>
</TR>
<TR><TD>libaff/lib/error.cc</TD>
<TD>16/12/02</TD><TD>20/12/2002</TD><TD>18/12/02</TD><TD> </TD>
</TR>
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: array_dec.h,v 1.18 2002-12-29 16:57:28 forbrig Exp $
* $Id: array_dec.h,v 1.19 2002-12-29 23:02:15 forbrig Exp $
* \author Thomas Forbriger
* \since 08/12/2002
*
......@@ -42,6 +42,13 @@
* - 29/12/2002 V1.7 (thof)
* - ConstArray now inherits from ConstSharedHeap
* (see "\ref sec_design_replicated")
* - use "using" syntax for access declarations
* - arrays do no longer derive from shared heap
* classes
* - reworked shared heap access concept fundamentally;
* code looks much simpler now
* - member template must be defined here
* - factored out copyin code
*
* ============================================================================
*/
......@@ -52,10 +59,12 @@
#define AFF_ARRAY_DEC_H_VERSION \
"AFF_ARRAY_DEC_H V1.7"
#define AFF_ARRAY_DEC_H_CVSID \
"$Id: array_dec.h,v 1.18 2002-12-29 16:57:28 forbrig Exp $"
"$Id: array_dec.h,v 1.19 2002-12-29 23:02:15 forbrig Exp $"
#include <aff/lib/sharedheap.h>
#include <aff/lib/strided.h>
#include <aff/lib/stridedstepper.h>
#include <aff/lib/deepcopy.h>
namespace aff {
......@@ -82,7 +91,7 @@ namespace prebuilt {
*/
template<class T>
class ConstArray:
private aff::Strided, private aff::ConstSharedHeap<T>
private aff::Strided
{
public:
/*! \name Various types
......@@ -142,12 +151,19 @@ namespace prebuilt {
ConstArray() { }
//! construct from shape and representation
ConstArray(const Tshape& shape,
const Trepresentation& representation);
const Trepresentation& representation):
Tshape(shape), Mrepresentation(representation)
{ check_consistency(); }
//! construct from shape (defines size and layout)
explicit ConstArray(const Tshape& shape);
//! construct from index range limits
explicit ConstArray(const Tshape& shape):
Tshape(shape.first(),shape.last()),
Mrepresentation(this->Tshape::memory_size())
{ check_consistency(); }
//! construct from dimension sizes
explicit ConstArray(const Tsize& s0, const Tsize& s1=1,
const Tsize& s2=1, const Tsize& s3=1);
const Tsize& s2=1, const Tsize& s3=1):
Tshape(s0, s1, s2, s3),
Mrepresentation(this->Tshape::memory_size()) { }
//@}
/*-----------------------------------------------------------------*/
......@@ -163,30 +179,25 @@ namespace prebuilt {
//@{
//! full dimensionality access
const T& operator()(const TIndexVec& index) const
{ return(this->Trepresentation::operator[](
this->Tshape::offset(index))); }
{ return(Mrepresentation[offset(index)]); }
//! access from 1 index value
const T& operator()(const Tsubscript& i0) const
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0))); }
{ return(Mrepresentation[offset(i0)]); }
//! access from 2 index values
const T& operator()(const Tsubscript& i0,
const Tsubscript& i1) const
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0, i1))); }
{ return(Mrepresentation[offset(i0, i1)]); }
//! access from 3 index values
const T& operator()(const Tsubscript& i0,
const Tsubscript& i1,
const Tsubscript& i2) const
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0, i1, i2))); }
{ return(Mrepresentation[offset(i0, i1, i2)]); }
//! access from 4 index values
const T& operator()(const Tsubscript& i0,
const Tsubscript& i1,
const Tsubscript& i2,
const Tsubscript& i3) const
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0, i1, i2, i3))); }
{ return(Mrepresentation[offset(i0, i1, i2, i3)]); }
//@}
/*-----------------------------------------------------------------*/
......@@ -220,19 +231,14 @@ namespace prebuilt {
* affect elements of \c A, this not the case for changes applied to
* \c B.
*/
Tcontainer copyout() const
{
ConstArray copy(Tshape(this->first(),this->last()));
copy.copyin(*this);
return(copy);
}
Tcontainer copyout() const;
//! \name access declarations
//@{
//! access to base class function
Tshape::first;
Tshape::last;
Tshape::size;
using Tshape::first;
using Tshape::last;
using Tshape::size;
//@}
//! provide access to const shape
......@@ -241,59 +247,18 @@ namespace prebuilt {
//! provide restricted access representation
const Trepresentation& representation() const
{ return (*this); }
{ return (Mrepresentation); }
/*-----------------------------------------------------------------*/
// here starts the PROTECTED section!
// ----------------------------------
protected:
/*! \name Data modifying operators and functions
*
* Only this base class derives directly from the representation
* class. Accessing the represenation directly from the non-const
* aff::Array would violate code encapsulation. Thus we provide these
* operators here and make them accessible in aff::Array through
* access declarations.
*/
//@{
//! copy values (deep copy) from other array of convertible type
template<class TT>
Tcontainer& copyin(const ConstArray<TT>& a);
/*-----------------------------------------------------------------*/
//! provide access to shape offset functions for derived class
using Tshape::offset;
//! set whole array to value
Tcontainer& operator=(const T& value);
/*-----------------------------------------------------------------*/
//! full dimensionality access
T& operator()(const TIndexVec& index)
{ return(this->Trepresentation::operator[](
this->Tshape::offset(index))); }
//! access from 1 index value
T& operator()(const Tsubscript& i0)
{ return(this->Trepresentation::operator[](
this->Tshape::offset(i0))); }
//! access from 2 index values
T& operator()(const Tsubscript& i0,
const Tsubscript& i1)
{ 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->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->Trepresentation::operator[](
this->Tshape::offset(i0, i1, i2, i3))); }
//@}
private:
//! check consitency between representation and shape
void check_consistency() const;
//! representation member
Trepresentation Mrepresentation;
}; // class ConstArray
......@@ -309,21 +274,9 @@ 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:
......@@ -396,17 +349,27 @@ namespace prebuilt {
*/
//@{
//! construct from nothing (empty)
Array(): Tbase() { }
Array() { }
//! construct from shape and representation
Array(const Tshape& shape,
const Trepresentation& representation):
Trepresentation(representation),
Tbase(shape, representation) { }
Tbase(shape, representation),
Mrepresentation(representation) { }
//! construct from shape (defines size and layout)
explicit Array(const Tshape& shape);
//! construct from index range limits
explicit Array(const Tshape& shape)
{
Tshape newshape(shape.first(), shape.last());
Mrepresentation=Trepresentation(newshape.memory_size());
this->Tbase::operator=(Tbase(newshape, Mrepresentation));
}
//! construct from dimension sizes
explicit Array(const Tsize& s0, const Tsize& s1=1,
const Tsize& s2=1, const Tsize& s3=1);
const Tsize& s2=1, const Tsize& s3=1)
{
Tshape newshape(s0, s1, s2, s3);
Mrepresentation=Trepresentation(newshape.memory_size());
this->Tbase::operator=(Tbase(newshape, Mrepresentation));
}
//@}
/*-----------------------------------------------------------------*/
......@@ -414,17 +377,9 @@ namespace prebuilt {
//! \name access declarations
//@{
//! access to base class function
Tbase::operator();
Tbase::operator=;
Tbase::shape;
using Tbase::operator();
using Tbase::shape;
//@}
//! set whole array to value
Array& operator=(const T& value)
{
this->Tbase::operator=(value);
return(*this);
}
/*! \brief copy values (deep copy) from other array of convertible type
*
......@@ -445,38 +400,65 @@ namespace prebuilt {
* \c A (which are not where interesting in this example). Changes
* applied to the contents of B will not affect the contents of A.
*
* \param a other array with element type convertible to element type
* of this array
* \param a other container with element type convertible to element
* type of this array and appropriate stepper class
* \return itself
*/
template<class TT>
Array& copyin(const ConstArray<TT>& a)
template<class C>
Array& copyin(const C& a)
{
this->Tbase::copyin(a);
aff::util::deepcopy(a, *this);
return(*this);
}
//! create a copy of this array
Tcontainer copyout() const
{
Array copy(Tshape(this->first(),this->last()));
Tcontainer copy(Tshape(this->first(),this->last()));
copy.copyin(*this);
return(copy);
}
//! return full access representation
const Trepresentation& representation()
{ return (*this); }
{ return (Mrepresentation); }
/*-----------------------------------------------------------------*/
//! set whole array to value
Tcontainer& operator=(const T& value);
/*-----------------------------------------------------------------*/
//! full dimensionality access
T& operator()(const TIndexVec& index)
{ return(Mrepresentation[this->Tbase::offset(index)]); }
//! access from 1 index value
T& operator()(const Tsubscript& i0)
{ return(Mrepresentation[this->Tbase::offset(i0)]); }
//! access from 2 index values
T& operator()(const Tsubscript& i0,
const Tsubscript& i1)
{ return(Mrepresentation[this->Tbase::offset(i0, i1)]); }
//! access from 3 index values
T& operator()(const Tsubscript& i0,
const Tsubscript& i1,
const Tsubscript& i2)
{ return(Mrepresentation[this->Tbase::offset(i0, i1, i2)]); }
//! access from 4 index values
T& operator()(const Tsubscript& i0,
const Tsubscript& i1,
const Tsubscript& i2,
const Tsubscript& i3)
{ return(Mrepresentation[this->Tbase::offset(i0, i1, i2, i3)]); }
private:
//! reimplement copy operator for base class to override access
//! declaration
Tcontainer& operator=(const Tcoc& array)
{ AFF_abort("illegal call"); return(*this); }
//! my (mutable) data representation
Trepresentation Mrepresentation;
}; // class Array
/*======================================================================*/
/*----------------------------------------------------------------------*/
#ifdef AFF_PREBUILT
} // namespace prebuilt
......
......@@ -3,7 +3,7 @@
*
* ----------------------------------------------------------------------------
*
* $Id: array_def.h,v 1.14 2002-12-29 16:57:28 forbrig Exp $
* $Id: array_def.h,v 1.15 2002-12-29 23:02:15 forbrig Exp $
* \author Thomas Forbriger
* \since 08/12/2002
*
......@@ -36,6 +36,11 @@
* - 28/12/2002 V1.5 (thof)
* - changed base class from specialization to
* independent class template
* - 29/12/2002 V1.6 (thof)
* - due to clearer concept of representation access
* constructors became more simple and are defined in
* declaration - only copy operations remain here
* - member template cannot be explicitely instantiated
*
* ============================================================================
*/
......@@ -48,12 +53,11 @@
#ifndef AFF_ARRAY_DEF_H_VERSION
#define AFF_ARRAY_DEF_H_VERSION \
"AFF_ARRAY_DEF_H V1.5"
"AFF_ARRAY_DEF_H V1.6"
#define AFF_ARRAY_DEF_H_CVSID \
"$Id: array_def.h,v 1.14 2002-12-29 16:57:28 forbrig Exp $"
"$Id: array_def.h,v 1.15 2002-12-29 23:02:15 forbrig Exp $"
#include<aff/lib/error.h>