Changed arrays to use vector/tockArrayView

Previously the arrays used the Blitz++ library, but this was not totally satisfactory.  I have therefore resorted (after looking at many different
libraries) to using std::vector (which could perhaps be boost::array instead) coupled with a roll-my-own "array view" class (tockArrayView) that
easily allows all the functionality that we need from arrays (slicing, indexing, copying, unknown dimensions,retyping,reshaping).  I have also
had to introduce a nasty little wrapper class tockBool, because vector<bool> is a specialisation that totally breaks things.  If I do move to
boost::array, I will be able to remove tockBool.
This commit is contained in:
Neil Brown 2007-07-31 21:19:52 +00:00
parent f997b823dc
commit a52d115060
2 changed files with 369 additions and 178 deletions

View File

@ -200,7 +200,7 @@ genInputSizeAssign :: A.InputItem -> CGen()
genInputSizeAssign (A.InVariable _ arr)
= return ()
genInputSizeAssign (A.InCounted _ count arr)
= genVariable count >> tell [" = "] >> genVariable arr >> tell [" .extent(blitz::firstDim);"]
= genVariable count >> tell [" = "] >> genVariable arr >> tell [" .extent(0);"]
--Generates the long boost::tie expression that will be used to get all the data out of a tuple that we have read
genInputTupleAssign :: Bool -> String -> [A.InputItem] -> CGen()
@ -338,22 +338,26 @@ genInputItem c (A.InCounted m cv av)
genVariable cv
tell [" = "]
genVariable av
tell [" .extent(blitz::firstDim); "]
tell [" .extent(0); "]
genInputItem c (A.InVariable m v)
= do genVariable c
tell ["->reader() >> "]
genVariable v
tell [";\n"]
--If we are sending an array, we use the versionToSend function to coerce away any annoying const tags on the array data:
genJustOutputItem :: A.OutputItem -> CGen()
genJustOutputItem (A.OutCounted m ce ae)
= do genJustOutputItem (A.OutExpression m ae)
tell[" (blitz::Range(0,"]
= do genExpression ae
tell[" .sliceFor("]
genExpression ce
tell[" - 1)) .copy() "]
--TODO fill the rest of the dimensions with blitz::Range::all()
tell[") .versionToSend() "]
genJustOutputItem (A.OutExpression m e)
= genExpression e
= do t <- typeOfExpression e
genExpression e
case t of
(A.Array _ _) -> tell [" .versionToSend() "]
_ -> return ()
genOutputItem :: A.Variable -> A.OutputItem -> CGen ()
genOutputItem chan item
@ -534,22 +538,47 @@ genProcCall n as
tell [");"]
--Changed from CIF's untyped channels to C++CSP's typed (templated) channels:
--Changed from CIF's untyped channels to C++CSP's typed (templated) channels, and changed the declaration type of an array to be a vector:
declareType :: A.Type -> CGen ()
declareType (A.Array ds t)
= do tell [" std::vector< "]
genType t
tell ["/**/>/**/"]
declareType (A.Counted countType valueType)
= do tell [" std::vector< "]
case valueType of
--Don't nest when it's a counted array of arrays:
(A.Array _ t) -> genType t
_ -> genType valueType
tell ["/**/>/**/"]
declareType (A.Chan t)
= do tell [" csp::One2OneChannel < "]
genType t
tell [" > "]
tell ["/**/>/**/ "]
declareType t = genType t
--Removed the channel part from GenerateC (not necessary in C++CSP, I think), and also changed the arrays:
--An array is actually stored as a std::vector, but an array-view object is automatically created with the array
--The vector has the suffix _actual, whereas the array-view is what is actually used in place of the array
--I think it may be possible to use boost::array instead of std::vector (which would be more efficient),
--but I will worry about that later
genDeclaration :: A.Type -> A.Name -> CGen ()
genDeclaration arrType@(A.Array ds t) n
= do declareType arrType
tell [" "]
genName n
genArraySize ds
tell [";\n"]
tell ["_actual ("]
genFlatArraySize ds
tell ["); "]
genType arrType
tell [" "]
genName n;
tell ["("]
genName n
tell ["_actual,tockDims("]
genDims ds
tell ["));\n"]
genDeclaration t n
= do declareType t
tell [" "]
@ -564,7 +593,7 @@ declareInit m t@(A.Array ds t') var
return (\sub -> Just $ do genVariable (sub var)
tell [" = new "]
declareType t'
tell ["();\n"]
tell [";\n"]
doMaybe $ declareInit m t' (sub var))
_ -> return (\sub -> declareInit m t' (sub var))
@ -646,15 +675,6 @@ abbrevExpression am t@(A.Array _ _) e
bad = missing "array expression abbreviation"
abbrevExpression am _ e = genExpression e
--Uses the Blitz library for giving array dimensions -- hence the round brackets, which actually are part of a constructor call
genArraySize :: [A.Dimension] -> CGen ()
genArraySize ds
= do tell ["( blitz::shape("]
sequence $ intersperse (tell [" , "])
[case d of A.Dimension n -> tell [show n] | d <- ds]
tell [") )"]
--Used to create boost::variant and boost::tuple types. Both these classes can have a maximum of nine items
--so if there are more than nine items, we must have variants containing variants, or tuples containing tuples
createChainedType :: String -> CGen() -> [CGen()] -> CGen ()
@ -686,8 +706,18 @@ tupleExpression useBrackets tupleType items
(firstNine,rest) = splitAt 9 items
--Takes a list of dimensions and outputs a comma-seperated list of the numerical values
--Unknown dimensions have value 0 (which is treated specially by the tockArrayView class)
genDims:: [A.Dimension] -> CGen()
genDims dims = infixComma $ map genDim dims
where
genDim :: A.Dimension -> CGen()
genDim (A.Dimension n) = tell [show n]
genDim (A.UnknownDimension) = tell ["0"]
--Generates an expression that yields the number of total elements in a declared multi-dimensional array
--Using it on arrays with unknown dimensions will cause an error (they should only be abbreviations, not declared as actual variables)
genFlatArraySize:: [A.Dimension] -> CGen()
genFlatArraySize dims = sequence_ $ intersperse (tell ["*"]) $ map genDim dims
where
genDim :: A.Dimension -> CGen()
genDim (A.Dimension n) = tell [show n]
@ -749,15 +779,15 @@ introduceSpec (A.Specification _ n (A.IsExpr _ am t e))
tell [" ",tmp, " [] = "]
rhs
tell [" ; "]
tell ["const tockArray< "]
tell ["const tockArrayView< const "]
genType ts
tell [" , ",show (length dims)," > "]
tell [" , ",show (length dims)," /**/>/**/ "]
genName n
tell ["(("]
genType ts
tell [" *)",tmp,",blitz::shape("]
tell [" *)",tmp,",tockDims("]
genDims dims
tell ["),blitz::duplicateData);\n"]
tell ["));\n"]
(A.ValAbbrev, A.Record _, A.Literal _ _ _) ->
-- Record literals are even trickier, because there's no way of
-- directly writing a struct literal in C that you can use -> on.
@ -774,19 +804,15 @@ introduceSpec (A.Specification _ n (A.IsExpr _ am t e))
tell [" = "]
rhs
tell [";\n"]
--TODO check this clause is ok
--We must create the channel array then fill it:
introduceSpec (A.Specification _ n (A.IsChannelArray _ t cs))
= do --tell ["tockArray< csp::One2OneChannel< "]
genType t
--tell [" > * , 1 > "]
tell [" "]
genName n
tell ["(blitz::shape(",show (length cs),"));"]
= do genDeclaration t n
sequence_ $ map genChanArrayElemInit (zip [0 .. ((length cs) - 1)] cs)
where
genChanArrayElemInit (index,var)
= do genName n
tell ["(",show index,") = "]
tell ["[",show index,"].access() = "] --Use the .access() function to cast a 0-dimension array into a T& for access
genVariable var
tell [";"]
--This clause is unchanged from GenerateC:
@ -817,15 +843,25 @@ introduceSpec (A.Specification _ n (A.ProtocolCase _ caseList))
typedef_genCaseType n (tag, typeList)
= createChainedType "boost::tuple" (genTupleProtocolTagName n tag) ((genProtocolTagName n tag) : (map genType typeList))
--TODO check this clause
--Clause changed to handle array retyping
introduceSpec (A.Specification _ n (A.Retypes m am t v))
= do origT <- typeOfVariable v
let rhs = abbrevVariable A.Abbrev origT v
genDecl am t n
tell [" = "]
case t of
(A.Array dims _) ->
--Arrays need to be handled differently because we need to feed the sizes in, not just perform a straight cast
do genDeclType am t
tell ["("]
rhs
tell [",tockDims("]
genDims dims
tell ["));"]
_ ->
-- For scalar types that are VAL abbreviations (e.g. VAL INT64),
-- we need to dereference the pointer that abbrevVariable gives us.
let deref = case (am, t) of
do let deref = case (am, t) of
(_, A.Array _ _) -> False
(_, A.Chan _) -> False
(A.ValAbbrev, _) -> True
@ -834,11 +870,13 @@ introduceSpec (A.Specification _ n (A.Retypes m am t v))
tell ["("]
genDeclType am t
when deref $ tell [" *"]
tell [") "]
tell [") ("]
rhs
tell [";\n"]
--TODO work out what this does
-- genRetypeSizes m am t n origT v
case origT of
--We must be retyping from an array, but not to an array (so to a primitive type or something):
(A.Array _ _) -> tell [".data()"]
_ -> return ()
tell [");\n"]
--This clause is unchanged from GenerateC:
introduceSpec n = missing $ "introduceSpec " ++ show n
@ -851,10 +889,10 @@ genExpression (A.MostPos m t) = genTypeSymbol "mostpos" t
genExpression (A.MostNeg m t) = genTypeSymbol "mostneg" t
genExpression (A.SizeExpr m e)
= do genExpression e
tell [" .extent(blitz::firstDim) "]
tell [" .extent(0) "]
genExpression (A.SizeVariable m v)
= do genVariable v
tell [" .extent(blitz::firstDim)"]
tell [" .extent(0)"]
genExpression (A.Conversion m cm t e) = genConversion m cm t e
genExpression (A.ExprVariable m v) = genVariable v
genExpression (A.Literal _ _ lr) = genLiteral lr
@ -875,8 +913,9 @@ genExpression t = missing $ "genExpression " ++ show t
-- | If a type maps to a simple C type, return Just that; else return Nothing.
--Changed from GenerateC to change the A.Timer type to use C++CSP time
--Also changed the bool type, because vector<bool> in C++ is odd, so we hide it from the compiler:
scalarType :: A.Type -> Maybe String
scalarType A.Bool = Just "bool"
scalarType A.Bool = Just "tockBool"
scalarType A.Byte = Just "uint8_t"
scalarType A.Int = Just "int"
scalarType A.Int16 = Just "int16_t"
@ -888,19 +927,20 @@ scalarType A.Timer = Just "csp::Time"
scalarType _ = Nothing
--Generates an array type, giving the Blitz++ array the correct dimensions
genArrayType :: A.Type -> Int -> CGen ()
genArrayType (A.Array dims t) rank
= genArrayType t (rank + (max 1 (length dims)))
genArrayType t rank
= do tell [" tockArray< "]
genArrayType :: Bool -> A.Type -> Int -> CGen ()
genArrayType const (A.Array dims t) rank
= genArrayType const t (rank + (max 1 (length dims)))
genArrayType const t rank
= do tell [" tockArrayView< "]
when (const) (tell [" const "])
genType t
tell [" , ",show rank, " > "]
tell [" , ",show rank, " > /**/"]
--Changed from GenerateC to change the arrays and the channels
--Also changed to add counted arrays and user protocols
genType :: A.Type -> CGen ()
genType arr@(A.Array _ _)
= genArrayType arr 0
= genArrayType False arr 0
genType (A.Record n) = genName n
genType (A.UserProtocol n) = genProtocolName n
genType (A.Chan t)
@ -908,7 +948,7 @@ genType (A.Chan t)
genType t
tell [" > * "]
genType (A.Counted countType valueType)
= genType (A.Array [] valueType)
= genType (A.Array [A.UnknownDimension] valueType)
genType (A.Any)
= tell [" tockAny "]
-- Any -- not used
@ -963,13 +1003,11 @@ genSlice _ v ty start count ds
-- We need to disable the index check here because we might be taking
-- element 0 of a 0-length array -- which is valid.
= do genVariableUnchecked v
tell ["(blitz::Range("]
tell [".sliceFromFor("]
genExpression start
tell [" , "]
genExpression start
tell [" + "]
genExpression count
tell [" ))"]
tell [")"]
--Removed the sizing and the & from GenerateC:
@ -982,9 +1020,7 @@ genArraySubscript :: Bool -> A.Variable -> [A.Expression] -> CGen ()
genArraySubscript checkValid v es
= do t <- typeOfVariable v
let numDims = case t of A.Array ds _ -> length ds
tell ["("]
sequence_ $ intersperse (tell [" , "]) $ genPlainSub v es [0..(numDims - 1)]
tell [")"]
sequence_ $ genPlainSub v es [0..(numDims - 1)]
where
-- | Generate the individual offsets that need adding together to find the
-- right place in the array.
@ -992,14 +1028,14 @@ genArraySubscript checkValid v es
-- smart C compiler should be able to work it out...
--Subtly changed this function so that empty dimensions have blitz::Range::all() in the C++ version:
--TODO doc
genPlainSub :: A.Variable -> [A.Expression] -> [Int] -> [CGen ()]
genPlainSub _ _ [] = []
genPlainSub v [] (sub:subs) = (tell [" blitz::Range::all() "]) : (genPlainSub v [] subs)
genPlainSub v [] (sub:subs) = (tell [" "]) : (genPlainSub v [] subs)
genPlainSub v (e:es) (sub:subs)
= gen : genPlainSub v es subs
= (tell ["["] >> genSub >> tell ["]"]) : genPlainSub v es subs
where
gen = genSub
genSub
= if checkValid
then do tell ["occam_check_index ("]
@ -1106,6 +1142,21 @@ genIfBody ifExc s = genStructured s doC
--}}}
--Changed to make array VAL abbreviations have constant data:
genDeclType :: A.AbbrevMode -> A.Type -> CGen ()
genDeclType am t
= do case t of
A.Array _ _ -> genArrayType (am == A.ValAbbrev) t 0
_ ->
do when (am == A.ValAbbrev) $ tell ["const "]
genType t
case t of
A.Chan _ -> return ()
A.Record _ -> tell [" *"]
_ -> when (am == A.Abbrev) $ tell [" *"]
{-
---------------------------------------------------------------------
@ -1380,15 +1431,6 @@ genCheckedConversion m fromT toT exp
--{{{ declarations
--All taken verbatim from GenerateC
genDeclType :: A.AbbrevMode -> A.Type -> CGen ()
genDeclType am t
= do when (am == A.ValAbbrev) $ tell ["const "]
genType t
case t of
A.Array _ _ -> return ()
A.Chan _ -> return ()
A.Record _ -> tell [" *"]
_ -> when (am == A.Abbrev) $ tell [" *"]
genDecl :: A.AbbrevMode -> A.Type -> A.Name -> CGen ()
genDecl am t n
@ -1486,6 +1528,10 @@ genVariable' checkValid v
= do let (es, v) = collectSubs sv
genVariable v
genArraySubscript checkValid v es
t <- typeOfVariable v
--To index an actual element of an array we must use the .access() function
--Only needed when we have applied enough subscripts to get out an element:
case t of A.Array dims _ -> when ((length dims) == (length es)) (tell [" .access() "])
inner (A.SubscriptedVariable _ (A.SubscriptField m n) v)
= do genVariable v
tell ["->"]

View File

@ -29,17 +29,11 @@ public:
#include <iostream>
#include <boost/tuple/tuple.hpp>
#include <boost/variant.hpp>
#include <boost/mpl/at.hpp>
#include <blitz/array.h>
#include <blitz/tinyvec-et.h>
#include <boost/any.hpp>
inline blitz::Array<unsigned char, 1> string_to_array(char* c)
{
const size_t n = strlen(c) + 1;
return blitz::Array<unsigned char, 1>((unsigned char*)c,blitz::shape(n),blitz::neverDeleteData);
}
#include <vector>
#include <boost/type_traits/remove_const.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
class StreamWriter : public csp::CSProcess
{
@ -105,93 +99,244 @@ public:
};
template < typename T, unsigned dims >
class tockArray : public blitz::Array<T,dims>
class tockBool
{
private:
bool b;
public:
inline tockArray(const tockArray<T,dims>& _array)
: blitz::Array<T,dims>(*(blitz::Array<T,dims>*)&_array) {}
inline tockArray(const tockAny& _any)
: blitz::Array<T,dims>(*(blitz::Array<T,dims>*)& (tockArray)_any) {}
template <typename U>
inline tockArray(const tockArray<U,dims>& _diffTypeArray)
: blitz::Array<T,dims>( (T*) (_diffTypeArray.dataFirst()), (_diffTypeArray.shape() * (int)sizeof(U)) / (int)sizeof(T),blitz::neverDeleteData) {}
template <unsigned D>
inline tockArray(const tockArray<T,D>& _diffDimArray)
: blitz::Array<T,dims>( (T*) (_diffDimArray.dataFirst()),blitz::shape(_diffDimArray.size()),blitz::neverDeleteData) {}
template <typename U>
inline tockArray(U* u)
: blitz::Array<T,dims>( (T*) u, sizeof(U) / sizeof(T),blitz::neverDeleteData) {}
inline tockArray(T t) : blitz::Array<T,dims>(1) {(*this)(0) = t;}
template <typename U>
inline tockArray(U u) : blitz::Array<T,dims>(u) {}
template <typename U,typename V>
inline tockArray(U u,V v) : blitz::Array<T,dims>(u,v) {}
template <typename U,typename V,typename W>
inline tockArray(U u,V v,W w) : blitz::Array<T,dims>(u,v,w) {}
template <typename U,typename V,typename W,typename X>
inline tockArray(U u,V v,W w,X x) : blitz::Array<T,dims>(u,v,w,x) {}
template <typename U,typename V,typename W,typename X,typename Y>
inline tockArray(U u,V v,W w,X x,Y y) : blitz::Array<T,dims>(u,v,w,x,y) {}
template <typename U,typename V,typename W,typename X,typename Y,typename Z>
inline tockArray(U u,V v,W w,X x,Y y,Z z) : blitz::Array<T,dims>(u,v,w,x,y,z) {}
template <typename U,typename V,typename W,typename X,typename Y,typename Z,typename Z0>
inline tockArray(U u,V v,W w,X x,Y y,Z z,Z0 z0) : blitz::Array<T,dims>(u,v,w,x,y,z,z0) {}
template <typename U,typename V,typename W,typename X,typename Y,typename Z,typename Z0,typename Z1>
inline tockArray(U u,V v,W w,X x,Y y,Z z,Z0 z0,Z1 z1) : blitz::Array<T,dims>(u,v,w,x,y,z,z0,z1) {}
template <typename U,typename V,typename W,typename X,typename Y,typename Z,typename Z0,typename Z1,typename Z2>
inline tockArray(U u,V v,W w,X x,Y y,Z z,Z0 z0,Z1 z1,Z2 z2) : blitz::Array<T,dims>(u,v,w,x,y,z,z0,z1,z2) {}
template <typename U,typename V,typename W,typename X,typename Y,typename Z,typename Z0,typename Z1,typename Z2,typename Z3>
inline tockArray(U u,V v,W w,X x,Y y,Z z,Z0 z0,Z1 z1,Z2 z2,Z3 z3) : blitz::Array<T,dims>(u,v,w,x,y,z,z0,z1,z2,z3) {}
inline tockArray() {}
inline tockArray& operator=(const tockArray<T,dims>& rhs)
{
resize(rhs.shape());
*((blitz::Array<T,dims>*)this) = *((blitz::Array<T,dims>*)&rhs);
return *this;
}
inline tockArray& operator=(const tockAny& any)
{
return (*this = (tockArray<T,dims>)any);
}
inline tockArray& operator=(const T& t)
{
this->resize(blitz::shape(1));
(*this)(0) = t;
return *this;
}
template <typename U>
operator U* ()
{
return (U*)(void*)(this->dataFirst());
}
template <typename U>
operator const U* const ()
{
return (const U*)(const void*)(this->dataFirst());
}
inline tockBool() {}
inline tockBool(bool _b) : b(_b) {}
inline operator bool () const {return b;}
inline void operator = (const bool& _b) {b = _b;}
};
inline std::pair< boost::array<unsigned,1> , unsigned > tockDims(const unsigned d0)
{
boost::array<unsigned,1> r;
r[0] = d0;
return std::pair< boost::array<unsigned,1> , unsigned >(r,1);
}
/*
Generates functions like this:
inline std::pair< boost::array<unsigned,2> , unsigned > tockDims(const unsigned d0,const unsigned d1,const unsigned d2)
{
boost::array<unsigned,2> r;
r[0] = d0;
r[1] = d1;
r[2] = d2;
return std::pair< boost::array<unsigned,2> , unsigned >(r,d1 * d2);
}
*/
#define TOCKDIMS_ARGS(___z,NUM,___data) ,const unsigned d##NUM
#define TOCKDIMS_ASSIGN(___z,NUM,___data) r[ NUM ] = d##NUM ;
#define TOCKDIMS_MULT(___z,NUM,___data) * d##NUM
#define TOCKDIMS(___z,NUM,___data) inline std::pair< boost::array<unsigned, NUM >,unsigned> tockDims(\
const unsigned d0 BOOST_PP_REPEAT_FROM_TO(1,NUM,TOCKDIMS_ARGS,0) ) { \
boost::array<unsigned, NUM > r; BOOST_PP_REPEAT(NUM,TOCKDIMS_ASSIGN,0) \
return std::pair< boost::array<unsigned, NUM > , unsigned >(r,1 BOOST_PP_REPEAT_FROM_TO(1,NUM,TOCKDIMS_MULT,0) ); }
//Up to 12 dimensions:
BOOST_PP_REPEAT_FROM_TO(2,12,TOCKDIMS,0)
template < typename T, unsigned DIMS >
class tockArrayView
{
T* realArray;
boost::array<unsigned,DIMS> dims;
//dims[1] * dims[2] * dims[3] ...
//If DIMS is 0 or 1, totalSubDim will be 1
unsigned totalSubDim;
template <typename U>
inline void operator=(const U&) {}
inline tockArrayView(T* _realArray,const boost::array<unsigned,DIMS+1>& _biggerDims,unsigned _totalSubDim)
: realArray(_realArray),totalSubDim(_totalSubDim)
{
memcpy(dims.c_array(),_biggerDims.data() + 1,sizeof(unsigned) * DIMS);
}
friend class tockArrayView<T,DIMS + 1>;
inline void correctDimsRetype(const unsigned totalSourceBytes)
{
if (totalSubDim == 0)
{
//Can only happen if one of the dimensions is zero, i.e. unknown
//We must find this dimension and calculate it:
unsigned zeroDim;
unsigned totalDim = 1;
for (unsigned i = 0;i < DIMS;i++)
{
if (dims[i] == 0)
zeroDim = i;
else
totalDim *= dims[i];
}
//Set the size of the unknown dimension:
dims[zeroDim] = (totalSourceBytes / totalDim) / sizeof(T);
totalSubDim = (totalDim * dims[zeroDim]) / dims[0];
}
}
public:
inline tockArrayView()
: realArray(NULL)
{
dims.assign(0);
totalSubDim = 0;
}
inline tockArrayView(const tockArrayView& v)
: realArray(v.realArray),
dims(v.dims),
totalSubDim(v.totalSubDim)
{
}
inline tockArrayView(T* _realArray,const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims)
: realArray(_realArray),dims(_dims.first),totalSubDim(_dims.second)
{
}
inline tockArrayView(std::vector<typename boost::remove_const<T>::type>& _vec,const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims)
: realArray(_vec.empty() ? NULL : &(_vec.at(0))),dims(_dims.first),totalSubDim(_dims.second)
{
}
//Retyping:
template <typename U>
inline tockArrayView(U* _realArray,const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims)
: realArray(reinterpret_cast<T*>(_realArray)),dims(_dims.first),totalSubDim(_dims.second)
{
//Assume it's a single U item:
correctDimsRetype(sizeof(U));
}
//Retyping, same number of dims:
template <typename U,unsigned FROMDIMS>
inline tockArrayView(const tockArrayView<U,FROMDIMS>& tav,const std::pair< boost::array<unsigned,DIMS> , unsigned >& _dims)
: realArray(reinterpret_cast<T*>(tav.data())),dims(_dims.first),totalSubDim(_dims.second)
{
correctDimsRetype(tav.size() * sizeof(U));
}
inline tockArrayView<T,DIMS - 1> operator[] (const unsigned index) const
{
return tockArrayView<T,DIMS - 1>(realArray + (totalSubDim * index),dims,totalSubDim / dims[0]);
}
inline tockArrayView<T,DIMS> sliceFor(const unsigned amount) const
{
return sliceFromFor(0,amount);
}
inline tockArrayView<T,DIMS> sliceFrom(const unsigned index) const
{
return sliceFromFor(index,dims[0] - index);
}
inline tockArrayView<T,DIMS> sliceFromFor(const unsigned index,const unsigned amount) const
{
boost::array<unsigned,DIMS> sliceDims = dims;
sliceDims[0] = amount;
return tockArrayView<T,DIMS>(realArray + (totalSubDim * index),std::make_pair(sliceDims,totalSubDim));
}
inline T* data() const
{
return realArray;
}
inline const boost::array<unsigned,DIMS>& getDims() const
{
return dims;
}
inline unsigned getTotalSubDim() const
{
return totalSubDim;
}
inline unsigned size() const
{
return dims[0] * totalSubDim;
}
inline unsigned extent(const unsigned dim) const
{
return dims[dim];
}
inline operator tockArrayView<const T,DIMS>() const
{
return tockArrayView<const T,DIMS>((const T*)realArray,std::make_pair(dims,totalSubDim));
}
inline void updateFromVector(std::vector<typename boost::remove_const<T>::type>& v)
{
realArray = v.empty() ? NULL : &(v.at(0));
}
inline tockArrayView<typename boost::remove_const<T>::type,DIMS> versionToSend()
{
return tockArrayView<typename boost::remove_const<T>::type,DIMS>(const_cast<typename boost::remove_const<T>::type*>(realArray),std::make_pair(dims,totalSubDim));
}
inline const tockArrayView<typename boost::remove_const<T>::type,DIMS> versionToSend() const
{
return tockArrayView<typename boost::remove_const<T>::type,DIMS>(const_cast<typename boost::remove_const<T>::type*>(realArray),std::make_pair(dims,totalSubDim));
}
inline tockArrayView& operator=(const tockArrayView& tav)
{
//TODO investigate speeding up when T is primitive (maybe there's a boost class for that?)
unsigned n = tav.size();
for (unsigned i = 0;i < n;i++)
{
realArray[i] = tav.realArray[i];
}
dims = tav.dims;
totalSubDim = tav.totalSubDim;
return *this;
}
inline tockArrayView& operator=(const tockAny&)
{
//TODO later on
}
};
template <typename T>
class tockArrayView<T,0>
{
T* realArray;
inline tockArrayView(T* _realArray,boost::array<unsigned,1>,unsigned)
: realArray(_realArray)
{
}
friend class tockArrayView<T,1>;
public:
//Should only be used on arrays with zero dimensions:
inline T& access() const
{
return *realArray;
}
};