Commit b8ea021a authored by Kenneth Leiter's avatar Kenneth Leiter

ENH: Improve how array keeps track of dimensionality in anticipation of working with hyperslabs.

parent 889c1c23
......@@ -253,12 +253,14 @@ public:
const unsigned int valuesStartIndex,
const unsigned int numValues,
const unsigned int arrayStride,
const unsigned int valuesStride) :
const unsigned int valuesStride,
std::vector<unsigned int> & dimensions) :
mStartIndex(startIndex),
mValuesStartIndex(valuesStartIndex),
mNumValues(numValues),
mArrayStride(arrayStride),
mValuesStride(valuesStride)
mValuesStride(valuesStride),
mDimensions(dimensions)
{
}
......@@ -273,6 +275,7 @@ public:
}
if(array->size() < size) {
array->resize(size);
mDimensions.clear();
}
for(unsigned int i=0; i<mNumValues; ++i) {
array->operator[](mStartIndex + i*mArrayStride) =
......@@ -287,6 +290,7 @@ private:
const unsigned int mNumValues;
const unsigned int mArrayStride;
const unsigned int mValuesStride;
std::vector<unsigned int> & mDimensions;
};
class XdmfArray::InternalizeArrayPointer : public boost::static_visitor<void> {
......@@ -389,16 +393,24 @@ const std::string XdmfArray::ItemTag = "DataItem";
void
XdmfArray::clear()
{
if(mHaveArrayPointer) {
internalizeArrayPointer();
}
if(mHaveArray) {
return boost::apply_visitor(Clear(), mArray);
boost::apply_visitor(Clear(), mArray);
mDimensions.clear();
}
}
void
XdmfArray::erase(const unsigned int index)
{
if(mHaveArrayPointer) {
internalizeArrayPointer();
}
if(mHaveArray) {
return boost::apply_visitor(Erase(index), mArray);
boost::apply_visitor(Erase(index), mArray);
mDimensions.clear();
}
}
......@@ -426,10 +438,34 @@ XdmfArray::getCapacity() const
return 0;
}
std::vector<unsigned int>
XdmfArray::getDimensions() const
{
if(mHaveArray) {
if(mDimensions.size() == 0) {
const unsigned int size = boost::apply_visitor(Size(), mArray);
if(size > 0) {
std::vector<unsigned int> toReturn(1, size);
return toReturn;
}
}
return mDimensions;
}
else if(mHaveArrayPointer) {
// FIXME:
}
else if(mHeavyDataController) {
return mHeavyDataController->getDimensions();
}
return mDimensions;
}
std::string
XdmfArray::getDimensionString() const
XdmfArray::getDimensionsString() const
{
return mDimensionString;
const std::vector<unsigned int> & dimensions = this->getDimensions();
return GetValuesString().getValuesString(&dimensions[0],
dimensions.size());
}
boost::shared_ptr<XdmfHeavyDataController>
......@@ -564,6 +600,18 @@ XdmfArray::initialize(const boost::shared_ptr<const XdmfArrayType> arrayType,
}
}
void
XdmfArray::initialize(const boost::shared_ptr<const XdmfArrayType> arrayType,
const std::vector<unsigned int> & dimensions)
{
mDimensions = dimensions;
const unsigned int size = std::accumulate(mDimensions.begin(),
mDimensions.end(),
1,
std::multiplies<unsigned int>());
return this->initialize(arrayType, size);
}
void
XdmfArray::insert(const unsigned int startIndex,
const boost::shared_ptr<const XdmfArray> values,
......@@ -587,7 +635,8 @@ XdmfArray::insert(const unsigned int startIndex,
valuesStartIndex,
numValues,
arrayStride,
valuesStride),
valuesStride,
mDimensions),
mArray,
values->mArray);
}
......@@ -627,16 +676,15 @@ XdmfArray::populateItem(const std::map<std::string, std::string> & itemPropertie
assert(false);
}
std::map<std::string, std::string>::const_iterator size =
std::map<std::string, std::string>::const_iterator dimensions =
itemProperties.find("Dimensions");
if(size != itemProperties.end()) {
boost::tokenizer<> tokens(size->second);
if(dimensions != itemProperties.end()) {
boost::tokenizer<> tokens(dimensions->second);
for(boost::tokenizer<>::const_iterator iter = tokens.begin();
iter != tokens.end();
++iter) {
sizeVal *= atoi((*iter).c_str());
mDimensions.push_back(atoi((*iter).c_str()));
}
mDimensionString = size->second;
}
else {
assert(false);
......@@ -669,22 +717,23 @@ XdmfArray::populateItem(const std::map<std::string, std::string> & itemPropertie
arrayType,
std::vector<unsigned int>(1, 0),
std::vector<unsigned int>(1, 1),
std::vector<unsigned int>(1, sizeVal));
mDimensions);
}
else {
assert(false);
}
}
else if(format->second.compare("XML") == 0) {
this->initialize(arrayType);
this->reserve(sizeVal);
this->initialize(arrayType,
mDimensions);
unsigned int index = 0;
boost::char_separator<char> sep(" \t\n");
boost::tokenizer<boost::char_separator<char> > tokens(contentVal, sep);
for(boost::tokenizer<boost::char_separator<char> >::const_iterator
iter = tokens.begin();
iter != tokens.end();
++iter) {
this->pushBack(atof((*iter).c_str()));
++iter, ++index) {
this->insert(index, atof((*iter).c_str()));
}
}
else {
......@@ -726,6 +775,7 @@ XdmfArray::releaseArray()
boost::shared_ptr<std::vector<char> > emptyArray;
mArray = emptyArray;
mHaveArray = false;
mDimensions.clear();
}
void
......@@ -772,6 +822,7 @@ XdmfArray::swap(const boost::shared_ptr<XdmfArray> array)
bool tmpHaveArrayPointer = array->mHaveArrayPointer;
boost::shared_ptr<XdmfHeavyDataController> tmpHeavyDataController =
array->mHeavyDataController;
std::vector<unsigned int> tmpDimensions = array->mDimensions;
array->mArray = mArray;
array->mArrayPointer = mArrayPointer;
......@@ -779,6 +830,7 @@ XdmfArray::swap(const boost::shared_ptr<XdmfArray> array)
array->mHaveArray = mHaveArray;
array->mHaveArrayPointer = mHaveArrayPointer;
array->mHeavyDataController = mHeavyDataController;
array->mDimensions = mDimensions;
mArray = tmpArray;
mArrayPointer = tmpArrayPointer;
......@@ -786,4 +838,5 @@ XdmfArray::swap(const boost::shared_ptr<XdmfArray> array)
mHaveArray = tmpHaveArray;
mHaveArrayPointer = tmpHaveArrayPointer;
mHeavyDataController = tmpHeavyDataController;
mDimensions = tmpDimensions;
}
......@@ -132,11 +132,18 @@ class XDMFCORE_EXPORT XdmfArray : public XdmfItem {
unsigned int getCapacity() const;
/**
* Get the dimensions of the array as a string.
* Get the dimensions of the array.
*
* @return the dimensions of the array.
*/
std::string getDimensionString() const;
std::vector<unsigned int> getDimensions() const;
/**
* Get the dimensions of the array as a string.
*
* @return the dimensions of the array as a string.
*/
std::string getDimensionsString() const;
/**
* Get the heavy data controller attached to this array.
......@@ -240,6 +247,18 @@ class XDMFCORE_EXPORT XdmfArray : public XdmfItem {
template <typename T>
boost::shared_ptr<std::vector<T> > initialize(const unsigned int size = 0);
/**
* Initialize the array to contain a particular type.
*
* @param dimensions the dimensions of the initialized array.
*
* @return a smart pointer to the internal vector of values
* initialized in this array.
*/
template <typename T>
boost::shared_ptr<std::vector<T> >
initialize(const std::vector<unsigned int> & dimensions);
/**
* Initialize the array to contain a particular type.
*
......@@ -249,6 +268,15 @@ class XDMFCORE_EXPORT XdmfArray : public XdmfItem {
void initialize(const boost::shared_ptr<const XdmfArrayType> arrayType,
const unsigned int size = 0);
/**
* Initialize the array to contain a particular type.
*
* @param arrayType the type of array to initialize.
* @param dimensions the number dimensions of the initialized array.
*/
void initialize(const boost::shared_ptr<const XdmfArrayType> arrayType,
const std::vector<unsigned int> & dimensions);
/**
* Insert value into this array
*
......@@ -338,6 +366,20 @@ class XDMFCORE_EXPORT XdmfArray : public XdmfItem {
void resize(const unsigned int numValues,
const T & value = 0);
/**
* Resizes the array to specified dimensions. If the number of
* values specified by the dimensions is larger than the current
* size, values are appended to the end of the array equal to
* value. If numValues is less than the current size, values at
* indices larger than numValues are removed.
*
* @param dimensions the dimensions to resize the arrat to.
* @param value the number to intialize newly created values to, if needed.
*/
template<typename T>
void resize(const std::vector<unsigned int> & dimensions,
const T & value = 0);
/**
* Attach an heavy data controller to this array.
*
......@@ -508,12 +550,12 @@ class XDMFCORE_EXPORT XdmfArray : public XdmfItem {
ArrayVariant mArray;
ArrayPointerVariant mArrayPointer;
unsigned int mArrayPointerNumValues;
std::vector<unsigned int> mDimensions;
bool mHaveArray;
bool mHaveArrayPointer;
boost::shared_ptr<XdmfHeavyDataController> mHeavyDataController;
std::string mName;
unsigned int mTmpReserveSize;
std::string mDimensionString;
};
#include "XdmfArray.tpp"
......
......@@ -21,6 +21,8 @@
/* */
/*****************************************************************************/
#include <functional>
#include <numeric>
#include "XdmfArray.hpp"
template <typename T>
......@@ -76,12 +78,14 @@ public:
const T * const valuesPointer,
const unsigned int numValues,
const unsigned int arrayStride,
const unsigned int valuesStride) :
const unsigned int valuesStride,
std::vector<unsigned int> & dimensions) :
mStartIndex(startIndex),
mValuesPointer(valuesPointer),
mNumValues(numValues),
mArrayStride(arrayStride),
mValuesStride(valuesStride)
mValuesStride(valuesStride),
mDimensions(dimensions)
{
}
......@@ -95,6 +99,7 @@ public:
}
if(array->size() < size) {
array->resize(size);
mDimensions.clear();
}
for(unsigned int i=0; i<mNumValues; ++i) {
array->operator[](mStartIndex + i*mArrayStride) =
......@@ -109,6 +114,7 @@ private:
const unsigned int mNumValues;
const unsigned int mArrayStride;
const unsigned int mValuesStride;
std::vector<unsigned int> & mDimensions;
};
template <typename T>
......@@ -234,6 +240,18 @@ XdmfArray::initialize(const unsigned int size)
return newArray;
}
template <typename T>
boost::shared_ptr<std::vector<T> >
XdmfArray::initialize(const std::vector<unsigned int> & dimensions)
{
mDimensions = dimensions;
const unsigned int size = std::accumulate(dimensions.begin(),
dimensions.end(),
1,
std::multiplies<unsigned int>());
return this->initialize<T>(size);
}
template<typename T>
void
XdmfArray::insert(const unsigned int index,
......@@ -245,7 +263,7 @@ XdmfArray::insert(const unsigned int index,
if(!mHaveArray) {
initialize<T>();
}
boost::apply_visitor(Insert<T>(index, &value, 1, 0, 0), mArray);
boost::apply_visitor(Insert<T>(index, &value, 1, 0, 0, mDimensions), mArray);
}
template <typename T>
......@@ -266,7 +284,8 @@ XdmfArray::insert(const unsigned int startIndex,
valuesPointer,
numValues,
arrayStride,
valuesStride),
valuesStride,
mDimensions),
mArray);
}
......@@ -280,6 +299,7 @@ XdmfArray::pushBack(const T & value)
if(!mHaveArray) {
initialize<T>();
}
mDimensions.clear();
return boost::apply_visitor(PushBack<T>(value), mArray);
}
......@@ -294,9 +314,23 @@ XdmfArray::resize(const unsigned int numValues,
if(!mHaveArray) {
initialize<T>();
}
mDimensions.clear();
return boost::apply_visitor(Resize<T>(numValues, value), mArray);
}
template<typename T>
void
XdmfArray::resize(const std::vector<unsigned int> & dimensions,
const T & value)
{
const unsigned int size = std::accumulate(dimensions.begin(),
dimensions.end(),
1,
std::multiplies<unsigned int>());
this->resize(size, value);
mDimensions = dimensions;
}
template <typename T>
void
XdmfArray::setValuesInternal(const T * const arrayPointer,
......
......@@ -64,7 +64,7 @@ XdmfHeavyDataController::getSize() const
return std::accumulate(mDimensions.begin(),
mDimensions.end(),
1,
std::multiplies<int>());
std::multiplies<unsigned int>());
}
boost::shared_ptr<const XdmfArrayType>
......
......@@ -19,6 +19,7 @@ ADD_TEST_CXX_PATH("${XDMF_BINARIES}")
# Read UseCxxTest.cmake for more information
# ---------------------------------------
ADD_TEST_CXX(TestXdmfArray)
ADD_TEST_CXX(TestXdmfArrayMultidimensional)
ADD_TEST_CXX(TestXdmfArrayWriteRead)
ADD_TEST_CXX(TestXdmfHDF5Controller)
ADD_TEST_CXX(TestXdmfHDF5Writer)
......@@ -34,6 +35,7 @@ ADD_TEST_CXX(TestXdmfVersion)
# Read UseCxxTest.cmake for more information
# ---------------------------------------
CLEAN_TEST_CXX(TestXdmfArray)
CLEAN_TEST_CXX(TestXdmfArrayMultidimensional)
CLEAN_TEST_CXX(TestXdmfArrayWriteRead
test.h5)
CLEAN_TEST_CXX(TestXdmfHDF5Controller)
......
......@@ -245,7 +245,7 @@ int main(int, char *)
//
/**
* RegetSize
* Resize
*/
boost::shared_ptr<XdmfArray> array8 = XdmfArray::New();
array8->insert(0, &values[0], 4, 1, 1);
......
#include "XdmfArray.hpp"
#include "XdmfArrayType.hpp"
#include <iostream>
int main(int, char *)
{
//
// Create 1D arrays
//
boost::shared_ptr<XdmfArray> array = XdmfArray::New();
array->initialize(XdmfArrayType::UInt32(), 2);
assert(array->getArrayType() == XdmfArrayType::UInt32());
assert(array->getSize() == 2);
std::vector<unsigned int> dimensions = array->getDimensions();
assert(dimensions.size() == 1);
assert(dimensions[0] == 2);
std::string dimensionsString = array->getDimensionsString();
assert(dimensionsString.compare("2 ") == 0);
array->resize<unsigned int>(3);
assert(array->getSize() == 3);
dimensions = array->getDimensions();
assert(dimensions.size() == 1);
assert(dimensions[0] == 3);
dimensionsString = array->getDimensionsString();
assert(dimensionsString.compare("3 ") == 0);
//
// Create 2D arrays
//
boost::shared_ptr<XdmfArray> array2 = XdmfArray::New();
std::vector<unsigned int> newDimensions(2, 2);
array2->initialize<unsigned short>(newDimensions);
assert(array2->getArrayType() == XdmfArrayType::UInt16());
assert(array2->getSize() == 4);
dimensions = array2->getDimensions();
assert(dimensions.size() == 2);
assert(dimensions[0] == 2 && dimensions[1] == 2);
dimensionsString = array2->getDimensionsString();
assert(dimensionsString.compare("2 2 ") == 0);
std::vector<unsigned int> newDimensions2(3,3);
array2->resize<unsigned short>(newDimensions2);
assert(array2->getSize() == 27);
dimensions = array2->getDimensions();
assert(dimensions.size() == 3);
assert(dimensions[0] == 3 && dimensions[1] == 3 && dimensions[2] == 3);
dimensionsString = array2->getDimensionsString();
assert(dimensionsString.compare("3 3 3 ") == 0);
int values[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
array2->insert(0, &values[0], 11);
assert(array2->getSize() == 27);
dimensions = array2->getDimensions();
assert(dimensions.size() == 3);
assert(dimensions[0] == 3 && dimensions[1] == 3 && dimensions[2] == 3);
array2->pushBack(10);
assert(array2->getSize() == 28);
dimensions = array2->getDimensions();
assert(dimensions.size() == 1);
assert(dimensions[0] == 28);
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment