Files
LBPM/common/Array.hpp
2015-04-22 14:23:55 -04:00

378 lines
10 KiB
C++

#ifndef included_ArrayClass_hpp
#define included_ArrayClass_hpp
#include "common/Array.h"
#include "common/Utilities.h"
#include <algorithm>
#include <limits>
template<class TYPE>
void DeleteArray( TYPE* x )
{
delete [] x;
}
/********************************************************
* Constructors *
********************************************************/
template<class TYPE>
Array<TYPE>::Array( )
{
d_ndim = 0;
d_length = 0;
for (size_t i=0; i<sizeof(d_N)/sizeof(size_t); i++)
d_N[i] = 1;
d_N[0] = 0;
d_data = d_ptr.get();
}
template<class TYPE>
Array<TYPE>::Array( size_t N )
{
allocate(std::vector<size_t>(1,N));
}
template<class TYPE>
Array<TYPE>::Array( size_t N_rows, size_t N_columns )
{
std::vector<size_t> N(2);
N[0] = N_rows;
N[1] = N_columns;
allocate(N);
}
template<class TYPE>
Array<TYPE>::Array( size_t N1, size_t N2, size_t N3 )
{
std::vector<size_t> N(3);
N[0] = N1;
N[1] = N2;
N[2] = N3;
allocate(N);
}
template<class TYPE>
Array<TYPE>::Array( const std::vector<size_t>& N )
{
allocate(N);
}
template<class TYPE>
void Array<TYPE>::allocate( const std::vector<size_t>& N )
{
d_ndim = N.size();
d_length = 1;
for (size_t i=0; i<sizeof(d_N)/sizeof(size_t); i++)
d_N[i] = 1;
for (size_t i=0; i<N.size(); i++) {
d_N[i] = N[i];
d_length *= N[i];
}
if ( N.empty() ) {
d_N[0] = 0;
d_length = 0;
}
if ( d_length==0 )
d_ptr.reset();
else
d_ptr = std::shared_ptr<TYPE>(new TYPE[d_length],DeleteArray<TYPE>);
d_data = d_ptr.get();
if ( d_length>0 && d_data==NULL )
ERROR("Failed to allocate array");
}
template<class TYPE>
Array<TYPE>::Array( const Array& rhs ):
d_ndim(rhs.d_ndim), d_length(rhs.d_length), d_data(NULL)
{
allocate( std::vector<size_t>(rhs.d_N,rhs.d_N+rhs.d_ndim) );
for (size_t i=0; i<d_length; i++)
d_data[i] = rhs.d_data[i];
}
template<class TYPE>
Array<TYPE>& Array<TYPE>::operator=( const Array& rhs )
{
if ( this == &rhs )
return *this;
this->allocate( std::vector<size_t>(rhs.d_N,rhs.d_N+rhs.d_data) );
for (size_t i=0; i<d_length; i++)
this->d_data[i] = rhs.d_data[i];
return *this;
}
template<class TYPE>
Array<TYPE>::~Array( )
{
}
/********************************************************
* Resize the array *
********************************************************/
template<class TYPE>
void Array<TYPE>::resize( size_t N )
{
resize(std::vector<size_t>(1,N));
}
template<class TYPE>
void Array<TYPE>::resize( size_t N1, size_t N2 )
{
std::vector<size_t> N(2);
N[0] = N1;
N[1] = N2;
resize(N);
}
template<class TYPE>
void Array<TYPE>::resize( size_t N1, size_t N2, size_t N3 )
{
std::vector<size_t> N(3);
N[0] = N1;
N[1] = N2;
N[2] = N3;
resize(N);
}
template<class TYPE>
void Array<TYPE>::resize( const std::vector<size_t>& N )
{
// Check if the array actually changed size
size_t new_length = 1;
for (size_t i=0; i<N.size(); i++)
new_length *= N[i];
bool changed = new_length!=d_length;
for (size_t i=0; i<N.size(); i++)
changed = changed || N[i]!=d_N[i];
if ( !changed )
return;
// Store the old data
const size_t ndim_max = sizeof(d_N)/sizeof(size_t);
std::vector<size_t> N1(ndim_max,1), N2(ndim_max,1);
for (size_t d=0; d<d_ndim; d++)
N1[d] = d_N[d];
for (size_t d=0; d<N.size(); d++)
N2[d] = N[d];
if ( d_ndim==0 ) { N1[0] = 0; }
if ( N.empty() ) { N2[0] = 0; }
std::shared_ptr<TYPE> old_data = d_ptr;
// Allocate new data
allocate(N);
// Copy the old values
if ( d_length > 0 ) {
ASSERT(sizeof(d_N)/sizeof(size_t)==3);
TYPE *data1 = old_data.get();
TYPE *data2 = d_data;
for (size_t k=0; k<std::min(N1[2],N2[2]); k++) {
for (size_t j=0; j<std::min(N1[1],N2[1]); j++) {
for (size_t i=0; i<std::min(N1[0],N2[0]); i++) {
size_t index1 = i + j*N1[0] + k*N1[0]*N1[1];
size_t index2 = i + j*N2[0] + k*N2[0]*N2[1];
data2[index2] = data1[index1];
}
}
}
}
}
/********************************************************
* Rehape the array *
********************************************************/
template<class TYPE>
void Array<TYPE>::reshape( const std::vector<size_t>& N )
{
size_t new_length = 1;
for (size_t i=0; i<N.size(); i++)
new_length *= N[i];
if ( new_length!=d_length )
ERROR("reshape is not allowed to change the array size");
d_ndim = N.size();
for (size_t i=0; i<sizeof(d_N)/sizeof(size_t); i++)
d_N[i] = 1;
for (size_t i=0; i<N.size(); i++)
d_N[i] = N[i];
}
/********************************************************
* Operator overloading *
********************************************************/
template<class TYPE>
bool Array<TYPE>::operator==( const Array& rhs ) const
{
if ( this==&rhs )
return true;
if ( d_length!=rhs.d_length )
return false;
bool match = true;
for (size_t i=0; i<d_length; i++)
match = match && d_data[i]==rhs.d_data[i];
return match;
}
/********************************************************
* Get a view of an C array *
********************************************************/
template<class TYPE>
std::shared_ptr<Array<TYPE> > Array<TYPE>::view( size_t N, std::shared_ptr<TYPE> data )
{
view(std::vector<size_t>(1,N),data);
}
template<class TYPE>
std::shared_ptr<Array<TYPE> > Array<TYPE>::view( size_t N1, size_t N2, std::shared_ptr<TYPE> data )
{
std::vector<size_t> N(2);
N[0] = N1;
N[1] = N2;
view(N,data);
}
template<class TYPE>
std::shared_ptr<Array<TYPE> > Array<TYPE>::view( size_t N1, size_t N2, size_t N3, std::shared_ptr<TYPE> data )
{
std::vector<size_t> N(3);
N[0] = N1;
N[1] = N2;
N[2] = N3;
view(N,data);
}
template<class TYPE>
std::shared_ptr<const Array<TYPE> > Array<TYPE>::constView( size_t N, std::shared_ptr<const TYPE> data )
{
constView(std::vector<size_t>(1,N),data);
}
template<class TYPE>
std::shared_ptr<const Array<TYPE> > Array<TYPE>::constView( size_t N1, size_t N2, std::shared_ptr<const TYPE> data )
{
std::vector<size_t> N(2);
N[0] = N1;
N[1] = N2;
constView(N,data);
}
template<class TYPE>
std::shared_ptr<const Array<TYPE> > Array<TYPE>::constView( size_t N1, size_t N2, size_t N3, std::shared_ptr<const TYPE> data )
{
std::vector<size_t> N(3);
N[0] = N1;
N[1] = N2;
N[2] = N3;
constView(N,data);
}
template<class TYPE>
std::shared_ptr<Array<TYPE> > Array<TYPE>::view( const std::vector<size_t>& N, std::shared_ptr<TYPE> data )
{
std::shared_ptr<Array<TYPE> > array(new Array<TYPE>());
array->d_ndim = N.size();
array->d_length = 1;
for (size_t i=0; i<N.size(); i++) {
array->d_N[i] = N[i];
array->d_length *= N[i];
}
array->d_ptr = data;
array->d_data = array->d_ptr.get();
return array;
}
template<class TYPE>
std::shared_ptr<const Array<TYPE> > Array<TYPE>::constView( const std::vector<size_t>& N, std::shared_ptr<const TYPE> data )
{
return view(N,std::const_pointer_cast<TYPE>(data));
}
/********************************************************
* Convert array types *
********************************************************/
template<class TYPE>
template<class TYPE2>
std::shared_ptr<Array<TYPE2> > Array<TYPE>::convert( std::shared_ptr<Array<TYPE> > array )
{
std::shared_ptr<Array<TYPE2> > array2( new Array<TYPE2>(array->size()) );
array2.copy( *array );
return array2;
}
template<class TYPE>
template<class TYPE2>
std::shared_ptr<const Array<TYPE2> > Array<TYPE>::convert( std::shared_ptr<const Array<TYPE> > array )
{
return Array<TYPE>::convert( std::const_pointer_cast<Array<TYPE2> >(array) );
}
template<class TYPE>
template<class TYPE2>
void Array<TYPE>::copy( const Array<TYPE2>& array )
{
resize( std::vector<size_t>(array.d_N,array.d_N+array.d_ndim) );
const TYPE2 *src = array.d_data;
for (size_t i=0; i<d_length; i++)
d_data[i] = static_cast<TYPE>(src[i]);
}
template<class TYPE>
template<class TYPE2>
void Array<TYPE>::copy( const TYPE2* src )
{
for (size_t i=0; i<d_length; i++)
d_data[i] = static_cast<TYPE>(src[i]);
}
template<class TYPE>
void Array<TYPE>::fill( const TYPE& value )
{
for (size_t i=0; i<d_length; i++)
d_data[i] = value;
}
/********************************************************
* Simple math operations *
********************************************************/
template<class TYPE>
bool Array<TYPE>::NaNs( ) const
{
bool test = false;
for (size_t i=0; i<d_length; i++)
test = test || d_data[i]!=d_data[i];
return test;
}
template<class TYPE>
TYPE Array<TYPE>::min( ) const
{
TYPE x = std::numeric_limits<TYPE>::max();
for (size_t i=0; i<d_length; i++)
x = std::min(x,d_data[i]);
return x;
}
template<class TYPE>
TYPE Array<TYPE>::max( ) const
{
TYPE x = std::numeric_limits<TYPE>::min();
for (size_t i=0; i<d_length; i++)
x = std::max(x,d_data[i]);
return x;
}
template<class TYPE>
TYPE Array<TYPE>::sum( ) const
{
TYPE x = 0;
for (size_t i=0; i<d_length; i++)
x += d_data[i];
return x;
}
template<class TYPE>
std::shared_ptr<Array<TYPE> > Array<TYPE>::sum( int dir ) const
{
std::vector<size_t> size_ans = size();
std::shared_ptr<Array<TYPE> > ans( new Array<TYPE>(size_ans) );
size_t N1=1, N2=1, N3=1;
for (int d=0; d<std::min(dir,d_ndim); d++)
N1 *= d_N[d];
N2 = d_N[dir];
for (int d=dir+1; d<std::min(dir,d_ndim); d++)
N3 *= d_N[d];
TYPE* data2 = ans->d_data;
for (int i3=0; i3<N3; i3++) {
for (int i1=0; i1<N1; i1++) {
TYPE x = 0;
for (size_t i2=0; i2<N2; i2++)
x += d_data[i1+i2*N1+i3*N1*N2];
data2[i1+i3*N1] = x;
}
}
return ans;
}
#endif