Commit 8858e32d authored by Andrew J. Burns (Cont's avatar Andrew J. Burns (Cont
Browse files

Revert "changes to array to allow for functions"

This reverts commit df13c70f.
parent df13c70f
......@@ -22,12 +22,9 @@
/*****************************************************************************/
#include <boost/tokenizer.hpp>
#include <boost/assign.hpp>
#include <limits>
#include <sstream>
#include <utility>
#include <stack>
#include <math.h>
#include "XdmfArray.hpp"
#include "XdmfArrayType.hpp"
#include "XdmfHDF5Controller.hpp"
......@@ -35,21 +32,6 @@
#include "XdmfVisitor.hpp"
#include "XdmfError.hpp"
std::string XdmfArray::mSupportedOperations = "|#()";
const std::string XdmfArray::mValidVariableChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_:.";
const std::string XdmfArray::mValidDigitChars = "-1234567890.";
//list the priorities for the operations, based on the order of operations
//the index of the corresponding operation in validOperationChars is the same as the index of its priority in this array
int XdmfArray::mOperationPriority [8] = {2, 1, 0, 0};
//the higher the value, the earlier the operation is evaluated in the order of operations
//with the exception of parenthesis which are evaluated as soon as the closing parenthesis is found
//note, it doesn't handle overloaded functions well. Will generate errors unless overload methods are typecast.
std::map<std::string, shared_ptr<XdmfArray> (*)(std::vector<shared_ptr<XdmfArray> >)> XdmfArray::arrayFunctions = boost::assign::map_list_of ("SUM", (shared_ptr<XdmfArray> (*)(std::vector<shared_ptr<XdmfArray> >))XdmfArray::sum) ("AVE", (shared_ptr<XdmfArray> (*)(std::vector<shared_ptr<XdmfArray> >))XdmfArray::ave);
std::map<char, shared_ptr<XdmfArray> (*)(shared_ptr<XdmfArray>, shared_ptr<XdmfArray>)> XdmfArray::operations = boost::assign::map_list_of ('|', XdmfArray::chunk) ('#', XdmfArray::interlace);
XDMF_CHILDREN_IMPLEMENTATION(XdmfArray,
XdmfHeavyDataController,
HeavyDataController,
......@@ -64,7 +46,7 @@ public:
}
void
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
return;
}
......@@ -85,7 +67,7 @@ public:
mArray->mArray);
}
private:
private:
XdmfArray * const mArray;
};
......@@ -100,7 +82,7 @@ public:
}
void
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
return;
}
......@@ -114,7 +96,7 @@ public:
template<typename T>
void
operator()(const boost::shared_array<const T> & array) const
operator()(const boost::shared_array<const T> &) const
{
mArray->internalizeArrayPointer();
boost::apply_visitor(*this,
......@@ -197,10 +179,10 @@ public:
}
shared_ptr<const XdmfArrayType>
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
if(mHeavyDataController) {
return mHeavyDataController->getType();
if(mHeavyDataController.size > 0) {
return mHeavyDataControllers[0]->getType();
}
return XdmfArrayType::Uninitialized();
}
......@@ -232,7 +214,7 @@ public:
}
unsigned int
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
return 0;
}
......@@ -246,7 +228,7 @@ public:
template<typename T>
unsigned int
operator()(const boost::shared_array<const T> & array) const
operator()(const boost::shared_array<const T> &) const
{
return 0;
}
......@@ -261,7 +243,7 @@ public:
}
const void *
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
return NULL;
}
......@@ -332,7 +314,7 @@ public:
}
std::string
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
return "";
}
......@@ -379,7 +361,7 @@ public:
}
void
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
mArray->initialize(mArrayToCopy->getArrayType());
boost::apply_visitor(*this,
......@@ -435,14 +417,14 @@ public:
}
void
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
return;
}
template<typename T>
void
operator()(const shared_ptr<std::vector<T> > & array) const
operator()(const shared_ptr<std::vector<T> > &) const
{
return;
}
......@@ -463,6 +445,33 @@ private:
XdmfArray * const mArray;
};
class XdmfArray::IsInitialized : public boost::static_visitor<bool> {
public:
IsInitialized()
{
}
bool
operator()(const boost::blank &) const
{
return false;
}
template<typename T>
bool
operator()(const shared_ptr<std::vector<T> > &) const
{
return true;
}
template<typename T>
bool
operator()(const T &) const
{
return true;
}
};
class XdmfArray::Reserve : public boost::static_visitor<void> {
public:
......@@ -474,7 +483,7 @@ public:
}
void
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
mArray->mTmpReserveSize = mSize;
}
......@@ -488,7 +497,7 @@ public:
template<typename T>
void
operator()(const boost::shared_array<const T> & array) const
operator()(const boost::shared_array<const T> &) const
{
mArray->internalizeArrayPointer();
boost::apply_visitor(*this,
......@@ -510,9 +519,9 @@ public:
}
unsigned int
operator()(const boost::blank & array) const
operator()(const boost::blank &) const
{
if(mArray->mHeavyDataControllers.size()>0) {
if(mArray->mHeavyDataControllers.size() > 0) {
return mArray->mHeavyDataControllers[0]->getSize();//modify this to compile all controllers
}
return 0;
......@@ -527,14 +536,14 @@ public:
template<typename T>
unsigned int
operator()(const boost::shared_array<const T> & array) const
operator()(const boost::shared_array<const T> &) const
{
return mArray->mArrayPointerNumValues;
}
private:
const XdmfArray * const mArray;
const XdmfArray * const mArray;
};
shared_ptr<XdmfArray>
......@@ -560,7 +569,7 @@ const std::string XdmfArray::ItemTag = "DataItem";
void
XdmfArray::clear()
{
boost::apply_visitor(Clear(this),
boost::apply_visitor(Clear(this),
mArray);
mDimensions.clear();
}
......@@ -574,734 +583,6 @@ XdmfArray::erase(const unsigned int index)
mDimensions.clear();
}
//This function and the functions it depends on are reimplemented in XdmfCore.i in order to properly interface with python.
//There are differences between the versions, but the overall algorithm remains mostly the same.
shared_ptr<XdmfArray>
XdmfArray::evaluateExpression(std::string expression, std::map<std::string, shared_ptr<XdmfArray> > variables)
{
std::stack<shared_ptr<XdmfArray> > valueStack;
std::stack<char> operationStack;
//string is parsed left to right
//elements of the same priority are evaluated right to left
for (int i = 0; i < expression.size(); i++)
{
if (mValidDigitChars.find(expression[i]) != std::string::npos)//found to be a digit
{
//progress until a non-digit is found
int valueStart = i;
while (mValidDigitChars.find(expression[i + 1]) != std::string::npos)
{
i++;
}
//push back to the value stack
shared_ptr<XdmfArray> valueArray = XdmfArray::New();
valueArray->insert(0, atof(expression.substr(valueStart, i + 1 - valueStart).c_str()));//use this to convert to double
valueStack.push(valueArray);
}
else if (mValidVariableChars.find(expression[i]) != std::string::npos)//found to be a variable
{
int valueStart = i;
//progress until a nonvariable value is found
while (mValidVariableChars.find(expression[i + 1]) != std::string::npos)
{
i++;
}
//convert to equivalent
if (variables.find(expression.substr(valueStart, i + 1 - valueStart)) == variables.end())
{
if (arrayFunctions.find(expression.substr(valueStart, i + 1 - valueStart)) == arrayFunctions.end())
{
XdmfError::message(XdmfError::FATAL,
"Error: Invalid Variable in evaluateExpression " + expression.substr(valueStart, i + 1 - valueStart));
}
else
{
std::string currentFunction = expression.substr(valueStart, i + 1 - valueStart);
//check if next character is an open parenthesis
if (expression[i+1] != '(')
{
XdmfError::message(XdmfError::FATAL,
"Error: No values supplied to function " + expression.substr(valueStart, i + 1 - valueStart));
}
//if it is grab the string between paranthesis
i = i + 2;
valueStart = i;
int numOpenParenthesis = 0;
while ((expression[i] != ')' || numOpenParenthesis) && i < expression.size())
{
if (expression[i] == '(')
{
numOpenParenthesis++;
}
else if (expression[i] == ')')
{
numOpenParenthesis--;
}
i++;
}
std::string functionParameters = expression.substr(valueStart, i - valueStart);
std::vector<shared_ptr<XdmfArray> > parameterVector;
//split that string at commas
size_t parameterSplit = 0;
while (parameterSplit != std::string::npos)
{
parameterSplit = 0;
parameterSplit = functionParameters.find_first_of(",", parameterSplit);
//feed the substrings to the parse function
if (parameterSplit == std::string::npos)
{
parameterVector.push_back(evaluateExpression(functionParameters, variables));
}
else
{
parameterVector.push_back(evaluateExpression(functionParameters.substr(0, parameterSplit), variables));
functionParameters = functionParameters.substr(parameterSplit+1);
}
}
valueStack.push(evaluateFunction(parameterVector, currentFunction));
}
}
else
{
//push equivalent to value stack
valueStack.push(variables.find(expression.substr(valueStart, i + 1 - valueStart))->second);
}
}
else if (mSupportedOperations.find(expression[i]) != std::string::npos)//found to be an operation
{
//pop operations off the stack until one of a lower or equal importance is found
if (operationStack.size() > 0)
{
if (expression[i] == ')')
{
//to close a parenthesis pop off all operations until another parentheis is found
while (operationStack.size() > 0 && operationStack.top() != '(')
{
if (valueStack.size() < 2)//must be at least two values for this loop to work properly
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Values in evaluateExpression");
}
else
{
shared_ptr<XdmfArray> val2 = valueStack.top();
valueStack.pop();
shared_ptr<XdmfArray> val1 = valueStack.top();
valueStack.pop();
valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
operationStack.pop();
}
}
operationStack.pop();
}
else if (expression[i] == '(')
{
//just add it if it's a start parenthesis
//nothing happens here in that case
//addition happens after the if statement
}
else
{
int operationLocation = getOperationPriority(expression[i]);
int topOperationLocation = getOperationPriority(operationStack.top());
//see order of operations to determine importance
while (operationStack.size() > 0 && operationLocation < topOperationLocation)
{
if (valueStack.size() < 2)//must be at least two values for this loop to work properly
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Values in evaluateExpression");
}
else
{
shared_ptr<XdmfArray> val2 = valueStack.top();
valueStack.pop();
shared_ptr<XdmfArray> val1 = valueStack.top();
valueStack.pop();
valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
operationStack.pop();
if (operationStack.size() == 0)
{
break;
}
topOperationLocation = getOperationPriority(operationStack.top());
}
}
}
}
if (expression[i] != ')')
{
//add the operation to the operation stack
operationStack.push(expression[i]);
}
}
//if not a value or operation the character is ignored
}
//empty what's left in the stacks before finishing
while (valueStack.size() > 1 && operationStack.size() > 0)
{
if (valueStack.size() < 2)//must be at least two values for this loop to work properly
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Values in evaluateExpression");
}
else
{
if(operationStack.top() == '(')
{
XdmfError::message(XdmfError::WARNING,
"Warning: Unpaired Parenthesis");
}
else
{
shared_ptr<XdmfArray> val2 = valueStack.top();
valueStack.pop();
shared_ptr<XdmfArray> val1 = valueStack.top();
valueStack.pop();
if (operationStack.size() == 0)
{
XdmfError::message(XdmfError::FATAL,
"Error: Not Enough Operators in evaluateExpression");
}
else
{
valueStack.push(evaluateOperation(val1, val2, operationStack.top()));
operationStack.pop();
}
}
}
}
//throw error if there's extra operations
if (operationStack.size() > 0)
{
XdmfError::message(XdmfError::WARNING,
"Warning: Left Over Operators in evaluateExpression");
}
if (valueStack.size() > 1)
{
XdmfError::message(XdmfError::WARNING,
"Warning: Left Over Values in evaluateExpression");
}
return valueStack.top();
}
shared_ptr<XdmfArray>
XdmfArray::evaluateOperation(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2, char operation)
{
if (operations.find(operation) != operations.end())
{
return (*(shared_ptr<XdmfArray>(*)(shared_ptr<XdmfArray>, shared_ptr<XdmfArray>))operations[operation])(val1, val2);
}
else
{
return shared_ptr<XdmfArray>();
}
}
int
XdmfArray::addOperation(char newoperator, shared_ptr<XdmfArray>(*operationref)(shared_ptr<XdmfArray>, shared_ptr<XdmfArray>), int priority)
{
if (newoperator == '(' || newoperator == ')')
{
XdmfError::message(XdmfError::FATAL,
"Error: Parenthesis can not be redefined");
}
//give warning if the operation already exists
size_t origsize = operations.size();
operations[newoperator] = operationref;//place reference in the associated location
if (origsize == operations.size())
{//it's nice to let people know they're doing this so they don't get surprised about changes in behavior
XdmfError::message(XdmfError::WARNING,
"Warning: Function Overwritten");
//overwrite the existing info for that operation
//add the priority to the specified location in the priority array
size_t priorityLocation = mSupportedOperations.find(newoperator);
mOperationPriority[priorityLocation] = priority;
}
else
{
//create new operation
//as long as the operation isn't a valid function character
if (mValidVariableChars.find(newoperator) != std::string::npos || mValidDigitChars.find(newoperator) != std::string::npos)
{
XdmfError::message(XdmfError::FATAL,
"Error: Operation Overlaps with Variables");
}
else //build the operation
{
//add operation to the supported character string
mSupportedOperations.push_back(newoperator);
int priorityArraySize = sizeof(mOperationPriority)/sizeof(int);
if (mSupportedOperations.size()-1 > priorityArraySize)//first check to see if the priority array is large enough
{
//if it isn't make it bigger, double size should be fine
int newArray [priorityArraySize*2];
std::copy(mOperationPriority, mOperationPriority+(priorityArraySize-1), newArray);
delete mOperationPriority;
*mOperationPriority = *newArray;
}
size_t priorityLocation = mSupportedOperations.find(newoperator);
mOperationPriority[priorityLocation] = priority;
}
}
return operations.size();
}
shared_ptr<XdmfArray>
XdmfArray::chunk(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2)
{
//join chunk (add the new array to the end of the first one)
//joins into new array and returns it
shared_ptr<XdmfArray> returnArray = XdmfArray::New();
returnArray->insert(0, val1, 0, val1->getSize(), 1, 1);
returnArray->insert(val1->getSize(), val2, 0, val2->getSize(), 1, 1);
return returnArray;
}
shared_ptr<XdmfArray>
XdmfArray::interlace(shared_ptr<XdmfArray> val1, shared_ptr<XdmfArray> val2)
{
//join interlace (evenly space the second array within the first one)
//builds a new array
shared_ptr<XdmfArray> returnArray = XdmfArray::New();
//resize to the combined size of both arrays
//determining what type to class it as in order to not lose data, and to still have the smallest data type of the two
shared_ptr<const XdmfArrayType> arrayType1 = val1->getArrayType();
shared_ptr<const XdmfArrayType> arrayType2 = val2->getArrayType();
if (arrayType1 == XdmfArrayType::Int8())
{
//if floats reclass as floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float32())
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float64())
{
double sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
//if uints reclass as ints of the appropriate size
else if (arrayType2 == XdmfArrayType::Int64() || arrayType2 == XdmfArrayType::UInt32())
{
long sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Int32() || arrayType2 == XdmfArrayType::UInt16())
{
int sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Int16() || arrayType2 == XdmfArrayType::UInt8())
{
short sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else
{
char sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
}
else if (arrayType1 == XdmfArrayType::Int16())
{
//if floats reclass as floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float32())
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float64())
{
double sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
//if uints reclass as ints of the appropriate size
else if (arrayType2 == XdmfArrayType::Int64() || arrayType2 == XdmfArrayType::UInt32())
{
long sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Int32() || arrayType2 == XdmfArrayType::UInt16())
{
int sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else
{
short sampleValue = 0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
}
else if (arrayType1 == XdmfArrayType::Int32())
{
//if floats reclass as floats of the appropriate size
if (arrayType2 == XdmfArrayType::String())
{
//string is the only compatible type here
std::string sampleValue = "";
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);
}
else if (arrayType2 == XdmfArrayType::Float32())
{
float sampleValue = 0.0;
returnArray->resize(val1->getSize()+val2->getSize(), sampleValue);