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:
parent
f997b823dc
commit
a52d115060
|
@ -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 ["->"]
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user