00001 #ifndef __FIBEROPERATIONS_EXTRACT_SLICE
00002 #define __FIBEROPERATIONS_EXTRACT_SLICE
00003
00004 #include <field/MemBase.hpp>
00005 #include <meta/LIST.hpp>
00006 #include "SliceSelection.hpp"
00007
00008 namespace Fiber
00009 {
00010
00011 template <class Array2D>
00012 struct ArrayCollector
00013 {
00014 typedef RefPtr<Array2D> result_t;
00015
00016 result_t result;
00017 Array2D & dst;
00018
00019 ArrayCollector(const MultiIndex<2>&Dims)
00020 : result( new Array2D(Dims) )
00021 , dst( *result )
00022 {
00023
00024 }
00025
00026 template <class ElementType>
00027 void collect(const MultiIndex<2>&Dims, const ElementType&T)
00028 {
00029 dst[ Dims ] = T;
00030 }
00031
00032 static result_t Invalid()
00033 {
00034 return MemCore::NullPtr();
00035 }
00036 };
00037
00038 template <class Operator, class Array3D>
00039 struct ExtractSlice
00040 {
00041
00042 static typename Operator::result_t get(const MultiIndex<3>&Dims,
00043 const RefPtr<MemBase>&Data, const SliceSelection&GO,
00044 index_t SliceID, const MultiIndex<3>&FragmentOffset)
00045 {
00046 RefPtr<Array3D> src = Data;
00047 if (!src)
00048 return Operator::Invalid();
00049
00050 index_t Xsize = Dims[ GO.X ];
00051 index_t Ysize = Dims[ GO.Y ];
00052
00053 Operator Op( MIndex(Xsize, Ysize) );
00054
00055 const Array3D&Src = *src;
00056
00057 for(index_t iy = 0; iy<Ysize; iy++)
00058 for(index_t ix = 0; ix<Xsize; ix++)
00059 {
00060 MultiIndex<3> P = FragmentOffset;
00061 P[GO.X] += ix; P[GO.Y] += iy; P[GO.Z] += SliceID;
00062
00063 MultiIndex<2> Pdst;
00064 Pdst[ 0 ] = ix;
00065 Pdst[ 1 ] = iy;
00066
00067 Op.collect( Pdst, Src[ P ] );
00068 }
00069
00070 return Op.result;
00071 }
00072 };
00073
00074 template <class Operator, class Array3D, class NEXT>
00075 struct ExtractSlice<Operator, META::LIST<Array3D, NEXT> >
00076 {
00077
00078 static typename Operator::result_t get(const MultiIndex<3>&Dims,
00079 const RefPtr<MemBase>&Data, const SliceSelection&O,
00080 index_t SliceID, const MultiIndex<3>&FragmentOffset)
00081 {
00082 if (typename Operator::result_t result =
00083 ExtractSlice<Operator, Array3D>::get(Dims, Data, O, SliceID, FragmentOffset) )
00084 {
00085 return result;
00086 }
00087 return ExtractSlice<Operator, NEXT>::get(Dims, Data, O, SliceID, FragmentOffset);
00088 }
00089 };
00090
00091 template <class Operator>
00092 struct ExtractSlice<Operator, META::NIL >
00093 {
00094
00095 static typename Operator::result_t get(const MultiIndex<3>&Dims,
00096 const RefPtr<MemBase>&Data, const SliceSelection&O,
00097 index_t SliceID, const MultiIndex<3>&FragmentOffset)
00098 {
00099 return Operator::Invalid();
00100 }
00101 };
00102
00103 }
00104
00105 #endif //__FIBEROPERATIONS_EXTRACT_SLICE