From 6d12ea03c30d8390922fe6502119021e03ea874d Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 00:26:39 -0400 Subject: [PATCH 01/19] ENH: Replace ArrayCalculator header/source with new type-rich API Rewrite ArrayCalculator.hpp with new enum classes (CalculatorErrorCode, CalculatorWarningCode, TokenType), value structs (Token, OperatorDef, CalcValue, RpnItem), parser class (ArrayCalculatorParser), and algorithm class (ArrayCalculator). The .cpp provides stub implementations so the algorithm files compile independently; ArrayCalculatorFilter.cpp will break until it is updated to use the new API in the next task. --- .../Filters/Algorithms/ArrayCalculator.cpp | 744 +----------------- .../Filters/Algorithms/ArrayCalculator.hpp | 218 ++++- 2 files changed, 227 insertions(+), 735 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 621911e38c..c7180f00e6 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -1,741 +1,69 @@ #include "ArrayCalculator.hpp" -#include "SimplnxCore/utils/ABSOperator.hpp" -#include "SimplnxCore/utils/ACosOperator.hpp" -#include "SimplnxCore/utils/ASinOperator.hpp" -#include "SimplnxCore/utils/ATanOperator.hpp" -#include "SimplnxCore/utils/AdditionOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" -#include "SimplnxCore/utils/CalculatorOperator.hpp" -#include "SimplnxCore/utils/CeilOperator.hpp" -#include "SimplnxCore/utils/CommaSeparator.hpp" -#include "SimplnxCore/utils/CosOperator.hpp" -#include "SimplnxCore/utils/DivisionOperator.hpp" -#include "SimplnxCore/utils/ExpOperator.hpp" -#include "SimplnxCore/utils/FloorOperator.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" -#include "SimplnxCore/utils/LnOperator.hpp" -#include "SimplnxCore/utils/Log10Operator.hpp" -#include "SimplnxCore/utils/LogOperator.hpp" -#include "SimplnxCore/utils/MaxOperator.hpp" -#include "SimplnxCore/utils/MinOperator.hpp" -#include "SimplnxCore/utils/MultiplicationOperator.hpp" -#include "SimplnxCore/utils/NegativeOperator.hpp" -#include "SimplnxCore/utils/PowOperator.hpp" -#include "SimplnxCore/utils/RightParenthesisItem.hpp" -#include "SimplnxCore/utils/RootOperator.hpp" -#include "SimplnxCore/utils/SinOperator.hpp" -#include "SimplnxCore/utils/SqrtOperator.hpp" -#include "SimplnxCore/utils/SubtractionOperator.hpp" -#include "SimplnxCore/utils/TanOperator.hpp" - -#include "simplnx/Common/TypesUtility.hpp" -#include "simplnx/DataStructure/DataArray.hpp" -#include "simplnx/Utilities/DataGroupUtilities.hpp" -#include "simplnx/Utilities/FilterUtilities.hpp" -#include "simplnx/Utilities/StringUtilities.hpp" - -#include +#include "simplnx/Common/Result.hpp" using namespace nx::core; -namespace -{ -struct CreateCalculatorArrayFunctor -{ - template - CalculatorItem::Pointer operator()(DataStructure& dataStructure, bool allocate, const IDataArray* iDataArrayPtr) - { - const auto* inputDataArray = dynamic_cast*>(iDataArrayPtr); - CalculatorItem::Pointer itemPtr = CalculatorArray::New(dataStructure, inputDataArray, ICalculatorArray::Array, allocate); - return itemPtr; - } -}; - -struct CopyArrayFunctor -{ - template - void operator()(DataStructure& dataStructure, const DataPath& calculatedArrayPath, const Float64Array* inputArray) - { - const auto& inputDataStore = inputArray->getDataStoreRef(); - if(nullptr != inputArray) - { - auto& convertedDataStore = dataStructure.getDataAsUnsafe>(calculatedArrayPath)->getDataStoreRef(); - - const usize count = inputDataStore.getSize(); - for(usize i = 0; i < count; i++) - { - if constexpr(std::is_same_v) - { - convertedDataStore[i] = inputDataStore[i]; - } - else - { - convertedDataStore[i] = static_cast(inputDataStore[i]); - } - } - } - } -}; - -struct InitializeArrayFunctor -{ - template - void operator()(DataStructure& dataStructure, const DataPath& calculatedArrayPath, const Float64Array* inputArray) - { - auto& convertedDataStore = dataStructure.getDataAsUnsafe>(calculatedArrayPath)->getDataStoreRef(); - if(nullptr != inputArray && inputArray->getSize() == 1) - { - if constexpr(std::is_same_v) - { - convertedDataStore.fill(inputArray->at(0)); - } - else - { - convertedDataStore.fill(static_cast(inputArray->at(0))); - } - } - } -}; - -void WrapFunctionArguments(std::vector& tokens) +// --------------------------------------------------------------------------- +// getOperatorRegistry (stub -- returns empty table) +// --------------------------------------------------------------------------- +const std::vector& nx::core::getOperatorRegistry() { - std::vector out; - out.reserve(tokens.size() * 2); - - for(size_t i = 0; i < tokens.size(); ++i) - { - const auto& tok = tokens[i]; - // Function call start: an Identifier followed by '(' - if(dynamic_cast(tok.get()) != nullptr && i + 1 < tokens.size() && dynamic_cast(tokens[i + 1].get()) != nullptr) - { - // Copy function name and '(' - out.push_back(tok); - out.push_back(tokens[++i]); - int depth = 1; - size_t argStart = out.size(); - - // Process until matching ')' - for(++i; i < tokens.size() && depth > 0; ++i) - { - auto cur = tokens[i]; - if(dynamic_cast(cur.get()) != nullptr) - { - ++depth; - out.push_back(cur); - } - else if(dynamic_cast(cur.get()) != nullptr) - { - --depth; - if(depth == 0) - { - // Close last argument - out.insert(out.begin() + argStart, LeftParenthesisItem::New()); - out.push_back(RightParenthesisItem::New()); - break; - } - out.push_back(cur); - } - else if(dynamic_cast(cur.get()) != nullptr && depth == 1) - { - // Wrap end of this argument, copy comma, start next - out.push_back(RightParenthesisItem::New()); - out.push_back(cur); - out.push_back(LeftParenthesisItem::New()); - } - else - { - out.push_back(cur); - } - } - --i; // we consumed the ')' - } - else - { - out.push_back(tok); - } - } - - tokens.swap(out); + static const std::vector s_Registry; + return s_Registry; } -} // namespace -// ----------------------------------------------------------------------------- -ArrayCalculator::ArrayCalculator(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ArrayCalculatorInputValues* inputValues) +// --------------------------------------------------------------------------- +// ArrayCalculatorParser +// --------------------------------------------------------------------------- +ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight) : m_DataStructure(dataStructure) -, m_InputValues(inputValues) -, m_ShouldCancel(shouldCancel) -, m_MessageHandler(mesgHandler) -{ -} - -// ----------------------------------------------------------------------------- -ArrayCalculator::~ArrayCalculator() noexcept = default; - -// ----------------------------------------------------------------------------- -const std::atomic_bool& ArrayCalculator::getCancel() -{ - return m_ShouldCancel; -} - -// ----------------------------------------------------------------------------- -Result<> ArrayCalculator::operator()() -{ - Result<> results; - - // Parse the infix expression from the user interface - ArrayCalculatorParser parser(m_DataStructure, m_InputValues->SelectedGroup, m_InputValues->InfixEquation, false); - std::vector parsedInfix; - Result<> parsedEquationResults = parser.parseInfixEquation(parsedInfix); - results.warnings() = parsedEquationResults.warnings(); - if(parsedEquationResults.invalid()) - { - results.errors() = parsedEquationResults.errors(); - return results; - } - if(parsedInfix.empty()) - { - results.errors().push_back(Error{-6550, "Error while parsing infix expression."}); - return results; - } - - // Convert the parsed infix expression into RPN - Result rpnResults = ArrayCalculatorParser::ToRPN(m_InputValues->InfixEquation, parsedInfix); - std::vector rpn = rpnResults.value(); - if(rpnResults.invalid() || rpn.empty()) - { - results.errors().push_back(Error{-6551, "Error while converting parsed infix expression to postfix notation"}); - return results; - } - - // Execute the RPN expression - DataPath temporaryCalculatedArrayPath = DataPath({m_InputValues->CalculatedArray.getTargetName() + "_TEMPORARY"}); - std::stack executionStack; - int totalItems = rpn.size(); - for(int rpnCount = 0; rpnCount < totalItems; rpnCount++) - { - m_MessageHandler({IFilter::Message::Type::Info, "Computing Operator " + StringUtilities::number(rpnCount + 1) + "/" + StringUtilities::number(totalItems)}); - - CalculatorItem::Pointer rpnItem = rpn[rpnCount]; - ICalculatorArray::Pointer calcArray = std::dynamic_pointer_cast(rpnItem); - if(nullptr != calcArray) - { - // This is an array - executionStack.push(calcArray); - } - else - { - // This is an operator - CalculatorOperator::Pointer rpnOperator = std::dynamic_pointer_cast(rpnItem); - - rpnOperator->calculate(parser.m_TemporaryDataStructure, m_InputValues->Units, temporaryCalculatedArrayPath, executionStack); - } - - if(getCancel()) - { - return results; - } - } - - // Grab the result from the stack - ICalculatorArray::Pointer arrayItem = ICalculatorArray::NullPointer(); - if(executionStack.size() != 1) - { - results.errors().push_back(Error{static_cast(CalculatorItem::ErrorCode::InvalidEquation), "The chosen infix equation is not a valid equation."}); - return results; - } - if(!executionStack.empty()) - { - arrayItem = executionStack.top(); - executionStack.pop(); - } - - if(arrayItem != ICalculatorArray::NullPointer()) - { - const Float64Array* resultArray = arrayItem->getArray(); - if(arrayItem->isNumber() && m_DataStructure.getDataAs(m_InputValues->CalculatedArray.getParent()) != nullptr) - { - ExecuteDataFunction(InitializeArrayFunctor{}, ConvertNumericTypeToDataType(m_InputValues->ScalarType), m_DataStructure, m_InputValues->CalculatedArray, resultArray); - } - else - { - ExecuteDataFunction(CopyArrayFunctor{}, ConvertNumericTypeToDataType(m_InputValues->ScalarType), m_DataStructure, m_InputValues->CalculatedArray, resultArray); - } - } - else - { - results.errors().push_back(Error{static_cast(CalculatorItem::ErrorCode::UnexpectedOutput), "Unexpected output item from chosen infix expression; the output item must be an array\n" - "Please contact the DREAM3D-NX developers for more information"}); - return results; - } - - return {}; -} - -ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStruct, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight) -: m_DataStructure(dataStruct) , m_SelectedGroupPath(selectedGroupPath) , m_InfixEquation(infixEquation) , m_IsPreflight(isPreflight) { - createSymbolMap(); -} - -// ----------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::parseInfixEquation(ParsedEquation& parsedInfix) -{ - parsedInfix.clear(); - Result<> results = {}; - std::vector itemList = getRegularExpressionMatches(); - - // Iterate through the QStringList and create the proper CalculatorItems - for(int i = 0; i < itemList.size(); i++) - { - std::string strItem = itemList[i]; - CalculatorItem::Pointer itemPtr = nullptr; - - bool ok = true; - double num; - try - { - num = std::stod(strItem); - } catch(std::exception& e) - { - ok = false; - } - if(ok) - { - // This is a numeric value - auto parsedNumericResults = parseNumericValue(strItem, parsedInfix, num); - results = MergeResults(results, parsedNumericResults); - if(results.invalid()) - { - parsedInfix.clear(); - return results; - } - } - else if(strItem == "-") - { - // This is a minus sign - auto parsedMinusResults = parseMinusSign(strItem, parsedInfix, i); - results = MergeResults(results, parsedMinusResults); - if(results.invalid()) - { - parsedInfix.clear(); - return results; - } - } - else if(StringUtilities::contains(strItem, "[") && StringUtilities::contains(strItem, "]")) - { - // This is an index operator - auto parsedIndexResults = parseIndexOperator(strItem, parsedInfix); - results = MergeResults(results, parsedIndexResults); - if(results.invalid()) - { - parsedInfix.clear(); - return results; - } - } - else - { - if(m_SymbolMap.find(strItem) != m_SymbolMap.end()) - { - itemPtr = m_SymbolMap[strItem]; - } - - if(nullptr != itemPtr) - { - // This is another type of operator - std::string ss = fmt::format("Item '{}' in the infix expression is the name of an array in the selected Attribute Matrix, but it is currently being used as a mathematical operator", strItem); - auto checkNameResults = checkForAmbiguousArrayName(strItem, ss); - results = MergeResults(results, checkNameResults); - if(results.invalid()) - { - parsedInfix.clear(); - return results; - } - - parsedInfix.push_back(itemPtr); - } - // It doesn't matter which path we use for the selected attribute matrix since we are only checking the target names - else if(ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, strItem) || (!strItem.empty() && strItem[0] == '\"' && strItem[strItem.size() - 1] == '\"')) - { - auto parsedArrayResults = parseArray(strItem, parsedInfix); - results = MergeResults(results, parsedArrayResults); - if(results.invalid()) - { - parsedInfix.clear(); - return results; - } - } - else - { - parsedInfix.clear(); - std::string ss = fmt::format("An unrecognized or invalid item '{}' was found in the chosen infix expression", strItem); - return MakeErrorResult(static_cast(CalculatorItem::ErrorCode::UnrecognizedItem), ss); - } - } - } - - ::WrapFunctionArguments(parsedInfix); - - // Return the parsed infix expression as a vector of CalculatorItems - return results; -} - -// ----------------------------------------------------------------------------- -std::vector ArrayCalculatorParser::getRegularExpressionMatches() -{ - // Parse all the items into a QVector of strings using a regular expression - std::vector itemList; - // Match all array names that start with two alphabetical characters and have spaces. Match all numbers, decimal or integer. - // Match one letter array names. Match all special character operators. - std::regex regExp(R"lit(("((\[)?\d+(\.\d+)?(\])?|(\[)?\.\d+(\])?|\w{1,1}((\w|\s|\d)*(\w|\d){1,1})?|\S)")|(((\[)?\d+(\.\d+)?(\])?|(\[)?\.\d+(\])?|\w{1,1}((\w|\s|\d)*(\w|\d){1,1})?|\S)))lit"); - - auto regExpMatchBegin = std::sregex_iterator(m_InfixEquation.begin(), m_InfixEquation.end(), regExp); - auto regExpMatchEnd = std::sregex_iterator(); - for(std::sregex_iterator i = regExpMatchBegin; i != regExpMatchEnd; ++i) - { - const std::smatch& match = *i; - itemList.push_back(match.str()); - } - - return itemList; } -// ----------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::parseNumericValue(std::string token, std::vector& parsedInfix, double number) +// --------------------------------------------------------------------------- +std::vector ArrayCalculatorParser::tokenize(const std::string& /*equation*/) { - // This is a number, so create an array with numOfTuples equal to 1 and set the value into it - Float64Array* ptr = Float64Array::CreateWithStore(m_TemporaryDataStructure, "INTERNAL_USE_ONLY_NumberArray" + StringUtilities::number(m_TemporaryDataStructure.getSize()), - std::vector{1}, std::vector{1}); - (*ptr)[0] = number; - CalculatorItem::Pointer itemPtr = CalculatorArray::New(m_TemporaryDataStructure, ptr, ICalculatorArray::Number, !m_IsPreflight); - parsedInfix.push_back(itemPtr); - - std::string ss = fmt::format("Item '{}' in the infix expression is the name of an array in the selected Attribute Matrix, but it is currently being used as a number", token); - return checkForAmbiguousArrayName(token, ss); + return {}; } -// ----------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::parseMinusSign(std::string token, std::vector& parsedInfix, int loopIdx) +// --------------------------------------------------------------------------- +Result<> ArrayCalculatorParser::parseAndValidate(std::vector& /*outTupleShape*/, std::vector& /*outComponentShape*/) { - CalculatorItem::Pointer itemPtr = nullptr; - - // This could be either a negative sign or subtraction sign, so we need to figure out which one it is - if(loopIdx == 0 || (((nullptr != std::dynamic_pointer_cast(parsedInfix.back()) && - std::dynamic_pointer_cast(parsedInfix.back())->getOperatorType() == CalculatorOperator::Binary) || - nullptr != std::dynamic_pointer_cast(parsedInfix.back()) || nullptr != std::dynamic_pointer_cast(parsedInfix.back())) && - nullptr == std::dynamic_pointer_cast(parsedInfix.back()))) - { - // By context, this is a negative sign - itemPtr = NegativeOperator::New(); - parsedInfix.push_back(itemPtr); - } - else - { - // By context, this is a subtraction sign - if(m_SymbolMap.find(token) != m_SymbolMap.end()) - { - itemPtr = m_SymbolMap[token]; - } - parsedInfix.push_back(itemPtr); - } - - std::string ss = fmt::format("Item '{}' in the infix expression is the name of an array in the selected attribute matrix, but it is currently being used as a mathematical operator", token); - return checkForAmbiguousArrayName(token, ss); + return MakeErrorResult(-1, "Not yet implemented"); } -// ----------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::parseIndexOperator(std::string token, std::vector& parsedInfix) +// --------------------------------------------------------------------------- +Result<> ArrayCalculatorParser::evaluateInto(DataStructure& /*dataStructure*/, const DataPath& /*outputPath*/, NumericType /*scalarType*/, CalculatorParameter::AngleUnits /*units*/) { - int idx = parsedInfix.size() - 1; - - std::string errorMsg = fmt::format("Index operator '{}' is not paired with a valid array name.", token); - int errCode = static_cast(CalculatorItem::ErrorCode::OrphanedComponent); - if(idx < 0) - { - return MakeErrorResult(errCode, errorMsg); - } - if(!parsedInfix[idx]->isICalculatorArray()) - { - return MakeErrorResult(errCode, errorMsg); - } - if(parsedInfix[idx]->isNumber()) - { - return MakeErrorResult(errCode, errorMsg); - } - - token = StringUtilities::replace(token, "[", ""); - token = StringUtilities::replace(token, "]", ""); - - int index = -1; - try - { - index = std::stoi(token); - } catch(std::exception& e) - { - std::string ss = "The chosen infix expression is not a valid expression"; - return MakeErrorResult(static_cast(CalculatorItem::ErrorCode::InvalidComponent), ss); - } - - ICalculatorArray::Pointer calcArray = std::dynamic_pointer_cast(parsedInfix.back()); - if(nullptr != calcArray && index >= calcArray->getArray()->getNumberOfComponents()) - { - std::string ss = fmt::format("'{}' has an component index that is out of range", calcArray->getArray()->getName()); - return MakeErrorResult(static_cast(CalculatorItem::ErrorCode::ComponentOutOfRange), ss); - } - - parsedInfix.pop_back(); - - Float64Array* reducedArray = calcArray->reduceToOneComponent(index, !m_IsPreflight); - CalculatorItem::Pointer itemPtr = CalculatorArray::New(m_TemporaryDataStructure, reducedArray, ICalculatorArray::Array, !m_IsPreflight); - parsedInfix.push_back(itemPtr); - - std::string ss = fmt::format("Item '{}' in the infix expression is the name of an array in the selected Attribute Matrix, but it is currently being used as an indexing operator", token); - return checkForAmbiguousArrayName(token, ss); + return MakeErrorResult(-1, "Not yet implemented"); } -// ----------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::parseArray(std::string token, std::vector& parsedInfix) +// --------------------------------------------------------------------------- +// ArrayCalculator +// --------------------------------------------------------------------------- +ArrayCalculator::ArrayCalculator(DataStructure& dataStructure, const IFilter::MessageHandler& mesgHandler, const std::atomic_bool& shouldCancel, ArrayCalculatorInputValues* inputValues) +: m_DataStructure(dataStructure) +, m_InputValues(inputValues) +, m_ShouldCancel(shouldCancel) +, m_MessageHandler(mesgHandler) { - int firstArray_NumTuples = -1; - std::string firstArray_Name = ""; - - token = StringUtilities::replace(token, "\"", ""); - if(!ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, token)) - { - std::string ss = fmt::format("The item '{}' is not the name of any valid array in the selected Attribute Matrix", token); - return MakeErrorResult(static_cast(CalculatorItem::ErrorCode::InvalidArrayName), ss); - } - - DataPath tokenArrayPath = m_SelectedGroupPath.empty() ? DataPath({token}) : m_SelectedGroupPath.createChildPath(token); - const auto* dataArray = m_DataStructure.getDataAs(tokenArrayPath); - if(firstArray_NumTuples < 0 && firstArray_Name.empty()) - { - firstArray_NumTuples = dataArray->getNumberOfTuples(); - firstArray_Name = dataArray->getName(); - } - else if(dataArray->getNumberOfTuples() != firstArray_NumTuples) - { - std::string ss = fmt::format("Arrays '{}' and '{}' in the infix expression have an inconsistent number of tuples", firstArray_Name, dataArray->getName()); - return MakeErrorResult(static_cast(CalculatorItem::ErrorCode::InconsistentTuples), ss); - } - - CalculatorItem::Pointer itemPtr = ExecuteDataFunction(CreateCalculatorArrayFunctor{}, dataArray->getDataType(), m_TemporaryDataStructure, !m_IsPreflight, dataArray); - parsedInfix.push_back(itemPtr); - return {}; } -// ----------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::checkForAmbiguousArrayName(const std::string& strItem, std::string warningMsg) -{ - if(m_IsPreflight && ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, strItem)) - { - warningMsg.append("\nTo treat this item as an array name, please add double quotes around the item (i.e. \"" + strItem + "\")."); - return MakeWarningVoidResult(static_cast(CalculatorItem::WarningCode::AmbiguousNameWarning), warningMsg); - } - return {}; -} +// --------------------------------------------------------------------------- +ArrayCalculator::~ArrayCalculator() noexcept = default; -// ----------------------------------------------------------------------------- -void ArrayCalculatorParser::createSymbolMap() +// --------------------------------------------------------------------------- +const std::atomic_bool& ArrayCalculator::getCancel() { - // Insert all items into the symbol map to use during expression parsing - { - LeftParenthesisItem::Pointer symbol = LeftParenthesisItem::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - RightParenthesisItem::Pointer symbol = RightParenthesisItem::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - CommaSeparator::Pointer symbol = CommaSeparator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - AdditionOperator::Pointer symbol = AdditionOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - SubtractionOperator::Pointer symbol = SubtractionOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - MultiplicationOperator::Pointer symbol = MultiplicationOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - DivisionOperator::Pointer symbol = DivisionOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - PowOperator::Pointer symbol = PowOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - ABSOperator::Pointer symbol = ABSOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - SinOperator::Pointer symbol = SinOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - CosOperator::Pointer symbol = CosOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - TanOperator::Pointer symbol = TanOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - ASinOperator::Pointer symbol = ASinOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - ACosOperator::Pointer symbol = ACosOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - ATanOperator::Pointer symbol = ATanOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - SqrtOperator::Pointer symbol = SqrtOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - RootOperator::Pointer symbol = RootOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - Log10Operator::Pointer symbol = Log10Operator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - LogOperator::Pointer symbol = LogOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - ExpOperator::Pointer symbol = ExpOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - LnOperator::Pointer symbol = LnOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - FloorOperator::Pointer symbol = FloorOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - CeilOperator::Pointer symbol = CeilOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - MinOperator::Pointer symbol = MinOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - MaxOperator::Pointer symbol = MaxOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } - { - NegativeOperator::Pointer symbol = NegativeOperator::New(); - m_SymbolMap[symbol->getInfixToken()] = symbol; - } + return m_ShouldCancel; } -// ----------------------------------------------------------------------------- -Result ArrayCalculatorParser::ToRPN(const std::string& unparsedInfixExpression, std::vector infixEquation) +// --------------------------------------------------------------------------- +Result<> ArrayCalculator::operator()() { - std::stack itemStack; - std::vector rpnEquation; - - bool* oneComponent = nullptr; - - // Iterate through the infix expression items - for(int i = 0; i < infixEquation.size(); i++) - { - CalculatorItem::Pointer calcItem = infixEquation[i]; - if(nullptr != std::dynamic_pointer_cast(calcItem)) - { - ICalculatorArray::Pointer arrayItem = std::dynamic_pointer_cast(calcItem); - - // This is a number or array, so push it onto the rpn expression output - rpnEquation.push_back(arrayItem); - } - else if(nullptr != std::dynamic_pointer_cast(calcItem)) - { - // This is a left parenthesis, so push it onto the item stack - itemStack.push(calcItem); - } - else if(nullptr != std::dynamic_pointer_cast(calcItem)) - { - // This is a right parenthesis, so push operators from the item stack onto the rpn expression output until we get to the left parenthesis - while(!itemStack.empty() && nullptr == std::dynamic_pointer_cast(itemStack.top())) - { - rpnEquation.push_back(itemStack.top()); - itemStack.pop(); - } - - // Discard the left parenthesis that we found - itemStack.pop(); - } - else if(nullptr != std::dynamic_pointer_cast(calcItem)) - { - // This is a comma, so we want to continue without adding it to anything - continue; - } - else - { - // This is an operator - CalculatorOperator::Pointer incomingOperator = std::dynamic_pointer_cast(calcItem); - - if(!itemStack.empty()) - { - /* If the operator's precedence is lower than the precedence of the operator on top of the item stack, push the operator at the top - of the item stack onto the rpn expression output. Keeping doing this until there isn't another operator at the top of the item - stack or the operator has a higher precedence than the one currently on top of the stack */ - CalculatorOperator::Pointer topOperator = std::dynamic_pointer_cast(itemStack.top()); - while(nullptr != topOperator && !incomingOperator->hasHigherPrecedence(topOperator)) - { - rpnEquation.push_back(itemStack.top()); - itemStack.pop(); - if(!itemStack.empty()) - { - topOperator = std::dynamic_pointer_cast(itemStack.top()); - } - else - { - topOperator = nullptr; - } - } - } - - // Push the operator onto the rpn expression output. - itemStack.push(calcItem); - } - } - - /* After we are done iterating through the infix expression items, keep transferring items from the item stack to the - rpn expression output until the stack is empty. */ - while(!itemStack.empty()) - { - CalculatorItem::Pointer item = itemStack.top(); - itemStack.pop(); - if(nullptr != std::dynamic_pointer_cast(item)) - { - std::string ss = fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'", unparsedInfixExpression); - return MakeErrorResult(static_cast(CalculatorItem::ErrorCode::MismatchedParentheses), ss); - } - - rpnEquation.push_back(item); - } - - delete oneComponent; - - return {std::move(rpnEquation)}; + return MakeErrorResult(-1, "Not yet implemented"); } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp index 26020a5abe..afee9c63a4 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp @@ -1,18 +1,174 @@ #pragma once #include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorItem.hpp" -#include "simplnx/DataStructure/AttributeMatrix.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/DataStructure/DataStructure.hpp" #include "simplnx/Filter/IFilter.hpp" #include "simplnx/Parameters/CalculatorParameter.hpp" #include "simplnx/Parameters/NumericTypeParameter.hpp" +#include +#include +#include +#include + namespace nx::core { +// --------------------------------------------------------------------------- +// Error codes preserved from the legacy CalculatorItem::ErrorCode enum +// --------------------------------------------------------------------------- +enum class CalculatorErrorCode : int +{ + Success = 0, + InvalidEquation = -4009, + InvalidComponent = -4010, + EmptyEquation = -4011, + EmptyCalArray = -4012, + EmptySelMatrix = -4013, + LostAttrMatrix = -4014, + IncorrectTupleCount = -4015, + InconsistentTuples = -4016, + UnrecognizedItem = -4017, + MismatchedParentheses = -4018, + UnexpectedOutput = -4019, + ComponentOutOfRange = -4020, + InvalidArrayName = -4022, + InconsistentIndexing = -4023, + InconsistentCompDims = -4024, + AttrArrayZeroTuplesWarning = -4025, + OrphanedComponent = -4026, + OperatorNoLeftValue = -4027, + OperatorNoRightValue = -4028, + OperatorNoOpeningParen = -4029, + OperatorNoClosingParen = -4030, + NoNumericArguments = -4031, + MissingArguments = -4032, + NotEnoughArguments = -4033, + TooManyArguments = -4034, + InvalidSymbol = -4035, + NoPrecedingUnaryOperator = -4036, + InvalidOutputArrayType = -4037, + AttributeMatrixInsertionError = -4038, + AmbiguousArrayName = -4039, + TupleOutOfRange = -4040 +}; + +// --------------------------------------------------------------------------- +// Warning codes preserved from the legacy CalculatorItem::WarningCode enum +// --------------------------------------------------------------------------- +enum class CalculatorWarningCode : int +{ + None = 0, + NumericValueWarning = -5010, + AmbiguousNameWarning = -5011 +}; + +// --------------------------------------------------------------------------- +// Lexer token types +// --------------------------------------------------------------------------- +enum class TokenType +{ + Number, + Identifier, + QuotedString, + Plus, + Minus, + Star, + Slash, + Caret, + Percent, + LParen, + RParen, + LBracket, + RBracket, + Comma +}; + +// --------------------------------------------------------------------------- +// A single token produced by the lexer +// --------------------------------------------------------------------------- +struct SIMPLNXCORE_EXPORT Token +{ + TokenType type; + std::string text; + size_t position = 0; +}; + +// --------------------------------------------------------------------------- +// Definition of an operator or function in the calculator language +// --------------------------------------------------------------------------- +struct SIMPLNXCORE_EXPORT OperatorDef +{ + std::string token; + + enum Kind + { + BinaryInfix, + Function, + UnaryPrefix + } kind; + + int precedence; + int numArgs; + + enum Associativity + { + Left, + Right + } associativity = Left; + + enum TrigMode + { + None, + ForwardTrig, + InverseTrig + } trigMode = None; + + std::function unaryOp; + std::function binaryOp; +}; + +// --------------------------------------------------------------------------- +// A value that lives on the evaluation stack (either a scalar or an array) +// --------------------------------------------------------------------------- +struct SIMPLNXCORE_EXPORT CalcValue +{ + enum class Kind + { + Number, + Array + } kind; + + DataObject::IdType arrayId; +}; + +// --------------------------------------------------------------------------- +// A single item in the RPN (reverse-polish notation) evaluation sequence +// --------------------------------------------------------------------------- +struct SIMPLNXCORE_EXPORT RpnItem +{ + enum class Type + { + Value, + Operator, + ComponentExtract + } type; + + CalcValue value; + const OperatorDef* op = nullptr; + int componentIndex = -1; +}; + +// --------------------------------------------------------------------------- +// Returns the global table of all supported operators and functions +// --------------------------------------------------------------------------- +SIMPLNXCORE_EXPORT const std::vector& getOperatorRegistry(); + +// --------------------------------------------------------------------------- +// Input values passed from ArrayCalculatorFilter to the algorithm +// --------------------------------------------------------------------------- struct SIMPLNXCORE_EXPORT ArrayCalculatorInputValues { DataPath SelectedGroup; @@ -22,42 +178,50 @@ struct SIMPLNXCORE_EXPORT ArrayCalculatorInputValues DataPath CalculatedArray; }; +// --------------------------------------------------------------------------- +// Parses and validates an infix calculator equation, then evaluates it +// --------------------------------------------------------------------------- class SIMPLNXCORE_EXPORT ArrayCalculatorParser { public: - using ParsedEquation = std::vector; - - ArrayCalculatorParser(const DataStructure& dataStruct, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight); - - Result<> parseInfixEquation(ParsedEquation& parsedInfix); - - static Result ToRPN(const std::string& unparsedInfixExpression, std::vector infixEquation); - - friend class ArrayCalculator; - -protected: - std::vector getRegularExpressionMatches(); - Result<> parseNumericValue(std::string token, std::vector& parsedInfix, double number); - Result<> parseMinusSign(std::string token, std::vector& parsedInfix, int loopIdx); - Result<> parseIndexOperator(std::string token, std::vector& parsedInfix); - Result<> parseArray(std::string token, std::vector& parsedInfix); - Result<> checkForAmbiguousArrayName(const std::string& strItem, std::string warningMsg); + ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight); + ~ArrayCalculatorParser() noexcept = default; + + ArrayCalculatorParser(const ArrayCalculatorParser&) = delete; + ArrayCalculatorParser(ArrayCalculatorParser&&) noexcept = delete; + ArrayCalculatorParser& operator=(const ArrayCalculatorParser&) = delete; + ArrayCalculatorParser& operator=(ArrayCalculatorParser&&) noexcept = delete; + + /** + * @brief Tokenises, parses, and validates the infix equation. + * On success the output tuple and component shapes are written to the + * out-parameters so the filter can create the output array in preflight. + */ + Result<> parseAndValidate(std::vector& outTupleShape, std::vector& outComponentShape); + + /** + * @brief Evaluates the already-parsed equation and writes the result into + * the output array at @p outputPath inside @p dataStructure. + */ + Result<> evaluateInto(DataStructure& dataStructure, const DataPath& outputPath, NumericType scalarType, CalculatorParameter::AngleUnits units); + + /** + * @brief Pure lexer -- splits an equation string into tokens. + */ + static std::vector tokenize(const std::string& equation); private: const DataStructure& m_DataStructure; - DataStructure m_TemporaryDataStructure; // data structure for holding the temporary calculator array items + DataStructure m_TempDataStructure; DataPath m_SelectedGroupPath; std::string m_InfixEquation; bool m_IsPreflight; - - std::map> m_SymbolMap; - - void createSymbolMap(); + usize m_ScratchCounter = 0; }; -/** - * @class - */ +// --------------------------------------------------------------------------- +// Top-level algorithm class invoked by ArrayCalculatorFilter::executeImpl() +// --------------------------------------------------------------------------- class SIMPLNXCORE_EXPORT ArrayCalculator { public: From 1a7a9bca6bd7c9c344e8ac5073955709d31d36b6 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 00:29:13 -0400 Subject: [PATCH 02/19] ENH: Implement ArrayCalculatorParser::tokenize() and add tokenizer unit tests Single-pass character scanner that produces tokens for numbers, identifiers, quoted strings, operators, brackets, and commas with position tracking. --- .../Filters/Algorithms/ArrayCalculator.cpp | 126 +++++++++++++++++- .../SimplnxCore/test/ArrayCalculatorTest.cpp | 116 ++++++++++++++++ 2 files changed, 240 insertions(+), 2 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index c7180f00e6..858708f470 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -25,9 +25,131 @@ ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStructure, } // --------------------------------------------------------------------------- -std::vector ArrayCalculatorParser::tokenize(const std::string& /*equation*/) +std::vector ArrayCalculatorParser::tokenize(const std::string& equation) { - return {}; + std::vector tokens; + const size_t len = equation.size(); + size_t i = 0; + + while(i < len) + { + const char c = equation[i]; + + // 1. Skip whitespace + if(std::isspace(static_cast(c))) + { + ++i; + continue; + } + + // 2. Numbers: starts with digit, or dot followed by a digit + if(std::isdigit(static_cast(c)) || (c == '.' && i + 1 < len && std::isdigit(static_cast(equation[i + 1])))) + { + size_t start = i; + bool hasDot = false; + while(i < len && (std::isdigit(static_cast(equation[i])) || equation[i] == '.')) + { + if(equation[i] == '.') + { + if(hasDot) + { + break; + } + hasDot = true; + } + ++i; + } + tokens.push_back({TokenType::Number, equation.substr(start, i - start), start}); + continue; + } + + // 3. Identifiers: start with letter or underscore + if(std::isalpha(static_cast(c)) || c == '_') + { + size_t start = i; + while(i < len && (std::isalnum(static_cast(equation[i])) || equation[i] == '_')) + { + ++i; + } + tokens.push_back({TokenType::Identifier, equation.substr(start, i - start), start}); + continue; + } + + // 4. Quoted strings + if(c == '"') + { + size_t start = i; + ++i; // skip opening quote + size_t contentStart = i; + while(i < len && equation[i] != '"') + { + ++i; + } + std::string content = equation.substr(contentStart, i - contentStart); + if(i < len) + { + ++i; // skip closing quote + } + tokens.push_back({TokenType::QuotedString, content, start}); + continue; + } + + // 5. Single-character operators + TokenType opType; + bool isOperator = true; + switch(c) + { + case '+': + opType = TokenType::Plus; + break; + case '-': + opType = TokenType::Minus; + break; + case '*': + opType = TokenType::Star; + break; + case '/': + opType = TokenType::Slash; + break; + case '^': + opType = TokenType::Caret; + break; + case '%': + opType = TokenType::Percent; + break; + case '(': + opType = TokenType::LParen; + break; + case ')': + opType = TokenType::RParen; + break; + case '[': + opType = TokenType::LBracket; + break; + case ']': + opType = TokenType::RBracket; + break; + case ',': + opType = TokenType::Comma; + break; + default: + isOperator = false; + break; + } + + if(isOperator) + { + tokens.push_back({opType, std::string(1, c), i}); + ++i; + continue; + } + + // 6. Unknown characters: produce an Identifier token + tokens.push_back({TokenType::Identifier, std::string(1, c), i}); + ++i; + } + + return tokens; } // --------------------------------------------------------------------------- diff --git a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp index ea16fb20ea..70bd213ea8 100644 --- a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp +++ b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp @@ -1,3 +1,4 @@ +#include "SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp" #include "SimplnxCore/Filters/ArrayCalculatorFilter.hpp" #include "SimplnxCore/SimplnxCore_test_dirs.hpp" #include "SimplnxCore/utils/CalculatorItem.hpp" @@ -876,3 +877,118 @@ TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Filter Execution") SingleComponentArrayCalculatorTest2(); MultiComponentArrayCalculatorTest(); } + +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Tokenizer") +{ + using TT = nx::core::TokenType; + + SECTION("Simple arithmetic") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("3 + 4.5"); + REQUIRE(tokens.size() == 3); + REQUIRE(tokens[0].type == TT::Number); + REQUIRE(tokens[0].text == "3"); + REQUIRE(tokens[0].position == 0); + REQUIRE(tokens[1].type == TT::Plus); + REQUIRE(tokens[1].position == 2); + REQUIRE(tokens[2].type == TT::Number); + REQUIRE(tokens[2].text == "4.5"); + REQUIRE(tokens[2].position == 4); + } + + SECTION("Single-word identifiers") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("Spaced Array + 1"); + REQUIRE(tokens.size() == 4); + REQUIRE(tokens[0].type == TT::Identifier); + REQUIRE(tokens[0].text == "Spaced"); + REQUIRE(tokens[1].type == TT::Identifier); + REQUIRE(tokens[1].text == "Array"); + REQUIRE(tokens[2].type == TT::Plus); + REQUIRE(tokens[3].type == TT::Number); + REQUIRE(tokens[3].text == "1"); + } + + SECTION("Quoted string") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("\"CellData/Confidence Index\" + 1"); + REQUIRE(tokens.size() == 3); + REQUIRE(tokens[0].type == TT::QuotedString); + REQUIRE(tokens[0].text == "CellData/Confidence Index"); + REQUIRE(tokens[1].type == TT::Plus); + REQUIRE(tokens[2].type == TT::Number); + } + + SECTION("Brackets and comma") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("Array[3, 2]"); + REQUIRE(tokens.size() == 6); + REQUIRE(tokens[0].type == TT::Identifier); + REQUIRE(tokens[0].text == "Array"); + REQUIRE(tokens[1].type == TT::LBracket); + REQUIRE(tokens[2].type == TT::Number); + REQUIRE(tokens[2].text == "3"); + REQUIRE(tokens[3].type == TT::Comma); + REQUIRE(tokens[4].type == TT::Number); + REQUIRE(tokens[4].text == "2"); + REQUIRE(tokens[5].type == TT::RBracket); + } + + SECTION("All operator tokens") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("+ - * / ^ %"); + REQUIRE(tokens.size() == 6); + REQUIRE(tokens[0].type == TT::Plus); + REQUIRE(tokens[1].type == TT::Minus); + REQUIRE(tokens[2].type == TT::Star); + REQUIRE(tokens[3].type == TT::Slash); + REQUIRE(tokens[4].type == TT::Caret); + REQUIRE(tokens[5].type == TT::Percent); + } + + SECTION("Decimal starting with dot") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize(".345"); + REQUIRE(tokens.size() == 1); + REQUIRE(tokens[0].type == TT::Number); + REQUIRE(tokens[0].text == ".345"); + } + + SECTION("Complex expression") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("sin(pi / 2)"); + REQUIRE(tokens.size() == 6); + REQUIRE(tokens[0].type == TT::Identifier); + REQUIRE(tokens[0].text == "sin"); + REQUIRE(tokens[1].type == TT::LParen); + REQUIRE(tokens[2].type == TT::Identifier); + REQUIRE(tokens[2].text == "pi"); + REQUIRE(tokens[3].type == TT::Slash); + REQUIRE(tokens[4].type == TT::Number); + REQUIRE(tokens[4].text == "2"); + REQUIRE(tokens[5].type == TT::RParen); + } + + SECTION("Negative number tokenizes as minus + number") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("-3.14"); + REQUIRE(tokens.size() == 2); + REQUIRE(tokens[0].type == TT::Minus); + REQUIRE(tokens[1].type == TT::Number); + REQUIRE(tokens[1].text == "3.14"); + } + + SECTION("Empty string") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize(""); + REQUIRE(tokens.empty()); + } + + SECTION("Parentheses") + { + auto tokens = nx::core::ArrayCalculatorParser::tokenize("(3+4)"); + REQUIRE(tokens.size() == 5); + REQUIRE(tokens[0].type == TT::LParen); + REQUIRE(tokens[4].type == TT::RParen); + } +} From 98bc131afa5e09ebd62a4a6e366eb4de8101b7f3 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 00:30:51 -0400 Subject: [PATCH 03/19] ENH: Implement operator registry with all 23 operators for ArrayCalculator Populate getOperatorRegistry() with the complete table of binary infix operators (+, -, *, /, %, ^), unary math functions (abs, sqrt, ceil, floor, exp, ln, log10), trig functions (sin, cos, tan, asin, acos, atan), and binary functions (log, root, min, max). log10 is placed before log in the vector so prefix-based identifier matching resolves correctly. --- .../Filters/Algorithms/ArrayCalculator.cpp | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 858708f470..86ddf05914 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -2,14 +2,59 @@ #include "simplnx/Common/Result.hpp" +#include +#include + using namespace nx::core; // --------------------------------------------------------------------------- -// getOperatorRegistry (stub -- returns empty table) +// getOperatorRegistry // --------------------------------------------------------------------------- const std::vector& nx::core::getOperatorRegistry() { - static const std::vector s_Registry; + static const std::vector s_Registry = []() + { + std::vector reg; + reg.reserve(23); + + // ---- Binary infix operators ---- + reg.push_back({"+", OperatorDef::BinaryInfix, 1, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return a + b; }}); + reg.push_back({"-", OperatorDef::BinaryInfix, 1, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return a - b; }}); + reg.push_back({"*", OperatorDef::BinaryInfix, 2, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return a * b; }}); + reg.push_back({"/", OperatorDef::BinaryInfix, 2, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return a / b; }}); + reg.push_back({"%", OperatorDef::BinaryInfix, 2, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return std::fmod(a, b); }}); + reg.push_back({"^", OperatorDef::BinaryInfix, 3, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return std::pow(a, b); }}); + + // ---- Unary functions (1-arg) ---- + reg.push_back({"abs", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::None, [](double x) { return std::abs(x); }, nullptr}); + reg.push_back({"sqrt", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::None, [](double x) { return std::sqrt(x); }, nullptr}); + reg.push_back({"ceil", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::None, [](double x) { return std::ceil(x); }, nullptr}); + reg.push_back({"floor", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::None, [](double x) { return std::floor(x); }, nullptr}); + reg.push_back({"exp", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::None, [](double x) { return std::exp(x); }, nullptr}); + reg.push_back({"ln", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::None, [](double x) { return std::log(x); }, nullptr}); + reg.push_back({"log10", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::None, [](double x) { return std::log10(x); }, nullptr}); + + // ---- Trig functions (1-arg, ForwardTrig) ---- + reg.push_back({"sin", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::ForwardTrig, [](double x) { return std::sin(x); }, nullptr}); + reg.push_back({"cos", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::ForwardTrig, [](double x) { return std::cos(x); }, nullptr}); + reg.push_back({"tan", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::ForwardTrig, [](double x) { return std::tan(x); }, nullptr}); + + // ---- Inverse trig functions (1-arg, InverseTrig) ---- + reg.push_back({"asin", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::InverseTrig, [](double x) { return std::asin(x); }, nullptr}); + reg.push_back({"acos", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::InverseTrig, [](double x) { return std::acos(x); }, nullptr}); + reg.push_back({"atan", OperatorDef::Function, 5, 1, OperatorDef::Left, OperatorDef::InverseTrig, [](double x) { return std::atan(x); }, nullptr}); + + // ---- Binary functions (2-arg) ---- + // NOTE: log (2-arg) must come AFTER log10 so that prefix matching during + // identifier resolution checks "log10" before "log". + reg.push_back({"log", OperatorDef::Function, 5, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double base, double val) { return std::log(val) / std::log(base); }}); + reg.push_back({"root", OperatorDef::Function, 5, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double val, double n) { return std::pow(val, 1.0 / n); }}); + reg.push_back({"min", OperatorDef::Function, 5, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return std::min(a, b); }}); + reg.push_back({"max", OperatorDef::Function, 5, 2, OperatorDef::Left, OperatorDef::None, nullptr, [](double a, double b) { return std::max(a, b); }}); + + return reg; + }(); + return s_Registry; } From 3165b415b7020de510b2403313ca2b3efc7c9e4d Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 00:46:52 -0400 Subject: [PATCH 04/19] ENH: Implement parser for ArrayCalculator rewrite Add the core parsing logic that converts tokens into typed ParsedItems ready for shunting-yard conversion. Includes multi-word identifier merging, identifier resolution with priority chain (operator > constant > selected group array > unique DataStructure array), bracket indexing for component and tuple+component extraction, minus sign disambiguation (unary negative vs binary subtraction), WrapFunctionArguments for multi-arg functions, and validation (matched parentheses, consistent tuple counts and component shapes). --- .../Filters/Algorithms/ArrayCalculator.cpp | 955 +++++++++++++++++- .../Filters/Algorithms/ArrayCalculator.hpp | 41 + 2 files changed, 994 insertions(+), 2 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 86ddf05914..32f59b8076 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -1,12 +1,226 @@ #include "ArrayCalculator.hpp" #include "simplnx/Common/Result.hpp" +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataStore.hpp" +#include "simplnx/Utilities/DataGroupUtilities.hpp" +#include "simplnx/Utilities/FilterUtilities.hpp" #include #include +#include using namespace nx::core; +// =========================================================================== +// Anonymous namespace: ParsedItem, helper functions, functors +// =========================================================================== +namespace +{ + +// --------------------------------------------------------------------------- +// Intermediate representation used between parsing and shunting-yard. +// Includes parentheses and commas that the final RpnItem list does not. +// --------------------------------------------------------------------------- +struct ParsedItem +{ + enum class Kind + { + Value, + Operator, + LParen, + RParen, + Comma, + ComponentExtract + } kind; + + CalcValue value{CalcValue::Kind::Number, 0}; + const OperatorDef* op = nullptr; + int componentIndex = -1; + bool isNegativePrefix = false; +}; + +// --------------------------------------------------------------------------- +// The static unary negative OperatorDef (not in the registry) +// --------------------------------------------------------------------------- +const OperatorDef& getUnaryNegativeOp() +{ + static const OperatorDef s_UnaryNeg = {"neg", OperatorDef::UnaryPrefix, 4, 1, OperatorDef::Right, OperatorDef::None, [](double x) { return -x; }, nullptr}; + return s_UnaryNeg; +} + +// --------------------------------------------------------------------------- +// Look up an operator/function in the registry by exact token match +// --------------------------------------------------------------------------- +const OperatorDef* findOperatorByToken(const std::string& token) +{ + const auto& registry = getOperatorRegistry(); + for(const auto& opDef : registry) + { + if(opDef.token == token) + { + return &opDef; + } + } + return nullptr; +} + +// --------------------------------------------------------------------------- +// Map single-character TokenType to the operator registry token string +// --------------------------------------------------------------------------- +const OperatorDef* operatorDefForSymbolToken(TokenType type) +{ + switch(type) + { + case TokenType::Plus: + return findOperatorByToken("+"); + case TokenType::Minus: + return findOperatorByToken("-"); + case TokenType::Star: + return findOperatorByToken("*"); + case TokenType::Slash: + return findOperatorByToken("/"); + case TokenType::Caret: + return findOperatorByToken("^"); + case TokenType::Percent: + return findOperatorByToken("%"); + default: + return nullptr; + } +} + +// --------------------------------------------------------------------------- +// Search the entire DataStructure for IDataArrays with a given name. +// Returns all DataPaths where a matching array is found. +// --------------------------------------------------------------------------- +std::vector findArraysByName(const DataStructure& ds, const std::string& name) +{ + std::vector results; + + // Search recursively from the root + auto allPaths = GetAllChildDataPathsRecursive(ds, DataPath{}, DataObject::Type::DataArray); + if(allPaths.has_value()) + { + for(const auto& path : allPaths.value()) + { + if(path.getTargetName() == name) + { + results.push_back(path); + } + } + } + + return results; +} + +// --------------------------------------------------------------------------- +// Functor to copy an IDataArray of any numeric type into a Float64Array +// --------------------------------------------------------------------------- +struct CopyToFloat64Functor +{ + template + void operator()(const IDataArray& sourceArray, Float64Array& destArray) + { + const auto& typedSource = dynamic_cast&>(sourceArray); + const usize totalElements = typedSource.getSize(); + for(usize i = 0; i < totalElements; i++) + { + destArray[i] = static_cast(typedSource.at(i)); + } + } +}; + +// --------------------------------------------------------------------------- +// Check whether the previous ParsedItem is a binary operator +// --------------------------------------------------------------------------- +bool isBinaryOp(const ParsedItem& item) +{ + return item.kind == ParsedItem::Kind::Operator && item.op != nullptr && item.op->kind == OperatorDef::BinaryInfix && !item.isNegativePrefix; +} + +// --------------------------------------------------------------------------- +// WrapFunctionArguments: for each function call in the parsed item list, +// wrap each comma-separated argument in extra parentheses so that the +// shunting-yard algorithm processes them correctly. +// +// Example: sin(a + b) stays as sin((a + b)) +// log(a, b) becomes log((a), (b)) +// --------------------------------------------------------------------------- +void wrapFunctionArguments(std::vector& items) +{ + std::vector out; + out.reserve(items.size() * 2); + + for(size_t i = 0; i < items.size(); ++i) + { + const auto& item = items[i]; + + // Detect: Function operator followed by LParen + if(item.kind == ParsedItem::Kind::Operator && item.op != nullptr && item.op->kind == OperatorDef::Function && i + 1 < items.size() && items[i + 1].kind == ParsedItem::Kind::LParen) + { + // Copy function and '(' + out.push_back(item); + out.push_back(items[++i]); + int depth = 1; + size_t argStart = out.size(); + + // Process until matching ')' + for(++i; i < items.size() && depth > 0; ++i) + { + const auto& cur = items[i]; + if(cur.kind == ParsedItem::Kind::LParen) + { + ++depth; + out.push_back(cur); + } + else if(cur.kind == ParsedItem::Kind::RParen) + { + --depth; + if(depth == 0) + { + // Close last argument with wrapping parens + ParsedItem lp; + lp.kind = ParsedItem::Kind::LParen; + out.insert(out.begin() + static_cast(argStart), lp); + + ParsedItem rp; + rp.kind = ParsedItem::Kind::RParen; + out.push_back(rp); + break; + } + out.push_back(cur); + } + else if(cur.kind == ParsedItem::Kind::Comma && depth == 1) + { + // End this argument, copy comma, start next argument + ParsedItem rp; + rp.kind = ParsedItem::Kind::RParen; + out.push_back(rp); + + out.push_back(cur); + + ParsedItem lp; + lp.kind = ParsedItem::Kind::LParen; + out.push_back(lp); + } + else + { + out.push_back(cur); + } + } + --i; // we consumed the ')' in the inner loop + } + else + { + out.push_back(item); + } + } + + items.swap(out); +} + +} // anonymous namespace + // --------------------------------------------------------------------------- // getOperatorRegistry // --------------------------------------------------------------------------- @@ -198,9 +412,746 @@ std::vector ArrayCalculatorParser::tokenize(const std::string& equation) } // --------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::parseAndValidate(std::vector& /*outTupleShape*/, std::vector& /*outComponentShape*/) +std::string ArrayCalculatorParser::nextScratchName() { - return MakeErrorResult(-1, "Not yet implemented"); + return "_calc_" + std::to_string(m_ScratchCounter++); +} + +// --------------------------------------------------------------------------- +DataObject::IdType ArrayCalculatorParser::createScalarInTemp(double value) +{ + auto* arr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), std::vector{1}, std::vector{1}); + (*arr)[0] = value; + return arr->getId(); +} + +// --------------------------------------------------------------------------- +DataObject::IdType ArrayCalculatorParser::copyArrayToTemp(const IDataArray& sourceArray) +{ + auto tupleShape = sourceArray.getTupleShape(); + auto compShape = sourceArray.getComponentShape(); + std::string scratchName = nextScratchName(); + + auto* destArr = Float64Array::CreateWithStore(m_TempDataStructure, scratchName, tupleShape, compShape); + + if(!m_IsPreflight) + { + ExecuteDataFunction(CopyToFloat64Functor{}, sourceArray.getDataType(), sourceArray, *destArr); + } + + return destArr->getId(); +} + +// --------------------------------------------------------------------------- +// parse() -- the core parsing pipeline +// --------------------------------------------------------------------------- +Result<> ArrayCalculatorParser::parse() +{ + Result<> result; + + // === Step 1: Tokenize === + std::vector tokens = tokenize(m_InfixEquation); + if(tokens.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::EmptyEquation), "The infix expression is empty."); + } + + // === Step 2: Multi-word identifier merging === + // Walk the token list. When consecutive Identifier tokens appear, try + // merging them with spaces (greedy longest-first) and check if the + // merged name matches an array name. + { + std::vector merged; + merged.reserve(tokens.size()); + size_t i = 0; + while(i < tokens.size()) + { + if(tokens[i].type == TokenType::Identifier) + { + // Find the run of consecutive Identifier tokens + size_t runStart = i; + size_t runEnd = i + 1; + while(runEnd < tokens.size() && tokens[runEnd].type == TokenType::Identifier) + { + ++runEnd; + } + size_t runLen = runEnd - runStart; + + if(runLen > 1) + { + // Greedy: try longest merge first + bool foundMatch = false; + for(size_t len = runLen; len >= 2; --len) + { + for(size_t start = runStart; start + len <= runEnd; ++start) + { + // Build the merged name + std::string mergedName = tokens[start].text; + for(size_t k = start + 1; k < start + len; ++k) + { + mergedName += " " + tokens[k].text; + } + + // Check if this name matches an array + bool found = false; + if(!m_SelectedGroupPath.empty()) + { + found = ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, mergedName); + } + if(!found) + { + auto paths = findArraysByName(m_DataStructure, mergedName); + found = !paths.empty(); + } + + if(found) + { + // Add tokens before the match + for(size_t k = runStart; k < start; ++k) + { + merged.push_back(tokens[k]); + } + // Add the merged token + merged.push_back({TokenType::Identifier, mergedName, tokens[start].position}); + // Add tokens after the match + for(size_t k = start + len; k < runEnd; ++k) + { + merged.push_back(tokens[k]); + } + i = runEnd; + foundMatch = true; + break; + } + } + if(foundMatch) + { + break; + } + } + if(!foundMatch) + { + // No merge found; copy all identifiers as-is + for(size_t k = runStart; k < runEnd; ++k) + { + merged.push_back(tokens[k]); + } + i = runEnd; + } + } + else + { + merged.push_back(tokens[i]); + ++i; + } + } + else + { + merged.push_back(tokens[i]); + ++i; + } + } + tokens = std::move(merged); + } + + // === Steps 3+4: Identifier resolution, token conversion, and bracket indexing === + // These steps are combined so brackets can reference the array they follow. + std::vector items; + items.reserve(tokens.size()); + + // Combined Step 3+4: resolve identifiers and handle brackets inline + for(size_t i = 0; i < tokens.size(); ++i) + { + const Token& tok = tokens[i]; + + // Check if this token starts a bracket expression [...] + if(tok.type == TokenType::LBracket) + { + // Parse bracket contents: [Number] or [Number, Number] + if(items.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::OrphanedComponent), "Index operator '[' is not paired with a valid array name or closing parenthesis."); + } + + // Collect tokens until matching ']' + std::vector bracketNumbers; + size_t j = i + 1; + while(j < tokens.size() && tokens[j].type != TokenType::RBracket) + { + if(tokens[j].type == TokenType::Number) + { + bracketNumbers.push_back(tokens[j].text); + } + else if(tokens[j].type == TokenType::Comma) + { + // skip comma + } + else + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid content inside bracket index: '{}'.", tokens[j].text)); + } + ++j; + } + if(j >= tokens.size()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), "Missing closing bracket ']'."); + } + // j now points to ']' + + ParsedItem& prevItem = items.back(); + + if(prevItem.kind == ParsedItem::Kind::Value && prevItem.value.kind == CalcValue::Kind::Array) + { + // Case A: Array[C] or Array[T, C] + auto* tempArr = m_TempDataStructure.getDataAs(prevItem.value.arrayId); + if(tempArr == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find temporary array for bracket indexing."); + } + + usize numComponents = tempArr->getNumberOfComponents(); + usize numTuples = tempArr->getNumberOfTuples(); + + if(bracketNumbers.size() == 1) + { + // [C]: component extraction + int compIdx = 0; + try + { + compIdx = std::stoi(bracketNumbers[0]); + } + catch(const std::exception&) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid component index '{}'.", bracketNumbers[0])); + } + + if(compIdx < 0 || static_cast(compIdx) >= numComponents) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), + fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); + } + + if(numComponents > 1) + { + // Create new single-component array by extracting component C + auto* newArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), tempArr->getTupleShape(), std::vector{1}); + if(!m_IsPreflight) + { + for(usize t = 0; t < numTuples; ++t) + { + (*newArr)[t] = (*tempArr)[t * numComponents + static_cast(compIdx)]; + } + } + prevItem.value.arrayId = newArr->getId(); + } + // If already single-component, leave as-is + } + else if(bracketNumbers.size() == 2) + { + // [T, C]: tuple+component extraction + int tupleIdx = 0; + int compIdx = 0; + try + { + tupleIdx = std::stoi(bracketNumbers[0]); + compIdx = std::stoi(bracketNumbers[1]); + } + catch(const std::exception&) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid tuple/component index in '[{}, {}]'.", bracketNumbers[0], bracketNumbers[1])); + } + + if(tupleIdx < 0 || static_cast(tupleIdx) >= numTuples) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::TupleOutOfRange), fmt::format("Tuple index {} is out of range for array with {} tuples.", tupleIdx, numTuples)); + } + if(compIdx < 0 || static_cast(compIdx) >= numComponents) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), + fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); + } + + double extractedValue = 0.0; + if(!m_IsPreflight) + { + extractedValue = (*tempArr)[static_cast(tupleIdx) * numComponents + static_cast(compIdx)]; + } + DataObject::IdType id = createScalarInTemp(extractedValue); + prevItem.value = CalcValue{CalcValue::Kind::Number, id}; + } + else + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), "Bracket index must contain 1 or 2 numbers (e.g. [C] or [T, C])."); + } + } + else if(prevItem.kind == ParsedItem::Kind::RParen) + { + // Case B: )[C] -- component extraction on sub-expression result + if(bracketNumbers.size() != 1) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), "Component extraction on sub-expression must have exactly one index: [C]."); + } + int compIdx = 0; + try + { + compIdx = std::stoi(bracketNumbers[0]); + } + catch(const std::exception&) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid component index '{}'.", bracketNumbers[0])); + } + + ParsedItem ce; + ce.kind = ParsedItem::Kind::ComponentExtract; + ce.componentIndex = compIdx; + items.push_back(ce); + } + else + { + return MakeErrorResult(static_cast(CalculatorErrorCode::OrphanedComponent), fmt::format("Index operator '{}' is not paired with a valid array name or closing parenthesis.", tok.text)); + } + + i = j; // skip past ']' + continue; + } + + // Normal token processing (same as step 3 above but now with brackets handled separately) + switch(tok.type) + { + case TokenType::Number: { + double numValue = 0.0; + try + { + numValue = std::stod(tok.text); + } + catch(const std::exception&) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), fmt::format("Invalid numeric value '{}'.", tok.text)); + } + DataObject::IdType id = createScalarInTemp(numValue); + + ParsedItem pi; + pi.kind = ParsedItem::Kind::Value; + pi.value = CalcValue{CalcValue::Kind::Number, id}; + items.push_back(pi); + + // Ambiguous name warning + if(m_IsPreflight) + { + bool arrayExists = false; + if(!m_SelectedGroupPath.empty()) + { + arrayExists = ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, tok.text); + } + if(!arrayExists) + { + arrayExists = !findArraysByName(m_DataStructure, tok.text).empty(); + } + if(arrayExists) + { + result.warnings().push_back( + Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a number." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); + } + } + break; + } + + case TokenType::Identifier: { + const OperatorDef* opDef = findOperatorByToken(tok.text); + if(opDef != nullptr) + { + if(m_IsPreflight) + { + bool arrayExists = false; + if(!m_SelectedGroupPath.empty()) + { + arrayExists = ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, tok.text); + } + if(!arrayExists) + { + arrayExists = !findArraysByName(m_DataStructure, tok.text).empty(); + } + if(arrayExists) + { + result.warnings().push_back( + Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a mathematical operator." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); + } + } + + ParsedItem pi; + pi.kind = ParsedItem::Kind::Operator; + pi.op = opDef; + items.push_back(pi); + } + else if(tok.text == "pi" || tok.text == "e") + { + double constValue = (tok.text == "pi") ? std::numbers::pi : std::numbers::e; + DataObject::IdType id = createScalarInTemp(constValue); + + ParsedItem pi; + pi.kind = ParsedItem::Kind::Value; + pi.value = CalcValue{CalcValue::Kind::Number, id}; + items.push_back(pi); + + if(m_IsPreflight) + { + bool arrayExists = false; + if(!m_SelectedGroupPath.empty()) + { + arrayExists = ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, tok.text); + } + if(!arrayExists) + { + arrayExists = !findArraysByName(m_DataStructure, tok.text).empty(); + } + if(arrayExists) + { + result.warnings().push_back( + Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a built-in constant." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); + } + } + } + else + { + // Try as array name + if(!m_SelectedGroupPath.empty() && ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, tok.text)) + { + DataPath arrayPath = m_SelectedGroupPath.createChildPath(tok.text); + const auto* dataArray = m_DataStructure.getDataAs(arrayPath); + if(dataArray == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::UnrecognizedItem), fmt::format("Could not access array '{}' in selected group.", tok.text)); + } + DataObject::IdType id = copyArrayToTemp(*dataArray); + + ParsedItem pi; + pi.kind = ParsedItem::Kind::Value; + pi.value = CalcValue{CalcValue::Kind::Array, id}; + items.push_back(pi); + } + else + { + auto foundPaths = findArraysByName(m_DataStructure, tok.text); + if(foundPaths.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::UnrecognizedItem), + fmt::format("An unrecognized or invalid item '{}' was found in the chosen infix expression.", tok.text)); + } + if(foundPaths.size() > 1) + { + std::string pathsList; + for(const auto& p : foundPaths) + { + if(!pathsList.empty()) + { + pathsList += ", "; + } + pathsList += p.toString(); + } + return MakeErrorResult(static_cast(CalculatorErrorCode::AmbiguousArrayName), + fmt::format("Array name '{}' is ambiguous. Multiple arrays found: [{}]." + "\nPlease use double quotes with the full path (e.g. \"Path/To/{}\") to disambiguate.", + tok.text, pathsList, tok.text)); + } + const auto* dataArray = m_DataStructure.getDataAs(foundPaths[0]); + if(dataArray == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::UnrecognizedItem), fmt::format("Could not access array '{}'.", tok.text)); + } + DataObject::IdType id = copyArrayToTemp(*dataArray); + + ParsedItem pi; + pi.kind = ParsedItem::Kind::Value; + pi.value = CalcValue{CalcValue::Kind::Array, id}; + items.push_back(pi); + } + } + break; + } + + case TokenType::QuotedString: { + std::vector pathComponents; + { + std::string component; + for(char ch : tok.text) + { + if(ch == '/') + { + if(!component.empty()) + { + pathComponents.push_back(component); + component.clear(); + } + } + else + { + component += ch; + } + } + if(!component.empty()) + { + pathComponents.push_back(component); + } + } + + DataPath quotedPath(pathComponents); + + // If single component, try as child of selected group first + if(pathComponents.size() == 1 && !m_SelectedGroupPath.empty()) + { + DataPath childPath = m_SelectedGroupPath.createChildPath(pathComponents[0]); + if(m_DataStructure.getDataAs(childPath) != nullptr) + { + quotedPath = childPath; + } + } + + const auto* dataArray = m_DataStructure.getDataAs(quotedPath); + if(dataArray == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidArrayName), fmt::format("The item '\"{}\"' is not a valid array path in the DataStructure.", tok.text)); + } + DataObject::IdType id = copyArrayToTemp(*dataArray); + + ParsedItem pi; + pi.kind = ParsedItem::Kind::Value; + pi.value = CalcValue{CalcValue::Kind::Array, id}; + items.push_back(pi); + break; + } + + case TokenType::Plus: + case TokenType::Minus: + case TokenType::Star: + case TokenType::Slash: + case TokenType::Caret: + case TokenType::Percent: { + const OperatorDef* opDef = operatorDefForSymbolToken(tok.type); + if(opDef == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidSymbol), fmt::format("Unknown operator symbol '{}'.", tok.text)); + } + ParsedItem pi; + pi.kind = ParsedItem::Kind::Operator; + pi.op = opDef; + items.push_back(pi); + break; + } + + case TokenType::LParen: { + ParsedItem pi; + pi.kind = ParsedItem::Kind::LParen; + items.push_back(pi); + break; + } + + case TokenType::RParen: { + ParsedItem pi; + pi.kind = ParsedItem::Kind::RParen; + items.push_back(pi); + break; + } + + case TokenType::Comma: { + ParsedItem pi; + pi.kind = ParsedItem::Kind::Comma; + items.push_back(pi); + break; + } + + case TokenType::LBracket: + case TokenType::RBracket: { + // Should not reach here since brackets are handled at the top of the loop + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Unexpected bracket token encountered."); + } + + } // end switch + } + + // === Step 5: Minus sign disambiguation === + for(size_t i = 0; i < items.size(); ++i) + { + auto& item = items[i]; + if(item.kind != ParsedItem::Kind::Operator || item.op == nullptr) + { + continue; + } + if(item.op->token != "-") + { + continue; + } + + // Determine if this is a unary negative + bool isUnary = false; + if(i == 0) + { + isUnary = true; + } + else + { + const auto& prev = items[i - 1]; + if(isBinaryOp(prev)) + { + isUnary = true; + } + else if(prev.kind == ParsedItem::Kind::Operator && prev.op != nullptr && prev.op->kind == OperatorDef::UnaryPrefix) + { + isUnary = true; + } + else if(prev.kind == ParsedItem::Kind::LParen) + { + isUnary = true; + } + else if(prev.kind == ParsedItem::Kind::Comma) + { + isUnary = true; + } + } + + if(isUnary) + { + item.op = &getUnaryNegativeOp(); + item.isNegativePrefix = true; + } + } + + // === Step 6: WrapFunctionArguments === + wrapFunctionArguments(items); + + // === Step 7: Validation === + // 7a: Check matched parentheses + { + int parenDepth = 0; + for(const auto& item : items) + { + if(item.kind == ParsedItem::Kind::LParen) + { + ++parenDepth; + } + else if(item.kind == ParsedItem::Kind::RParen) + { + --parenDepth; + } + if(parenDepth < 0) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), + fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); + } + } + if(parenDepth != 0) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), + fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); + } + } + + // 7b: Collect array-type values and verify consistent tuple/component info + std::vector arrayTupleShape; + std::vector arrayCompShape; + usize arrayNumTuples = 0; + bool hasArray = false; + bool hasNumericValue = false; + bool tupleShapesMatch = true; + + for(const auto& item : items) + { + if(item.kind == ParsedItem::Kind::Value) + { + hasNumericValue = true; + if(item.value.kind == CalcValue::Kind::Array) + { + auto* arr = m_TempDataStructure.getDataAs(item.value.arrayId); + if(arr != nullptr) + { + auto ts = arr->getTupleShape(); + auto cs = arr->getComponentShape(); + usize nt = arr->getNumberOfTuples(); + + if(hasArray) + { + if(!arrayCompShape.empty() && arrayCompShape != cs) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentCompDims), + "Attribute Array symbols in the infix expression have mismatching component dimensions."); + } + if(arrayNumTuples != 0 && nt != arrayNumTuples) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentTuples), + "Attribute Array symbols in the infix expression have mismatching number of tuples."); + } + if(!arrayTupleShape.empty() && arrayTupleShape != ts) + { + tupleShapesMatch = false; + } + } + + hasArray = true; + arrayTupleShape = ts; + arrayCompShape = cs; + arrayNumTuples = nt; + } + } + } + } + + // 7c: Ensure at least one numeric argument exists + if(!hasNumericValue) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), "The expression does not have any arguments that simplify down to a number."); + } + + // Store the parsed shape info for use by parseAndValidate() + if(hasArray) + { + if(tupleShapesMatch) + { + m_ParsedTupleShape = arrayTupleShape; + } + else + { + m_ParsedTupleShape = {arrayNumTuples}; + } + m_ParsedComponentShape = arrayCompShape; + } + else + { + // All scalars: output is {1} tuples, {1} components + m_ParsedTupleShape = {1}; + m_ParsedComponentShape = {1}; + } + + // === Convert ParsedItems to RPN using shunting-yard === + // (This will be fully implemented in Task 1e. For now, store the + // parsed items so that parseAndValidate can return shapes.) + + // For now, build a simple RpnItem list from the parsed items. + // Task 1e will replace this with proper shunting-yard conversion. + m_RpnItems.clear(); + + return result; +} + +// --------------------------------------------------------------------------- +Result<> ArrayCalculatorParser::parseAndValidate(std::vector& outTupleShape, std::vector& outComponentShape) +{ + Result<> parseResult = parse(); + if(parseResult.invalid()) + { + return parseResult; + } + + outTupleShape = m_ParsedTupleShape; + outComponentShape = m_ParsedComponentShape; + + return parseResult; } // --------------------------------------------------------------------------- diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp index afee9c63a4..7f3fec261e 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp @@ -4,6 +4,7 @@ #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/DataStructure/DataStructure.hpp" +#include "simplnx/DataStructure/IDataArray.hpp" #include "simplnx/Filter/IFilter.hpp" #include "simplnx/Parameters/CalculatorParameter.hpp" #include "simplnx/Parameters/NumericTypeParameter.hpp" @@ -210,13 +211,53 @@ class SIMPLNXCORE_EXPORT ArrayCalculatorParser */ static std::vector tokenize(const std::string& equation); + // Expose temp DataStructure for evaluator (Task 1e will use this) + DataStructure& getTempDataStructure() + { + return m_TempDataStructure; + } + private: + /** + * @brief Runs the full parsing pipeline (tokenize, merge identifiers, + * resolve, bracket indexing, minus disambiguation, wrap function args, + * validate) and populates m_ParsedItems. + */ + Result<> parse(); + + /** + * @brief Creates a unique scratch name for temporary arrays. + */ + std::string nextScratchName(); + + /** + * @brief Creates a Float64Array in m_TempDataStructure from a source + * IDataArray, converting all values to double. When m_IsPreflight is + * true the array is allocated but data is not copied. + * @return the DataObject::IdType of the newly created array + */ + DataObject::IdType copyArrayToTemp(const IDataArray& sourceArray); + + /** + * @brief Creates a 1-element Float64Array in m_TempDataStructure with the + * given scalar value. + * @return the DataObject::IdType of the newly created array + */ + DataObject::IdType createScalarInTemp(double value); + const DataStructure& m_DataStructure; DataStructure m_TempDataStructure; DataPath m_SelectedGroupPath; std::string m_InfixEquation; bool m_IsPreflight; usize m_ScratchCounter = 0; + + // Populated by parse(); consumed by evaluateInto() (Task 1e) + std::vector m_RpnItems; + + // Shape info determined during validation + std::vector m_ParsedTupleShape; + std::vector m_ParsedComponentShape; }; // --------------------------------------------------------------------------- From d566d969e007566b834041e74515184be7722801 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 00:51:31 -0400 Subject: [PATCH 05/19] ENH: Implement shunting-yard, RPN evaluator, and public API for ArrayCalculator Add the final engine components to complete the ArrayCalculator rewrite: - Shunting-yard algorithm at the end of parse() converts ParsedItems to RPN - RPN stack evaluator in evaluateInto() with unary/binary ops, scalar broadcasting, trig angle unit conversion, and component extraction - CopyResultFunctor for type-dispatched output with scalar fill support - ArrayCalculator::operator()() wires the parser to the filter algorithm --- .../Filters/Algorithms/ArrayCalculator.cpp | 321 +++++++++++++++++- 1 file changed, 313 insertions(+), 8 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 32f59b8076..602a39dc24 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -1,6 +1,7 @@ #include "ArrayCalculator.hpp" #include "simplnx/Common/Result.hpp" +#include "simplnx/Common/TypesUtility.hpp" #include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataStore.hpp" #include "simplnx/Utilities/DataGroupUtilities.hpp" @@ -9,6 +10,7 @@ #include #include #include +#include using namespace nx::core; @@ -219,6 +221,30 @@ void wrapFunctionArguments(std::vector& items) items.swap(out); } +// --------------------------------------------------------------------------- +// Functor to copy a Float64Array result into the output DataArray of any +// numeric type, performing static_cast on each element. +// --------------------------------------------------------------------------- +struct CopyResultFunctor +{ + template + void operator()(DataStructure& ds, const DataPath& outputPath, const Float64Array* resultArray, bool isScalar) + { + auto& output = ds.getDataRefAs>(outputPath).getDataStoreRef(); + if(isScalar && resultArray->getSize() == 1) + { + output.fill(static_cast(resultArray->at(0))); + } + else + { + for(usize i = 0; i < output.getSize(); i++) + { + output[i] = static_cast(resultArray->at(i)); + } + } + } +}; + } // anonymous namespace // --------------------------------------------------------------------------- @@ -1129,12 +1155,99 @@ Result<> ArrayCalculatorParser::parse() } // === Convert ParsedItems to RPN using shunting-yard === - // (This will be fully implemented in Task 1e. For now, store the - // parsed items so that parseAndValidate can return shapes.) - - // For now, build a simple RpnItem list from the parsed items. - // Task 1e will replace this with proper shunting-yard conversion. m_RpnItems.clear(); + std::vector opStack; + + for(const auto& item : items) + { + switch(item.kind) + { + case ParsedItem::Kind::Value: { + m_RpnItems.push_back(RpnItem{RpnItem::Type::Value, item.value, nullptr, -1}); + break; + } + + case ParsedItem::Kind::LParen: { + opStack.push_back(item); + break; + } + + case ParsedItem::Kind::RParen: { + // Pop operators to output until we find the matching LParen + while(!opStack.empty() && opStack.back().kind != ParsedItem::Kind::LParen) + { + const auto& top = opStack.back(); + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, -1}); + opStack.pop_back(); + } + if(opStack.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), + fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); + } + // Discard the LParen + opStack.pop_back(); + break; + } + + case ParsedItem::Kind::Comma: { + // Pop operators to output until we find the LParen (but don't discard it) + while(!opStack.empty() && opStack.back().kind != ParsedItem::Kind::LParen) + { + const auto& top = opStack.back(); + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, -1}); + opStack.pop_back(); + } + break; + } + + case ParsedItem::Kind::Operator: { + const OperatorDef* incomingOp = item.isNegativePrefix ? &getUnaryNegativeOp() : item.op; + int incomingPrec = incomingOp->precedence; + bool isLeftAssoc = (incomingOp->associativity == OperatorDef::Left); + + while(!opStack.empty() && opStack.back().kind == ParsedItem::Kind::Operator) + { + const auto& topItem = opStack.back(); + const OperatorDef* topOp = topItem.isNegativePrefix ? &getUnaryNegativeOp() : topItem.op; + int topPrec = topOp->precedence; + + if(topPrec > incomingPrec || (topPrec == incomingPrec && isLeftAssoc)) + { + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, -1}); + opStack.pop_back(); + } + else + { + break; + } + } + + opStack.push_back(item); + break; + } + + case ParsedItem::Kind::ComponentExtract: { + m_RpnItems.push_back(RpnItem{RpnItem::Type::ComponentExtract, CalcValue{CalcValue::Kind::Number, 0}, nullptr, item.componentIndex}); + break; + } + + } // end switch + } + + // Pop remaining operators from the stack + while(!opStack.empty()) + { + const auto& top = opStack.back(); + if(top.kind == ParsedItem::Kind::LParen) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), + fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); + } + const OperatorDef* topOp = top.isNegativePrefix ? &getUnaryNegativeOp() : top.op; + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, -1}); + opStack.pop_back(); + } return result; } @@ -1155,9 +1268,200 @@ Result<> ArrayCalculatorParser::parseAndValidate(std::vector& outTupleSha } // --------------------------------------------------------------------------- -Result<> ArrayCalculatorParser::evaluateInto(DataStructure& /*dataStructure*/, const DataPath& /*outputPath*/, NumericType /*scalarType*/, CalculatorParameter::AngleUnits /*units*/) +Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const DataPath& outputPath, NumericType scalarType, CalculatorParameter::AngleUnits units) { - return MakeErrorResult(-1, "Not yet implemented"); + // 1. Parse (which now populates m_RpnItems via shunting-yard) + Result<> parseResult = parse(); + if(parseResult.invalid()) + { + return parseResult; + } + + // 2. Walk the RPN items using an evaluation stack + std::stack evalStack; + + for(const auto& rpnItem : m_RpnItems) + { + switch(rpnItem.type) + { + case RpnItem::Type::Value: { + evalStack.push(rpnItem.value); + break; + } + + case RpnItem::Type::Operator: { + const OperatorDef* op = rpnItem.op; + if(op == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: null operator in RPN evaluation."); + } + + if(op->numArgs == 1) + { + // Unary operator / 1-arg function + if(evalStack.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for unary operator."); + } + CalcValue operand = evalStack.top(); + evalStack.pop(); + + auto* operandArr = m_TempDataStructure.getDataAs(operand.arrayId); + if(operandArr == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand array during evaluation."); + } + + auto tupleShape = operandArr->getTupleShape(); + auto compShape = operandArr->getComponentShape(); + auto* resultArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), tupleShape, compShape); + + usize totalSize = operandArr->getSize(); + for(usize i = 0; i < totalSize; i++) + { + double val = operandArr->at(i); + + // Handle trig angle unit conversions + if(op->trigMode == OperatorDef::ForwardTrig && units == CalculatorParameter::AngleUnits::Degrees) + { + val = val * (std::numbers::pi / 180.0); + } + + double res = op->unaryOp(val); + + if(op->trigMode == OperatorDef::InverseTrig && units == CalculatorParameter::AngleUnits::Degrees) + { + res = res * (180.0 / std::numbers::pi); + } + + (*resultArr)[i] = res; + } + + evalStack.push(CalcValue{operand.kind, resultArr->getId()}); + } + else if(op->numArgs == 2) + { + // Binary operator / 2-arg function + if(evalStack.size() < 2) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for binary operator."); + } + CalcValue rightVal = evalStack.top(); + evalStack.pop(); + CalcValue leftVal = evalStack.top(); + evalStack.pop(); + + auto* leftArr = m_TempDataStructure.getDataAs(leftVal.arrayId); + auto* rightArr = m_TempDataStructure.getDataAs(rightVal.arrayId); + if(leftArr == nullptr || rightArr == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand arrays during evaluation."); + } + + // Determine output shape: use array operand's shape (broadcast scalars) + std::vector outTupleShape; + std::vector outCompShape; + if(leftVal.kind == CalcValue::Kind::Array) + { + outTupleShape = leftArr->getTupleShape(); + outCompShape = leftArr->getComponentShape(); + } + else + { + outTupleShape = rightArr->getTupleShape(); + outCompShape = rightArr->getComponentShape(); + } + + usize numTuples = 1; + for(auto d : outTupleShape) + { + numTuples *= d; + } + usize numComps = 1; + for(auto d : outCompShape) + { + numComps *= d; + } + usize totalSize = numTuples * numComps; + + auto* resultArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), outTupleShape, outCompShape); + + for(usize i = 0; i < totalSize; i++) + { + double lv = (leftVal.kind == CalcValue::Kind::Array) ? leftArr->at(i) : leftArr->at(0); + double rv = (rightVal.kind == CalcValue::Kind::Array) ? rightArr->at(i) : rightArr->at(0); + (*resultArr)[i] = op->binaryOp(lv, rv); + } + + CalcValue::Kind resultKind = (leftVal.kind == CalcValue::Kind::Array || rightVal.kind == CalcValue::Kind::Array) ? CalcValue::Kind::Array : CalcValue::Kind::Number; + evalStack.push(CalcValue{resultKind, resultArr->getId()}); + } + else + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), fmt::format("Internal error: operator '{}' has unsupported numArgs={}.", op->token, op->numArgs)); + } + break; + } + + case RpnItem::Type::ComponentExtract: { + if(evalStack.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for component extraction."); + } + CalcValue operand = evalStack.top(); + evalStack.pop(); + + auto* operandArr = m_TempDataStructure.getDataAs(operand.arrayId); + if(operandArr == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand array for component extraction."); + } + + usize numComps = operandArr->getNumberOfComponents(); + usize numTuples = operandArr->getNumberOfTuples(); + int compIdx = rpnItem.componentIndex; + + if(compIdx < 0 || static_cast(compIdx) >= numComps) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), + fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); + } + + auto* newArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), operandArr->getTupleShape(), std::vector{1}); + for(usize t = 0; t < numTuples; ++t) + { + (*newArr)[t] = operandArr->at(t * numComps + static_cast(compIdx)); + } + + evalStack.push(CalcValue{operand.kind, newArr->getId()}); + break; + } + + } // end switch + } + + // 3. Final result + if(evalStack.size() != 1) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), + fmt::format("Internal error: evaluation stack has {} items remaining; expected exactly 1.", evalStack.size())); + } + + CalcValue finalVal = evalStack.top(); + evalStack.pop(); + + auto* resultArr = m_TempDataStructure.getDataAs(finalVal.arrayId); + if(resultArr == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find final result array."); + } + + // 4. Copy/cast result into the output array + DataType outputDataType = ConvertNumericTypeToDataType(scalarType); + bool isScalar = (finalVal.kind == CalcValue::Kind::Number); + ExecuteDataFunction(CopyResultFunctor{}, outputDataType, dataStructure, outputPath, resultArr, isScalar); + + return parseResult; } // --------------------------------------------------------------------------- @@ -1183,5 +1487,6 @@ const std::atomic_bool& ArrayCalculator::getCancel() // --------------------------------------------------------------------------- Result<> ArrayCalculator::operator()() { - return MakeErrorResult(-1, "Not yet implemented"); + ArrayCalculatorParser parser(m_DataStructure, m_InputValues->SelectedGroup, m_InputValues->InfixEquation, false); + return parser.evaluateInto(m_DataStructure, m_InputValues->CalculatedArray, m_InputValues->ScalarType, m_InputValues->Units); } From a2e7ca7ab6dac097fafccb9cdc9f4b8fc6b16462 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 00:54:39 -0400 Subject: [PATCH 06/19] ENH: Wire ArrayCalculatorFilter to new parser/evaluator engine Relax CalculatorParameter::validate() to accept empty or non-existent selected groups (the path is only a resolution hint). Rewrite preflightImpl() to use ArrayCalculatorParser::parseAndValidate() and executeImpl() to delegate to the ArrayCalculator algorithm class. Remove old ICalculatorArray include and bump parametersVersion to 2. --- .../Filters/ArrayCalculatorFilter.cpp | 128 +++--------------- .../Parameters/CalculatorParameter.cpp | 18 +-- 2 files changed, 22 insertions(+), 124 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp index 3111f2dee3..c0d7a49f71 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp @@ -1,17 +1,15 @@ #include "ArrayCalculatorFilter.hpp" #include "SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp" -#include "SimplnxCore/utils/ICalculatorArray.hpp" #include "simplnx/Common/TypesUtility.hpp" +#include "simplnx/DataStructure/AttributeMatrix.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/Filter/Actions/CreateArrayAction.hpp" #include "simplnx/Parameters/ArrayCreationParameter.hpp" #include "simplnx/Parameters/CalculatorParameter.hpp" - -#include "simplnx/Utilities/SIMPLConversion.hpp" - #include "simplnx/Parameters/NumericTypeParameter.hpp" +#include "simplnx/Utilities/SIMPLConversion.hpp" using namespace nx::core; @@ -65,7 +63,7 @@ Parameters ArrayCalculatorFilter::parameters() const //------------------------------------------------------------------------------ IFilter::VersionType ArrayCalculatorFilter::parametersVersion() const { - return 1; + return 2; } //------------------------------------------------------------------------------ @@ -81,135 +79,45 @@ IFilter::PreflightResult ArrayCalculatorFilter::preflightImpl(const DataStructur auto pInfixEquationValue = filterArgs.value(k_CalculatorParameter_Key); auto pScalarTypeValue = filterArgs.value(k_ScalarType_Key); auto pCalculatedArrayPath = filterArgs.value(k_CalculatedArray_Key); - - auto pSelectedGroupPath = pInfixEquationValue.m_SelectedGroup; auto outputGroupPath = pCalculatedArrayPath.getParent(); - PreflightResult preflightResult; nx::core::Result resultOutputActions; - std::vector preflightUpdatedValues; - - // parse the infix expression - ArrayCalculatorParser parser(dataStructure, pSelectedGroupPath, pInfixEquationValue.m_Equation, true); - std::vector parsedInfix; - Result<> parsedEquationResults = parser.parseInfixEquation(parsedInfix); - resultOutputActions.warnings() = parsedEquationResults.warnings(); - if(parsedEquationResults.invalid()) - { - return {nonstd::make_unexpected(parsedEquationResults.errors())}; - } - if(parsedInfix.empty()) - { - return MakePreflightErrorResult(-7760, "Error while parsing infix expression."); - } - - // check individual infix expression items for validity - for(int i = 0; i < parsedInfix.size(); i++) - { - CalculatorItem::Pointer calcItem = parsedInfix[i]; - std::string errMsg = ""; - CalculatorItem::ErrorCode err = calcItem->checkValidity(parsedInfix, i, errMsg); - int errInt = static_cast(err); - if(errInt < 0) - { - return MakePreflightErrorResult(errInt, errMsg); - } - } - // collect calculated array dimensions, check for consistent array component dimensions in infix expression & make sure it yields a numeric result + // Parse and validate the expression + ArrayCalculatorParser parser(dataStructure, pInfixEquationValue.m_SelectedGroup, pInfixEquationValue.m_Equation, true); std::vector calculatedTupleShape; std::vector calculatedComponentShape; - usize calculatedNumOfTuples = 0; - bool tupleShapesMatch = true; - ICalculatorArray::ValueType resultType = ICalculatorArray::ValueType::Unknown; + Result<> parseResult = parser.parseAndValidate(calculatedTupleShape, calculatedComponentShape); - // We only check that the arrays have consistent tuple counts and determine the tuple shape based on whether all arrays have - // matching tuple shapes or not. We DO NOT take into account the operator at all; we assume that all operators that input an array - // also output an array of the same tuple size. Adding operators that can take in an array and output an array of a different size - // (like finding the minimum or maximum of a single array) will require a significant redesign of this filter since determining the - // final output tuple size/shape from an infix equation with those types of operators in it will be significantly more complicated. - for(const auto& item1 : parsedInfix) - { - if(item1->isICalculatorArray()) - { - ICalculatorArray::Pointer array1 = std::dynamic_pointer_cast(item1); - auto tupleShape = array1->getArray()->getTupleShape(); - auto compShape = array1->getArray()->getComponentShape(); - auto numTuples = array1->getArray()->getNumberOfTuples(); - if(item1->isArray()) - { - if(resultType == ICalculatorArray::ValueType::Array) - { - if(!calculatedComponentShape.empty() && calculatedComponentShape != array1->getArray()->getComponentShape()) - { - return MakePreflightErrorResult(static_cast(CalculatorItem::ErrorCode::InconsistentCompDims), - fmt::format("Attribute Array '{}' has component dimensions {} which do not match the previously encountered component dimensions {} in the expression.", - array1->getArray()->getName(), fmt::join(array1->getArray()->getComponentShape(), "x"), fmt::join(calculatedComponentShape, "x"))); - } - if(!calculatedTupleShape.empty() && calculatedNumOfTuples != array1->getArray()->getNumberOfTuples()) - { - return MakePreflightErrorResult(static_cast(CalculatorItem::ErrorCode::InconsistentTuples), - fmt::format("Attribute Array '{}' has {} tuples which does not match the previously encountered tuple count of {} in the expression.", - array1->getArray()->getName(), array1->getArray()->getNumberOfTuples(), calculatedNumOfTuples)); - } - if(!calculatedTupleShape.empty() && calculatedTupleShape != tupleShape) - { - tupleShapesMatch = false; - } - } + // Transfer warnings + resultOutputActions.warnings() = parseResult.warnings(); - resultType = ICalculatorArray::ValueType::Array; - calculatedComponentShape = compShape; - calculatedTupleShape = tupleShape; - calculatedNumOfTuples = numTuples; - } - else if(resultType == ICalculatorArray::ValueType::Unknown) - { - resultType = ICalculatorArray::ValueType::Number; - calculatedComponentShape = array1->getArray()->getComponentShape(); - calculatedTupleShape = {array1->getArray()->getNumberOfTuples()}; - } - } - } - if(resultType == ICalculatorArray::ValueType::Unknown) + if(parseResult.invalid()) { - return MakePreflightErrorResult(static_cast(CalculatorItem::ErrorCode::NoNumericArguments), "The expression does not have any arguments that simplify down to a number."); + return {nonstd::make_unexpected(parseResult.errors())}; } - if(resultType == ICalculatorArray::ValueType::Number) + // If the result is a scalar (1 tuple) and the output is in an AttributeMatrix, + // use the AttributeMatrix's shape instead + if(calculatedTupleShape.size() == 1 && calculatedTupleShape[0] == 1) { if(const auto* attributeMatrix = dataStructure.getDataAs(outputGroupPath); attributeMatrix != nullptr) { calculatedTupleShape = attributeMatrix->getShape(); } } - else if(!tupleShapesMatch) - { - calculatedTupleShape = {calculatedNumOfTuples}; - } - - // convert to postfix notation - Result rpnResults = ArrayCalculatorParser::ToRPN(pInfixEquationValue.m_Equation, parsedInfix); - std::vector rpn = rpnResults.value(); - if(rpnResults.invalid() || rpn.empty()) - { - return MakePreflightErrorResult(-7761, "Error while converting parsed infix expression to postfix notation"); - } - // create the destination array for the calculated results - { - auto createArrayAction = std::make_unique(ConvertNumericTypeToDataType(pScalarTypeValue), calculatedTupleShape, calculatedComponentShape, pCalculatedArrayPath); - resultOutputActions.value().appendAction(std::move(createArrayAction)); - } + // Create the output array + auto createArrayAction = std::make_unique(ConvertNumericTypeToDataType(pScalarTypeValue), calculatedTupleShape, calculatedComponentShape, pCalculatedArrayPath); + resultOutputActions.value().appendAction(std::move(createArrayAction)); - return {std::move(resultOutputActions), std::move(preflightUpdatedValues)}; -} // namespace nx::core + return {std::move(resultOutputActions)}; +} //------------------------------------------------------------------------------ Result<> ArrayCalculatorFilter::executeImpl(DataStructure& dataStructure, const Arguments& filterArgs, const PipelineFilter* pipelineNode, const MessageHandler& messageHandler, const std::atomic_bool& shouldCancel, const ExecutionContext& executionContext) const { - ArrayCalculatorInputValues inputValues; auto pInfixEquationValue = filterArgs.value(k_CalculatorParameter_Key); inputValues.InfixEquation = pInfixEquationValue.m_Equation; diff --git a/src/simplnx/Parameters/CalculatorParameter.cpp b/src/simplnx/Parameters/CalculatorParameter.cpp index 8694ddaefc..00c1044315 100644 --- a/src/simplnx/Parameters/CalculatorParameter.cpp +++ b/src/simplnx/Parameters/CalculatorParameter.cpp @@ -115,20 +115,10 @@ Result<> CalculatorParameter::validate(const DataStructure& dataStructure, const { return MakeErrorResult(FilterParameter::Constants::k_Validate_Empty_Value, fmt::format("{}expression cannot be empty", prefix)); } - if(!structValue.m_SelectedGroup.empty()) // if empty then using root group - { - const DataObject* dataObject = dataStructure.getData(structValue.m_SelectedGroup); - if(dataObject == nullptr) - { - return nx::core::MakeErrorResult(nx::core::FilterParameter::Constants::k_Validate_DuplicateValue, - fmt::format("{}Object does not exist at path '{}'", prefix, structValue.m_SelectedGroup.toString())); - } - const auto baseGroupObj = dataStructure.getDataAs(structValue.m_SelectedGroup); - if(baseGroupObj == nullptr) - { - return MakeErrorResult(FilterParameter::Constants::k_Validate_DuplicateValue, fmt::format("{}Object at path '{}' is not a BaseGroup type", prefix, structValue.m_SelectedGroup.toString())); - } - } + + // m_SelectedGroup is only a resolution hint for array name lookups. + // An empty path means "use root", and a non-existent or non-BaseGroup + // path is silently accepted -- the parser will handle any issues. return {}; } From b225086a13f6343f01a96c0535504dfb72bdaa79 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 01:05:49 -0400 Subject: [PATCH 07/19] ENH: Update test includes and fix backward-compat error codes in ArrayCalculator Replace CalculatorItem:: enum references with CalculatorErrorCode:: and CalculatorWarningCode:: in ArrayCalculatorTest.cpp. Remove the old CalculatorItem.hpp include since the test now uses the new ArrayCalculator.hpp header exclusively. Add validation in the parser to emit the same legacy error codes: - OperatorNoOpeningParen / OperatorNoClosingParen for bare functions - OperatorNoLeftValue / OperatorNoRightValue for binary operators - TooManyArguments / NotEnoughArguments for function argument counts - NoPrecedingUnaryOperator for commas in non-function parens - AmbiguousNameWarning for operator symbols matching array names --- .../Filters/Algorithms/ArrayCalculator.cpp | 224 +++++++++- .../SimplnxCore/test/ArrayCalculatorTest.cpp | 393 +++++++++--------- 2 files changed, 419 insertions(+), 198 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 602a39dc24..10656737a7 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -965,6 +965,29 @@ Result<> ArrayCalculatorParser::parse() { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidSymbol), fmt::format("Unknown operator symbol '{}'.", tok.text)); } + + // Check if the operator symbol is also the name of an array + if(m_IsPreflight) + { + bool arrayExists = false; + if(!m_SelectedGroupPath.empty()) + { + arrayExists = ContainsDataArrayName(m_DataStructure, m_SelectedGroupPath, tok.text); + } + if(!arrayExists) + { + arrayExists = !findArraysByName(m_DataStructure, tok.text).empty(); + } + if(arrayExists) + { + result.warnings().push_back( + Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a mathematical operator." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); + } + } + ParsedItem pi; pi.kind = ParsedItem::Kind::Operator; pi.op = opDef; @@ -1053,7 +1076,206 @@ Result<> ArrayCalculatorParser::parse() wrapFunctionArguments(items); // === Step 7: Validation === - // 7a: Check matched parentheses + + // 7a-1: Check for function/unary operators: opening/closing paren, argument count, empty args + for(size_t i = 0; i < items.size(); ++i) + { + const auto& item = items[i]; + if(item.kind == ParsedItem::Kind::Operator && item.op != nullptr && item.op->kind == OperatorDef::Function) + { + // A function operator must be followed by LParen + if(i + 1 >= items.size() || items[i + 1].kind != ParsedItem::Kind::LParen) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoOpeningParen), + fmt::format("The operator/function '{}' does not have a valid opening parenthesis.", item.op->token)); + } + + // Find the matching RParen and count commas/values at depth 1 + int depth = 0; + bool foundClose = false; + size_t closeIdx = 0; + int commaCount = 0; + bool hasValueInside = false; + for(size_t j = i + 1; j < items.size(); ++j) + { + if(items[j].kind == ParsedItem::Kind::LParen) + { + ++depth; + } + else if(items[j].kind == ParsedItem::Kind::RParen) + { + --depth; + if(depth == 0) + { + foundClose = true; + closeIdx = j; + break; + } + } + else if(items[j].kind == ParsedItem::Kind::Comma && depth == 1) + { + ++commaCount; + } + else if(depth >= 1 && (items[j].kind == ParsedItem::Kind::Value || (items[j].kind == ParsedItem::Kind::Operator && items[j].op != nullptr))) + { + hasValueInside = true; + } + } + if(!foundClose) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoClosingParen), + fmt::format("The operator/function '{}' does not have a valid closing parenthesis.", item.op->token)); + } + + // Check for empty function call: func() with no values or commas inside + if(!hasValueInside && commaCount == 0) + { + // For 2-arg functions with empty parens: NotEnoughArguments + if(item.op->numArgs == 2) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), + fmt::format("The function '{}' requires {} arguments, but none were provided.", item.op->token, item.op->numArgs)); + } + // For 1-arg functions with empty parens: NoNumericArguments + return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), + fmt::format("The function '{}' does not have any arguments that simplify down to a number.", item.op->token)); + } + + // Check for commas in the empty-value case: func(,) -- commas but no real values + if(!hasValueInside && commaCount > 0) + { + if(item.op->numArgs == 1) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::TooManyArguments), + fmt::format("The function '{}' requires {} argument, but more were provided.", item.op->token, item.op->numArgs)); + } + // For 2-arg functions: NoNumericArguments (commas but no values) + return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), + fmt::format("The function '{}' does not have any arguments that simplify down to a number.", item.op->token)); + } + + // Argument count: numArgs from OperatorDef, commaCount gives (numArgs-1) + int providedArgs = commaCount + 1; + if(item.op->numArgs == 1 && commaCount > 0) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::TooManyArguments), + fmt::format("The function '{}' requires {} argument, but {} were provided.", item.op->token, item.op->numArgs, providedArgs)); + } + if(item.op->numArgs == 2 && commaCount < 1 && hasValueInside) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), + fmt::format("The function '{}' requires {} arguments, but only {} was provided.", item.op->token, item.op->numArgs, providedArgs)); + } + } + } + + // 7a-1b: Check for commas inside non-function parentheses (NoPrecedingUnaryOperator) + for(size_t i = 0; i < items.size(); ++i) + { + if(items[i].kind == ParsedItem::Kind::Comma) + { + // Walk backwards to find the opening paren at the same depth, and check if preceded by a function + int depth = 0; + bool foundFunction = false; + for(int j = static_cast(i) - 1; j >= 0; --j) + { + if(items[j].kind == ParsedItem::Kind::RParen) + { + ++depth; + } + else if(items[j].kind == ParsedItem::Kind::LParen) + { + if(depth == 0) + { + // Found the opening paren; check if preceded by a function + if(j > 0 && items[j - 1].kind == ParsedItem::Kind::Operator && items[j - 1].op != nullptr && items[j - 1].op->kind == OperatorDef::Function) + { + foundFunction = true; + } + break; + } + --depth; + } + } + if(!foundFunction) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NoPrecedingUnaryOperator), + "A comma was found in parentheses without a preceding function operator."); + } + } + } + + // 7a-2: Check for binary operators missing left or right operands + for(size_t i = 0; i < items.size(); ++i) + { + const auto& item = items[i]; + if(!isBinaryOp(item)) + { + continue; + } + // Check left: the item before must be a value or RParen (something that produces a value) + bool hasLeft = false; + if(i > 0) + { + const auto& prev = items[i - 1]; + if(prev.kind == ParsedItem::Kind::Value || prev.kind == ParsedItem::Kind::RParen) + { + hasLeft = true; + } + } + if(!hasLeft) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoLeftValue), + fmt::format("The binary operator '{}' does not have a valid left-hand value.", item.op->token)); + } + // Check right: the item after must be a value, LParen, or unary operator (something that produces a value) + bool hasRight = false; + if(i + 1 < items.size()) + { + const auto& next = items[i + 1]; + if(next.kind == ParsedItem::Kind::Value || next.kind == ParsedItem::Kind::LParen) + { + hasRight = true; + } + else if(next.kind == ParsedItem::Kind::Operator && next.op != nullptr) + { + hasRight = true; // Could be a unary prefix or function + } + } + if(!hasRight) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoRightValue), + fmt::format("The binary operator '{}' does not have a valid right-hand value.", item.op->token)); + } + } + + // 7a-3: Check for unary negative with no right operand + for(size_t i = 0; i < items.size(); ++i) + { + const auto& item = items[i]; + if(item.isNegativePrefix) + { + bool hasRight = false; + if(i + 1 < items.size()) + { + const auto& next = items[i + 1]; + if(next.kind == ParsedItem::Kind::Value || next.kind == ParsedItem::Kind::LParen) + { + hasRight = true; + } + else if(next.kind == ParsedItem::Kind::Operator && next.op != nullptr) + { + hasRight = true; // e.g. -sin(...) + } + } + if(!hasRight) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoRightValue), "The unary negative operator does not have a valid right-hand value."); + } + } + } + + // 7a-4: Check matched parentheses (generic, after operator-specific checks) { int parenDepth = 0; for(const auto& item : items) diff --git a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp index 70bd213ea8..5e7e390101 100644 --- a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp +++ b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp @@ -1,7 +1,6 @@ #include "SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp" #include "SimplnxCore/Filters/ArrayCalculatorFilter.hpp" #include "SimplnxCore/SimplnxCore_test_dirs.hpp" -#include "SimplnxCore/utils/CalculatorItem.hpp" #include "simplnx/Common/Numbers.hpp" #include "simplnx/DataStructure/AttributeMatrix.hpp" @@ -95,7 +94,7 @@ IFilter::ExecuteResult createAndExecuteArrayCalculatorFilter(const std::string& } // ----------------------------------------------------------------------------- -void runTest(const std::string& equation, const DataPath& targetArrayPath, int32 expectedErrorCondition, CalculatorItem::WarningCode expectedWarningCondition, +void runTest(const std::string& equation, const DataPath& targetArrayPath, int32 expectedErrorCondition, CalculatorWarningCode expectedWarningCondition, const int* expectedNumberOfTuples = nullptr, const double* expectedValue = nullptr, CalculatorParameter::AngleUnits units = CalculatorParameter::AngleUnits::Radians) { std::cout << " Testing equation: ==>" << equation << "<==" << std::endl; @@ -111,7 +110,7 @@ void runTest(const std::string& equation, const DataPath& targetArrayPath, int32 // Execute the filter and check the result auto executeResult = filter.execute(dataStructure, args); - if(expectedErrorCondition == static_cast(CalculatorItem::ErrorCode::Success)) + if(expectedErrorCondition == static_cast(CalculatorErrorCode::Success)) { SIMPLNX_RESULT_REQUIRE_VALID(executeResult.result); } @@ -123,12 +122,12 @@ void runTest(const std::string& equation, const DataPath& targetArrayPath, int32 if(executeResult.result.warnings().size() != 0) { - REQUIRE(expectedWarningCondition != CalculatorItem::WarningCode::None); + REQUIRE(expectedWarningCondition != CalculatorWarningCode::None); REQUIRE(executeResult.result.warnings()[0].code == static_cast(expectedWarningCondition)); } else { - REQUIRE(expectedWarningCondition == CalculatorItem::WarningCode::None); + REQUIRE(expectedWarningCondition == CalculatorWarningCode::None); } Float64Array* arrayPtr = dataStructure.getDataAs(targetArrayPath); @@ -268,7 +267,7 @@ void MultiComponentArrayCalculatorTest() UInt32Array* sArray = dataStructure.getDataAs(k_SignArrayPath); SIMPLNX_RESULT_REQUIRE_INVALID(results.result); - REQUIRE(results.result.errors()[0].code == static_cast(CalculatorItem::ErrorCode::InconsistentCompDims)); + REQUIRE(results.result.errors()[0].code == static_cast(CalculatorErrorCode::InconsistentCompDims)); } SECTION("Multi-Component Out of bounds error") @@ -279,7 +278,7 @@ void MultiComponentArrayCalculatorTest() UInt32Array* sArray = dataStructure.getDataAs(k_SignArrayPath); SIMPLNX_RESULT_REQUIRE_INVALID(results.result); - REQUIRE(results.result.errors()[0].code == static_cast(CalculatorItem::ErrorCode::ComponentOutOfRange)); + REQUIRE(results.result.errors()[0].code == static_cast(CalculatorErrorCode::ComponentOutOfRange)); } UnitTest::CheckArraysInheritTupleDims(dataStructure); @@ -290,39 +289,39 @@ void SingleComponentArrayCalculatorTest1() { SECTION("Empty Tests") { - runTest("", k_NumericArrayPath, FilterParameter::Constants::k_Validate_Empty_Value, CalculatorItem::WarningCode::None); - runTest(" ", k_NumericArrayPath, FilterParameter::Constants::k_Validate_Empty_Value, CalculatorItem::WarningCode::None); + runTest("", k_NumericArrayPath, FilterParameter::Constants::k_Validate_Empty_Value, CalculatorWarningCode::None); + runTest(" ", k_NumericArrayPath, FilterParameter::Constants::k_Validate_Empty_Value, CalculatorWarningCode::None); } SECTION("Single Value Tests") { int numTuple = 1; double value = -3; - runTest("-3", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("-3", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); numTuple = 1; value = 14; - runTest("14", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("14", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); numTuple = 1; value = 0.345; - runTest(".345", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest(".345", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Mismatched Parentheses Tests") { int numTuple = 1; double value = 12; - runTest("(3*4)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); - runTest("(3*4", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::MismatchedParentheses), CalculatorItem::WarningCode::None); - runTest("3*4)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::MismatchedParentheses), CalculatorItem::WarningCode::None); + runTest("(3*4)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("(3*4", k_NumericArrayPath, static_cast(CalculatorErrorCode::MismatchedParentheses), CalculatorWarningCode::None); + runTest("3*4)", k_NumericArrayPath, static_cast(CalculatorErrorCode::MismatchedParentheses), CalculatorWarningCode::None); } SECTION("Nested Unary Operator Test") { int numTuple = 1; float64 value = sin(pow(fabs(cos(fabs(static_cast(3)) / 4) + 7), 2)); - runTest("sin( abs( cos( abs(3)/4) + 7)^2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("sin( abs( cos( abs(3)/4) + 7)^2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); // term1 = (12.5 * (3.14 + 2.718)) / (7 - (8 * (9 + 4))) float64 term1 = (12.5 * (3.14 + 2.718)) / (7.0 - (8.0 * (9.0 + 4.0))); @@ -345,451 +344,451 @@ void SingleComponentArrayCalculatorTest1() value = std::min(term1, term2) + term3; runTest("min(((12.5*(3.14+2.718))/(7-(8*(9+4)))),max(sin(3.141592653589793/(4*(2+6))),root((5^(1+2)),(10/((3^2)+1)))))+abs(-((15+3)-(20/(5+5))))", k_NumericArrayPath, - static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); } SECTION("Single Array Tests (Force Incorrect Tuple Counts)") { - runTest("-InputArray1", k_NumericArrayPath, -268, CalculatorItem::WarningCode::None); - runTest(k_InputArray2, k_NumericArrayPath, -268, CalculatorItem::WarningCode::None); + runTest("-InputArray1", k_NumericArrayPath, -268, CalculatorWarningCode::None); + runTest(k_InputArray2, k_NumericArrayPath, -268, CalculatorWarningCode::None); int numTuple = 10; double value = 18; - runTest("12 + 6", k_AttributeArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("12 + 6", k_AttributeArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Unrecognized Item Tests") { - runTest("-foo", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::UnrecognizedItem), CalculatorItem::WarningCode::None); - runTest("InputArray3", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::UnrecognizedItem), CalculatorItem::WarningCode::None); - runTest("sin(InputArray 2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::UnrecognizedItem), CalculatorItem::WarningCode::None); + runTest("-foo", k_NumericArrayPath, static_cast(CalculatorErrorCode::UnrecognizedItem), CalculatorWarningCode::None); + runTest("InputArray3", k_NumericArrayPath, static_cast(CalculatorErrorCode::UnrecognizedItem), CalculatorWarningCode::None); + runTest("sin(InputArray 2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::UnrecognizedItem), CalculatorWarningCode::None); } // Operator Tests SECTION("Addition Operator") { - runTest("+", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); - runTest("3 +", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoRightValue), CalculatorItem::WarningCode::None); - runTest("+ 12.5", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); + runTest("+", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); + runTest("3 +", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoRightValue), CalculatorWarningCode::None); + runTest("+ 12.5", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); int numTuple = 1; double value = 18; - runTest("12 + 6", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("12 + 6", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -6; - runTest("-12 + 6", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); - runTest("6 + -12", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("-12 + 6", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); + runTest("6 + -12", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Subtraction Operator") { - runTest("-89.2 -", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoRightValue), CalculatorItem::WarningCode::None); + runTest("-89.2 -", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoRightValue), CalculatorWarningCode::None); int numTuple = 1; double value = 43; - runTest("97 - 54", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("97 - 54", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -34; - runTest("-32 - 2", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("-32 - 2", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 19; - runTest("7 - -12", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("7 - -12", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Multiplication Operator") { - runTest("*", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); - runTest("3 *", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoRightValue), CalculatorItem::WarningCode::None); - runTest("* 12.5", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); + runTest("*", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); + runTest("3 *", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoRightValue), CalculatorWarningCode::None); + runTest("* 12.5", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); int numTuple = 1; double value = 72; - runTest("12 * 6", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("12 * 6", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); value = -72; - runTest("-12 * 6", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); - runTest("6 * -12", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("-12 * 6", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("6 * -12", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); } SECTION("Division Operator") { - runTest("/", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); - runTest("3 /", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoRightValue), CalculatorItem::WarningCode::None); - runTest("/ 12.5", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); + runTest("/", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); + runTest("3 /", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoRightValue), CalculatorWarningCode::None); + runTest("/ 12.5", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); int numTuple = 1; double value = 2; - runTest("12 / 6", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("12 / 6", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -2; - runTest("-12 / 6", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("-12 / 6", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -0.5; - runTest("6 / -12", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("6 / -12", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Pow Operator") { - runTest("^", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); - runTest("3 ^", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoRightValue), CalculatorItem::WarningCode::None); - runTest("^ 12.5", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoLeftValue), CalculatorItem::WarningCode::None); + runTest("^", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); + runTest("3 ^", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoRightValue), CalculatorWarningCode::None); + runTest("^ 12.5", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoLeftValue), CalculatorWarningCode::None); int numTuple = 1; double value = 125; - runTest("5 ^ 3", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("5 ^ 3", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -8; - runTest("-2 ^ 3", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("-2 ^ 3", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 0.25; - runTest("2 ^ -2", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("2 ^ -2", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Abs Operator") { - runTest("abs", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("abs(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("abs)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("abs()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("abs", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("abs(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("abs)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("abs()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 2; - runTest("abs(2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("abs(2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 4.3; - runTest("abs(-4.3)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("abs(-4.3)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 6.7; - runTest("abs(abs(6.7))", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("abs(abs(6.7))", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Sin Operator") { - runTest("sin", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("sin(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("sin)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("sin()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("sin", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("sin(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("sin)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("sin()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 1; - runTest("sin(90)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("sin(90)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = 0; - runTest("sin(-180)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("sin(-180)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = 0.5; - runTest("sin(" + k_Pi_Str + "/6)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("sin(" + k_Pi_Str + "/6)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); value = 1; - runTest("sin(" + k_Pi_Str + "/2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("sin(" + k_Pi_Str + "/2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); } SECTION("Cos Operator") { - runTest("cos", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("cos(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("cos)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("cos()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("cos", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("cos(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("cos)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("cos()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 0; - runTest("cos(90)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("cos(90)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = -1; - runTest("cos(-180)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("cos(-180)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = 0.5; - runTest("cos(" + k_Pi_Str + "/3)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("cos(" + k_Pi_Str + "/3)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); value = -0.5; - runTest("cos(2*" + k_Pi_Str + "/3)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value, + runTest("cos(2*" + k_Pi_Str + "/3)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value, CalculatorParameter::Radians); } SECTION("Tan Operator") { - runTest("tan", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("tan(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("tan)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("tan()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("tan", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("tan(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("tan)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("tan()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 1; - runTest("tan(45)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("tan(45)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = sqrt(3); - runTest("tan(60)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("tan(60)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = 1; - runTest("tan(" + k_Pi_Str + "/4)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value, + runTest("tan(" + k_Pi_Str + "/4)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value, CalculatorParameter::Radians); value = -sqrt(static_cast(1) / static_cast(3)); - runTest("tan(5*" + k_Pi_Str + "/6)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value, + runTest("tan(5*" + k_Pi_Str + "/6)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value, CalculatorParameter::Radians); } SECTION("ASin Operator") { - runTest("asin", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("asin(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("asin)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("asin()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("asin", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("asin(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("asin)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("asin()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 30; - runTest("asin(0.5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("asin(0.5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = 45; - runTest("asin(sqrt(2)/2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("asin(sqrt(2)/2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = numbers::pi / 3; - runTest("asin(sqrt(3)/2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("asin(sqrt(3)/2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); value = numbers::pi / 2; - runTest("asin(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("asin(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); } SECTION("ACos Operator") { - runTest("acos", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("acos(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("acos)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("acos()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("acos", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("acos(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("acos)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("acos()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 60; - runTest("acos(0.5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("acos(0.5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = 45; - runTest("acos(sqrt(2)/2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("acos(sqrt(2)/2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = numbers::pi / 6; - runTest("acos(sqrt(3)/2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("acos(sqrt(3)/2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); value = 0; - runTest("acos(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("acos(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); } SECTION("ATan Operator") { - runTest("atan", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("atan(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("atan)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("atan()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("atan", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("atan(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("atan)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("atan()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = -45; - runTest("atan(-1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("atan(-1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = -60; - runTest("atan(-sqrt(3))", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); + runTest("atan(-sqrt(3))", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Degrees); value = numbers::pi / 6; - runTest("atan(1/sqrt(3))", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("atan(1/sqrt(3))", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); value = numbers::pi / 3; - runTest("atan(sqrt(3))", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value, CalculatorParameter::Radians); + runTest("atan(sqrt(3))", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value, CalculatorParameter::Radians); } SECTION("Sqrt Operator") { - runTest("sqrt", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("sqrt(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("sqrt)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("sqrt()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); - runTest("sqrt(1, 3)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); + runTest("sqrt", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("sqrt(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("sqrt)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("sqrt()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); + runTest("sqrt(1, 3)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 3; - runTest("sqrt(9)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("sqrt(9)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 4; - runTest("sqrt(4*4)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("sqrt(4*4)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); value = 3; - runTest("sqrt(3^2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("sqrt(3^2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Root Operator") { - runTest("root", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("root(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("root)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("root()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("root(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("root(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("root", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("root(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("root)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("root()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("root(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("root(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 3; - runTest("root(9, 2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("root(9, 2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 4; - runTest("root(4*4, 2)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("root(4*4, 2)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); value = 4; - runTest("root(4*4+0, 1*2+0)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("root(4*4+0, 1*2+0)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); value = 4; - runTest("root(64, 3)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("root(64, 3)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Log10 Operator") { - runTest("log10", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("log10(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("log10)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("log10()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); - runTest("log10(1, 3)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); - runTest("log10(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); + runTest("log10", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("log10(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("log10)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("log10()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); + runTest("log10(1, 3)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); + runTest("log10(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); int numTuple = 1; double value = log10(10); - runTest("log10(10)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("log10(10)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = log10(40); - runTest("log10(40)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("log10(40)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Log Operator") { - runTest("log", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("log(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("log)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("log()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("log(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("log(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("log", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("log(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("log)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("log()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("log(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("log(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = log(5) / log(2); - runTest("log(2, 5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("log(2, 5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 2; - runTest("log(10, 100)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("log(10, 100)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Exp Operator") { - runTest("exp", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("exp(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("exp)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("exp()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); - runTest("exp(1, 5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); - runTest("exp(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); + runTest("exp", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("exp(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("exp)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("exp()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); + runTest("exp(1, 5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); + runTest("exp(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 2.7182818284590452354; // M_E - runTest("exp(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("exp(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 1; - runTest("exp(0)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("exp(0)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Ln Operator") { - runTest("ln", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("ln(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("ln)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("ln()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); - runTest("ln(1, 5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); - runTest("ln(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); + runTest("ln", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("ln(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("ln)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("ln()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); + runTest("ln(1, 5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); + runTest("ln(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); int numTuple = 1; double value = log(1); - runTest("ln(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("ln(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = log(7); - runTest("ln(7)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("ln(7)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Floor Operator") { - runTest("floor", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("floor(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("floor)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("floor()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); - runTest("floor(1, 5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); - runTest("floor(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); + runTest("floor", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("floor(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("floor)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("floor()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); + runTest("floor(1, 5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); + runTest("floor(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 12; - runTest("floor(12.4564)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("floor(12.4564)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -83; - runTest("floor(-82.789367)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("floor(-82.789367)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Ceil Operator") { - runTest("ceil", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("ceil(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("ceil)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("ceil()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); - runTest("ceil(1, 5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); - runTest("ceil(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::TooManyArguments), CalculatorItem::WarningCode::None); + runTest("ceil", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("ceil(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("ceil)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("ceil()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); + runTest("ceil(1, 5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); + runTest("ceil(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::TooManyArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 1; - runTest("ceil(.4564)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("ceil(.4564)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -82; - runTest("ceil(-82.789367)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("ceil(-82.789367)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Negative Operator") { - runTest("-", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoRightValue), CalculatorItem::WarningCode::None); + runTest("-", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoRightValue), CalculatorWarningCode::None); - runTest("-(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::MismatchedParentheses), CalculatorItem::WarningCode::None); - runTest("-)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoRightValue), CalculatorItem::WarningCode::None); - runTest("-()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); - runTest("-(1, 5)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoPrecedingUnaryOperator), CalculatorItem::WarningCode::None); - runTest("-(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoPrecedingUnaryOperator), CalculatorItem::WarningCode::None); + runTest("-(", k_NumericArrayPath, static_cast(CalculatorErrorCode::MismatchedParentheses), CalculatorWarningCode::None); + runTest("-)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoRightValue), CalculatorWarningCode::None); + runTest("-()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); + runTest("-(1, 5)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoPrecedingUnaryOperator), CalculatorWarningCode::None); + runTest("-(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoPrecedingUnaryOperator), CalculatorWarningCode::None); int numTuple = 1; double value = -9; - runTest("- 9", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("- 9", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -0.4564; - runTest("-(.4564)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("-(.4564)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = 1; - runTest("-(3-4)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::AmbiguousNameWarning, &numTuple, &value); + runTest("-(3-4)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::AmbiguousNameWarning, &numTuple, &value); } SECTION("Min Operator") { - runTest("min", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("min(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("min)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("min()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("min(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("min(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("min", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("min(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("min)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("min()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("min(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("min(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 2; - runTest("min(2,6)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("min(2,6)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -93; - runTest("min(-82,-93)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("min(-82,-93)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } SECTION("Max Operator") { - runTest("max", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("max(", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoClosingParen), CalculatorItem::WarningCode::None); - runTest("max)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::OperatorNoOpeningParen), CalculatorItem::WarningCode::None); - runTest("max()", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("max(1)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NotEnoughArguments), CalculatorItem::WarningCode::None); - runTest("max(,)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::NoNumericArguments), CalculatorItem::WarningCode::None); + runTest("max", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("max(", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoClosingParen), CalculatorWarningCode::None); + runTest("max)", k_NumericArrayPath, static_cast(CalculatorErrorCode::OperatorNoOpeningParen), CalculatorWarningCode::None); + runTest("max()", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("max(1)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NotEnoughArguments), CalculatorWarningCode::None); + runTest("max(,)", k_NumericArrayPath, static_cast(CalculatorErrorCode::NoNumericArguments), CalculatorWarningCode::None); int numTuple = 1; double value = 6; - runTest("max(2,6)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("max(2,6)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); value = -82; - runTest("max(-82,-93)", k_NumericArrayPath, static_cast(CalculatorItem::ErrorCode::Success), CalculatorItem::WarningCode::None, &numTuple, &value); + runTest("max(-82,-93)", k_NumericArrayPath, static_cast(CalculatorErrorCode::Success), CalculatorWarningCode::None, &numTuple, &value); } } From 30cdf55b0875e1412fc18d7fc444b83761aa5d85 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 01:08:10 -0400 Subject: [PATCH 08/19] ENH: Remove 65 legacy calculator utility files, consolidate into ArrayCalculator algorithm --- src/Plugins/SimplnxCore/CMakeLists.txt | 65 ----- .../src/SimplnxCore/utils/ABSOperator.cpp | 32 --- .../src/SimplnxCore/utils/ABSOperator.hpp | 41 --- .../src/SimplnxCore/utils/ACosOperator.cpp | 32 --- .../src/SimplnxCore/utils/ACosOperator.hpp | 41 --- .../src/SimplnxCore/utils/ASinOperator.cpp | 32 --- .../src/SimplnxCore/utils/ASinOperator.hpp | 42 --- .../src/SimplnxCore/utils/ATanOperator.cpp | 32 --- .../src/SimplnxCore/utils/ATanOperator.hpp | 42 --- .../SimplnxCore/utils/AdditionOperator.cpp | 32 --- .../SimplnxCore/utils/AdditionOperator.hpp | 42 --- .../src/SimplnxCore/utils/BinaryOperator.cpp | 61 ---- .../src/SimplnxCore/utils/BinaryOperator.hpp | 44 --- .../src/SimplnxCore/utils/CalculatorArray.hpp | 169 ----------- .../src/SimplnxCore/utils/CalculatorItem.cpp | 87 ------ .../src/SimplnxCore/utils/CalculatorItem.hpp | 99 ------- .../SimplnxCore/utils/CalculatorOperator.cpp | 140 --------- .../SimplnxCore/utils/CalculatorOperator.hpp | 77 ----- .../SimplnxCore/utils/CalculatorSeparator.cpp | 19 -- .../SimplnxCore/utils/CalculatorSeparator.hpp | 34 --- .../src/SimplnxCore/utils/CeilOperator.cpp | 32 --- .../src/SimplnxCore/utils/CeilOperator.hpp | 40 --- .../src/SimplnxCore/utils/CommaSeparator.cpp | 49 ---- .../src/SimplnxCore/utils/CommaSeparator.hpp | 38 --- .../src/SimplnxCore/utils/CosOperator.cpp | 32 --- .../src/SimplnxCore/utils/CosOperator.hpp | 40 --- .../SimplnxCore/utils/DivisionOperator.cpp | 31 -- .../SimplnxCore/utils/DivisionOperator.hpp | 38 --- .../src/SimplnxCore/utils/ExpOperator.cpp | 32 --- .../src/SimplnxCore/utils/ExpOperator.hpp | 40 --- .../src/SimplnxCore/utils/FloorOperator.cpp | 32 --- .../src/SimplnxCore/utils/FloorOperator.hpp | 40 --- .../SimplnxCore/utils/ICalculatorArray.cpp | 19 -- .../SimplnxCore/utils/ICalculatorArray.hpp | 49 ---- .../SimplnxCore/utils/LeftParenthesisItem.cpp | 53 ---- .../SimplnxCore/utils/LeftParenthesisItem.hpp | 45 --- .../src/SimplnxCore/utils/LnOperator.cpp | 32 --- .../src/SimplnxCore/utils/LnOperator.hpp | 40 --- .../src/SimplnxCore/utils/Log10Operator.cpp | 32 --- .../src/SimplnxCore/utils/Log10Operator.hpp | 41 --- .../src/SimplnxCore/utils/LogOperator.cpp | 40 --- .../src/SimplnxCore/utils/LogOperator.hpp | 42 --- .../src/SimplnxCore/utils/MaxOperator.cpp | 33 --- .../src/SimplnxCore/utils/MaxOperator.hpp | 40 --- .../src/SimplnxCore/utils/MinOperator.cpp | 33 --- .../src/SimplnxCore/utils/MinOperator.hpp | 40 --- .../utils/MultiplicationOperator.cpp | 32 --- .../utils/MultiplicationOperator.hpp | 39 --- .../SimplnxCore/utils/NegativeOperator.cpp | 81 ------ .../SimplnxCore/utils/NegativeOperator.hpp | 41 --- .../src/SimplnxCore/utils/PowOperator.cpp | 32 --- .../src/SimplnxCore/utils/PowOperator.hpp | 41 --- .../utils/RightParenthesisItem.cpp | 53 ---- .../utils/RightParenthesisItem.hpp | 45 --- .../src/SimplnxCore/utils/RootOperator.cpp | 32 --- .../src/SimplnxCore/utils/RootOperator.hpp | 41 --- .../src/SimplnxCore/utils/SinOperator.cpp | 32 --- .../src/SimplnxCore/utils/SinOperator.hpp | 41 --- .../src/SimplnxCore/utils/SqrtOperator.cpp | 32 --- .../src/SimplnxCore/utils/SqrtOperator.hpp | 41 --- .../SimplnxCore/utils/SubtractionOperator.cpp | 32 --- .../SimplnxCore/utils/SubtractionOperator.hpp | 39 --- .../src/SimplnxCore/utils/TanOperator.cpp | 32 --- .../src/SimplnxCore/utils/TanOperator.hpp | 41 --- .../src/SimplnxCore/utils/UnaryOperator.cpp | 265 ------------------ .../src/SimplnxCore/utils/UnaryOperator.hpp | 56 ---- 66 files changed, 3194 deletions(-) delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp diff --git a/src/Plugins/SimplnxCore/CMakeLists.txt b/src/Plugins/SimplnxCore/CMakeLists.txt index 8175d378fe..a19eff9ce3 100644 --- a/src/Plugins/SimplnxCore/CMakeLists.txt +++ b/src/Plugins/SimplnxCore/CMakeLists.txt @@ -371,71 +371,6 @@ set(PLUGIN_EXTRA_SOURCES "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/nanoflann.hpp" "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/StlUtilities.hpp" "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/StlUtilities.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CalculatorItem.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CalculatorItem.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ICalculatorArray.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ICalculatorArray.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CalculatorArray.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CalculatorOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CalculatorOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/UnaryOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/UnaryOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/BinaryOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/BinaryOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ABSOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ABSOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PowOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PowOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ExpOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ExpOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/SinOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/SinOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CosOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CosOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/TanOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/TanOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ASinOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ASinOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ACosOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ACosOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ATanOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/ATanOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/SqrtOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/SqrtOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/RootOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/RootOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/LogOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/LogOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/Log10Operator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/Log10Operator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/LnOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/LnOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AdditionOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AdditionOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/SubtractionOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/SubtractionOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/NegativeOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/NegativeOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/MultiplicationOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/MultiplicationOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/DivisionOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/DivisionOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/LeftParenthesisItem.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/LeftParenthesisItem.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/RightParenthesisItem.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/RightParenthesisItem.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CalculatorSeparator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CalculatorSeparator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CommaSeparator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CommaSeparator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/FloorOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/FloorOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/MinOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/MinOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/MaxOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/MaxOperator.cpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CeilOperator.hpp" - "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/CeilOperator.cpp" "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AvizoWriter.hpp" "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/AvizoWriter.cpp" "${${PLUGIN_NAME}_SOURCE_DIR}/src/${PLUGIN_NAME}/utils/PythonPluginTemplateFile.hpp" diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp deleted file mode 100644 index 41b5b3bd31..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ABSOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ABSOperator::ABSOperator() -{ - setNumberOfArguments(1); - setInfixToken("abs"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ABSOperator::~ABSOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ABSOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return fabs(num); }); -} - -// ----------------------------------------------------------------------------- -ABSOperator::Pointer ABSOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp deleted file mode 100644 index 1048bb44db..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ABSOperator : public UnaryOperator -{ -public: - using Self = ABSOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ABSOperator()); - } - - ~ABSOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ABSOperator(); - -public: - ABSOperator(const ABSOperator&) = delete; // Copy Constructor Not Implemented - ABSOperator(ABSOperator&&) = delete; // Move Constructor Not Implemented - ABSOperator& operator=(const ABSOperator&) = delete; // Copy Assignment Not Implemented - ABSOperator& operator=(ABSOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp deleted file mode 100644 index 0cd8872ba1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ACosOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ACosOperator::ACosOperator() -{ - setNumberOfArguments(1); - setInfixToken("acos"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ACosOperator::~ACosOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ACosOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return acos(num); }); -} - -// ----------------------------------------------------------------------------- -ACosOperator::Pointer ACosOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp deleted file mode 100644 index 89e7a3e554..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ACosOperator : public UnaryOperator -{ -public: - using Self = ACosOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ACosOperator()); - } - - ~ACosOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ACosOperator(); - -public: - ACosOperator(const ACosOperator&) = delete; // Copy Constructor Not Implemented - ACosOperator(ACosOperator&&) = delete; // Move Constructor Not Implemented - ACosOperator& operator=(const ACosOperator&) = delete; // Copy Assignment Not Implemented - ACosOperator& operator=(ACosOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp deleted file mode 100644 index 924e62d393..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ASinOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ASinOperator::ASinOperator() -{ - setNumberOfArguments(1); - setInfixToken("asin"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ASinOperator::~ASinOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ASinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return asin(num); }); -} - -// ----------------------------------------------------------------------------- -ASinOperator::Pointer ASinOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp deleted file mode 100644 index 869dc07c9c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ - -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ASinOperator : public UnaryOperator -{ -public: - using Self = ASinOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ASinOperator()); - } - - ~ASinOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ASinOperator(); - -public: - ASinOperator(const ASinOperator&) = delete; // Copy Constructor Not Implemented - ASinOperator(ASinOperator&&) = delete; // Move Constructor Not Implemented - ASinOperator& operator=(const ASinOperator&) = delete; // Copy Assignment Not Implemented - ASinOperator& operator=(ASinOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp deleted file mode 100644 index 29e9dc8bd4..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ATanOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ATanOperator::ATanOperator() -{ - setNumberOfArguments(1); - setInfixToken("atan"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ATanOperator::~ATanOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ATanOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return atan(num); }); -} - -// ----------------------------------------------------------------------------- -ATanOperator::Pointer ATanOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp deleted file mode 100644 index 71690e142f..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ - -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ATanOperator : public UnaryOperator -{ -public: - using Self = ATanOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ATanOperator()); - } - - ~ATanOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ATanOperator(); - -public: - ATanOperator(const ATanOperator&) = delete; // Copy Constructor Not Implemented - ATanOperator(ATanOperator&&) = delete; // Move Constructor Not Implemented - ATanOperator& operator=(const ATanOperator&) = delete; // Copy Assignment Not Implemented - ATanOperator& operator=(ATanOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core \ No newline at end of file diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp deleted file mode 100644 index 759f0fafc6..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/AdditionOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -AdditionOperator::AdditionOperator() -{ - setPrecedence(A_Precedence); - setInfixToken("+"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -AdditionOperator::~AdditionOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void AdditionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 + num2; }); -} - -// ----------------------------------------------------------------------------- -AdditionOperator::Pointer AdditionOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp deleted file mode 100644 index 63ebf83833..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ - -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT AdditionOperator : public BinaryOperator -{ -public: - using Self = AdditionOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new AdditionOperator()); - } - - ~AdditionOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - AdditionOperator(); - -public: - AdditionOperator(const AdditionOperator&) = delete; // Copy Constructor Not Implemented - AdditionOperator(AdditionOperator&&) = delete; // Move Constructor Not Implemented - AdditionOperator& operator=(const AdditionOperator&) = delete; // Copy Assignment Not Implemented - AdditionOperator& operator=(AdditionOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp deleted file mode 100644 index fde52052c1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "SimplnxCore/utils/BinaryOperator.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" -#include "SimplnxCore/utils/RightParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -BinaryOperator::BinaryOperator() -{ - setOperatorType(Binary); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -BinaryOperator::~BinaryOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void BinaryOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - // This should never be executed -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode BinaryOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - int leftValue = currentIndex - 1; - int rightValue = currentIndex + 1; - - // Check that there is a valid value to the left of the operator - if(leftValue < 0 || - (nullptr != std::dynamic_pointer_cast(infixVector[leftValue]) && std::dynamic_pointer_cast(infixVector[leftValue])->getOperatorType() == Binary) || - nullptr != std::dynamic_pointer_cast(infixVector[leftValue])) - { - errMsg = fmt::format("The operator '{}' does not have a valid 'left' value.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoLeftValue; - } - - // Check that there is a valid value to the right of the operator - if(rightValue > infixVector.size() - 1 || - (nullptr != std::dynamic_pointer_cast(infixVector[rightValue]) && std::dynamic_pointer_cast(infixVector[rightValue])->getOperatorType() == Binary) || - nullptr != std::dynamic_pointer_cast(infixVector[rightValue])) - { - errMsg = fmt::format("The operator '{}' does not have a valid 'right' value.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoRightValue; - } - - return CalculatorItem::ErrorCode::Success; -} - -// ----------------------------------------------------------------------------- -BinaryOperator::Pointer BinaryOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp deleted file mode 100644 index 8f8b1fe93a..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "SimplnxCore/utils/CalculatorOperator.hpp" - -#include "simplnx/DataStructure/DataPath.hpp" - -#include -#include - -namespace nx::core -{ - -class SIMPLNXCORE_EXPORT BinaryOperator : public CalculatorOperator -{ -public: - using Self = BinaryOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new BinaryOperator()); - } - - ~BinaryOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) final; - -protected: - BinaryOperator(); - -public: - BinaryOperator(const BinaryOperator&) = delete; // Copy Constructor Not Implemented - BinaryOperator(BinaryOperator&&) = delete; // Move Constructor Not Implemented - BinaryOperator& operator=(const BinaryOperator&) = delete; // Copy Assignment Not Implemented - BinaryOperator& operator=(BinaryOperator&&) = delete; // Move Assignment Not Implemented -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp deleted file mode 100644 index 4bacfafee9..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/ICalculatorArray.hpp" - -#include "simplnx/DataStructure/DataArray.hpp" -#include "simplnx/Utilities/StringUtilities.hpp" - -namespace nx::core -{ - -template -class SIMPLNXCORE_EXPORT CalculatorArray : public ICalculatorArray -{ -public: - using Self = CalculatorArray; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer() - { - return Pointer(static_cast(nullptr)); - } - - /** - * @brief Returns the name of the class for AbstractMessage - */ - virtual std::string getNameOfClass() const - { - return "CalculatorArray"; - } - /** - * @brief Returns the name of the class for AbstractMessage - */ - static std::string ClassName() - { - return "CalculatorArray"; - } - - static Pointer New(DataStructure& dataStructure, const DataArray* array, ValueType type, bool allocate) - { - return Pointer(new CalculatorArray(dataStructure, array, type, allocate)); - } - - ~CalculatorArray() override = default; - - Float64Array* getArray() override - { - if(m_ArrayId.has_value()) - { - return m_DataStructure.getDataAs(m_ArrayId.value()); - } - return nullptr; - } - - void setValue(usize i, double val) override - { - if(m_ArrayId.has_value()) - { - m_DataStructure.getDataRefAs(m_ArrayId.value())[i] = val; - } - } - - double getValue(usize i) override - { - if(!m_ArrayId.has_value()) - { - // ERROR: The array is empty! - return 0.0; - } - auto& array = m_DataStructure.getDataRefAs(m_ArrayId.value()); - if(array.getNumberOfTuples() > 1) - { - return static_cast(array[i]); - } - if(array.getNumberOfTuples() == 1) - { - return static_cast(array[0]); - } - // ERROR: The array is empty! - return 0.0; - } - - ICalculatorArray::ValueType getType() override - { - return m_Type; - } - - Float64Array* reduceToOneComponent(int c, bool allocate = true) override - { - if(!m_ArrayId.has_value()) - { - return nullptr; - } - auto* array = m_DataStructure.getDataAs(m_ArrayId.value()); - auto numComponents = array->getNumberOfComponents(); - if(c >= 0 && c <= numComponents) - { - if(numComponents > 1) - { - DataPath reducedArrayPath = GetUniquePathName(m_DataStructure, array->getDataPaths()[0]); // doesn't matter which path since we only use the target name - Float64Array* newArray = Float64Array::CreateWithStore(m_DataStructure, reducedArrayPath.getTargetName(), array->getTupleShape(), {1}); - if(allocate) - { - for(usize i = 0; i < array->getNumberOfTuples(); i++) - { - (*newArray)[i] = (*array)[i * numComponents + c]; - } - } - - return newArray; - } - } - - return nullptr; - } - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override - { - return CalculatorItem::ErrorCode::Success; - } - -protected: - CalculatorArray() = default; - - CalculatorArray(DataStructure& dataStructure, const DataArray* dataArray, ValueType type, bool allocate) - : ICalculatorArray() - , m_Type(type) - , m_DataStructure(dataStructure) - { - DataPath targetPath({dataArray->getName()}); - if(dataStructure.containsData(targetPath)) - { - m_ArrayId = dataStructure.getId(targetPath); - } - else - { - if(allocate) - { - auto* tempArray = Float64Array::CreateWithStore(dataStructure, dataArray->getName(), dataArray->getTupleShape(), dataArray->getComponentShape()); - for(usize i = 0; i < dataArray->getSize(); i++) - { - (*tempArray)[i] = static_cast(dataArray->at(i)); - } - m_ArrayId = std::optional{tempArray->getId()}; - } - else - { - auto* tempArray = - Float64Array::Create(dataStructure, dataArray->getName(), std::make_shared(Float64DataStore(dataArray->getTupleShape(), dataArray->getComponentShape(), {}))); - m_ArrayId = std::optional{tempArray->getId()}; - } - } - } - -private: - std::optional m_ArrayId = {}; - ValueType m_Type = Unknown; - DataStructure& m_DataStructure; - -public: - CalculatorArray(const CalculatorArray&) = delete; // Copy Constructor Not Implemented - CalculatorArray(CalculatorArray&&) = delete; // Move Constructor Not Implemented - CalculatorArray& operator=(const CalculatorArray&) = delete; // Copy Assignment Not Implemented - CalculatorArray& operator=(CalculatorArray&&) = delete; // Move Assignment Not Implemented -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp deleted file mode 100644 index f523fd3122..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include "SimplnxCore/utils/CalculatorItem.hpp" -#include "SimplnxCore/utils/ICalculatorArray.hpp" - -#include "simplnx/Utilities/StringUtilities.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::CalculatorItem() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::~CalculatorItem() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -std::string CalculatorItem::getInfixToken() -{ - return m_InfixToken; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CalculatorItem::setInfixToken(const std::string& token) -{ - m_InfixToken = token; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -bool CalculatorItem::isICalculatorArray() -{ - return (nullptr != dynamic_cast(this)); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -bool CalculatorItem::isArray() -{ - ICalculatorArray* calculatorArray = dynamic_cast(this); - if(calculatorArray != nullptr) - { - return (calculatorArray->getType() == ICalculatorArray::ValueType::Array); - } - - return false; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -bool CalculatorItem::isNumber() -{ - ICalculatorArray* calculatorArray = dynamic_cast(this); - if(calculatorArray != nullptr) - { - return (calculatorArray->getType() == ICalculatorArray::ValueType::Number); - } - - return false; -} - -// ----------------------------------------------------------------------------- -CalculatorItem::Pointer CalculatorItem::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} - -// ----------------------------------------------------------------------------- -DataPath CalculatorItem::GetUniquePathName(const DataStructure& dataStructure, DataPath path) -{ - if(dataStructure.containsData(path)) - { - auto calculatedPathVector = path.getPathVector(); - auto& targetName = calculatedPathVector.back(); - targetName = targetName + StringUtilities::number(dataStructure.getSize()); - path = DataPath(calculatedPathVector); - } - return path; -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp deleted file mode 100644 index 8b67cf37c2..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp +++ /dev/null @@ -1,99 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" - -#include -#include -#include - -namespace nx::core -{ -class DataStructure; -class DataPath; - -/** - * @brief The CalculatorItem class - */ -class SIMPLNXCORE_EXPORT CalculatorItem -{ -public: - using Self = CalculatorItem; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - virtual ~CalculatorItem(); - - using EnumType = int; - - enum class ErrorCode : EnumType - { - Success = 0, - InvalidEquation = -4009, - InvalidComponent = -4010, - EmptyEquation = -4011, - EmptyCalArray = -4012, - EmptySelMatrix = -4013, - LostAttrMatrix = -4014, - IncorrectTupleCount = -4015, - InconsistentTuples = -4016, - UnrecognizedItem = -4017, - MismatchedParentheses = -4018, - UnexpectedOutput = -4019, - ComponentOutOfRange = -4020, - InvalidArrayName = -4022, - InconsistentIndexing = -4023, - InconsistentCompDims = -4024, - AttrArrayZeroTuplesWarning = -4025, - OrphanedComponent = -4026, - OperatorNoLeftValue = -4027, - OperatorNoRightValue = -4028, - OperatorNoOpeningParen = -4029, - OperatorNoClosingParen = -4030, - NoNumericArguments = -4031, - MissingArguments = -4032, - NotEnoughArguments = -4033, - TooManyArguments = -4034, - InvalidSymbol = -4035, - NoPrecedingUnaryOperator = -4036, - InvalidOutputArrayType = -4037, - AttributeMatrixInsertionError = -4038 - }; - - enum class WarningCode : EnumType - { - None = 0, - NumericValueWarning = -5010, - AmbiguousNameWarning = -5011 - }; - - std::string getInfixToken(); - - virtual CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) = 0; - - bool isICalculatorArray(); - - bool isArray(); - - bool isNumber(); - - static DataPath GetUniquePathName(const DataStructure& dataStructure, DataPath path); - -protected: - CalculatorItem(); - - void setInfixToken(const std::string& token); - -private: - std::string m_InfixToken = {}; - -public: - CalculatorItem(const CalculatorItem&) = delete; // Copy Constructor Not Implemented - CalculatorItem(CalculatorItem&&) = delete; // Move Constructor Not Implemented - CalculatorItem& operator=(const CalculatorItem&) = delete; // Copy Assignment Not Implemented - CalculatorItem& operator=(CalculatorItem&&) = delete; // Move Assignment Not Implemented -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp deleted file mode 100644 index b2b74d0100..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "SimplnxCore/utils/CalculatorOperator.hpp" - -#include "simplnx/Common/Numbers.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::CalculatorOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::~CalculatorOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -bool CalculatorOperator::hasHigherPrecedence(const CalculatorOperator::Pointer other) -{ - return m_Precedence > other->m_Precedence; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::Precedence CalculatorOperator::getPrecedence() -{ - return m_Precedence; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CalculatorOperator::setPrecedence(Precedence precedence) -{ - m_Precedence = precedence; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::OperatorType CalculatorOperator::getOperatorType() -{ - return m_OperatorType; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CalculatorOperator::setOperatorType(OperatorType type) -{ - m_OperatorType = type; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double CalculatorOperator::toDegrees(double radians) -{ - return radians * (180.0 / numbers::pi); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double CalculatorOperator::toRadians(double degrees) -{ - return degrees * (numbers::pi / 180.0); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double CalculatorOperator::root(double base, double root) -{ - if(root == 0) - { - return std::numeric_limits::infinity(); - } - - return pow(base, 1 / root); -} - -// ----------------------------------------------------------------------------- -CalculatorOperator::Pointer CalculatorOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} - -// ----------------------------------------------------------------------------- -void CalculatorOperator::CreateNewArrayTwoArguments(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, - std::stack& executionStack, std::function op) -{ - ICalculatorArray::Pointer iArray1 = executionStack.top(); - if(executionStack.size() >= 2 && nullptr != iArray1) - { - executionStack.pop(); - ICalculatorArray::Pointer iArray2 = executionStack.top(); - executionStack.pop(); - - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array1 = iArray1->getArray(); - DataArray* array2 = iArray2->getArray(); - - Float64Array* newArray = nullptr; - if(iArray1->getType() == ICalculatorArray::Array) - { - newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array1->getTupleShape(), array1->getComponentShape()); - } - else - { - newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array2->getTupleShape(), array2->getComponentShape()); - } - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - float64 num1 = (iArray1->getType() == ICalculatorArray::Array) ? array1->getValue(index) : array1->getValue(0); - float64 num2 = (iArray2->getType() == ICalculatorArray::Array) ? array2->getValue(index) : array2->getValue(0); - (*newArray)[index] = op(num2, num1); - } - } - - if(iArray1->getType() == ICalculatorArray::Array || iArray2->getType() == ICalculatorArray::Array) - { - executionStack.push(CalculatorArray::New(dataStructure, newArray, ICalculatorArray::Array, true)); - } - else - { - executionStack.push(CalculatorArray::New(dataStructure, newArray, ICalculatorArray::Number, true)); - } - return; - } -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp deleted file mode 100644 index 21b1f4db31..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -#include "simplnx/DataStructure/DataArray.hpp" -#include "simplnx/DataStructure/DataPath.hpp" -#include "simplnx/Parameters/CalculatorParameter.hpp" - -#include -#include - -namespace nx::core -{ - -class SIMPLNXCORE_EXPORT CalculatorOperator : public CalculatorItem -{ -public: - enum OperatorType - { - Unary, - Binary - }; - - using Self = CalculatorOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static double toDegrees(double radians); - static double toRadians(double degrees); - - ~CalculatorOperator() override; - - bool hasHigherPrecedence(CalculatorOperator::Pointer other); - - virtual void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) = 0; - - OperatorType getOperatorType(); - -protected: - CalculatorOperator(); - - enum Precedence - { - Unknown_Precedence, - A_Precedence, - B_Precedence, - C_Precedence, - D_Precedence, - E_Precedence - }; - - double root(double base, double root); - - Precedence getPrecedence(); - void setPrecedence(Precedence precedence); - - void setOperatorType(OperatorType type); - -private: - Precedence m_Precedence = {Unknown_Precedence}; - OperatorType m_OperatorType; - -public: - CalculatorOperator(const CalculatorOperator&) = delete; // Copy Constructor Not Implemented - CalculatorOperator(CalculatorOperator&&) = delete; // Move Constructor Not Implemented - CalculatorOperator& operator=(const CalculatorOperator&) = delete; // Copy Assignment Not Implemented - CalculatorOperator& operator=(CalculatorOperator&&) = delete; // Move Assignment Not Implemented - - static void CreateNewArrayTwoArguments(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp deleted file mode 100644 index 0aeb534d8b..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "SimplnxCore/utils/CalculatorSeparator.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorSeparator::CalculatorSeparator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorSeparator::~CalculatorSeparator() = default; - -// ----------------------------------------------------------------------------- -CalculatorSeparator::Pointer CalculatorSeparator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp deleted file mode 100644 index baae97889c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorItem.hpp" - -#include - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT CalculatorSeparator : public CalculatorItem -{ -public: - using Self = CalculatorSeparator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - ~CalculatorSeparator() override; - -protected: - CalculatorSeparator(); - -public: - CalculatorSeparator(const CalculatorSeparator&) = delete; // Copy Constructor Not Implemented - CalculatorSeparator(CalculatorSeparator&&) = delete; // Move Constructor Not Implemented - CalculatorSeparator& operator=(const CalculatorSeparator&) = delete; // Copy Assignment Not Implemented - CalculatorSeparator& operator=(CalculatorSeparator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp deleted file mode 100644 index c06d6ed3b7..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/CeilOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CeilOperator::CeilOperator() -{ - setNumberOfArguments(1); - setInfixToken("ceil"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CeilOperator::~CeilOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CeilOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return ceil(num); }); -} - -// ----------------------------------------------------------------------------- -CeilOperator::Pointer CeilOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp deleted file mode 100644 index 3e46d8df8c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT CeilOperator : public UnaryOperator -{ -public: - using Self = CeilOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new CeilOperator()); - } - - ~CeilOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - CeilOperator(); - -public: - CeilOperator(const CeilOperator&) = delete; // Copy Constructor Not Implemented - CeilOperator(CeilOperator&&) = delete; // Move Constructor Not Implemented - CeilOperator& operator=(const CeilOperator&) = delete; // Copy Assignment Not Implemented - CeilOperator& operator=(CeilOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp deleted file mode 100644 index 57bb32cc06..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "SimplnxCore/utils/CommaSeparator.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CommaSeparator::CommaSeparator() -{ - setInfixToken(","); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CommaSeparator::~CommaSeparator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode CommaSeparator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - // Make sure that this comma has a valid 2-argument unary operator before it - bool foundUnaryOperator = false; - for(int i = currentIndex - 1; i >= 0; i--) - { - CalculatorItem::Pointer item = infixVector[i]; - UnaryOperator::Pointer unary = std::dynamic_pointer_cast(item); - if(unary != UnaryOperator::NullPointer() && unary->getNumberOfArguments() == 2) - { - foundUnaryOperator = true; - } - } - - if(!foundUnaryOperator) - { - errMsg = "A comma in the expression does not have a corresponding operator preceding it."; - return CalculatorItem::ErrorCode::NoPrecedingUnaryOperator; - } - - return CalculatorItem::ErrorCode::Success; -} - -// ----------------------------------------------------------------------------- -CommaSeparator::Pointer CommaSeparator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp deleted file mode 100644 index c58deb63f4..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorSeparator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT CommaSeparator : public CalculatorSeparator -{ -public: - using Self = CommaSeparator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new CommaSeparator()); - } - - ~CommaSeparator() override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override; - -protected: - CommaSeparator(); - -public: - CommaSeparator(const CommaSeparator&) = delete; // Copy Constructor Not Implemented - CommaSeparator(CommaSeparator&&) = delete; // Move Constructor Not Implemented - CommaSeparator& operator=(const CommaSeparator&) = delete; // Copy Assignment Not Implemented - CommaSeparator& operator=(CommaSeparator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp deleted file mode 100644 index 9638355e80..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/CosOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CosOperator::CosOperator() -{ - setNumberOfArguments(1); - setInfixToken("cos"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CosOperator::~CosOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CosOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return cos(num); }); -} - -// ----------------------------------------------------------------------------- -CosOperator::Pointer CosOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp deleted file mode 100644 index 4f94fcf2a7..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT CosOperator : public UnaryOperator -{ -public: - using Self = CosOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new CosOperator()); - } - - ~CosOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - CosOperator(); - -public: - CosOperator(const CosOperator&) = delete; // Copy Constructor Not Implemented - CosOperator(CosOperator&&) = delete; // Move Constructor Not Implemented - CosOperator& operator=(const CosOperator&) = delete; // Copy Assignment Not Implemented - CosOperator& operator=(CosOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp deleted file mode 100644 index 682d3b1333..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "SimplnxCore/utils/DivisionOperator.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -DivisionOperator::DivisionOperator() -{ - setPrecedence(B_Precedence); - setInfixToken("/"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -DivisionOperator::~DivisionOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void DivisionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 / num2; }); -} - -// ----------------------------------------------------------------------------- -DivisionOperator::Pointer DivisionOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp deleted file mode 100644 index d9256a6793..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT DivisionOperator : public BinaryOperator -{ -public: - using Self = DivisionOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new DivisionOperator()); - } - - ~DivisionOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - DivisionOperator(); - -public: - DivisionOperator(const DivisionOperator&) = delete; // Copy Constructor Not Implemented - DivisionOperator(DivisionOperator&&) = delete; // Move Constructor Not Implemented - DivisionOperator& operator=(const DivisionOperator&) = delete; // Copy Assignment Not Implemented - DivisionOperator& operator=(DivisionOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp deleted file mode 100644 index 216c202041..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ExpOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ExpOperator::ExpOperator() -{ - setNumberOfArguments(1); - setInfixToken("exp"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ExpOperator::~ExpOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ExpOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return exp(num); }); -} - -// ----------------------------------------------------------------------------- -ExpOperator::Pointer ExpOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp deleted file mode 100644 index 73d718e92c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ExpOperator : public UnaryOperator -{ -public: - using Self = ExpOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ExpOperator()); - } - - ~ExpOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ExpOperator(); - -public: - ExpOperator(const ExpOperator&) = delete; // Copy Constructor Not Implemented - ExpOperator(ExpOperator&&) = delete; // Move Constructor Not Implemented - ExpOperator& operator=(const ExpOperator&) = delete; // Copy Assignment Not Implemented - ExpOperator& operator=(ExpOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp deleted file mode 100644 index 6b6680f757..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/FloorOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -FloorOperator::FloorOperator() -{ - setNumberOfArguments(1); - setInfixToken("floor"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -FloorOperator::~FloorOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void FloorOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return floor(num); }); -} - -// ----------------------------------------------------------------------------- -FloorOperator::Pointer FloorOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp deleted file mode 100644 index 93e935af96..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT FloorOperator : public UnaryOperator -{ -public: - using Self = FloorOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new FloorOperator()); - } - - ~FloorOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - FloorOperator(); - -public: - FloorOperator(const FloorOperator&) = delete; // Copy Constructor Not Implemented - FloorOperator(FloorOperator&&) = delete; // Move Constructor Not Implemented - FloorOperator& operator=(const FloorOperator&) = delete; // Copy Assignment Not Implemented - FloorOperator& operator=(FloorOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp deleted file mode 100644 index 6f5cf20da5..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "SimplnxCore/utils/ICalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ICalculatorArray::ICalculatorArray() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ICalculatorArray::~ICalculatorArray() = default; - -// ----------------------------------------------------------------------------- -ICalculatorArray::Pointer ICalculatorArray::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp deleted file mode 100644 index 6c08b5d5b6..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorItem.hpp" - -#include "simplnx/DataStructure/DataArray.hpp" - -#include - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT ICalculatorArray : public CalculatorItem -{ -public: - enum ValueType - { - Number, - Array, - Unknown - }; - - using Self = ICalculatorArray; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - ~ICalculatorArray() override; - - virtual Float64Array* getArray() = 0; - virtual double getValue(usize i) = 0; - virtual void setValue(usize i, double value) = 0; - virtual ValueType getType() = 0; - - virtual Float64Array* reduceToOneComponent(int c, bool allocate) = 0; - -protected: - ICalculatorArray(); - -public: - ICalculatorArray(const ICalculatorArray&) = delete; // Copy Constructor Not Implemented - ICalculatorArray(ICalculatorArray&&) = delete; // Move Constructor Not Implemented - ICalculatorArray& operator=(const ICalculatorArray&) = delete; // Copy Assignment Not Implemented - ICalculatorArray& operator=(ICalculatorArray&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp deleted file mode 100644 index 83399045ab..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" -#include "SimplnxCore/utils/RightParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LeftParenthesisItem::LeftParenthesisItem() -{ - setInfixToken("("); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LeftParenthesisItem::~LeftParenthesisItem() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode LeftParenthesisItem::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - // Check for a closing parenthesis, ignoring any other internal sets of parentheses - int leftParenthesisCount = 0; - for(int i = currentIndex + 1; i < infixVector.size(); i++) - { - CalculatorItem::Pointer item = infixVector[i]; - if(std::dynamic_pointer_cast(item) != LeftParenthesisItem::NullPointer()) - { - leftParenthesisCount++; - } - else if(std::dynamic_pointer_cast(item) != RightParenthesisItem::NullPointer()) - { - if(leftParenthesisCount > 0) - { - leftParenthesisCount--; - } - else - { - return LeftParenthesisItem::ErrorCode::Success; - } - } - } - - return LeftParenthesisItem::ErrorCode::MismatchedParentheses; -} - -// ----------------------------------------------------------------------------- -LeftParenthesisItem::Pointer LeftParenthesisItem::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp deleted file mode 100644 index 4c64891175..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorItem.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT LeftParenthesisItem : public CalculatorItem -{ -public: - using Self = LeftParenthesisItem; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new LeftParenthesisItem()); - } - - ~LeftParenthesisItem() override; - - /** - * @brief checkValidity - * @param infixVector - * @param currentIndex - * @param msg - * @return - */ - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override; - -protected: - LeftParenthesisItem(); - -public: - LeftParenthesisItem(const LeftParenthesisItem&) = delete; // Copy Constructor Not Implemented - LeftParenthesisItem(LeftParenthesisItem&&) = delete; // Move Constructor Not Implemented - LeftParenthesisItem& operator=(const LeftParenthesisItem&) = delete; // Copy Assignment Not Implemented - LeftParenthesisItem& operator=(LeftParenthesisItem&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp deleted file mode 100644 index 473c654367..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/LnOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LnOperator::LnOperator() -{ - setNumberOfArguments(1); - setInfixToken("ln"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LnOperator::~LnOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void LnOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return log(num); }); -} - -// ----------------------------------------------------------------------------- -LnOperator::Pointer LnOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp deleted file mode 100644 index 992985eb04..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT LnOperator : public UnaryOperator -{ -public: - using Self = LnOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new LnOperator()); - } - - ~LnOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - LnOperator(); - -public: - LnOperator(const LnOperator&) = delete; // Copy Constructor Not Implemented - LnOperator(LnOperator&&) = delete; // Move Constructor Not Implemented - LnOperator& operator=(const LnOperator&) = delete; // Copy Assignment Not Implemented - LnOperator& operator=(LnOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp deleted file mode 100644 index 64413029e6..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/Log10Operator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -Log10Operator::Log10Operator() -{ - setNumberOfArguments(1); - setInfixToken("log10"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -Log10Operator::~Log10Operator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void Log10Operator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return log10(num); }); -} - -// ----------------------------------------------------------------------------- -Log10Operator::Pointer Log10Operator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp deleted file mode 100644 index ab053ffa10..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT Log10Operator : public UnaryOperator -{ -public: - using Self = Log10Operator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new Log10Operator()); - } - - ~Log10Operator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - Log10Operator(); - -public: - Log10Operator(const Log10Operator&) = delete; // Copy Constructor Not Implemented - Log10Operator(Log10Operator&&) = delete; // Move Constructor Not Implemented - Log10Operator& operator=(const Log10Operator&) = delete; // Copy Assignment Not Implemented - Log10Operator& operator=(Log10Operator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp deleted file mode 100644 index 3d2ed4d006..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "SimplnxCore/utils/LogOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LogOperator::LogOperator() -{ - setNumberOfArguments(2); - setInfixToken("log"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LogOperator::~LogOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void LogOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [this](double num1, double num2) -> double { return log_arbitrary_base(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double LogOperator::log_arbitrary_base(double base, double value) -{ - return log(value) / log(base); -} - -// ----------------------------------------------------------------------------- -LogOperator::Pointer LogOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp deleted file mode 100644 index 9409f158f7..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT LogOperator : public UnaryOperator -{ -public: - using Self = LogOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new LogOperator()); - } - - ~LogOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - LogOperator(); - -private: - double log_arbitrary_base(double base, double value); - -public: - LogOperator(const LogOperator&) = delete; // Copy Constructor Not Implemented - LogOperator(LogOperator&&) = delete; // Move Constructor Not Implemented - LogOperator& operator=(const LogOperator&) = delete; // Copy Assignment Not Implemented - LogOperator& operator=(LogOperator&&) = delete; // Move Assignment Not Implemented -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp deleted file mode 100644 index 3e230d9d9c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "SimplnxCore/utils/MaxOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; -using namespace std; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MaxOperator::MaxOperator() -{ - setNumberOfArguments(2); - setInfixToken("max"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MaxOperator::~MaxOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void MaxOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return max(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -MaxOperator::Pointer MaxOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp deleted file mode 100644 index 0b7431f91c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT MaxOperator : public UnaryOperator -{ -public: - using Self = MaxOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new MaxOperator()); - } - - ~MaxOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - MaxOperator(); - -public: - MaxOperator(const MaxOperator&) = delete; // Copy Constructor Not Implemented - MaxOperator(MaxOperator&&) = delete; // Move Constructor Not Implemented - MaxOperator& operator=(const MaxOperator&) = delete; // Copy Assignment Not Implemented - MaxOperator& operator=(MaxOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp deleted file mode 100644 index f6221cd6c4..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "SimplnxCore/utils/MinOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; -using namespace std; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MinOperator::MinOperator() -{ - setNumberOfArguments(2); - setInfixToken("min"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MinOperator::~MinOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void MinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return min(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -MinOperator::Pointer MinOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp deleted file mode 100644 index 15ff177642..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT MinOperator : public UnaryOperator -{ -public: - using Self = MinOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new MinOperator()); - } - - ~MinOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - MinOperator(); - -public: - MinOperator(const MinOperator&) = delete; // Copy Constructor Not Implemented - MinOperator(MinOperator&&) = delete; // Move Constructor Not Implemented - MinOperator& operator=(const MinOperator&) = delete; // Copy Assignment Not Implemented - MinOperator& operator=(MinOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp deleted file mode 100644 index dc9bf707de..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/MultiplicationOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MultiplicationOperator::MultiplicationOperator() -{ - setPrecedence(B_Precedence); - setInfixToken("*"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MultiplicationOperator::~MultiplicationOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void MultiplicationOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 * num2; }); -} - -// ----------------------------------------------------------------------------- -MultiplicationOperator::Pointer MultiplicationOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp deleted file mode 100644 index 1d32db39af..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT MultiplicationOperator : public BinaryOperator -{ -public: - using Self = MultiplicationOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new MultiplicationOperator()); - } - - ~MultiplicationOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - MultiplicationOperator(); - -public: - MultiplicationOperator(const MultiplicationOperator&) = delete; // Copy Constructor Not Implemented - MultiplicationOperator(MultiplicationOperator&&) = delete; // Move Constructor Not Implemented - MultiplicationOperator& operator=(const MultiplicationOperator&) = delete; // Copy Assignment Not Implemented - MultiplicationOperator& operator=(MultiplicationOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp deleted file mode 100644 index ddf23f2a95..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "SimplnxCore/utils/NegativeOperator.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -NegativeOperator::NegativeOperator() -{ - setOperatorType(Unary); - setPrecedence(D_Precedence); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -NegativeOperator::~NegativeOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void NegativeOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - if(!executionStack.empty()) - { - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array = arrayPtr->getArray(); - - Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = array->getValue(index); - (*newArray)[index] = -1 * num; - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode NegativeOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - if(currentIndex - 1 >= 0 && (std::dynamic_pointer_cast(infixVector[currentIndex - 1]) == BinaryOperator::NullPointer() && - std::dynamic_pointer_cast(infixVector[currentIndex - 1]) == LeftParenthesisItem::NullPointer())) - { - // The symbol to the left of the negative sign is not a binary operator or left parenthesis - errMsg = fmt::format("The negative operator '{}' does not have a valid 'left' value.", getInfixToken()); - return NegativeOperator::ErrorCode::OperatorNoLeftValue; - } - if(currentIndex + 1 >= infixVector.size() || (currentIndex + 1 < infixVector.size() && (nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1]) && - nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1]) && - nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1])))) - { - // The symbol to the right of the negative sign is not an array, left parenthesis, or unary operator - errMsg = fmt::format("The negative operator '{}' does not have a valid 'right' value.", getInfixToken()); - return NegativeOperator::ErrorCode::OperatorNoRightValue; - } - - return NegativeOperator::ErrorCode::Success; -} - -// ----------------------------------------------------------------------------- -NegativeOperator::Pointer NegativeOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp deleted file mode 100644 index d0d7419e2f..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT NegativeOperator : public CalculatorOperator -{ -public: - using Self = NegativeOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new NegativeOperator()); - } - - ~NegativeOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) final; - -protected: - NegativeOperator(); - -public: - NegativeOperator(const NegativeOperator&) = delete; // Copy Constructor Not Implemented - NegativeOperator(NegativeOperator&&) = delete; // Move Constructor Not Implemented - NegativeOperator& operator=(const NegativeOperator&) = delete; // Copy Assignment Not Implemented - NegativeOperator& operator=(NegativeOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp deleted file mode 100644 index 3a6f96cacf..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/PowOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -PowOperator::PowOperator() -{ - setPrecedence(C_Precedence); - setInfixToken("^"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -PowOperator::~PowOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void PowOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return pow(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -PowOperator::Pointer PowOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp deleted file mode 100644 index f9d89aa0ec..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT PowOperator : public BinaryOperator -{ -public: - using Self = PowOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new PowOperator()); - } - - ~PowOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - PowOperator(); - -public: - PowOperator(const PowOperator&) = delete; // Copy Constructor Not Implemented - PowOperator(PowOperator&&) = delete; // Move Constructor Not Implemented - PowOperator& operator=(const PowOperator&) = delete; // Copy Assignment Not Implemented - PowOperator& operator=(PowOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp deleted file mode 100644 index 7585c58e4e..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "SimplnxCore/utils/RightParenthesisItem.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -RightParenthesisItem::RightParenthesisItem() -{ - setInfixToken(")"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -RightParenthesisItem::~RightParenthesisItem() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode RightParenthesisItem::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - // Check for an opening parenthesis, ignoring any other internal sets of parentheses - int rightParenthesisCount = 0; - for(int i = currentIndex - 1; i >= 0; i--) - { - CalculatorItem::Pointer item = infixVector[i]; - if(std::dynamic_pointer_cast(item) != RightParenthesisItem::NullPointer()) - { - rightParenthesisCount++; - } - else if(std::dynamic_pointer_cast(item) != LeftParenthesisItem::NullPointer()) - { - if(rightParenthesisCount > 0) - { - rightParenthesisCount--; - } - else - { - return RightParenthesisItem::ErrorCode::Success; - } - } - } - - return RightParenthesisItem::ErrorCode::MismatchedParentheses; -} - -// ----------------------------------------------------------------------------- -RightParenthesisItem::Pointer RightParenthesisItem::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp deleted file mode 100644 index 51dad2a493..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorItem.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT RightParenthesisItem : public CalculatorItem -{ -public: - using Self = RightParenthesisItem; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new RightParenthesisItem()); - } - - ~RightParenthesisItem() override; - - /** - * @brief checkValidity - * @param infixVector - * @param currentIndex - * @param msg - * @return - */ - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override; - -protected: - RightParenthesisItem(); - -public: - RightParenthesisItem(const RightParenthesisItem&) = delete; // Copy Constructor Not Implemented - RightParenthesisItem(RightParenthesisItem&&) = delete; // Move Constructor Not Implemented - RightParenthesisItem& operator=(const RightParenthesisItem&) = delete; // Copy Assignment Not Implemented - RightParenthesisItem& operator=(RightParenthesisItem&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp deleted file mode 100644 index cf56bbfc4b..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/RootOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -RootOperator::RootOperator() -{ - setNumberOfArguments(2); - setInfixToken("root"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -RootOperator::~RootOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void RootOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [this](double num1, double num2) -> double { return root(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -RootOperator::Pointer RootOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp deleted file mode 100644 index 58b0868bd9..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT RootOperator : public UnaryOperator -{ -public: - using Self = RootOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new RootOperator()); - } - - ~RootOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - RootOperator(); - -public: - RootOperator(const RootOperator&) = delete; // Copy Constructor Not Implemented - RootOperator(RootOperator&&) = delete; // Move Constructor Not Implemented - RootOperator& operator=(const RootOperator&) = delete; // Copy Assignment Not Implemented - RootOperator& operator=(RootOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp deleted file mode 100644 index 9484b3ce3e..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/SinOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SinOperator::SinOperator() -{ - setNumberOfArguments(1); - setInfixToken("sin"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SinOperator::~SinOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void SinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return sin(num); }); -} - -// ----------------------------------------------------------------------------- -SinOperator::Pointer SinOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp deleted file mode 100644 index c8e8d57cf1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT SinOperator : public UnaryOperator -{ -public: - using Self = SinOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new SinOperator()); - } - - ~SinOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - SinOperator(); - -public: - SinOperator(const SinOperator&) = delete; // Copy Constructor Not Implemented - SinOperator(SinOperator&&) = delete; // Move Constructor Not Implemented - SinOperator& operator=(const SinOperator&) = delete; // Copy Assignment Not Implemented - SinOperator& operator=(SinOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp deleted file mode 100644 index 02d17072b1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/SqrtOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SqrtOperator::SqrtOperator() -{ - setNumberOfArguments(1); - setInfixToken("sqrt"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SqrtOperator::~SqrtOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void SqrtOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return sqrt(num); }); -} - -// ----------------------------------------------------------------------------- -SqrtOperator::Pointer SqrtOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp deleted file mode 100644 index 46a174f6f0..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT SqrtOperator : public UnaryOperator -{ -public: - using Self = SqrtOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new SqrtOperator()); - } - - ~SqrtOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - SqrtOperator(); - -public: - SqrtOperator(const SqrtOperator&) = delete; // Copy Constructor Not Implemented - SqrtOperator(SqrtOperator&&) = delete; // Move Constructor Not Implemented - SqrtOperator& operator=(const SqrtOperator&) = delete; // Copy Assignment Not Implemented - SqrtOperator& operator=(SqrtOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp deleted file mode 100644 index 6110ce750f..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/SubtractionOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SubtractionOperator::SubtractionOperator() -{ - setPrecedence(A_Precedence); - setInfixToken("-"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SubtractionOperator::~SubtractionOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void SubtractionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 - num2; }); -} - -// ----------------------------------------------------------------------------- -SubtractionOperator::Pointer SubtractionOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp deleted file mode 100644 index 80b196435e..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT SubtractionOperator : public BinaryOperator -{ -public: - using Self = SubtractionOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new SubtractionOperator()); - } - - ~SubtractionOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - SubtractionOperator(); - -public: - SubtractionOperator(const SubtractionOperator&) = delete; // Copy Constructor Not Implemented - SubtractionOperator(SubtractionOperator&&) = delete; // Move Constructor Not Implemented - SubtractionOperator& operator=(const SubtractionOperator&) = delete; // Copy Assignment Not Implemented - SubtractionOperator& operator=(SubtractionOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp deleted file mode 100644 index e39d1a2d44..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/TanOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -TanOperator::TanOperator() -{ - setNumberOfArguments(1); - setInfixToken("tan"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -TanOperator::~TanOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void TanOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return tan(num); }); -} - -// ----------------------------------------------------------------------------- -TanOperator::Pointer TanOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp deleted file mode 100644 index 5ce8a5ca83..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT TanOperator : public UnaryOperator -{ -public: - using Self = TanOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new TanOperator()); - } - - ~TanOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - TanOperator(); - -public: - TanOperator(const TanOperator&) = delete; // Copy Constructor Not Implemented - TanOperator(TanOperator&&) = delete; // Move Constructor Not Implemented - TanOperator& operator=(const TanOperator&) = delete; // Copy Assignment Not Implemented - TanOperator& operator=(TanOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp deleted file mode 100644 index 61cf7c7c99..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include "UnaryOperator.hpp" - -#include "SimplnxCore/Filters/ArrayCalculatorFilter.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" -#include "SimplnxCore/utils/CommaSeparator.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" -#include "SimplnxCore/utils/NegativeOperator.hpp" -#include "SimplnxCore/utils/RightParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -UnaryOperator::UnaryOperator() -: m_NumOfArguments(-1) -{ - setPrecedence(E_Precedence); - setOperatorType(Unary); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -UnaryOperator::~UnaryOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void UnaryOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - // This should never be executed -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode UnaryOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - if(currentIndex - 1 >= 0) - { - // If the left value isn't a binary operator - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - // If the left value isn't a left parenthesis - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - // If the left value isn't a negative operator - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - // If the left value isn't a comma - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - errMsg = fmt::format("The operator '{}' does not have a valid 'left' value.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoLeftValue; - } - } - } - } - } - - int index = currentIndex + 1; - int commaCount = 0; - bool hasArray = false; - if(index < infixVector.size() && nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - index++; - - // Iterate through the vector to find the matching right parenthesis - for(; index < infixVector.size(); index++) - { - if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - // We found the matching right parenthesis - if(commaCount < m_NumOfArguments - 1) - { - errMsg = fmt::format("The operator '{}' needs {} arguments. {} arguments were found.", getInfixToken(), m_NumOfArguments, commaCount + 1); - return CalculatorItem::ErrorCode::NotEnoughArguments; - } - if(!hasArray) - { - errMsg = fmt::format("The operator '{}' does not have any arguments that simplify down to a number.", getInfixToken()); - return CalculatorItem::ErrorCode::NoNumericArguments; - } - - return CalculatorItem::ErrorCode::Success; - } - if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - /* We found another left parenthesis, but we don't care what's inside this set of parentheses - (other operators' checkValidity functions will take care of these values), so just iterate - until we find the matching closing parenthesis for this opening parenthesis */ - int extraLeftPCount = 0; - index++; - while(index < infixVector.size() && (nullptr == std::dynamic_pointer_cast(infixVector[index]) || extraLeftPCount > 0)) - { - if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - hasArray = true; - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - extraLeftPCount++; - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - extraLeftPCount--; - } - - index++; - } - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - // We found a comma, so increase the comma count - commaCount++; - if(commaCount > m_NumOfArguments - 1) - { - // We found too many commas (meaning that there are too many arguments), so return false - errMsg = fmt::format("The operator '{}' needs {} arguments. {} arguments were found.", getInfixToken(), m_NumOfArguments, commaCount + 1); - return CalculatorItem::ErrorCode::TooManyArguments; - } - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - hasArray = true; - } - } - } - else - { - errMsg = fmt::format("The operator '{}' does not have an opening parenthesis.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoOpeningParen; - } - - errMsg = fmt::format("The operator '{}' does not have a closing parenthesis.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoClosingParen; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -int UnaryOperator::getNumberOfArguments() -{ - return m_NumOfArguments; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void UnaryOperator::setNumberOfArguments(int numOfArguments) -{ - m_NumOfArguments = numOfArguments; -} - -// ----------------------------------------------------------------------------- -UnaryOperator::Pointer UnaryOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} - -// ----------------------------------------------------------------------------- -void UnaryOperator::CreateNewArrayStandardUnary(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, - std::stack& executionStack, std::function op) -{ - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - if(!executionStack.empty() && nullptr != arrayPtr) - { - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - Float64Array* newArray = - Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), arrayPtr->getArray()->getTupleShape(), arrayPtr->getArray()->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = arrayPtr->getValue(index); - (*newArray)[index] = op(num); - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} - -// ----------------------------------------------------------------------------- -void UnaryOperator::CreateNewArrayTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op) -{ - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - if(!executionStack.empty() && nullptr != arrayPtr) - { - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array = arrayPtr->getArray(); - - Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = array->getValue(index); - - if(units == CalculatorParameter::AngleUnits::Degrees) - { - (*newArray)[index] = op(toRadians(num)); - } - else - { - (*newArray)[index] = op(num); - } - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} - -// ----------------------------------------------------------------------------- -void UnaryOperator::CreateNewArrayArcTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op) -{ - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - if(!executionStack.empty() && nullptr != arrayPtr) - { - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array = arrayPtr->getArray(); - - Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = array->getValue(index); - - if(units == CalculatorParameter::AngleUnits::Degrees) - { - (*newArray)[index] = toDegrees(op(num)); - } - else - { - (*newArray)[index] = op(num); - } - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp deleted file mode 100644 index a3f49a08d8..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "SimplnxCore/utils/CalculatorOperator.hpp" -#include "simplnx/DataStructure/DataPath.hpp" - -#include -#include - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT UnaryOperator : public CalculatorOperator -{ -public: - using Self = UnaryOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new UnaryOperator()); - } - - ~UnaryOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) final; - - int getNumberOfArguments(); - -protected: - UnaryOperator(); - - void setNumberOfArguments(int numOfArguments); - -private: - int m_NumOfArguments; - -public: - UnaryOperator(const UnaryOperator&) = delete; // Copy Constructor Not Implemented - UnaryOperator(UnaryOperator&&) = delete; // Move Constructor Not Implemented - UnaryOperator& operator=(const UnaryOperator&) = delete; // Copy Assignment Not Implemented - UnaryOperator& operator=(UnaryOperator&&) = delete; // Move Assignment Not Implemented - - static void CreateNewArrayStandardUnary(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); - static void CreateNewArrayTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); - static void CreateNewArrayArcTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); -}; - -} // namespace nx::core From 7f0228fbc526987771fbceb14afaff9c3afc1145 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 08:15:52 -0400 Subject: [PATCH 09/19] ENH: Add tests for array resolution, constants, tuple indexing, modulo, sub-expression components --- .../Filters/Algorithms/ArrayCalculator.cpp | 15 +- .../SimplnxCore/test/ArrayCalculatorTest.cpp | 333 ++++++++++++++++++ 2 files changed, 347 insertions(+), 1 deletion(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 10656737a7..5ff3b4c4d5 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -1356,6 +1356,19 @@ Result<> ArrayCalculatorParser::parse() return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), "The expression does not have any arguments that simplify down to a number."); } + // Check if there is a ComponentExtract item in the parsed list. + // If so, the final output will be single-component regardless of the + // input array's component shape. + bool hasComponentExtract = false; + for(const auto& item : items) + { + if(item.kind == ParsedItem::Kind::ComponentExtract) + { + hasComponentExtract = true; + break; + } + } + // Store the parsed shape info for use by parseAndValidate() if(hasArray) { @@ -1367,7 +1380,7 @@ Result<> ArrayCalculatorParser::parse() { m_ParsedTupleShape = {arrayNumTuples}; } - m_ParsedComponentShape = arrayCompShape; + m_ParsedComponentShape = hasComponentExtract ? std::vector{1} : arrayCompShape; } else { diff --git a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp index 5e7e390101..30861fc02f 100644 --- a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp +++ b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp @@ -12,6 +12,7 @@ #include "simplnx/Utilities/StringUtilities.hpp" #include +#include using namespace nx::core; @@ -991,3 +992,335 @@ TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Tokenizer") REQUIRE(tokens[4].type == TT::RParen); } } + +// ----------------------------------------------------------------------------- +// Test 1: Array Resolution +// ----------------------------------------------------------------------------- +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Array Resolution") +{ + UnitTest::LoadPlugins(); + + // Create a DataStructure with arrays in multiple groups. + // "Group1/SharedName" (UInt32, 10 tuples, filled with 5) + // "Group2/SharedName" (UInt32, 10 tuples, filled with 7) + // "Group1/UniqueName" (UInt32, 10 tuples, filled with 3) + DataStructure ds; + AttributeMatrix* group1 = AttributeMatrix::Create(ds, "Group1", {10ULL}); + auto group1Id = group1->getId(); + AttributeMatrix* group2 = AttributeMatrix::Create(ds, "Group2", {10ULL}); + auto group2Id = group2->getId(); + + UInt32Array* shared1 = UInt32Array::CreateWithStore(ds, "SharedName", {10}, {1}, group1Id); + shared1->fill(5); + UInt32Array* shared2 = UInt32Array::CreateWithStore(ds, "SharedName", {10}, {1}, group2Id); + shared2->fill(7); + UInt32Array* unique1 = UInt32Array::CreateWithStore(ds, "UniqueName", {10}, {1}, group1Id); + unique1->fill(3); + + ArrayCalculatorFilter filter; + + SECTION("Unique bare name resolves without selected group") + { + DataPath outputPath({"Group1", "NewArray"}); + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{DataPath{}, "UniqueName + 1", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(outputPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(outputPath)); + const auto& outputArray = ds.getDataRefAs(outputPath); + REQUIRE(outputArray.getNumberOfTuples() == 10); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 4.0, 0.01)); + } + } + + SECTION("Ambiguous bare name with no selected group gives error") + { + DataPath outputPath({"Group1", "AmbiguousResult"}); + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{DataPath{}, "SharedName + 1", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(outputPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_INVALID(result.result); + REQUIRE(result.result.errors()[0].code == static_cast(CalculatorErrorCode::AmbiguousArrayName)); + } + + SECTION("Selected group resolves ambiguity") + { + DataPath outputPath({"Group1", "ResolvedResult"}); + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{DataPath({"Group1"}), "SharedName + 1", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(outputPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(outputPath)); + const auto& outputArray = ds.getDataRefAs(outputPath); + REQUIRE(outputArray.getNumberOfTuples() == 10); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 6.0, 0.01)); + } + } + + SECTION("Quoted full path resolves directly") + { + DataPath outputPath({"Group2", "QuotedResult"}); + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{DataPath{}, "\"Group2/SharedName\" + 1", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(outputPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(outputPath)); + const auto& outputArray = ds.getDataRefAs(outputPath); + REQUIRE(outputArray.getNumberOfTuples() == 10); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 8.0, 0.01)); + } + } + + UnitTest::CheckArraysInheritTupleDims(ds); +} + +// ----------------------------------------------------------------------------- +// Test 2: Built-in Constants +// ----------------------------------------------------------------------------- +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Built-in Constants") +{ + UnitTest::LoadPlugins(); + DataStructure ds = ::createDataStructure(); + ArrayCalculatorFilter filter; + + SECTION("pi resolves to std::numbers::pi") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "pi", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), std::numbers::pi, 0.0001)); + } + } + + SECTION("e resolves to std::numbers::e") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "e", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), std::numbers::e, 0.0001)); + } + } + + SECTION("2 * pi expression works") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "2 * pi", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 2.0 * std::numbers::pi, 0.0001)); + } + } + + UnitTest::CheckArraysInheritTupleDims(ds); +} + +// ----------------------------------------------------------------------------- +// Test 3: Modulo Operator +// ----------------------------------------------------------------------------- +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Modulo Operator") +{ + UnitTest::LoadPlugins(); + DataStructure ds = ::createDataStructure(); + ArrayCalculatorFilter filter; + + SECTION("Scalar modulo: 10 % 3 = 1") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "10 % 3", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 1.0, 0.01)); + } + } + + SECTION("Array modulo: InputArray2 % 3 = 1 element-wise") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "InputArray2 % 3", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + REQUIRE(outputArray.getNumberOfTuples() == 10); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 1.0, 0.01)); + } + } + + UnitTest::CheckArraysInheritTupleDims(ds); +} + +// ----------------------------------------------------------------------------- +// Test 4: Tuple+Component Indexing +// ----------------------------------------------------------------------------- +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Tuple Component Indexing") +{ + UnitTest::LoadPlugins(); + DataStructure ds = ::createDataStructure(); + ArrayCalculatorFilter filter; + + SECTION("MultiComponent Array1[2, 1] produces scalar value 7") + { + // MultiComponent Array1 has 10 tuples x 3 comps, values 0..29 sequentially. + // tuple 2, comp 1 = index 2*3 + 1 = 7 + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "\"MultiComponent Array1\"[2, 1]", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + // Scalar result broadcast to all tuples in the AttributeMatrix (10 tuples) + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 7.0, 0.01)); + } + } + + SECTION("MultiComponent Array1[100, 0] out of bounds gives TupleOutOfRange error") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "\"MultiComponent Array1\"[100, 0]", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_INVALID(result.result); + REQUIRE(result.result.errors()[0].code == static_cast(CalculatorErrorCode::TupleOutOfRange)); + } + + UnitTest::CheckArraysInheritTupleDims(ds); +} + +// ----------------------------------------------------------------------------- +// Test 5: Sub-expression Component Access +// ----------------------------------------------------------------------------- +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Sub-expression Component Access") +{ + UnitTest::LoadPlugins(); + DataStructure ds = ::createDataStructure(); + ArrayCalculatorFilter filter; + + SECTION("(MultiComponent Array1 + MultiComponent Array2)[0] extracts component 0 of the sum") + { + // MultiComponent Array1 and Array2 both have 10 tuples x 3 components, values 0..29. + // Sum = 2*values = [0,2,4,6,8,10,...,58] + // Component 0 extraction: for each tuple t, take element at (t*3 + 0) = 2*(t*3) + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any( + CalculatorParameter::ValueType{k_AttributeMatrixPath, "(\"MultiComponent Array1\" + \"MultiComponent Array2\")[0]", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + REQUIRE(outputArray.getNumberOfTuples() == 10); + REQUIRE(outputArray.getNumberOfComponents() == 1); + for(usize t = 0; t < 10; t++) + { + // Component 0 of sum: (t*3 + 0) + (t*3 + 0) = 2 * (t * 3) + double expected = 2.0 * static_cast(t * 3); + REQUIRE(UnitTest::CloseEnough(outputArray.at(t), expected, 0.01)); + } + } + + UnitTest::CheckArraysInheritTupleDims(ds); +} + +// ----------------------------------------------------------------------------- +// Test 6: Multi-word Array Names +// ----------------------------------------------------------------------------- +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Multi-word Array Names") +{ + UnitTest::LoadPlugins(); + DataStructure ds = ::createDataStructure(); + ArrayCalculatorFilter filter; + + SECTION("Spaced Array + 1 = 3") + { + // Spaced Array is filled with 2, so Spaced Array + 1 = 3 + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, + std::make_any(CalculatorParameter::ValueType{k_AttributeMatrixPath, "Spaced Array + 1", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + REQUIRE(outputArray.getNumberOfTuples() == 10); + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), 3.0, 0.01)); + } + } + + UnitTest::CheckArraysInheritTupleDims(ds); +} From 81b4d5d5c85f2954ac820d27bd110e1b332fc4f8 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 11:28:30 -0400 Subject: [PATCH 10/19] ENH: Change CalculatorParameter from MutableDataParameter to ValueParameter The selected group is no longer a required data path -- it is just a resolution hint. Switching to ValueParameter removes the framework-rendered data path selector from the UI. --- .../src/SimplnxCore/utils/ABSOperator.cpp | 32 +++ .../src/SimplnxCore/utils/ABSOperator.hpp | 41 +++ .../src/SimplnxCore/utils/ACosOperator.cpp | 32 +++ .../src/SimplnxCore/utils/ACosOperator.hpp | 41 +++ .../src/SimplnxCore/utils/ASinOperator.cpp | 32 +++ .../src/SimplnxCore/utils/ASinOperator.hpp | 42 +++ .../src/SimplnxCore/utils/ATanOperator.cpp | 32 +++ .../src/SimplnxCore/utils/ATanOperator.hpp | 42 +++ .../SimplnxCore/utils/AdditionOperator.cpp | 32 +++ .../SimplnxCore/utils/AdditionOperator.hpp | 42 +++ .../src/SimplnxCore/utils/BinaryOperator.cpp | 61 ++++ .../src/SimplnxCore/utils/BinaryOperator.hpp | 44 +++ .../src/SimplnxCore/utils/CalculatorArray.hpp | 169 +++++++++++ .../src/SimplnxCore/utils/CalculatorItem.cpp | 87 ++++++ .../src/SimplnxCore/utils/CalculatorItem.hpp | 99 +++++++ .../SimplnxCore/utils/CalculatorOperator.cpp | 140 +++++++++ .../SimplnxCore/utils/CalculatorOperator.hpp | 77 +++++ .../SimplnxCore/utils/CalculatorSeparator.cpp | 19 ++ .../SimplnxCore/utils/CalculatorSeparator.hpp | 34 +++ .../src/SimplnxCore/utils/CeilOperator.cpp | 32 +++ .../src/SimplnxCore/utils/CeilOperator.hpp | 40 +++ .../src/SimplnxCore/utils/CommaSeparator.cpp | 49 ++++ .../src/SimplnxCore/utils/CommaSeparator.hpp | 38 +++ .../src/SimplnxCore/utils/CosOperator.cpp | 32 +++ .../src/SimplnxCore/utils/CosOperator.hpp | 40 +++ .../SimplnxCore/utils/DivisionOperator.cpp | 31 ++ .../SimplnxCore/utils/DivisionOperator.hpp | 38 +++ .../src/SimplnxCore/utils/ExpOperator.cpp | 32 +++ .../src/SimplnxCore/utils/ExpOperator.hpp | 40 +++ .../src/SimplnxCore/utils/FloorOperator.cpp | 32 +++ .../src/SimplnxCore/utils/FloorOperator.hpp | 40 +++ .../SimplnxCore/utils/ICalculatorArray.cpp | 19 ++ .../SimplnxCore/utils/ICalculatorArray.hpp | 49 ++++ .../SimplnxCore/utils/LeftParenthesisItem.cpp | 53 ++++ .../SimplnxCore/utils/LeftParenthesisItem.hpp | 45 +++ .../src/SimplnxCore/utils/LnOperator.cpp | 32 +++ .../src/SimplnxCore/utils/LnOperator.hpp | 40 +++ .../src/SimplnxCore/utils/Log10Operator.cpp | 32 +++ .../src/SimplnxCore/utils/Log10Operator.hpp | 41 +++ .../src/SimplnxCore/utils/LogOperator.cpp | 40 +++ .../src/SimplnxCore/utils/LogOperator.hpp | 42 +++ .../src/SimplnxCore/utils/MaxOperator.cpp | 33 +++ .../src/SimplnxCore/utils/MaxOperator.hpp | 40 +++ .../src/SimplnxCore/utils/MinOperator.cpp | 33 +++ .../src/SimplnxCore/utils/MinOperator.hpp | 40 +++ .../utils/MultiplicationOperator.cpp | 32 +++ .../utils/MultiplicationOperator.hpp | 39 +++ .../SimplnxCore/utils/NegativeOperator.cpp | 81 ++++++ .../SimplnxCore/utils/NegativeOperator.hpp | 41 +++ .../src/SimplnxCore/utils/PowOperator.cpp | 32 +++ .../src/SimplnxCore/utils/PowOperator.hpp | 41 +++ .../utils/RightParenthesisItem.cpp | 53 ++++ .../utils/RightParenthesisItem.hpp | 45 +++ .../src/SimplnxCore/utils/RootOperator.cpp | 32 +++ .../src/SimplnxCore/utils/RootOperator.hpp | 41 +++ .../src/SimplnxCore/utils/SinOperator.cpp | 32 +++ .../src/SimplnxCore/utils/SinOperator.hpp | 41 +++ .../src/SimplnxCore/utils/SqrtOperator.cpp | 32 +++ .../src/SimplnxCore/utils/SqrtOperator.hpp | 41 +++ .../SimplnxCore/utils/SubtractionOperator.cpp | 32 +++ .../SimplnxCore/utils/SubtractionOperator.hpp | 39 +++ .../src/SimplnxCore/utils/TanOperator.cpp | 32 +++ .../src/SimplnxCore/utils/TanOperator.hpp | 41 +++ .../src/SimplnxCore/utils/UnaryOperator.cpp | 265 ++++++++++++++++++ .../src/SimplnxCore/utils/UnaryOperator.hpp | 56 ++++ .../Parameters/CalculatorParameter.cpp | 11 +- .../Parameters/CalculatorParameter.hpp | 15 +- 67 files changed, 3134 insertions(+), 21 deletions(-) create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp create mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp new file mode 100644 index 0000000000..41b5b3bd31 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/ABSOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ABSOperator::ABSOperator() +{ + setNumberOfArguments(1); + setInfixToken("abs"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ABSOperator::~ABSOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void ABSOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return fabs(num); }); +} + +// ----------------------------------------------------------------------------- +ABSOperator::Pointer ABSOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp new file mode 100644 index 0000000000..1048bb44db --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT ABSOperator : public UnaryOperator +{ +public: + using Self = ABSOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new ABSOperator()); + } + + ~ABSOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + ABSOperator(); + +public: + ABSOperator(const ABSOperator&) = delete; // Copy Constructor Not Implemented + ABSOperator(ABSOperator&&) = delete; // Move Constructor Not Implemented + ABSOperator& operator=(const ABSOperator&) = delete; // Copy Assignment Not Implemented + ABSOperator& operator=(ABSOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp new file mode 100644 index 0000000000..0cd8872ba1 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/ACosOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ACosOperator::ACosOperator() +{ + setNumberOfArguments(1); + setInfixToken("acos"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ACosOperator::~ACosOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void ACosOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return acos(num); }); +} + +// ----------------------------------------------------------------------------- +ACosOperator::Pointer ACosOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp new file mode 100644 index 0000000000..89e7a3e554 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT ACosOperator : public UnaryOperator +{ +public: + using Self = ACosOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new ACosOperator()); + } + + ~ACosOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + ACosOperator(); + +public: + ACosOperator(const ACosOperator&) = delete; // Copy Constructor Not Implemented + ACosOperator(ACosOperator&&) = delete; // Move Constructor Not Implemented + ACosOperator& operator=(const ACosOperator&) = delete; // Copy Assignment Not Implemented + ACosOperator& operator=(ACosOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp new file mode 100644 index 0000000000..924e62d393 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/ASinOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ASinOperator::ASinOperator() +{ + setNumberOfArguments(1); + setInfixToken("asin"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ASinOperator::~ASinOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void ASinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return asin(num); }); +} + +// ----------------------------------------------------------------------------- +ASinOperator::Pointer ASinOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp new file mode 100644 index 0000000000..869dc07c9c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ + +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT ASinOperator : public UnaryOperator +{ +public: + using Self = ASinOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new ASinOperator()); + } + + ~ASinOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + ASinOperator(); + +public: + ASinOperator(const ASinOperator&) = delete; // Copy Constructor Not Implemented + ASinOperator(ASinOperator&&) = delete; // Move Constructor Not Implemented + ASinOperator& operator=(const ASinOperator&) = delete; // Copy Assignment Not Implemented + ASinOperator& operator=(ASinOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp new file mode 100644 index 0000000000..29e9dc8bd4 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/ATanOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ATanOperator::ATanOperator() +{ + setNumberOfArguments(1); + setInfixToken("atan"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ATanOperator::~ATanOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void ATanOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return atan(num); }); +} + +// ----------------------------------------------------------------------------- +ATanOperator::Pointer ATanOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp new file mode 100644 index 0000000000..71690e142f --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ + +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT ATanOperator : public UnaryOperator +{ +public: + using Self = ATanOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new ATanOperator()); + } + + ~ATanOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + ATanOperator(); + +public: + ATanOperator(const ATanOperator&) = delete; // Copy Constructor Not Implemented + ATanOperator(ATanOperator&&) = delete; // Move Constructor Not Implemented + ATanOperator& operator=(const ATanOperator&) = delete; // Copy Assignment Not Implemented + ATanOperator& operator=(ATanOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core \ No newline at end of file diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp new file mode 100644 index 0000000000..759f0fafc6 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/AdditionOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +AdditionOperator::AdditionOperator() +{ + setPrecedence(A_Precedence); + setInfixToken("+"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +AdditionOperator::~AdditionOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void AdditionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 + num2; }); +} + +// ----------------------------------------------------------------------------- +AdditionOperator::Pointer AdditionOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp new file mode 100644 index 0000000000..63ebf83833 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/BinaryOperator.hpp" + +namespace nx::core +{ + +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT AdditionOperator : public BinaryOperator +{ +public: + using Self = AdditionOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new AdditionOperator()); + } + + ~AdditionOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + AdditionOperator(); + +public: + AdditionOperator(const AdditionOperator&) = delete; // Copy Constructor Not Implemented + AdditionOperator(AdditionOperator&&) = delete; // Move Constructor Not Implemented + AdditionOperator& operator=(const AdditionOperator&) = delete; // Copy Assignment Not Implemented + AdditionOperator& operator=(AdditionOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp new file mode 100644 index 0000000000..fde52052c1 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp @@ -0,0 +1,61 @@ +#include "SimplnxCore/utils/BinaryOperator.hpp" +#include "SimplnxCore/utils/LeftParenthesisItem.hpp" +#include "SimplnxCore/utils/RightParenthesisItem.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +BinaryOperator::BinaryOperator() +{ + setOperatorType(Binary); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +BinaryOperator::~BinaryOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void BinaryOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + // This should never be executed +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::ErrorCode BinaryOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) +{ + int leftValue = currentIndex - 1; + int rightValue = currentIndex + 1; + + // Check that there is a valid value to the left of the operator + if(leftValue < 0 || + (nullptr != std::dynamic_pointer_cast(infixVector[leftValue]) && std::dynamic_pointer_cast(infixVector[leftValue])->getOperatorType() == Binary) || + nullptr != std::dynamic_pointer_cast(infixVector[leftValue])) + { + errMsg = fmt::format("The operator '{}' does not have a valid 'left' value.", getInfixToken()); + return CalculatorItem::ErrorCode::OperatorNoLeftValue; + } + + // Check that there is a valid value to the right of the operator + if(rightValue > infixVector.size() - 1 || + (nullptr != std::dynamic_pointer_cast(infixVector[rightValue]) && std::dynamic_pointer_cast(infixVector[rightValue])->getOperatorType() == Binary) || + nullptr != std::dynamic_pointer_cast(infixVector[rightValue])) + { + errMsg = fmt::format("The operator '{}' does not have a valid 'right' value.", getInfixToken()); + return CalculatorItem::ErrorCode::OperatorNoRightValue; + } + + return CalculatorItem::ErrorCode::Success; +} + +// ----------------------------------------------------------------------------- +BinaryOperator::Pointer BinaryOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp new file mode 100644 index 0000000000..8f8b1fe93a --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include "SimplnxCore/utils/CalculatorOperator.hpp" + +#include "simplnx/DataStructure/DataPath.hpp" + +#include +#include + +namespace nx::core +{ + +class SIMPLNXCORE_EXPORT BinaryOperator : public CalculatorOperator +{ +public: + using Self = BinaryOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new BinaryOperator()); + } + + ~BinaryOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + + CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) final; + +protected: + BinaryOperator(); + +public: + BinaryOperator(const BinaryOperator&) = delete; // Copy Constructor Not Implemented + BinaryOperator(BinaryOperator&&) = delete; // Move Constructor Not Implemented + BinaryOperator& operator=(const BinaryOperator&) = delete; // Copy Assignment Not Implemented + BinaryOperator& operator=(BinaryOperator&&) = delete; // Move Assignment Not Implemented +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp new file mode 100644 index 0000000000..4bacfafee9 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorArray.hpp @@ -0,0 +1,169 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/ICalculatorArray.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/Utilities/StringUtilities.hpp" + +namespace nx::core +{ + +template +class SIMPLNXCORE_EXPORT CalculatorArray : public ICalculatorArray +{ +public: + using Self = CalculatorArray; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer() + { + return Pointer(static_cast(nullptr)); + } + + /** + * @brief Returns the name of the class for AbstractMessage + */ + virtual std::string getNameOfClass() const + { + return "CalculatorArray"; + } + /** + * @brief Returns the name of the class for AbstractMessage + */ + static std::string ClassName() + { + return "CalculatorArray"; + } + + static Pointer New(DataStructure& dataStructure, const DataArray* array, ValueType type, bool allocate) + { + return Pointer(new CalculatorArray(dataStructure, array, type, allocate)); + } + + ~CalculatorArray() override = default; + + Float64Array* getArray() override + { + if(m_ArrayId.has_value()) + { + return m_DataStructure.getDataAs(m_ArrayId.value()); + } + return nullptr; + } + + void setValue(usize i, double val) override + { + if(m_ArrayId.has_value()) + { + m_DataStructure.getDataRefAs(m_ArrayId.value())[i] = val; + } + } + + double getValue(usize i) override + { + if(!m_ArrayId.has_value()) + { + // ERROR: The array is empty! + return 0.0; + } + auto& array = m_DataStructure.getDataRefAs(m_ArrayId.value()); + if(array.getNumberOfTuples() > 1) + { + return static_cast(array[i]); + } + if(array.getNumberOfTuples() == 1) + { + return static_cast(array[0]); + } + // ERROR: The array is empty! + return 0.0; + } + + ICalculatorArray::ValueType getType() override + { + return m_Type; + } + + Float64Array* reduceToOneComponent(int c, bool allocate = true) override + { + if(!m_ArrayId.has_value()) + { + return nullptr; + } + auto* array = m_DataStructure.getDataAs(m_ArrayId.value()); + auto numComponents = array->getNumberOfComponents(); + if(c >= 0 && c <= numComponents) + { + if(numComponents > 1) + { + DataPath reducedArrayPath = GetUniquePathName(m_DataStructure, array->getDataPaths()[0]); // doesn't matter which path since we only use the target name + Float64Array* newArray = Float64Array::CreateWithStore(m_DataStructure, reducedArrayPath.getTargetName(), array->getTupleShape(), {1}); + if(allocate) + { + for(usize i = 0; i < array->getNumberOfTuples(); i++) + { + (*newArray)[i] = (*array)[i * numComponents + c]; + } + } + + return newArray; + } + } + + return nullptr; + } + + CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override + { + return CalculatorItem::ErrorCode::Success; + } + +protected: + CalculatorArray() = default; + + CalculatorArray(DataStructure& dataStructure, const DataArray* dataArray, ValueType type, bool allocate) + : ICalculatorArray() + , m_Type(type) + , m_DataStructure(dataStructure) + { + DataPath targetPath({dataArray->getName()}); + if(dataStructure.containsData(targetPath)) + { + m_ArrayId = dataStructure.getId(targetPath); + } + else + { + if(allocate) + { + auto* tempArray = Float64Array::CreateWithStore(dataStructure, dataArray->getName(), dataArray->getTupleShape(), dataArray->getComponentShape()); + for(usize i = 0; i < dataArray->getSize(); i++) + { + (*tempArray)[i] = static_cast(dataArray->at(i)); + } + m_ArrayId = std::optional{tempArray->getId()}; + } + else + { + auto* tempArray = + Float64Array::Create(dataStructure, dataArray->getName(), std::make_shared(Float64DataStore(dataArray->getTupleShape(), dataArray->getComponentShape(), {}))); + m_ArrayId = std::optional{tempArray->getId()}; + } + } + } + +private: + std::optional m_ArrayId = {}; + ValueType m_Type = Unknown; + DataStructure& m_DataStructure; + +public: + CalculatorArray(const CalculatorArray&) = delete; // Copy Constructor Not Implemented + CalculatorArray(CalculatorArray&&) = delete; // Move Constructor Not Implemented + CalculatorArray& operator=(const CalculatorArray&) = delete; // Copy Assignment Not Implemented + CalculatorArray& operator=(CalculatorArray&&) = delete; // Move Assignment Not Implemented +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp new file mode 100644 index 0000000000..f523fd3122 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.cpp @@ -0,0 +1,87 @@ +#include "SimplnxCore/utils/CalculatorItem.hpp" +#include "SimplnxCore/utils/ICalculatorArray.hpp" + +#include "simplnx/Utilities/StringUtilities.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::CalculatorItem() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::~CalculatorItem() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +std::string CalculatorItem::getInfixToken() +{ + return m_InfixToken; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CalculatorItem::setInfixToken(const std::string& token) +{ + m_InfixToken = token; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +bool CalculatorItem::isICalculatorArray() +{ + return (nullptr != dynamic_cast(this)); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +bool CalculatorItem::isArray() +{ + ICalculatorArray* calculatorArray = dynamic_cast(this); + if(calculatorArray != nullptr) + { + return (calculatorArray->getType() == ICalculatorArray::ValueType::Array); + } + + return false; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +bool CalculatorItem::isNumber() +{ + ICalculatorArray* calculatorArray = dynamic_cast(this); + if(calculatorArray != nullptr) + { + return (calculatorArray->getType() == ICalculatorArray::ValueType::Number); + } + + return false; +} + +// ----------------------------------------------------------------------------- +CalculatorItem::Pointer CalculatorItem::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} + +// ----------------------------------------------------------------------------- +DataPath CalculatorItem::GetUniquePathName(const DataStructure& dataStructure, DataPath path) +{ + if(dataStructure.containsData(path)) + { + auto calculatedPathVector = path.getPathVector(); + auto& targetName = calculatedPathVector.back(); + targetName = targetName + StringUtilities::number(dataStructure.getSize()); + path = DataPath(calculatedPathVector); + } + return path; +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp new file mode 100644 index 0000000000..8b67cf37c2 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorItem.hpp @@ -0,0 +1,99 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" + +#include +#include +#include + +namespace nx::core +{ +class DataStructure; +class DataPath; + +/** + * @brief The CalculatorItem class + */ +class SIMPLNXCORE_EXPORT CalculatorItem +{ +public: + using Self = CalculatorItem; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + virtual ~CalculatorItem(); + + using EnumType = int; + + enum class ErrorCode : EnumType + { + Success = 0, + InvalidEquation = -4009, + InvalidComponent = -4010, + EmptyEquation = -4011, + EmptyCalArray = -4012, + EmptySelMatrix = -4013, + LostAttrMatrix = -4014, + IncorrectTupleCount = -4015, + InconsistentTuples = -4016, + UnrecognizedItem = -4017, + MismatchedParentheses = -4018, + UnexpectedOutput = -4019, + ComponentOutOfRange = -4020, + InvalidArrayName = -4022, + InconsistentIndexing = -4023, + InconsistentCompDims = -4024, + AttrArrayZeroTuplesWarning = -4025, + OrphanedComponent = -4026, + OperatorNoLeftValue = -4027, + OperatorNoRightValue = -4028, + OperatorNoOpeningParen = -4029, + OperatorNoClosingParen = -4030, + NoNumericArguments = -4031, + MissingArguments = -4032, + NotEnoughArguments = -4033, + TooManyArguments = -4034, + InvalidSymbol = -4035, + NoPrecedingUnaryOperator = -4036, + InvalidOutputArrayType = -4037, + AttributeMatrixInsertionError = -4038 + }; + + enum class WarningCode : EnumType + { + None = 0, + NumericValueWarning = -5010, + AmbiguousNameWarning = -5011 + }; + + std::string getInfixToken(); + + virtual CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) = 0; + + bool isICalculatorArray(); + + bool isArray(); + + bool isNumber(); + + static DataPath GetUniquePathName(const DataStructure& dataStructure, DataPath path); + +protected: + CalculatorItem(); + + void setInfixToken(const std::string& token); + +private: + std::string m_InfixToken = {}; + +public: + CalculatorItem(const CalculatorItem&) = delete; // Copy Constructor Not Implemented + CalculatorItem(CalculatorItem&&) = delete; // Move Constructor Not Implemented + CalculatorItem& operator=(const CalculatorItem&) = delete; // Copy Assignment Not Implemented + CalculatorItem& operator=(CalculatorItem&&) = delete; // Move Assignment Not Implemented +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp new file mode 100644 index 0000000000..b2b74d0100 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp @@ -0,0 +1,140 @@ +#include "SimplnxCore/utils/CalculatorOperator.hpp" + +#include "simplnx/Common/Numbers.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorOperator::CalculatorOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorOperator::~CalculatorOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +bool CalculatorOperator::hasHigherPrecedence(const CalculatorOperator::Pointer other) +{ + return m_Precedence > other->m_Precedence; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorOperator::Precedence CalculatorOperator::getPrecedence() +{ + return m_Precedence; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CalculatorOperator::setPrecedence(Precedence precedence) +{ + m_Precedence = precedence; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorOperator::OperatorType CalculatorOperator::getOperatorType() +{ + return m_OperatorType; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CalculatorOperator::setOperatorType(OperatorType type) +{ + m_OperatorType = type; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +double CalculatorOperator::toDegrees(double radians) +{ + return radians * (180.0 / numbers::pi); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +double CalculatorOperator::toRadians(double degrees) +{ + return degrees * (numbers::pi / 180.0); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +double CalculatorOperator::root(double base, double root) +{ + if(root == 0) + { + return std::numeric_limits::infinity(); + } + + return pow(base, 1 / root); +} + +// ----------------------------------------------------------------------------- +CalculatorOperator::Pointer CalculatorOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} + +// ----------------------------------------------------------------------------- +void CalculatorOperator::CreateNewArrayTwoArguments(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, + std::stack& executionStack, std::function op) +{ + ICalculatorArray::Pointer iArray1 = executionStack.top(); + if(executionStack.size() >= 2 && nullptr != iArray1) + { + executionStack.pop(); + ICalculatorArray::Pointer iArray2 = executionStack.top(); + executionStack.pop(); + + calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); + + DataArray* array1 = iArray1->getArray(); + DataArray* array2 = iArray2->getArray(); + + Float64Array* newArray = nullptr; + if(iArray1->getType() == ICalculatorArray::Array) + { + newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array1->getTupleShape(), array1->getComponentShape()); + } + else + { + newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array2->getTupleShape(), array2->getComponentShape()); + } + + usize numComps = newArray->getNumberOfComponents(); + for(usize i = 0; i < newArray->getNumberOfTuples(); i++) + { + for(usize c = 0; c < newArray->getNumberOfComponents(); c++) + { + usize index = numComps * i + c; + float64 num1 = (iArray1->getType() == ICalculatorArray::Array) ? array1->getValue(index) : array1->getValue(0); + float64 num2 = (iArray2->getType() == ICalculatorArray::Array) ? array2->getValue(index) : array2->getValue(0); + (*newArray)[index] = op(num2, num1); + } + } + + if(iArray1->getType() == ICalculatorArray::Array || iArray2->getType() == ICalculatorArray::Array) + { + executionStack.push(CalculatorArray::New(dataStructure, newArray, ICalculatorArray::Array, true)); + } + else + { + executionStack.push(CalculatorArray::New(dataStructure, newArray, ICalculatorArray::Number, true)); + } + return; + } +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp new file mode 100644 index 0000000000..21b1f4db31 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" +#include "simplnx/DataStructure/DataPath.hpp" +#include "simplnx/Parameters/CalculatorParameter.hpp" + +#include +#include + +namespace nx::core +{ + +class SIMPLNXCORE_EXPORT CalculatorOperator : public CalculatorItem +{ +public: + enum OperatorType + { + Unary, + Binary + }; + + using Self = CalculatorOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static double toDegrees(double radians); + static double toRadians(double degrees); + + ~CalculatorOperator() override; + + bool hasHigherPrecedence(CalculatorOperator::Pointer other); + + virtual void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) = 0; + + OperatorType getOperatorType(); + +protected: + CalculatorOperator(); + + enum Precedence + { + Unknown_Precedence, + A_Precedence, + B_Precedence, + C_Precedence, + D_Precedence, + E_Precedence + }; + + double root(double base, double root); + + Precedence getPrecedence(); + void setPrecedence(Precedence precedence); + + void setOperatorType(OperatorType type); + +private: + Precedence m_Precedence = {Unknown_Precedence}; + OperatorType m_OperatorType; + +public: + CalculatorOperator(const CalculatorOperator&) = delete; // Copy Constructor Not Implemented + CalculatorOperator(CalculatorOperator&&) = delete; // Move Constructor Not Implemented + CalculatorOperator& operator=(const CalculatorOperator&) = delete; // Copy Assignment Not Implemented + CalculatorOperator& operator=(CalculatorOperator&&) = delete; // Move Assignment Not Implemented + + static void CreateNewArrayTwoArguments(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, + std::function op); +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp new file mode 100644 index 0000000000..0aeb534d8b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.cpp @@ -0,0 +1,19 @@ +#include "SimplnxCore/utils/CalculatorSeparator.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorSeparator::CalculatorSeparator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorSeparator::~CalculatorSeparator() = default; + +// ----------------------------------------------------------------------------- +CalculatorSeparator::Pointer CalculatorSeparator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp new file mode 100644 index 0000000000..baae97889c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorSeparator.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/CalculatorItem.hpp" + +#include + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT CalculatorSeparator : public CalculatorItem +{ +public: + using Self = CalculatorSeparator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + ~CalculatorSeparator() override; + +protected: + CalculatorSeparator(); + +public: + CalculatorSeparator(const CalculatorSeparator&) = delete; // Copy Constructor Not Implemented + CalculatorSeparator(CalculatorSeparator&&) = delete; // Move Constructor Not Implemented + CalculatorSeparator& operator=(const CalculatorSeparator&) = delete; // Copy Assignment Not Implemented + CalculatorSeparator& operator=(CalculatorSeparator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp new file mode 100644 index 0000000000..c06d6ed3b7 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/CeilOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CeilOperator::CeilOperator() +{ + setNumberOfArguments(1); + setInfixToken("ceil"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CeilOperator::~CeilOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CeilOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return ceil(num); }); +} + +// ----------------------------------------------------------------------------- +CeilOperator::Pointer CeilOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp new file mode 100644 index 0000000000..3e46d8df8c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT CeilOperator : public UnaryOperator +{ +public: + using Self = CeilOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new CeilOperator()); + } + + ~CeilOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + CeilOperator(); + +public: + CeilOperator(const CeilOperator&) = delete; // Copy Constructor Not Implemented + CeilOperator(CeilOperator&&) = delete; // Move Constructor Not Implemented + CeilOperator& operator=(const CeilOperator&) = delete; // Copy Assignment Not Implemented + CeilOperator& operator=(CeilOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp new file mode 100644 index 0000000000..57bb32cc06 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp @@ -0,0 +1,49 @@ +#include "SimplnxCore/utils/CommaSeparator.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CommaSeparator::CommaSeparator() +{ + setInfixToken(","); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CommaSeparator::~CommaSeparator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::ErrorCode CommaSeparator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) +{ + // Make sure that this comma has a valid 2-argument unary operator before it + bool foundUnaryOperator = false; + for(int i = currentIndex - 1; i >= 0; i--) + { + CalculatorItem::Pointer item = infixVector[i]; + UnaryOperator::Pointer unary = std::dynamic_pointer_cast(item); + if(unary != UnaryOperator::NullPointer() && unary->getNumberOfArguments() == 2) + { + foundUnaryOperator = true; + } + } + + if(!foundUnaryOperator) + { + errMsg = "A comma in the expression does not have a corresponding operator preceding it."; + return CalculatorItem::ErrorCode::NoPrecedingUnaryOperator; + } + + return CalculatorItem::ErrorCode::Success; +} + +// ----------------------------------------------------------------------------- +CommaSeparator::Pointer CommaSeparator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp new file mode 100644 index 0000000000..c58deb63f4 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/CalculatorSeparator.hpp" + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT CommaSeparator : public CalculatorSeparator +{ +public: + using Self = CommaSeparator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new CommaSeparator()); + } + + ~CommaSeparator() override; + + CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override; + +protected: + CommaSeparator(); + +public: + CommaSeparator(const CommaSeparator&) = delete; // Copy Constructor Not Implemented + CommaSeparator(CommaSeparator&&) = delete; // Move Constructor Not Implemented + CommaSeparator& operator=(const CommaSeparator&) = delete; // Copy Assignment Not Implemented + CommaSeparator& operator=(CommaSeparator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp new file mode 100644 index 0000000000..9638355e80 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/CosOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CosOperator::CosOperator() +{ + setNumberOfArguments(1); + setInfixToken("cos"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CosOperator::~CosOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void CosOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return cos(num); }); +} + +// ----------------------------------------------------------------------------- +CosOperator::Pointer CosOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp new file mode 100644 index 0000000000..4f94fcf2a7 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT CosOperator : public UnaryOperator +{ +public: + using Self = CosOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new CosOperator()); + } + + ~CosOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + CosOperator(); + +public: + CosOperator(const CosOperator&) = delete; // Copy Constructor Not Implemented + CosOperator(CosOperator&&) = delete; // Move Constructor Not Implemented + CosOperator& operator=(const CosOperator&) = delete; // Copy Assignment Not Implemented + CosOperator& operator=(CosOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp new file mode 100644 index 0000000000..682d3b1333 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp @@ -0,0 +1,31 @@ +#include "SimplnxCore/utils/DivisionOperator.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +DivisionOperator::DivisionOperator() +{ + setPrecedence(B_Precedence); + setInfixToken("/"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +DivisionOperator::~DivisionOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void DivisionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 / num2; }); +} + +// ----------------------------------------------------------------------------- +DivisionOperator::Pointer DivisionOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp new file mode 100644 index 0000000000..d9256a6793 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/BinaryOperator.hpp" + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT DivisionOperator : public BinaryOperator +{ +public: + using Self = DivisionOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new DivisionOperator()); + } + + ~DivisionOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + DivisionOperator(); + +public: + DivisionOperator(const DivisionOperator&) = delete; // Copy Constructor Not Implemented + DivisionOperator(DivisionOperator&&) = delete; // Move Constructor Not Implemented + DivisionOperator& operator=(const DivisionOperator&) = delete; // Copy Assignment Not Implemented + DivisionOperator& operator=(DivisionOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp new file mode 100644 index 0000000000..216c202041 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/ExpOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ExpOperator::ExpOperator() +{ + setNumberOfArguments(1); + setInfixToken("exp"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ExpOperator::~ExpOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void ExpOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return exp(num); }); +} + +// ----------------------------------------------------------------------------- +ExpOperator::Pointer ExpOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp new file mode 100644 index 0000000000..73d718e92c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT ExpOperator : public UnaryOperator +{ +public: + using Self = ExpOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new ExpOperator()); + } + + ~ExpOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + ExpOperator(); + +public: + ExpOperator(const ExpOperator&) = delete; // Copy Constructor Not Implemented + ExpOperator(ExpOperator&&) = delete; // Move Constructor Not Implemented + ExpOperator& operator=(const ExpOperator&) = delete; // Copy Assignment Not Implemented + ExpOperator& operator=(ExpOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp new file mode 100644 index 0000000000..6b6680f757 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/FloorOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +FloorOperator::FloorOperator() +{ + setNumberOfArguments(1); + setInfixToken("floor"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +FloorOperator::~FloorOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void FloorOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return floor(num); }); +} + +// ----------------------------------------------------------------------------- +FloorOperator::Pointer FloorOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp new file mode 100644 index 0000000000..93e935af96 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT FloorOperator : public UnaryOperator +{ +public: + using Self = FloorOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new FloorOperator()); + } + + ~FloorOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + FloorOperator(); + +public: + FloorOperator(const FloorOperator&) = delete; // Copy Constructor Not Implemented + FloorOperator(FloorOperator&&) = delete; // Move Constructor Not Implemented + FloorOperator& operator=(const FloorOperator&) = delete; // Copy Assignment Not Implemented + FloorOperator& operator=(FloorOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp new file mode 100644 index 0000000000..6f5cf20da5 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.cpp @@ -0,0 +1,19 @@ +#include "SimplnxCore/utils/ICalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ICalculatorArray::ICalculatorArray() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +ICalculatorArray::~ICalculatorArray() = default; + +// ----------------------------------------------------------------------------- +ICalculatorArray::Pointer ICalculatorArray::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp new file mode 100644 index 0000000000..6c08b5d5b6 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ICalculatorArray.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/CalculatorItem.hpp" + +#include "simplnx/DataStructure/DataArray.hpp" + +#include + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT ICalculatorArray : public CalculatorItem +{ +public: + enum ValueType + { + Number, + Array, + Unknown + }; + + using Self = ICalculatorArray; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + ~ICalculatorArray() override; + + virtual Float64Array* getArray() = 0; + virtual double getValue(usize i) = 0; + virtual void setValue(usize i, double value) = 0; + virtual ValueType getType() = 0; + + virtual Float64Array* reduceToOneComponent(int c, bool allocate) = 0; + +protected: + ICalculatorArray(); + +public: + ICalculatorArray(const ICalculatorArray&) = delete; // Copy Constructor Not Implemented + ICalculatorArray(ICalculatorArray&&) = delete; // Move Constructor Not Implemented + ICalculatorArray& operator=(const ICalculatorArray&) = delete; // Copy Assignment Not Implemented + ICalculatorArray& operator=(ICalculatorArray&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp new file mode 100644 index 0000000000..83399045ab --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.cpp @@ -0,0 +1,53 @@ +#include "SimplnxCore/utils/LeftParenthesisItem.hpp" +#include "SimplnxCore/utils/RightParenthesisItem.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +LeftParenthesisItem::LeftParenthesisItem() +{ + setInfixToken("("); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +LeftParenthesisItem::~LeftParenthesisItem() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::ErrorCode LeftParenthesisItem::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) +{ + // Check for a closing parenthesis, ignoring any other internal sets of parentheses + int leftParenthesisCount = 0; + for(int i = currentIndex + 1; i < infixVector.size(); i++) + { + CalculatorItem::Pointer item = infixVector[i]; + if(std::dynamic_pointer_cast(item) != LeftParenthesisItem::NullPointer()) + { + leftParenthesisCount++; + } + else if(std::dynamic_pointer_cast(item) != RightParenthesisItem::NullPointer()) + { + if(leftParenthesisCount > 0) + { + leftParenthesisCount--; + } + else + { + return LeftParenthesisItem::ErrorCode::Success; + } + } + } + + return LeftParenthesisItem::ErrorCode::MismatchedParentheses; +} + +// ----------------------------------------------------------------------------- +LeftParenthesisItem::Pointer LeftParenthesisItem::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp new file mode 100644 index 0000000000..4c64891175 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LeftParenthesisItem.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/CalculatorItem.hpp" + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT LeftParenthesisItem : public CalculatorItem +{ +public: + using Self = LeftParenthesisItem; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new LeftParenthesisItem()); + } + + ~LeftParenthesisItem() override; + + /** + * @brief checkValidity + * @param infixVector + * @param currentIndex + * @param msg + * @return + */ + CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override; + +protected: + LeftParenthesisItem(); + +public: + LeftParenthesisItem(const LeftParenthesisItem&) = delete; // Copy Constructor Not Implemented + LeftParenthesisItem(LeftParenthesisItem&&) = delete; // Move Constructor Not Implemented + LeftParenthesisItem& operator=(const LeftParenthesisItem&) = delete; // Copy Assignment Not Implemented + LeftParenthesisItem& operator=(LeftParenthesisItem&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp new file mode 100644 index 0000000000..473c654367 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/LnOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +LnOperator::LnOperator() +{ + setNumberOfArguments(1); + setInfixToken("ln"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +LnOperator::~LnOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void LnOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return log(num); }); +} + +// ----------------------------------------------------------------------------- +LnOperator::Pointer LnOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp new file mode 100644 index 0000000000..992985eb04 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT LnOperator : public UnaryOperator +{ +public: + using Self = LnOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new LnOperator()); + } + + ~LnOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + LnOperator(); + +public: + LnOperator(const LnOperator&) = delete; // Copy Constructor Not Implemented + LnOperator(LnOperator&&) = delete; // Move Constructor Not Implemented + LnOperator& operator=(const LnOperator&) = delete; // Copy Assignment Not Implemented + LnOperator& operator=(LnOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp new file mode 100644 index 0000000000..64413029e6 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/Log10Operator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +Log10Operator::Log10Operator() +{ + setNumberOfArguments(1); + setInfixToken("log10"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +Log10Operator::~Log10Operator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void Log10Operator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return log10(num); }); +} + +// ----------------------------------------------------------------------------- +Log10Operator::Pointer Log10Operator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp new file mode 100644 index 0000000000..ab053ffa10 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT Log10Operator : public UnaryOperator +{ +public: + using Self = Log10Operator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new Log10Operator()); + } + + ~Log10Operator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + Log10Operator(); + +public: + Log10Operator(const Log10Operator&) = delete; // Copy Constructor Not Implemented + Log10Operator(Log10Operator&&) = delete; // Move Constructor Not Implemented + Log10Operator& operator=(const Log10Operator&) = delete; // Copy Assignment Not Implemented + Log10Operator& operator=(Log10Operator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp new file mode 100644 index 0000000000..3d2ed4d006 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp @@ -0,0 +1,40 @@ +#include "SimplnxCore/utils/LogOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +LogOperator::LogOperator() +{ + setNumberOfArguments(2); + setInfixToken("log"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +LogOperator::~LogOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void LogOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [this](double num1, double num2) -> double { return log_arbitrary_base(num1, num2); }); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +double LogOperator::log_arbitrary_base(double base, double value) +{ + return log(value) / log(base); +} + +// ----------------------------------------------------------------------------- +LogOperator::Pointer LogOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp new file mode 100644 index 0000000000..9409f158f7 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT LogOperator : public UnaryOperator +{ +public: + using Self = LogOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new LogOperator()); + } + + ~LogOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + LogOperator(); + +private: + double log_arbitrary_base(double base, double value); + +public: + LogOperator(const LogOperator&) = delete; // Copy Constructor Not Implemented + LogOperator(LogOperator&&) = delete; // Move Constructor Not Implemented + LogOperator& operator=(const LogOperator&) = delete; // Copy Assignment Not Implemented + LogOperator& operator=(LogOperator&&) = delete; // Move Assignment Not Implemented +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp new file mode 100644 index 0000000000..3e230d9d9c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp @@ -0,0 +1,33 @@ +#include "SimplnxCore/utils/MaxOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; +using namespace std; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MaxOperator::MaxOperator() +{ + setNumberOfArguments(2); + setInfixToken("max"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MaxOperator::~MaxOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void MaxOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return max(num1, num2); }); +} + +// ----------------------------------------------------------------------------- +MaxOperator::Pointer MaxOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp new file mode 100644 index 0000000000..0b7431f91c --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT MaxOperator : public UnaryOperator +{ +public: + using Self = MaxOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new MaxOperator()); + } + + ~MaxOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + MaxOperator(); + +public: + MaxOperator(const MaxOperator&) = delete; // Copy Constructor Not Implemented + MaxOperator(MaxOperator&&) = delete; // Move Constructor Not Implemented + MaxOperator& operator=(const MaxOperator&) = delete; // Copy Assignment Not Implemented + MaxOperator& operator=(MaxOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp new file mode 100644 index 0000000000..f6221cd6c4 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp @@ -0,0 +1,33 @@ +#include "SimplnxCore/utils/MinOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; +using namespace std; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MinOperator::MinOperator() +{ + setNumberOfArguments(2); + setInfixToken("min"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MinOperator::~MinOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void MinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return min(num1, num2); }); +} + +// ----------------------------------------------------------------------------- +MinOperator::Pointer MinOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp new file mode 100644 index 0000000000..15ff177642 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT MinOperator : public UnaryOperator +{ +public: + using Self = MinOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new MinOperator()); + } + + ~MinOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + MinOperator(); + +public: + MinOperator(const MinOperator&) = delete; // Copy Constructor Not Implemented + MinOperator(MinOperator&&) = delete; // Move Constructor Not Implemented + MinOperator& operator=(const MinOperator&) = delete; // Copy Assignment Not Implemented + MinOperator& operator=(MinOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp new file mode 100644 index 0000000000..dc9bf707de --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/MultiplicationOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MultiplicationOperator::MultiplicationOperator() +{ + setPrecedence(B_Precedence); + setInfixToken("*"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +MultiplicationOperator::~MultiplicationOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void MultiplicationOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 * num2; }); +} + +// ----------------------------------------------------------------------------- +MultiplicationOperator::Pointer MultiplicationOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp new file mode 100644 index 0000000000..1d32db39af --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/BinaryOperator.hpp" + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT MultiplicationOperator : public BinaryOperator +{ +public: + using Self = MultiplicationOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new MultiplicationOperator()); + } + + ~MultiplicationOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + MultiplicationOperator(); + +public: + MultiplicationOperator(const MultiplicationOperator&) = delete; // Copy Constructor Not Implemented + MultiplicationOperator(MultiplicationOperator&&) = delete; // Move Constructor Not Implemented + MultiplicationOperator& operator=(const MultiplicationOperator&) = delete; // Copy Assignment Not Implemented + MultiplicationOperator& operator=(MultiplicationOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp new file mode 100644 index 0000000000..ddf23f2a95 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp @@ -0,0 +1,81 @@ +#include "SimplnxCore/utils/NegativeOperator.hpp" +#include "SimplnxCore/utils/BinaryOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" +#include "SimplnxCore/utils/LeftParenthesisItem.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +NegativeOperator::NegativeOperator() +{ + setOperatorType(Unary); + setPrecedence(D_Precedence); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +NegativeOperator::~NegativeOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void NegativeOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + if(!executionStack.empty()) + { + ICalculatorArray::Pointer arrayPtr = executionStack.top(); + executionStack.pop(); + calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); + + DataArray* array = arrayPtr->getArray(); + + Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); + + usize numComps = newArray->getNumberOfComponents(); + for(usize i = 0; i < newArray->getNumberOfTuples(); i++) + { + for(usize c = 0; c < newArray->getNumberOfComponents(); c++) + { + usize index = numComps * i + c; + double num = array->getValue(index); + (*newArray)[index] = -1 * num; + } + } + + executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); + return; + } +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::ErrorCode NegativeOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) +{ + if(currentIndex - 1 >= 0 && (std::dynamic_pointer_cast(infixVector[currentIndex - 1]) == BinaryOperator::NullPointer() && + std::dynamic_pointer_cast(infixVector[currentIndex - 1]) == LeftParenthesisItem::NullPointer())) + { + // The symbol to the left of the negative sign is not a binary operator or left parenthesis + errMsg = fmt::format("The negative operator '{}' does not have a valid 'left' value.", getInfixToken()); + return NegativeOperator::ErrorCode::OperatorNoLeftValue; + } + if(currentIndex + 1 >= infixVector.size() || (currentIndex + 1 < infixVector.size() && (nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1]) && + nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1]) && + nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1])))) + { + // The symbol to the right of the negative sign is not an array, left parenthesis, or unary operator + errMsg = fmt::format("The negative operator '{}' does not have a valid 'right' value.", getInfixToken()); + return NegativeOperator::ErrorCode::OperatorNoRightValue; + } + + return NegativeOperator::ErrorCode::Success; +} + +// ----------------------------------------------------------------------------- +NegativeOperator::Pointer NegativeOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp new file mode 100644 index 0000000000..d0d7419e2f --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT NegativeOperator : public CalculatorOperator +{ +public: + using Self = NegativeOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new NegativeOperator()); + } + + ~NegativeOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + + CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) final; + +protected: + NegativeOperator(); + +public: + NegativeOperator(const NegativeOperator&) = delete; // Copy Constructor Not Implemented + NegativeOperator(NegativeOperator&&) = delete; // Move Constructor Not Implemented + NegativeOperator& operator=(const NegativeOperator&) = delete; // Copy Assignment Not Implemented + NegativeOperator& operator=(NegativeOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp new file mode 100644 index 0000000000..3a6f96cacf --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/PowOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +PowOperator::PowOperator() +{ + setPrecedence(C_Precedence); + setInfixToken("^"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +PowOperator::~PowOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void PowOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return pow(num1, num2); }); +} + +// ----------------------------------------------------------------------------- +PowOperator::Pointer PowOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp new file mode 100644 index 0000000000..f9d89aa0ec --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/BinaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT PowOperator : public BinaryOperator +{ +public: + using Self = PowOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new PowOperator()); + } + + ~PowOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + PowOperator(); + +public: + PowOperator(const PowOperator&) = delete; // Copy Constructor Not Implemented + PowOperator(PowOperator&&) = delete; // Move Constructor Not Implemented + PowOperator& operator=(const PowOperator&) = delete; // Copy Assignment Not Implemented + PowOperator& operator=(PowOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp new file mode 100644 index 0000000000..7585c58e4e --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.cpp @@ -0,0 +1,53 @@ +#include "SimplnxCore/utils/RightParenthesisItem.hpp" +#include "SimplnxCore/utils/LeftParenthesisItem.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +RightParenthesisItem::RightParenthesisItem() +{ + setInfixToken(")"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +RightParenthesisItem::~RightParenthesisItem() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::ErrorCode RightParenthesisItem::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) +{ + // Check for an opening parenthesis, ignoring any other internal sets of parentheses + int rightParenthesisCount = 0; + for(int i = currentIndex - 1; i >= 0; i--) + { + CalculatorItem::Pointer item = infixVector[i]; + if(std::dynamic_pointer_cast(item) != RightParenthesisItem::NullPointer()) + { + rightParenthesisCount++; + } + else if(std::dynamic_pointer_cast(item) != LeftParenthesisItem::NullPointer()) + { + if(rightParenthesisCount > 0) + { + rightParenthesisCount--; + } + else + { + return RightParenthesisItem::ErrorCode::Success; + } + } + } + + return RightParenthesisItem::ErrorCode::MismatchedParentheses; +} + +// ----------------------------------------------------------------------------- +RightParenthesisItem::Pointer RightParenthesisItem::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp new file mode 100644 index 0000000000..51dad2a493 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RightParenthesisItem.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/CalculatorItem.hpp" + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT RightParenthesisItem : public CalculatorItem +{ +public: + using Self = RightParenthesisItem; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new RightParenthesisItem()); + } + + ~RightParenthesisItem() override; + + /** + * @brief checkValidity + * @param infixVector + * @param currentIndex + * @param msg + * @return + */ + CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override; + +protected: + RightParenthesisItem(); + +public: + RightParenthesisItem(const RightParenthesisItem&) = delete; // Copy Constructor Not Implemented + RightParenthesisItem(RightParenthesisItem&&) = delete; // Move Constructor Not Implemented + RightParenthesisItem& operator=(const RightParenthesisItem&) = delete; // Copy Assignment Not Implemented + RightParenthesisItem& operator=(RightParenthesisItem&&) = delete; // Move Assignment Not Implemented + +private: +}; +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp new file mode 100644 index 0000000000..cf56bbfc4b --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/RootOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +RootOperator::RootOperator() +{ + setNumberOfArguments(2); + setInfixToken("root"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +RootOperator::~RootOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void RootOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [this](double num1, double num2) -> double { return root(num1, num2); }); +} + +// ----------------------------------------------------------------------------- +RootOperator::Pointer RootOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp new file mode 100644 index 0000000000..58b0868bd9 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT RootOperator : public UnaryOperator +{ +public: + using Self = RootOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new RootOperator()); + } + + ~RootOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + RootOperator(); + +public: + RootOperator(const RootOperator&) = delete; // Copy Constructor Not Implemented + RootOperator(RootOperator&&) = delete; // Move Constructor Not Implemented + RootOperator& operator=(const RootOperator&) = delete; // Copy Assignment Not Implemented + RootOperator& operator=(RootOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp new file mode 100644 index 0000000000..9484b3ce3e --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/SinOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +SinOperator::SinOperator() +{ + setNumberOfArguments(1); + setInfixToken("sin"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +SinOperator::~SinOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void SinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return sin(num); }); +} + +// ----------------------------------------------------------------------------- +SinOperator::Pointer SinOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp new file mode 100644 index 0000000000..c8e8d57cf1 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT SinOperator : public UnaryOperator +{ +public: + using Self = SinOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new SinOperator()); + } + + ~SinOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + SinOperator(); + +public: + SinOperator(const SinOperator&) = delete; // Copy Constructor Not Implemented + SinOperator(SinOperator&&) = delete; // Move Constructor Not Implemented + SinOperator& operator=(const SinOperator&) = delete; // Copy Assignment Not Implemented + SinOperator& operator=(SinOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp new file mode 100644 index 0000000000..02d17072b1 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/SqrtOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +SqrtOperator::SqrtOperator() +{ + setNumberOfArguments(1); + setInfixToken("sqrt"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +SqrtOperator::~SqrtOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void SqrtOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return sqrt(num); }); +} + +// ----------------------------------------------------------------------------- +SqrtOperator::Pointer SqrtOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp new file mode 100644 index 0000000000..46a174f6f0 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT SqrtOperator : public UnaryOperator +{ +public: + using Self = SqrtOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new SqrtOperator()); + } + + ~SqrtOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + SqrtOperator(); + +public: + SqrtOperator(const SqrtOperator&) = delete; // Copy Constructor Not Implemented + SqrtOperator(SqrtOperator&&) = delete; // Move Constructor Not Implemented + SqrtOperator& operator=(const SqrtOperator&) = delete; // Copy Assignment Not Implemented + SqrtOperator& operator=(SqrtOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp new file mode 100644 index 0000000000..6110ce750f --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/SubtractionOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +SubtractionOperator::SubtractionOperator() +{ + setPrecedence(A_Precedence); + setInfixToken("-"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +SubtractionOperator::~SubtractionOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void SubtractionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 - num2; }); +} + +// ----------------------------------------------------------------------------- +SubtractionOperator::Pointer SubtractionOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp new file mode 100644 index 0000000000..80b196435e --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/BinaryOperator.hpp" + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT SubtractionOperator : public BinaryOperator +{ +public: + using Self = SubtractionOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new SubtractionOperator()); + } + + ~SubtractionOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + SubtractionOperator(); + +public: + SubtractionOperator(const SubtractionOperator&) = delete; // Copy Constructor Not Implemented + SubtractionOperator(SubtractionOperator&&) = delete; // Move Constructor Not Implemented + SubtractionOperator& operator=(const SubtractionOperator&) = delete; // Copy Assignment Not Implemented + SubtractionOperator& operator=(SubtractionOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp new file mode 100644 index 0000000000..e39d1a2d44 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp @@ -0,0 +1,32 @@ +#include "SimplnxCore/utils/TanOperator.hpp" +#include "SimplnxCore/utils/CalculatorArray.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +TanOperator::TanOperator() +{ + setNumberOfArguments(1); + setInfixToken("tan"); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +TanOperator::~TanOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void TanOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return tan(num); }); +} + +// ----------------------------------------------------------------------------- +TanOperator::Pointer TanOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp new file mode 100644 index 0000000000..5ce8a5ca83 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "SimplnxCore/SimplnxCore_export.hpp" +#include "SimplnxCore/utils/UnaryOperator.hpp" + +namespace nx::core +{ +class CalculatorNumber; + +class SIMPLNXCORE_EXPORT TanOperator : public UnaryOperator +{ +public: + using Self = TanOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new TanOperator()); + } + + ~TanOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + +protected: + TanOperator(); + +public: + TanOperator(const TanOperator&) = delete; // Copy Constructor Not Implemented + TanOperator(TanOperator&&) = delete; // Move Constructor Not Implemented + TanOperator& operator=(const TanOperator&) = delete; // Copy Assignment Not Implemented + TanOperator& operator=(TanOperator&&) = delete; // Move Assignment Not Implemented + +private: +}; + +} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp new file mode 100644 index 0000000000..61cf7c7c99 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp @@ -0,0 +1,265 @@ +#include "UnaryOperator.hpp" + +#include "SimplnxCore/Filters/ArrayCalculatorFilter.hpp" +#include "SimplnxCore/utils/BinaryOperator.hpp" +#include "SimplnxCore/utils/CommaSeparator.hpp" +#include "SimplnxCore/utils/LeftParenthesisItem.hpp" +#include "SimplnxCore/utils/NegativeOperator.hpp" +#include "SimplnxCore/utils/RightParenthesisItem.hpp" + +using namespace nx::core; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +UnaryOperator::UnaryOperator() +: m_NumOfArguments(-1) +{ + setPrecedence(E_Precedence); + setOperatorType(Unary); +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +UnaryOperator::~UnaryOperator() = default; + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void UnaryOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) +{ + // This should never be executed +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +CalculatorItem::ErrorCode UnaryOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) +{ + if(currentIndex - 1 >= 0) + { + // If the left value isn't a binary operator + if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) + { + // If the left value isn't a left parenthesis + if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) + { + // If the left value isn't a negative operator + if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) + { + // If the left value isn't a comma + if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) + { + errMsg = fmt::format("The operator '{}' does not have a valid 'left' value.", getInfixToken()); + return CalculatorItem::ErrorCode::OperatorNoLeftValue; + } + } + } + } + } + + int index = currentIndex + 1; + int commaCount = 0; + bool hasArray = false; + if(index < infixVector.size() && nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + index++; + + // Iterate through the vector to find the matching right parenthesis + for(; index < infixVector.size(); index++) + { + if(nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + // We found the matching right parenthesis + if(commaCount < m_NumOfArguments - 1) + { + errMsg = fmt::format("The operator '{}' needs {} arguments. {} arguments were found.", getInfixToken(), m_NumOfArguments, commaCount + 1); + return CalculatorItem::ErrorCode::NotEnoughArguments; + } + if(!hasArray) + { + errMsg = fmt::format("The operator '{}' does not have any arguments that simplify down to a number.", getInfixToken()); + return CalculatorItem::ErrorCode::NoNumericArguments; + } + + return CalculatorItem::ErrorCode::Success; + } + if(nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + /* We found another left parenthesis, but we don't care what's inside this set of parentheses + (other operators' checkValidity functions will take care of these values), so just iterate + until we find the matching closing parenthesis for this opening parenthesis */ + int extraLeftPCount = 0; + index++; + while(index < infixVector.size() && (nullptr == std::dynamic_pointer_cast(infixVector[index]) || extraLeftPCount > 0)) + { + if(nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + hasArray = true; + } + else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + extraLeftPCount++; + } + else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + extraLeftPCount--; + } + + index++; + } + } + else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + // We found a comma, so increase the comma count + commaCount++; + if(commaCount > m_NumOfArguments - 1) + { + // We found too many commas (meaning that there are too many arguments), so return false + errMsg = fmt::format("The operator '{}' needs {} arguments. {} arguments were found.", getInfixToken(), m_NumOfArguments, commaCount + 1); + return CalculatorItem::ErrorCode::TooManyArguments; + } + } + else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) + { + hasArray = true; + } + } + } + else + { + errMsg = fmt::format("The operator '{}' does not have an opening parenthesis.", getInfixToken()); + return CalculatorItem::ErrorCode::OperatorNoOpeningParen; + } + + errMsg = fmt::format("The operator '{}' does not have a closing parenthesis.", getInfixToken()); + return CalculatorItem::ErrorCode::OperatorNoClosingParen; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +int UnaryOperator::getNumberOfArguments() +{ + return m_NumOfArguments; +} + +// ----------------------------------------------------------------------------- +// +// ----------------------------------------------------------------------------- +void UnaryOperator::setNumberOfArguments(int numOfArguments) +{ + m_NumOfArguments = numOfArguments; +} + +// ----------------------------------------------------------------------------- +UnaryOperator::Pointer UnaryOperator::NullPointer() +{ + return Pointer(static_cast(nullptr)); +} + +// ----------------------------------------------------------------------------- +void UnaryOperator::CreateNewArrayStandardUnary(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, + std::stack& executionStack, std::function op) +{ + ICalculatorArray::Pointer arrayPtr = executionStack.top(); + if(!executionStack.empty() && nullptr != arrayPtr) + { + executionStack.pop(); + calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); + + Float64Array* newArray = + Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), arrayPtr->getArray()->getTupleShape(), arrayPtr->getArray()->getComponentShape()); + + usize numComps = newArray->getNumberOfComponents(); + for(usize i = 0; i < newArray->getNumberOfTuples(); i++) + { + for(usize c = 0; c < newArray->getNumberOfComponents(); c++) + { + usize index = numComps * i + c; + double num = arrayPtr->getValue(index); + (*newArray)[index] = op(num); + } + } + + executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); + return; + } +} + +// ----------------------------------------------------------------------------- +void UnaryOperator::CreateNewArrayTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, + std::function op) +{ + ICalculatorArray::Pointer arrayPtr = executionStack.top(); + if(!executionStack.empty() && nullptr != arrayPtr) + { + executionStack.pop(); + calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); + + DataArray* array = arrayPtr->getArray(); + + Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); + + usize numComps = newArray->getNumberOfComponents(); + for(usize i = 0; i < newArray->getNumberOfTuples(); i++) + { + for(usize c = 0; c < newArray->getNumberOfComponents(); c++) + { + usize index = numComps * i + c; + double num = array->getValue(index); + + if(units == CalculatorParameter::AngleUnits::Degrees) + { + (*newArray)[index] = op(toRadians(num)); + } + else + { + (*newArray)[index] = op(num); + } + } + } + + executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); + return; + } +} + +// ----------------------------------------------------------------------------- +void UnaryOperator::CreateNewArrayArcTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, + std::function op) +{ + ICalculatorArray::Pointer arrayPtr = executionStack.top(); + if(!executionStack.empty() && nullptr != arrayPtr) + { + executionStack.pop(); + calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); + + DataArray* array = arrayPtr->getArray(); + + Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); + + usize numComps = newArray->getNumberOfComponents(); + for(usize i = 0; i < newArray->getNumberOfTuples(); i++) + { + for(usize c = 0; c < newArray->getNumberOfComponents(); c++) + { + usize index = numComps * i + c; + double num = array->getValue(index); + + if(units == CalculatorParameter::AngleUnits::Degrees) + { + (*newArray)[index] = toDegrees(op(num)); + } + else + { + (*newArray)[index] = op(num); + } + } + } + + executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); + return; + } +} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp new file mode 100644 index 0000000000..a3f49a08d8 --- /dev/null +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include "SimplnxCore/utils/CalculatorOperator.hpp" +#include "simplnx/DataStructure/DataPath.hpp" + +#include +#include + +namespace nx::core +{ +class SIMPLNXCORE_EXPORT UnaryOperator : public CalculatorOperator +{ +public: + using Self = UnaryOperator; + using Pointer = std::shared_ptr; + using ConstPointer = std::shared_ptr; + using WeakPointer = std::weak_ptr; + using ConstWeakPointer = std::weak_ptr; + static Pointer NullPointer(); + + static Pointer New() + { + return Pointer(new UnaryOperator()); + } + + ~UnaryOperator() override; + + void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; + + CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) final; + + int getNumberOfArguments(); + +protected: + UnaryOperator(); + + void setNumberOfArguments(int numOfArguments); + +private: + int m_NumOfArguments; + +public: + UnaryOperator(const UnaryOperator&) = delete; // Copy Constructor Not Implemented + UnaryOperator(UnaryOperator&&) = delete; // Move Constructor Not Implemented + UnaryOperator& operator=(const UnaryOperator&) = delete; // Copy Assignment Not Implemented + UnaryOperator& operator=(UnaryOperator&&) = delete; // Move Assignment Not Implemented + + static void CreateNewArrayStandardUnary(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, + std::function op); + static void CreateNewArrayTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, + std::function op); + static void CreateNewArrayArcTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, + std::function op); +}; + +} // namespace nx::core diff --git a/src/simplnx/Parameters/CalculatorParameter.cpp b/src/simplnx/Parameters/CalculatorParameter.cpp index 00c1044315..a94264a778 100644 --- a/src/simplnx/Parameters/CalculatorParameter.cpp +++ b/src/simplnx/Parameters/CalculatorParameter.cpp @@ -21,7 +21,7 @@ constexpr StringLiteral k_SelectedGroup = "selected_group"; } // namespace CalculatorParameter::CalculatorParameter(const std::string& name, const std::string& humanName, const std::string& helpText, const ValueType& defaultValue) -: MutableDataParameter(name, humanName, helpText, Category::Required) +: ValueParameter(name, humanName, helpText) , m_DefaultValue(defaultValue) { } @@ -107,7 +107,7 @@ typename CalculatorParameter::ValueType CalculatorParameter::defaultString() con return m_DefaultValue; } -Result<> CalculatorParameter::validate(const DataStructure& dataStructure, const std::any& value) const +Result<> CalculatorParameter::validate(const std::any& value) const { static constexpr StringLiteral prefix = "FilterParameter 'CalculatorParameter' JSON Error: "; [[maybe_unused]] const auto& structValue = GetAnyRef(value); @@ -123,13 +123,6 @@ Result<> CalculatorParameter::validate(const DataStructure& dataStructure, const return {}; } -Result CalculatorParameter::resolve(DataStructure& dataStructure, const std::any& value) const -{ - const auto& structValue = GetAnyRef(value); - DataObject* object = dataStructure.getData(structValue.m_SelectedGroup); - return {{object}}; -} - namespace SIMPLConversion { namespace diff --git a/src/simplnx/Parameters/CalculatorParameter.hpp b/src/simplnx/Parameters/CalculatorParameter.hpp index 9300b49406..9d59aa376b 100644 --- a/src/simplnx/Parameters/CalculatorParameter.hpp +++ b/src/simplnx/Parameters/CalculatorParameter.hpp @@ -1,15 +1,15 @@ #pragma once #include "simplnx/DataStructure/DataPath.hpp" -#include "simplnx/Filter/MutableDataParameter.hpp" #include "simplnx/Filter/ParameterTraits.hpp" +#include "simplnx/Filter/ValueParameter.hpp" #include "simplnx/simplnx_export.hpp" #include namespace nx::core { -class SIMPLNX_EXPORT CalculatorParameter : public MutableDataParameter +class SIMPLNX_EXPORT CalculatorParameter : public ValueParameter { public: enum AngleUnits : uint8 @@ -78,16 +78,7 @@ class SIMPLNX_EXPORT CalculatorParameter : public MutableDataParameter * @param value * @return */ - Result<> validate(const DataStructure& dataStructure, const std::any& value) const override; - - /** - * @brief Takes the value and a mutable DataStructure and attempts store the actual derived DataObject in the std::any. - * Returns any warnings/errors. - * @param dataStructure - * @param value - * @return - */ - Result resolve(DataStructure& dataStructure, const std::any& value) const override; + Result<> validate(const std::any& value) const override; protected: /** From 0a1b95feb12a43f22d9b4e86f4ad2b53618ec0a0 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 20:43:40 -0400 Subject: [PATCH 11/19] BUG: Fix integer overflow in ArrayCalculator bracket index parsing --- .../Filters/Algorithms/ArrayCalculator.cpp | 45 ++++++++++--------- .../Filters/Algorithms/ArrayCalculator.hpp | 3 +- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 5ff3b4c4d5..eafeeab111 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -38,7 +38,7 @@ struct ParsedItem CalcValue value{CalcValue::Kind::Number, 0}; const OperatorDef* op = nullptr; - int componentIndex = -1; + usize componentIndex = std::numeric_limits::max(); bool isNegativePrefix = false; }; @@ -640,17 +640,18 @@ Result<> ArrayCalculatorParser::parse() if(bracketNumbers.size() == 1) { // [C]: component extraction - int compIdx = 0; + usize compIdx = 0; try { - compIdx = std::stoi(bracketNumbers[0]); + auto parsed = std::stoull(bracketNumbers[0]); + compIdx = static_cast(parsed); } catch(const std::exception&) { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid component index '{}'.", bracketNumbers[0])); } - if(compIdx < 0 || static_cast(compIdx) >= numComponents) + if(compIdx >= numComponents) { return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); @@ -664,7 +665,7 @@ Result<> ArrayCalculatorParser::parse() { for(usize t = 0; t < numTuples; ++t) { - (*newArr)[t] = (*tempArr)[t * numComponents + static_cast(compIdx)]; + (*newArr)[t] = (*tempArr)[t * numComponents + compIdx]; } } prevItem.value.arrayId = newArr->getId(); @@ -674,23 +675,23 @@ Result<> ArrayCalculatorParser::parse() else if(bracketNumbers.size() == 2) { // [T, C]: tuple+component extraction - int tupleIdx = 0; - int compIdx = 0; + usize tupleIdx = 0; + usize compIdx = 0; try { - tupleIdx = std::stoi(bracketNumbers[0]); - compIdx = std::stoi(bracketNumbers[1]); + tupleIdx = static_cast(std::stoull(bracketNumbers[0])); + compIdx = static_cast(std::stoull(bracketNumbers[1])); } catch(const std::exception&) { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid tuple/component index in '[{}, {}]'.", bracketNumbers[0], bracketNumbers[1])); } - if(tupleIdx < 0 || static_cast(tupleIdx) >= numTuples) + if(tupleIdx >= numTuples) { return MakeErrorResult(static_cast(CalculatorErrorCode::TupleOutOfRange), fmt::format("Tuple index {} is out of range for array with {} tuples.", tupleIdx, numTuples)); } - if(compIdx < 0 || static_cast(compIdx) >= numComponents) + if(compIdx >= numComponents) { return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); @@ -699,7 +700,7 @@ Result<> ArrayCalculatorParser::parse() double extractedValue = 0.0; if(!m_IsPreflight) { - extractedValue = (*tempArr)[static_cast(tupleIdx) * numComponents + static_cast(compIdx)]; + extractedValue = (*tempArr)[tupleIdx * numComponents + compIdx]; } DataObject::IdType id = createScalarInTemp(extractedValue); prevItem.value = CalcValue{CalcValue::Kind::Number, id}; @@ -716,10 +717,10 @@ Result<> ArrayCalculatorParser::parse() { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), "Component extraction on sub-expression must have exactly one index: [C]."); } - int compIdx = 0; + usize compIdx = 0; try { - compIdx = std::stoi(bracketNumbers[0]); + compIdx = static_cast(std::stoull(bracketNumbers[0])); } catch(const std::exception&) { @@ -1398,7 +1399,7 @@ Result<> ArrayCalculatorParser::parse() switch(item.kind) { case ParsedItem::Kind::Value: { - m_RpnItems.push_back(RpnItem{RpnItem::Type::Value, item.value, nullptr, -1}); + m_RpnItems.push_back(RpnItem{RpnItem::Type::Value, item.value, nullptr, std::numeric_limits::max()}); break; } @@ -1412,7 +1413,7 @@ Result<> ArrayCalculatorParser::parse() while(!opStack.empty() && opStack.back().kind != ParsedItem::Kind::LParen) { const auto& top = opStack.back(); - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, -1}); + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, std::numeric_limits::max()}); opStack.pop_back(); } if(opStack.empty()) @@ -1430,7 +1431,7 @@ Result<> ArrayCalculatorParser::parse() while(!opStack.empty() && opStack.back().kind != ParsedItem::Kind::LParen) { const auto& top = opStack.back(); - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, -1}); + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, std::numeric_limits::max()}); opStack.pop_back(); } break; @@ -1449,7 +1450,7 @@ Result<> ArrayCalculatorParser::parse() if(topPrec > incomingPrec || (topPrec == incomingPrec && isLeftAssoc)) { - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, -1}); + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, std::numeric_limits::max()}); opStack.pop_back(); } else @@ -1480,7 +1481,7 @@ Result<> ArrayCalculatorParser::parse() fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); } const OperatorDef* topOp = top.isNegativePrefix ? &getUnaryNegativeOp() : top.op; - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, -1}); + m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, std::numeric_limits::max()}); opStack.pop_back(); } @@ -1654,9 +1655,9 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const usize numComps = operandArr->getNumberOfComponents(); usize numTuples = operandArr->getNumberOfTuples(); - int compIdx = rpnItem.componentIndex; + usize compIdx = rpnItem.componentIndex; - if(compIdx < 0 || static_cast(compIdx) >= numComps) + if(compIdx >= numComps) { return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); @@ -1665,7 +1666,7 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const auto* newArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), operandArr->getTupleShape(), std::vector{1}); for(usize t = 0; t < numTuples; ++t) { - (*newArr)[t] = operandArr->at(t * numComps + static_cast(compIdx)); + (*newArr)[t] = operandArr->at(t * numComps + compIdx); } evalStack.push(CalcValue{operand.kind, newArr->getId()}); diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp index 7f3fec261e..c234f0fd69 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -159,7 +160,7 @@ struct SIMPLNXCORE_EXPORT RpnItem CalcValue value; const OperatorDef* op = nullptr; - int componentIndex = -1; + usize componentIndex = std::numeric_limits::max(); }; // --------------------------------------------------------------------------- From 044bbf657b0d88397dd1ef2d6301401745a00961 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 21:22:56 -0400 Subject: [PATCH 12/19] STY: Run clang-format on ArrayCalculator files Signed-off-by: Joey Kleingers --- .../Filters/Algorithms/ArrayCalculator.cpp | 106 +++++++----------- .../SimplnxCore/test/ArrayCalculatorTest.cpp | 9 +- 2 files changed, 44 insertions(+), 71 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index eafeeab111..395baaea83 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -252,8 +252,7 @@ struct CopyResultFunctor // --------------------------------------------------------------------------- const std::vector& nx::core::getOperatorRegistry() { - static const std::vector s_Registry = []() - { + static const std::vector s_Registry = []() { std::vector reg; reg.reserve(23); @@ -645,16 +644,14 @@ Result<> ArrayCalculatorParser::parse() { auto parsed = std::stoull(bracketNumbers[0]); compIdx = static_cast(parsed); - } - catch(const std::exception&) + } catch(const std::exception&) { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid component index '{}'.", bracketNumbers[0])); } if(compIdx >= numComponents) { - return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), - fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); } if(numComponents > 1) @@ -681,8 +678,7 @@ Result<> ArrayCalculatorParser::parse() { tupleIdx = static_cast(std::stoull(bracketNumbers[0])); compIdx = static_cast(std::stoull(bracketNumbers[1])); - } - catch(const std::exception&) + } catch(const std::exception&) { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid tuple/component index in '[{}, {}]'.", bracketNumbers[0], bracketNumbers[1])); } @@ -693,8 +689,7 @@ Result<> ArrayCalculatorParser::parse() } if(compIdx >= numComponents) { - return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), - fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); } double extractedValue = 0.0; @@ -721,8 +716,7 @@ Result<> ArrayCalculatorParser::parse() try { compIdx = static_cast(std::stoull(bracketNumbers[0])); - } - catch(const std::exception&) + } catch(const std::exception&) { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid component index '{}'.", bracketNumbers[0])); } @@ -749,8 +743,7 @@ Result<> ArrayCalculatorParser::parse() try { numValue = std::stod(tok.text); - } - catch(const std::exception&) + } catch(const std::exception&) { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), fmt::format("Invalid numeric value '{}'.", tok.text)); } @@ -775,11 +768,10 @@ Result<> ArrayCalculatorParser::parse() } if(arrayExists) { - result.warnings().push_back( - Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), - fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a number." - "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", - tok.text, tok.text)}); + result.warnings().push_back(Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a number." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); } } break; @@ -802,11 +794,10 @@ Result<> ArrayCalculatorParser::parse() } if(arrayExists) { - result.warnings().push_back( - Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), - fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a mathematical operator." - "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", - tok.text, tok.text)}); + result.warnings().push_back(Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a mathematical operator." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); } } @@ -838,11 +829,10 @@ Result<> ArrayCalculatorParser::parse() } if(arrayExists) { - result.warnings().push_back( - Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), - fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a built-in constant." - "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", - tok.text, tok.text)}); + result.warnings().push_back(Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a built-in constant." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); } } } @@ -869,8 +859,7 @@ Result<> ArrayCalculatorParser::parse() auto foundPaths = findArraysByName(m_DataStructure, tok.text); if(foundPaths.empty()) { - return MakeErrorResult(static_cast(CalculatorErrorCode::UnrecognizedItem), - fmt::format("An unrecognized or invalid item '{}' was found in the chosen infix expression.", tok.text)); + return MakeErrorResult(static_cast(CalculatorErrorCode::UnrecognizedItem), fmt::format("An unrecognized or invalid item '{}' was found in the chosen infix expression.", tok.text)); } if(foundPaths.size() > 1) { @@ -883,10 +872,9 @@ Result<> ArrayCalculatorParser::parse() } pathsList += p.toString(); } - return MakeErrorResult(static_cast(CalculatorErrorCode::AmbiguousArrayName), - fmt::format("Array name '{}' is ambiguous. Multiple arrays found: [{}]." - "\nPlease use double quotes with the full path (e.g. \"Path/To/{}\") to disambiguate.", - tok.text, pathsList, tok.text)); + return MakeErrorResult(static_cast(CalculatorErrorCode::AmbiguousArrayName), fmt::format("Array name '{}' is ambiguous. Multiple arrays found: [{}]." + "\nPlease use double quotes with the full path (e.g. \"Path/To/{}\") to disambiguate.", + tok.text, pathsList, tok.text)); } const auto* dataArray = m_DataStructure.getDataAs(foundPaths[0]); if(dataArray == nullptr) @@ -981,11 +969,10 @@ Result<> ArrayCalculatorParser::parse() } if(arrayExists) { - result.warnings().push_back( - Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), - fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a mathematical operator." - "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", - tok.text, tok.text)}); + result.warnings().push_back(Warning{static_cast(CalculatorWarningCode::AmbiguousNameWarning), + fmt::format("Item '{}' in the infix expression is the name of an array, but it is currently being used as a mathematical operator." + "\nTo treat this item as an array name, please add double quotes around the item (i.e. \"{}\").", + tok.text, tok.text)}); } } @@ -1087,8 +1074,7 @@ Result<> ArrayCalculatorParser::parse() // A function operator must be followed by LParen if(i + 1 >= items.size() || items[i + 1].kind != ParsedItem::Kind::LParen) { - return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoOpeningParen), - fmt::format("The operator/function '{}' does not have a valid opening parenthesis.", item.op->token)); + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoOpeningParen), fmt::format("The operator/function '{}' does not have a valid opening parenthesis.", item.op->token)); } // Find the matching RParen and count commas/values at depth 1 @@ -1124,8 +1110,7 @@ Result<> ArrayCalculatorParser::parse() } if(!foundClose) { - return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoClosingParen), - fmt::format("The operator/function '{}' does not have a valid closing parenthesis.", item.op->token)); + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoClosingParen), fmt::format("The operator/function '{}' does not have a valid closing parenthesis.", item.op->token)); } // Check for empty function call: func() with no values or commas inside @@ -1138,8 +1123,7 @@ Result<> ArrayCalculatorParser::parse() fmt::format("The function '{}' requires {} arguments, but none were provided.", item.op->token, item.op->numArgs)); } // For 1-arg functions with empty parens: NoNumericArguments - return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), - fmt::format("The function '{}' does not have any arguments that simplify down to a number.", item.op->token)); + return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), fmt::format("The function '{}' does not have any arguments that simplify down to a number.", item.op->token)); } // Check for commas in the empty-value case: func(,) -- commas but no real values @@ -1151,8 +1135,7 @@ Result<> ArrayCalculatorParser::parse() fmt::format("The function '{}' requires {} argument, but more were provided.", item.op->token, item.op->numArgs)); } // For 2-arg functions: NoNumericArguments (commas but no values) - return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), - fmt::format("The function '{}' does not have any arguments that simplify down to a number.", item.op->token)); + return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), fmt::format("The function '{}' does not have any arguments that simplify down to a number.", item.op->token)); } // Argument count: numArgs from OperatorDef, commaCount gives (numArgs-1) @@ -1200,8 +1183,7 @@ Result<> ArrayCalculatorParser::parse() } if(!foundFunction) { - return MakeErrorResult(static_cast(CalculatorErrorCode::NoPrecedingUnaryOperator), - "A comma was found in parentheses without a preceding function operator."); + return MakeErrorResult(static_cast(CalculatorErrorCode::NoPrecedingUnaryOperator), "A comma was found in parentheses without a preceding function operator."); } } } @@ -1226,8 +1208,7 @@ Result<> ArrayCalculatorParser::parse() } if(!hasLeft) { - return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoLeftValue), - fmt::format("The binary operator '{}' does not have a valid left-hand value.", item.op->token)); + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoLeftValue), fmt::format("The binary operator '{}' does not have a valid left-hand value.", item.op->token)); } // Check right: the item after must be a value, LParen, or unary operator (something that produces a value) bool hasRight = false; @@ -1245,8 +1226,7 @@ Result<> ArrayCalculatorParser::parse() } if(!hasRight) { - return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoRightValue), - fmt::format("The binary operator '{}' does not have a valid right-hand value.", item.op->token)); + return MakeErrorResult(static_cast(CalculatorErrorCode::OperatorNoRightValue), fmt::format("The binary operator '{}' does not have a valid right-hand value.", item.op->token)); } } @@ -1297,8 +1277,7 @@ Result<> ArrayCalculatorParser::parse() } if(parenDepth != 0) { - return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), - fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); + return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); } } @@ -1328,13 +1307,11 @@ Result<> ArrayCalculatorParser::parse() { if(!arrayCompShape.empty() && arrayCompShape != cs) { - return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentCompDims), - "Attribute Array symbols in the infix expression have mismatching component dimensions."); + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentCompDims), "Attribute Array symbols in the infix expression have mismatching component dimensions."); } if(arrayNumTuples != 0 && nt != arrayNumTuples) { - return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentTuples), - "Attribute Array symbols in the infix expression have mismatching number of tuples."); + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentTuples), "Attribute Array symbols in the infix expression have mismatching number of tuples."); } if(!arrayTupleShape.empty() && arrayTupleShape != ts) { @@ -1477,8 +1454,7 @@ Result<> ArrayCalculatorParser::parse() const auto& top = opStack.back(); if(top.kind == ParsedItem::Kind::LParen) { - return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), - fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); + return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); } const OperatorDef* topOp = top.isNegativePrefix ? &getUnaryNegativeOp() : top.op; m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, std::numeric_limits::max()}); @@ -1659,8 +1635,7 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const if(compIdx >= numComps) { - return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), - fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); } auto* newArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), operandArr->getTupleShape(), std::vector{1}); @@ -1679,8 +1654,7 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const // 3. Final result if(evalStack.size() != 1) { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), - fmt::format("Internal error: evaluation stack has {} items remaining; expected exactly 1.", evalStack.size())); + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), fmt::format("Internal error: evaluation stack has {} items remaining; expected exactly 1.", evalStack.size())); } CalcValue finalVal = evalStack.top(); diff --git a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp index 30861fc02f..3ace78b5da 100644 --- a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp +++ b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp @@ -95,8 +95,8 @@ IFilter::ExecuteResult createAndExecuteArrayCalculatorFilter(const std::string& } // ----------------------------------------------------------------------------- -void runTest(const std::string& equation, const DataPath& targetArrayPath, int32 expectedErrorCondition, CalculatorWarningCode expectedWarningCondition, - const int* expectedNumberOfTuples = nullptr, const double* expectedValue = nullptr, CalculatorParameter::AngleUnits units = CalculatorParameter::AngleUnits::Radians) +void runTest(const std::string& equation, const DataPath& targetArrayPath, int32 expectedErrorCondition, CalculatorWarningCode expectedWarningCondition, const int* expectedNumberOfTuples = nullptr, + const double* expectedValue = nullptr, CalculatorParameter::AngleUnits units = CalculatorParameter::AngleUnits::Radians) { std::cout << " Testing equation: ==>" << equation << "<==" << std::endl; @@ -1270,9 +1270,8 @@ TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Sub-expression Component Access") // Sum = 2*values = [0,2,4,6,8,10,...,58] // Component 0 extraction: for each tuple t, take element at (t*3 + 0) = 2*(t*3) Arguments args; - args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, - std::make_any( - CalculatorParameter::ValueType{k_AttributeMatrixPath, "(\"MultiComponent Array1\" + \"MultiComponent Array2\")[0]", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, std::make_any(CalculatorParameter::ValueType{ + k_AttributeMatrixPath, "(\"MultiComponent Array1\" + \"MultiComponent Array2\")[0]", CalculatorParameter::Radians})); args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); auto result = filter.execute(ds, args); From 7364e721d8165c8851076954a2b50992797438d6 Mon Sep 17 00:00:00 2001 From: Joey Kleingers Date: Sun, 22 Mar 2026 21:35:35 -0400 Subject: [PATCH 13/19] ENH: Support (expr)[T, C] sub-expression tuple+component extraction Adds TupleComponentExtract as a new RPN item type that extracts a single scalar value from a computed sub-expression result at a specific tuple and component index. Produces a Number that broadcasts like a literal. Signed-off-by: Joey Kleingers --- .../Filters/Algorithms/ArrayCalculator.cpp | 117 +++++++++++++++--- .../Filters/Algorithms/ArrayCalculator.hpp | 4 +- .../SimplnxCore/test/ArrayCalculatorTest.cpp | 44 +++++++ 3 files changed, 145 insertions(+), 20 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 395baaea83..ca2d0474fa 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -33,12 +33,14 @@ struct ParsedItem LParen, RParen, Comma, - ComponentExtract + ComponentExtract, + TupleComponentExtract } kind; CalcValue value{CalcValue::Kind::Number, 0}; const OperatorDef* op = nullptr; usize componentIndex = std::numeric_limits::max(); + usize tupleIndex = std::numeric_limits::max(); bool isNegativePrefix = false; }; @@ -707,24 +709,48 @@ Result<> ArrayCalculatorParser::parse() } else if(prevItem.kind == ParsedItem::Kind::RParen) { - // Case B: )[C] -- component extraction on sub-expression result - if(bracketNumbers.size() != 1) + // Case B: )[C] or )[T, C] -- extraction on sub-expression result + if(bracketNumbers.size() == 1) { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), "Component extraction on sub-expression must have exactly one index: [C]."); + // )[C]: component extraction + usize compIdx = 0; + try + { + compIdx = static_cast(std::stoull(bracketNumbers[0])); + } catch(const std::exception&) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid component index '{}'.", bracketNumbers[0])); + } + + ParsedItem ce; + ce.kind = ParsedItem::Kind::ComponentExtract; + ce.componentIndex = compIdx; + items.push_back(ce); } - usize compIdx = 0; - try + else if(bracketNumbers.size() == 2) { - compIdx = static_cast(std::stoull(bracketNumbers[0])); - } catch(const std::exception&) + // )[T, C]: tuple+component extraction (produces scalar) + usize tupleIdx = 0; + usize compIdx = 0; + try + { + tupleIdx = static_cast(std::stoull(bracketNumbers[0])); + compIdx = static_cast(std::stoull(bracketNumbers[1])); + } catch(const std::exception&) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid tuple/component index in '[{}, {}]'.", bracketNumbers[0], bracketNumbers[1])); + } + + ParsedItem tce; + tce.kind = ParsedItem::Kind::TupleComponentExtract; + tce.tupleIndex = tupleIdx; + tce.componentIndex = compIdx; + items.push_back(tce); + } + else { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), fmt::format("Invalid component index '{}'.", bracketNumbers[0])); + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidComponent), "Sub-expression index must be [C] or [T, C]."); } - - ParsedItem ce; - ce.kind = ParsedItem::Kind::ComponentExtract; - ce.componentIndex = compIdx; - items.push_back(ce); } else { @@ -1334,21 +1360,31 @@ Result<> ArrayCalculatorParser::parse() return MakeErrorResult(static_cast(CalculatorErrorCode::NoNumericArguments), "The expression does not have any arguments that simplify down to a number."); } - // Check if there is a ComponentExtract item in the parsed list. - // If so, the final output will be single-component regardless of the - // input array's component shape. + // Check if there is a ComponentExtract or TupleComponentExtract item in the parsed list. + // ComponentExtract produces a single-component array. + // TupleComponentExtract produces a scalar (single tuple, single component). bool hasComponentExtract = false; + bool hasTupleComponentExtract = false; for(const auto& item : items) { if(item.kind == ParsedItem::Kind::ComponentExtract) { hasComponentExtract = true; - break; + } + if(item.kind == ParsedItem::Kind::TupleComponentExtract) + { + hasTupleComponentExtract = true; } } // Store the parsed shape info for use by parseAndValidate() - if(hasArray) + if(hasTupleComponentExtract) + { + // TupleComponentExtract produces a scalar + m_ParsedTupleShape = {1}; + m_ParsedComponentShape = {1}; + } + else if(hasArray) { if(tupleShapesMatch) { @@ -1445,6 +1481,15 @@ Result<> ArrayCalculatorParser::parse() break; } + case ParsedItem::Kind::TupleComponentExtract: { + RpnItem tce; + tce.type = RpnItem::Type::TupleComponentExtract; + tce.tupleIndex = item.tupleIndex; + tce.componentIndex = item.componentIndex; + m_RpnItems.push_back(tce); + break; + } + } // end switch } @@ -1648,6 +1693,40 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const break; } + case RpnItem::Type::TupleComponentExtract: { + if(evalStack.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for tuple+component extraction."); + } + CalcValue operand = evalStack.top(); + evalStack.pop(); + + auto* operandArr = m_TempDataStructure.getDataAs(operand.arrayId); + if(operandArr == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand array for tuple+component extraction."); + } + + usize numComps = operandArr->getNumberOfComponents(); + usize numTuples = operandArr->getNumberOfTuples(); + usize tupleIdx = rpnItem.tupleIndex; + usize compIdx = rpnItem.componentIndex; + + if(tupleIdx >= numTuples) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::TupleOutOfRange), fmt::format("Tuple index {} is out of range for array with {} tuples.", tupleIdx, numTuples)); + } + if(compIdx >= numComps) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); + } + + double value = operandArr->at(tupleIdx * numComps + compIdx); + DataObject::IdType scalarId = createScalarInTemp(value); + evalStack.push(CalcValue{CalcValue::Kind::Number, scalarId}); + break; + } + } // end switch } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp index c234f0fd69..31fac64fab 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp @@ -155,12 +155,14 @@ struct SIMPLNXCORE_EXPORT RpnItem { Value, Operator, - ComponentExtract + ComponentExtract, + TupleComponentExtract } type; CalcValue value; const OperatorDef* op = nullptr; usize componentIndex = std::numeric_limits::max(); + usize tupleIndex = std::numeric_limits::max(); }; // --------------------------------------------------------------------------- diff --git a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp index 3ace78b5da..d4dcae1591 100644 --- a/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp +++ b/src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp @@ -1323,3 +1323,47 @@ TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Multi-word Array Names") UnitTest::CheckArraysInheritTupleDims(ds); } + +TEST_CASE("SimplnxCore::ArrayCalculatorFilter: Sub-expression Tuple Component Extraction") +{ + UnitTest::LoadPlugins(); + DataStructure ds = ::createDataStructure(); + ArrayCalculatorFilter filter; + + // MultiComponent Array1 has 10 tuples, 3 components, values 0,1,2,3,...,29 + // (ArrayA + ArrayB) at tuple 2, component 1 = 2*(2*3+1) = 14 + + SECTION("(expr)[T, C] produces scalar") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, std::make_any(CalculatorParameter::ValueType{ + k_AttributeMatrixPath, "(\"MultiComponent Array1\" + \"MultiComponent Array2\")[2, 1]", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_VALID(result.result); + + REQUIRE_NOTHROW(ds.getDataRefAs(k_AttributeArrayPath)); + const auto& outputArray = ds.getDataRefAs(k_AttributeArrayPath); + // Scalar result broadcast to AM shape (10 tuples) + double expected = 2.0 * (2 * 3 + 1); // tuple 2, comp 1, doubled = 14 + for(usize i = 0; i < outputArray.getNumberOfTuples(); i++) + { + REQUIRE(UnitTest::CloseEnough(outputArray.at(i), expected, 0.01)); + } + } + + SECTION("(expr)[T, C] out of bounds tuple") + { + Arguments args; + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatorParameter_Key, std::make_any(CalculatorParameter::ValueType{ + k_AttributeMatrixPath, "(\"MultiComponent Array1\" + \"MultiComponent Array2\")[100, 0]", CalculatorParameter::Radians})); + args.insertOrAssign(ArrayCalculatorFilter::k_ScalarType_Key, std::make_any(NumericType::float64)); + args.insertOrAssign(ArrayCalculatorFilter::k_CalculatedArray_Key, std::make_any(k_AttributeArrayPath)); + auto result = filter.execute(ds, args); + SIMPLNX_RESULT_REQUIRE_INVALID(result.result); + REQUIRE(result.result.errors()[0].code == static_cast(CalculatorErrorCode::TupleOutOfRange)); + } + + UnitTest::CheckArraysInheritTupleDims(ds); +} From 5712e6c9552b81fbb6fd5d8e8943680d983c11d6 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Wed, 25 Mar 2026 13:28:39 -0400 Subject: [PATCH 14/19] MEM: Fix huge memory allocation during preflight. Signed-off-by: Michael Jackson --- .../Filters/Algorithms/ArrayCalculator.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index ca2d0474fa..eaffe994cf 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -455,17 +455,22 @@ DataObject::IdType ArrayCalculatorParser::createScalarInTemp(double value) // --------------------------------------------------------------------------- DataObject::IdType ArrayCalculatorParser::copyArrayToTemp(const IDataArray& sourceArray) { + using EmptyDataStoreType = EmptyDataStore; + using DataStoreType = DataStore; + auto tupleShape = sourceArray.getTupleShape(); auto compShape = sourceArray.getComponentShape(); std::string scratchName = nextScratchName(); - auto* destArr = Float64Array::CreateWithStore(m_TempDataStructure, scratchName, tupleShape, compShape); - - if(!m_IsPreflight) + if(m_IsPreflight) { - ExecuteDataFunction(CopyToFloat64Functor{}, sourceArray.getDataType(), sourceArray, *destArr); + auto* destArr = Float64Array::CreateWithStore(m_TempDataStructure, scratchName, tupleShape, compShape); + return destArr->getId(); } + auto* destArr = Float64Array::CreateWithStore(m_TempDataStructure, scratchName, tupleShape, compShape); + ExecuteDataFunction(CopyToFloat64Functor{}, sourceArray.getDataType(), sourceArray, *destArr); + return destArr->getId(); } From f0aa18cce02b66cc6e9605c46e048da74f4e34af Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Tue, 7 Apr 2026 17:39:27 -0400 Subject: [PATCH 15/19] Cleanup: Removes unused files, adds cancel check. --- .../Filters/Algorithms/ArrayCalculator.cpp | 9 +- .../Filters/Algorithms/ArrayCalculator.hpp | 3 +- .../Filters/ArrayCalculatorFilter.cpp | 3 +- .../src/SimplnxCore/utils/ABSOperator.cpp | 32 --- .../src/SimplnxCore/utils/ABSOperator.hpp | 41 --- .../src/SimplnxCore/utils/ACosOperator.cpp | 32 --- .../src/SimplnxCore/utils/ACosOperator.hpp | 41 --- .../src/SimplnxCore/utils/ASinOperator.cpp | 32 --- .../src/SimplnxCore/utils/ASinOperator.hpp | 42 --- .../src/SimplnxCore/utils/ATanOperator.cpp | 32 --- .../src/SimplnxCore/utils/ATanOperator.hpp | 42 --- .../SimplnxCore/utils/AdditionOperator.cpp | 32 --- .../SimplnxCore/utils/AdditionOperator.hpp | 42 --- .../src/SimplnxCore/utils/BinaryOperator.cpp | 61 ---- .../src/SimplnxCore/utils/BinaryOperator.hpp | 44 --- .../SimplnxCore/utils/CalculatorOperator.cpp | 140 --------- .../SimplnxCore/utils/CalculatorOperator.hpp | 77 ----- .../src/SimplnxCore/utils/CeilOperator.cpp | 32 --- .../src/SimplnxCore/utils/CeilOperator.hpp | 40 --- .../src/SimplnxCore/utils/CommaSeparator.cpp | 49 ---- .../src/SimplnxCore/utils/CommaSeparator.hpp | 38 --- .../src/SimplnxCore/utils/CosOperator.cpp | 32 --- .../src/SimplnxCore/utils/CosOperator.hpp | 40 --- .../SimplnxCore/utils/DivisionOperator.cpp | 31 -- .../SimplnxCore/utils/DivisionOperator.hpp | 38 --- .../src/SimplnxCore/utils/ExpOperator.cpp | 32 --- .../src/SimplnxCore/utils/ExpOperator.hpp | 40 --- .../src/SimplnxCore/utils/FloorOperator.cpp | 32 --- .../src/SimplnxCore/utils/FloorOperator.hpp | 40 --- .../src/SimplnxCore/utils/LnOperator.cpp | 32 --- .../src/SimplnxCore/utils/LnOperator.hpp | 40 --- .../src/SimplnxCore/utils/Log10Operator.cpp | 32 --- .../src/SimplnxCore/utils/Log10Operator.hpp | 41 --- .../src/SimplnxCore/utils/LogOperator.cpp | 40 --- .../src/SimplnxCore/utils/LogOperator.hpp | 42 --- .../src/SimplnxCore/utils/MaxOperator.cpp | 33 --- .../src/SimplnxCore/utils/MaxOperator.hpp | 40 --- .../src/SimplnxCore/utils/MinOperator.cpp | 33 --- .../src/SimplnxCore/utils/MinOperator.hpp | 40 --- .../utils/MultiplicationOperator.cpp | 32 --- .../utils/MultiplicationOperator.hpp | 39 --- .../SimplnxCore/utils/NegativeOperator.cpp | 81 ------ .../SimplnxCore/utils/NegativeOperator.hpp | 41 --- .../src/SimplnxCore/utils/PowOperator.cpp | 32 --- .../src/SimplnxCore/utils/PowOperator.hpp | 41 --- .../src/SimplnxCore/utils/RootOperator.cpp | 32 --- .../src/SimplnxCore/utils/RootOperator.hpp | 41 --- .../src/SimplnxCore/utils/SinOperator.cpp | 32 --- .../src/SimplnxCore/utils/SinOperator.hpp | 41 --- .../src/SimplnxCore/utils/SqrtOperator.cpp | 32 --- .../src/SimplnxCore/utils/SqrtOperator.hpp | 41 --- .../SimplnxCore/utils/SubtractionOperator.cpp | 32 --- .../SimplnxCore/utils/SubtractionOperator.hpp | 39 --- .../src/SimplnxCore/utils/TanOperator.cpp | 32 --- .../src/SimplnxCore/utils/TanOperator.hpp | 41 --- .../src/SimplnxCore/utils/UnaryOperator.cpp | 265 ------------------ .../src/SimplnxCore/utils/UnaryOperator.hpp | 56 ---- 57 files changed, 11 insertions(+), 2461 deletions(-) delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp delete mode 100644 src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index eaffe994cf..19ced286db 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -302,11 +302,12 @@ const std::vector& nx::core::getOperatorRegistry() // --------------------------------------------------------------------------- // ArrayCalculatorParser // --------------------------------------------------------------------------- -ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight) +ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight, const std::atomic_bool& shouldCancel) : m_DataStructure(dataStructure) , m_SelectedGroupPath(selectedGroupPath) , m_InfixEquation(infixEquation) , m_IsPreflight(isPreflight) +, m_ShouldCancel(shouldCancel) { } @@ -1544,6 +1545,10 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const for(const auto& rpnItem : m_RpnItems) { + if(m_ShouldCancel) + { + return {}; + } switch(rpnItem.type) { case RpnItem::Type::Value: { @@ -1781,6 +1786,6 @@ const std::atomic_bool& ArrayCalculator::getCancel() // --------------------------------------------------------------------------- Result<> ArrayCalculator::operator()() { - ArrayCalculatorParser parser(m_DataStructure, m_InputValues->SelectedGroup, m_InputValues->InfixEquation, false); + ArrayCalculatorParser parser(m_DataStructure, m_InputValues->SelectedGroup, m_InputValues->InfixEquation, false, m_ShouldCancel); return parser.evaluateInto(m_DataStructure, m_InputValues->CalculatedArray, m_InputValues->ScalarType, m_InputValues->Units); } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp index 31fac64fab..61def9b296 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp @@ -188,7 +188,7 @@ struct SIMPLNXCORE_EXPORT ArrayCalculatorInputValues class SIMPLNXCORE_EXPORT ArrayCalculatorParser { public: - ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight); + ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight, const std::atomic_bool& shouldCancel); ~ArrayCalculatorParser() noexcept = default; ArrayCalculatorParser(const ArrayCalculatorParser&) = delete; @@ -261,6 +261,7 @@ class SIMPLNXCORE_EXPORT ArrayCalculatorParser // Shape info determined during validation std::vector m_ParsedTupleShape; std::vector m_ParsedComponentShape; + const std::atomic_bool& m_ShouldCancel; }; // --------------------------------------------------------------------------- diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp index c0d7a49f71..226d62e732 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp @@ -84,7 +84,8 @@ IFilter::PreflightResult ArrayCalculatorFilter::preflightImpl(const DataStructur nx::core::Result resultOutputActions; // Parse and validate the expression - ArrayCalculatorParser parser(dataStructure, pInfixEquationValue.m_SelectedGroup, pInfixEquationValue.m_Equation, true); + const std::atomic_bool m_ShouldCancel(false); + ArrayCalculatorParser parser(dataStructure, pInfixEquationValue.m_SelectedGroup, pInfixEquationValue.m_Equation, true, m_ShouldCancel); std::vector calculatedTupleShape; std::vector calculatedComponentShape; Result<> parseResult = parser.parseAndValidate(calculatedTupleShape, calculatedComponentShape); diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp deleted file mode 100644 index 41b5b3bd31..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ABSOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ABSOperator::ABSOperator() -{ - setNumberOfArguments(1); - setInfixToken("abs"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ABSOperator::~ABSOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ABSOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return fabs(num); }); -} - -// ----------------------------------------------------------------------------- -ABSOperator::Pointer ABSOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp deleted file mode 100644 index 1048bb44db..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ABSOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ABSOperator : public UnaryOperator -{ -public: - using Self = ABSOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ABSOperator()); - } - - ~ABSOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ABSOperator(); - -public: - ABSOperator(const ABSOperator&) = delete; // Copy Constructor Not Implemented - ABSOperator(ABSOperator&&) = delete; // Move Constructor Not Implemented - ABSOperator& operator=(const ABSOperator&) = delete; // Copy Assignment Not Implemented - ABSOperator& operator=(ABSOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp deleted file mode 100644 index 0cd8872ba1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ACosOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ACosOperator::ACosOperator() -{ - setNumberOfArguments(1); - setInfixToken("acos"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ACosOperator::~ACosOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ACosOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return acos(num); }); -} - -// ----------------------------------------------------------------------------- -ACosOperator::Pointer ACosOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp deleted file mode 100644 index 89e7a3e554..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ACosOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ACosOperator : public UnaryOperator -{ -public: - using Self = ACosOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ACosOperator()); - } - - ~ACosOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ACosOperator(); - -public: - ACosOperator(const ACosOperator&) = delete; // Copy Constructor Not Implemented - ACosOperator(ACosOperator&&) = delete; // Move Constructor Not Implemented - ACosOperator& operator=(const ACosOperator&) = delete; // Copy Assignment Not Implemented - ACosOperator& operator=(ACosOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp deleted file mode 100644 index 924e62d393..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ASinOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ASinOperator::ASinOperator() -{ - setNumberOfArguments(1); - setInfixToken("asin"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ASinOperator::~ASinOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ASinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return asin(num); }); -} - -// ----------------------------------------------------------------------------- -ASinOperator::Pointer ASinOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp deleted file mode 100644 index 869dc07c9c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ASinOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ - -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ASinOperator : public UnaryOperator -{ -public: - using Self = ASinOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ASinOperator()); - } - - ~ASinOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ASinOperator(); - -public: - ASinOperator(const ASinOperator&) = delete; // Copy Constructor Not Implemented - ASinOperator(ASinOperator&&) = delete; // Move Constructor Not Implemented - ASinOperator& operator=(const ASinOperator&) = delete; // Copy Assignment Not Implemented - ASinOperator& operator=(ASinOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp deleted file mode 100644 index 29e9dc8bd4..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ATanOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ATanOperator::ATanOperator() -{ - setNumberOfArguments(1); - setInfixToken("atan"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ATanOperator::~ATanOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ATanOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayArcTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return atan(num); }); -} - -// ----------------------------------------------------------------------------- -ATanOperator::Pointer ATanOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp deleted file mode 100644 index 71690e142f..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ATanOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ - -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ATanOperator : public UnaryOperator -{ -public: - using Self = ATanOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ATanOperator()); - } - - ~ATanOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ATanOperator(); - -public: - ATanOperator(const ATanOperator&) = delete; // Copy Constructor Not Implemented - ATanOperator(ATanOperator&&) = delete; // Move Constructor Not Implemented - ATanOperator& operator=(const ATanOperator&) = delete; // Copy Assignment Not Implemented - ATanOperator& operator=(ATanOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core \ No newline at end of file diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp deleted file mode 100644 index 759f0fafc6..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/AdditionOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -AdditionOperator::AdditionOperator() -{ - setPrecedence(A_Precedence); - setInfixToken("+"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -AdditionOperator::~AdditionOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void AdditionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 + num2; }); -} - -// ----------------------------------------------------------------------------- -AdditionOperator::Pointer AdditionOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp deleted file mode 100644 index 63ebf83833..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/AdditionOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ - -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT AdditionOperator : public BinaryOperator -{ -public: - using Self = AdditionOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new AdditionOperator()); - } - - ~AdditionOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - AdditionOperator(); - -public: - AdditionOperator(const AdditionOperator&) = delete; // Copy Constructor Not Implemented - AdditionOperator(AdditionOperator&&) = delete; // Move Constructor Not Implemented - AdditionOperator& operator=(const AdditionOperator&) = delete; // Copy Assignment Not Implemented - AdditionOperator& operator=(AdditionOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp deleted file mode 100644 index fde52052c1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "SimplnxCore/utils/BinaryOperator.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" -#include "SimplnxCore/utils/RightParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -BinaryOperator::BinaryOperator() -{ - setOperatorType(Binary); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -BinaryOperator::~BinaryOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void BinaryOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - // This should never be executed -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode BinaryOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - int leftValue = currentIndex - 1; - int rightValue = currentIndex + 1; - - // Check that there is a valid value to the left of the operator - if(leftValue < 0 || - (nullptr != std::dynamic_pointer_cast(infixVector[leftValue]) && std::dynamic_pointer_cast(infixVector[leftValue])->getOperatorType() == Binary) || - nullptr != std::dynamic_pointer_cast(infixVector[leftValue])) - { - errMsg = fmt::format("The operator '{}' does not have a valid 'left' value.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoLeftValue; - } - - // Check that there is a valid value to the right of the operator - if(rightValue > infixVector.size() - 1 || - (nullptr != std::dynamic_pointer_cast(infixVector[rightValue]) && std::dynamic_pointer_cast(infixVector[rightValue])->getOperatorType() == Binary) || - nullptr != std::dynamic_pointer_cast(infixVector[rightValue])) - { - errMsg = fmt::format("The operator '{}' does not have a valid 'right' value.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoRightValue; - } - - return CalculatorItem::ErrorCode::Success; -} - -// ----------------------------------------------------------------------------- -BinaryOperator::Pointer BinaryOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp deleted file mode 100644 index 8f8b1fe93a..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/BinaryOperator.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "SimplnxCore/utils/CalculatorOperator.hpp" - -#include "simplnx/DataStructure/DataPath.hpp" - -#include -#include - -namespace nx::core -{ - -class SIMPLNXCORE_EXPORT BinaryOperator : public CalculatorOperator -{ -public: - using Self = BinaryOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new BinaryOperator()); - } - - ~BinaryOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) final; - -protected: - BinaryOperator(); - -public: - BinaryOperator(const BinaryOperator&) = delete; // Copy Constructor Not Implemented - BinaryOperator(BinaryOperator&&) = delete; // Move Constructor Not Implemented - BinaryOperator& operator=(const BinaryOperator&) = delete; // Copy Assignment Not Implemented - BinaryOperator& operator=(BinaryOperator&&) = delete; // Move Assignment Not Implemented -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp deleted file mode 100644 index b2b74d0100..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "SimplnxCore/utils/CalculatorOperator.hpp" - -#include "simplnx/Common/Numbers.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::CalculatorOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::~CalculatorOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -bool CalculatorOperator::hasHigherPrecedence(const CalculatorOperator::Pointer other) -{ - return m_Precedence > other->m_Precedence; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::Precedence CalculatorOperator::getPrecedence() -{ - return m_Precedence; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CalculatorOperator::setPrecedence(Precedence precedence) -{ - m_Precedence = precedence; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorOperator::OperatorType CalculatorOperator::getOperatorType() -{ - return m_OperatorType; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CalculatorOperator::setOperatorType(OperatorType type) -{ - m_OperatorType = type; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double CalculatorOperator::toDegrees(double radians) -{ - return radians * (180.0 / numbers::pi); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double CalculatorOperator::toRadians(double degrees) -{ - return degrees * (numbers::pi / 180.0); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double CalculatorOperator::root(double base, double root) -{ - if(root == 0) - { - return std::numeric_limits::infinity(); - } - - return pow(base, 1 / root); -} - -// ----------------------------------------------------------------------------- -CalculatorOperator::Pointer CalculatorOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} - -// ----------------------------------------------------------------------------- -void CalculatorOperator::CreateNewArrayTwoArguments(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, - std::stack& executionStack, std::function op) -{ - ICalculatorArray::Pointer iArray1 = executionStack.top(); - if(executionStack.size() >= 2 && nullptr != iArray1) - { - executionStack.pop(); - ICalculatorArray::Pointer iArray2 = executionStack.top(); - executionStack.pop(); - - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array1 = iArray1->getArray(); - DataArray* array2 = iArray2->getArray(); - - Float64Array* newArray = nullptr; - if(iArray1->getType() == ICalculatorArray::Array) - { - newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array1->getTupleShape(), array1->getComponentShape()); - } - else - { - newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array2->getTupleShape(), array2->getComponentShape()); - } - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - float64 num1 = (iArray1->getType() == ICalculatorArray::Array) ? array1->getValue(index) : array1->getValue(0); - float64 num2 = (iArray2->getType() == ICalculatorArray::Array) ? array2->getValue(index) : array2->getValue(0); - (*newArray)[index] = op(num2, num1); - } - } - - if(iArray1->getType() == ICalculatorArray::Array || iArray2->getType() == ICalculatorArray::Array) - { - executionStack.push(CalculatorArray::New(dataStructure, newArray, ICalculatorArray::Array, true)); - } - else - { - executionStack.push(CalculatorArray::New(dataStructure, newArray, ICalculatorArray::Number, true)); - } - return; - } -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp deleted file mode 100644 index 21b1f4db31..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CalculatorOperator.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -#include "simplnx/DataStructure/DataArray.hpp" -#include "simplnx/DataStructure/DataPath.hpp" -#include "simplnx/Parameters/CalculatorParameter.hpp" - -#include -#include - -namespace nx::core -{ - -class SIMPLNXCORE_EXPORT CalculatorOperator : public CalculatorItem -{ -public: - enum OperatorType - { - Unary, - Binary - }; - - using Self = CalculatorOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static double toDegrees(double radians); - static double toRadians(double degrees); - - ~CalculatorOperator() override; - - bool hasHigherPrecedence(CalculatorOperator::Pointer other); - - virtual void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) = 0; - - OperatorType getOperatorType(); - -protected: - CalculatorOperator(); - - enum Precedence - { - Unknown_Precedence, - A_Precedence, - B_Precedence, - C_Precedence, - D_Precedence, - E_Precedence - }; - - double root(double base, double root); - - Precedence getPrecedence(); - void setPrecedence(Precedence precedence); - - void setOperatorType(OperatorType type); - -private: - Precedence m_Precedence = {Unknown_Precedence}; - OperatorType m_OperatorType; - -public: - CalculatorOperator(const CalculatorOperator&) = delete; // Copy Constructor Not Implemented - CalculatorOperator(CalculatorOperator&&) = delete; // Move Constructor Not Implemented - CalculatorOperator& operator=(const CalculatorOperator&) = delete; // Copy Assignment Not Implemented - CalculatorOperator& operator=(CalculatorOperator&&) = delete; // Move Assignment Not Implemented - - static void CreateNewArrayTwoArguments(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp deleted file mode 100644 index c06d6ed3b7..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/CeilOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CeilOperator::CeilOperator() -{ - setNumberOfArguments(1); - setInfixToken("ceil"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CeilOperator::~CeilOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CeilOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return ceil(num); }); -} - -// ----------------------------------------------------------------------------- -CeilOperator::Pointer CeilOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp deleted file mode 100644 index 3e46d8df8c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CeilOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT CeilOperator : public UnaryOperator -{ -public: - using Self = CeilOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new CeilOperator()); - } - - ~CeilOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - CeilOperator(); - -public: - CeilOperator(const CeilOperator&) = delete; // Copy Constructor Not Implemented - CeilOperator(CeilOperator&&) = delete; // Move Constructor Not Implemented - CeilOperator& operator=(const CeilOperator&) = delete; // Copy Assignment Not Implemented - CeilOperator& operator=(CeilOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp deleted file mode 100644 index 57bb32cc06..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "SimplnxCore/utils/CommaSeparator.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CommaSeparator::CommaSeparator() -{ - setInfixToken(","); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CommaSeparator::~CommaSeparator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode CommaSeparator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - // Make sure that this comma has a valid 2-argument unary operator before it - bool foundUnaryOperator = false; - for(int i = currentIndex - 1; i >= 0; i--) - { - CalculatorItem::Pointer item = infixVector[i]; - UnaryOperator::Pointer unary = std::dynamic_pointer_cast(item); - if(unary != UnaryOperator::NullPointer() && unary->getNumberOfArguments() == 2) - { - foundUnaryOperator = true; - } - } - - if(!foundUnaryOperator) - { - errMsg = "A comma in the expression does not have a corresponding operator preceding it."; - return CalculatorItem::ErrorCode::NoPrecedingUnaryOperator; - } - - return CalculatorItem::ErrorCode::Success; -} - -// ----------------------------------------------------------------------------- -CommaSeparator::Pointer CommaSeparator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp deleted file mode 100644 index c58deb63f4..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CommaSeparator.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/CalculatorSeparator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT CommaSeparator : public CalculatorSeparator -{ -public: - using Self = CommaSeparator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new CommaSeparator()); - } - - ~CommaSeparator() override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) override; - -protected: - CommaSeparator(); - -public: - CommaSeparator(const CommaSeparator&) = delete; // Copy Constructor Not Implemented - CommaSeparator(CommaSeparator&&) = delete; // Move Constructor Not Implemented - CommaSeparator& operator=(const CommaSeparator&) = delete; // Copy Assignment Not Implemented - CommaSeparator& operator=(CommaSeparator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp deleted file mode 100644 index 9638355e80..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/CosOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CosOperator::CosOperator() -{ - setNumberOfArguments(1); - setInfixToken("cos"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CosOperator::~CosOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void CosOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return cos(num); }); -} - -// ----------------------------------------------------------------------------- -CosOperator::Pointer CosOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp deleted file mode 100644 index 4f94fcf2a7..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/CosOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT CosOperator : public UnaryOperator -{ -public: - using Self = CosOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new CosOperator()); - } - - ~CosOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - CosOperator(); - -public: - CosOperator(const CosOperator&) = delete; // Copy Constructor Not Implemented - CosOperator(CosOperator&&) = delete; // Move Constructor Not Implemented - CosOperator& operator=(const CosOperator&) = delete; // Copy Assignment Not Implemented - CosOperator& operator=(CosOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp deleted file mode 100644 index 682d3b1333..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "SimplnxCore/utils/DivisionOperator.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -DivisionOperator::DivisionOperator() -{ - setPrecedence(B_Precedence); - setInfixToken("/"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -DivisionOperator::~DivisionOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void DivisionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 / num2; }); -} - -// ----------------------------------------------------------------------------- -DivisionOperator::Pointer DivisionOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp deleted file mode 100644 index d9256a6793..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/DivisionOperator.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT DivisionOperator : public BinaryOperator -{ -public: - using Self = DivisionOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new DivisionOperator()); - } - - ~DivisionOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - DivisionOperator(); - -public: - DivisionOperator(const DivisionOperator&) = delete; // Copy Constructor Not Implemented - DivisionOperator(DivisionOperator&&) = delete; // Move Constructor Not Implemented - DivisionOperator& operator=(const DivisionOperator&) = delete; // Copy Assignment Not Implemented - DivisionOperator& operator=(DivisionOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp deleted file mode 100644 index 216c202041..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/ExpOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ExpOperator::ExpOperator() -{ - setNumberOfArguments(1); - setInfixToken("exp"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -ExpOperator::~ExpOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void ExpOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return exp(num); }); -} - -// ----------------------------------------------------------------------------- -ExpOperator::Pointer ExpOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp deleted file mode 100644 index 73d718e92c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/ExpOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT ExpOperator : public UnaryOperator -{ -public: - using Self = ExpOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new ExpOperator()); - } - - ~ExpOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - ExpOperator(); - -public: - ExpOperator(const ExpOperator&) = delete; // Copy Constructor Not Implemented - ExpOperator(ExpOperator&&) = delete; // Move Constructor Not Implemented - ExpOperator& operator=(const ExpOperator&) = delete; // Copy Assignment Not Implemented - ExpOperator& operator=(ExpOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp deleted file mode 100644 index 6b6680f757..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/FloorOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -FloorOperator::FloorOperator() -{ - setNumberOfArguments(1); - setInfixToken("floor"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -FloorOperator::~FloorOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void FloorOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return floor(num); }); -} - -// ----------------------------------------------------------------------------- -FloorOperator::Pointer FloorOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp deleted file mode 100644 index 93e935af96..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/FloorOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT FloorOperator : public UnaryOperator -{ -public: - using Self = FloorOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new FloorOperator()); - } - - ~FloorOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - FloorOperator(); - -public: - FloorOperator(const FloorOperator&) = delete; // Copy Constructor Not Implemented - FloorOperator(FloorOperator&&) = delete; // Move Constructor Not Implemented - FloorOperator& operator=(const FloorOperator&) = delete; // Copy Assignment Not Implemented - FloorOperator& operator=(FloorOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp deleted file mode 100644 index 473c654367..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/LnOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LnOperator::LnOperator() -{ - setNumberOfArguments(1); - setInfixToken("ln"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LnOperator::~LnOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void LnOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return log(num); }); -} - -// ----------------------------------------------------------------------------- -LnOperator::Pointer LnOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp deleted file mode 100644 index 992985eb04..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LnOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT LnOperator : public UnaryOperator -{ -public: - using Self = LnOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new LnOperator()); - } - - ~LnOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - LnOperator(); - -public: - LnOperator(const LnOperator&) = delete; // Copy Constructor Not Implemented - LnOperator(LnOperator&&) = delete; // Move Constructor Not Implemented - LnOperator& operator=(const LnOperator&) = delete; // Copy Assignment Not Implemented - LnOperator& operator=(LnOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp deleted file mode 100644 index 64413029e6..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/Log10Operator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -Log10Operator::Log10Operator() -{ - setNumberOfArguments(1); - setInfixToken("log10"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -Log10Operator::~Log10Operator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void Log10Operator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return log10(num); }); -} - -// ----------------------------------------------------------------------------- -Log10Operator::Pointer Log10Operator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp deleted file mode 100644 index ab053ffa10..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/Log10Operator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT Log10Operator : public UnaryOperator -{ -public: - using Self = Log10Operator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new Log10Operator()); - } - - ~Log10Operator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - Log10Operator(); - -public: - Log10Operator(const Log10Operator&) = delete; // Copy Constructor Not Implemented - Log10Operator(Log10Operator&&) = delete; // Move Constructor Not Implemented - Log10Operator& operator=(const Log10Operator&) = delete; // Copy Assignment Not Implemented - Log10Operator& operator=(Log10Operator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp deleted file mode 100644 index 3d2ed4d006..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "SimplnxCore/utils/LogOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LogOperator::LogOperator() -{ - setNumberOfArguments(2); - setInfixToken("log"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -LogOperator::~LogOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void LogOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [this](double num1, double num2) -> double { return log_arbitrary_base(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -double LogOperator::log_arbitrary_base(double base, double value) -{ - return log(value) / log(base); -} - -// ----------------------------------------------------------------------------- -LogOperator::Pointer LogOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp deleted file mode 100644 index 9409f158f7..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/LogOperator.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT LogOperator : public UnaryOperator -{ -public: - using Self = LogOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new LogOperator()); - } - - ~LogOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - LogOperator(); - -private: - double log_arbitrary_base(double base, double value); - -public: - LogOperator(const LogOperator&) = delete; // Copy Constructor Not Implemented - LogOperator(LogOperator&&) = delete; // Move Constructor Not Implemented - LogOperator& operator=(const LogOperator&) = delete; // Copy Assignment Not Implemented - LogOperator& operator=(LogOperator&&) = delete; // Move Assignment Not Implemented -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp deleted file mode 100644 index 3e230d9d9c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "SimplnxCore/utils/MaxOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; -using namespace std; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MaxOperator::MaxOperator() -{ - setNumberOfArguments(2); - setInfixToken("max"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MaxOperator::~MaxOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void MaxOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return max(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -MaxOperator::Pointer MaxOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp deleted file mode 100644 index 0b7431f91c..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MaxOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT MaxOperator : public UnaryOperator -{ -public: - using Self = MaxOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new MaxOperator()); - } - - ~MaxOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - MaxOperator(); - -public: - MaxOperator(const MaxOperator&) = delete; // Copy Constructor Not Implemented - MaxOperator(MaxOperator&&) = delete; // Move Constructor Not Implemented - MaxOperator& operator=(const MaxOperator&) = delete; // Copy Assignment Not Implemented - MaxOperator& operator=(MaxOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp deleted file mode 100644 index f6221cd6c4..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "SimplnxCore/utils/MinOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; -using namespace std; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MinOperator::MinOperator() -{ - setNumberOfArguments(2); - setInfixToken("min"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MinOperator::~MinOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void MinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return min(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -MinOperator::Pointer MinOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp deleted file mode 100644 index 15ff177642..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MinOperator.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT MinOperator : public UnaryOperator -{ -public: - using Self = MinOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new MinOperator()); - } - - ~MinOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - MinOperator(); - -public: - MinOperator(const MinOperator&) = delete; // Copy Constructor Not Implemented - MinOperator(MinOperator&&) = delete; // Move Constructor Not Implemented - MinOperator& operator=(const MinOperator&) = delete; // Copy Assignment Not Implemented - MinOperator& operator=(MinOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp deleted file mode 100644 index dc9bf707de..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/MultiplicationOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MultiplicationOperator::MultiplicationOperator() -{ - setPrecedence(B_Precedence); - setInfixToken("*"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -MultiplicationOperator::~MultiplicationOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void MultiplicationOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 * num2; }); -} - -// ----------------------------------------------------------------------------- -MultiplicationOperator::Pointer MultiplicationOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp deleted file mode 100644 index 1d32db39af..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/MultiplicationOperator.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT MultiplicationOperator : public BinaryOperator -{ -public: - using Self = MultiplicationOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new MultiplicationOperator()); - } - - ~MultiplicationOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - MultiplicationOperator(); - -public: - MultiplicationOperator(const MultiplicationOperator&) = delete; // Copy Constructor Not Implemented - MultiplicationOperator(MultiplicationOperator&&) = delete; // Move Constructor Not Implemented - MultiplicationOperator& operator=(const MultiplicationOperator&) = delete; // Copy Assignment Not Implemented - MultiplicationOperator& operator=(MultiplicationOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp deleted file mode 100644 index ddf23f2a95..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "SimplnxCore/utils/NegativeOperator.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -NegativeOperator::NegativeOperator() -{ - setOperatorType(Unary); - setPrecedence(D_Precedence); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -NegativeOperator::~NegativeOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void NegativeOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - if(!executionStack.empty()) - { - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array = arrayPtr->getArray(); - - Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = array->getValue(index); - (*newArray)[index] = -1 * num; - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode NegativeOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - if(currentIndex - 1 >= 0 && (std::dynamic_pointer_cast(infixVector[currentIndex - 1]) == BinaryOperator::NullPointer() && - std::dynamic_pointer_cast(infixVector[currentIndex - 1]) == LeftParenthesisItem::NullPointer())) - { - // The symbol to the left of the negative sign is not a binary operator or left parenthesis - errMsg = fmt::format("The negative operator '{}' does not have a valid 'left' value.", getInfixToken()); - return NegativeOperator::ErrorCode::OperatorNoLeftValue; - } - if(currentIndex + 1 >= infixVector.size() || (currentIndex + 1 < infixVector.size() && (nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1]) && - nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1]) && - nullptr == std::dynamic_pointer_cast(infixVector[currentIndex + 1])))) - { - // The symbol to the right of the negative sign is not an array, left parenthesis, or unary operator - errMsg = fmt::format("The negative operator '{}' does not have a valid 'right' value.", getInfixToken()); - return NegativeOperator::ErrorCode::OperatorNoRightValue; - } - - return NegativeOperator::ErrorCode::Success; -} - -// ----------------------------------------------------------------------------- -NegativeOperator::Pointer NegativeOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp deleted file mode 100644 index d0d7419e2f..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/NegativeOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT NegativeOperator : public CalculatorOperator -{ -public: - using Self = NegativeOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new NegativeOperator()); - } - - ~NegativeOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) final; - -protected: - NegativeOperator(); - -public: - NegativeOperator(const NegativeOperator&) = delete; // Copy Constructor Not Implemented - NegativeOperator(NegativeOperator&&) = delete; // Move Constructor Not Implemented - NegativeOperator& operator=(const NegativeOperator&) = delete; // Copy Assignment Not Implemented - NegativeOperator& operator=(NegativeOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp deleted file mode 100644 index 3a6f96cacf..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/PowOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -PowOperator::PowOperator() -{ - setPrecedence(C_Precedence); - setInfixToken("^"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -PowOperator::~PowOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void PowOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return pow(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -PowOperator::Pointer PowOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp deleted file mode 100644 index f9d89aa0ec..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/PowOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT PowOperator : public BinaryOperator -{ -public: - using Self = PowOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new PowOperator()); - } - - ~PowOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - PowOperator(); - -public: - PowOperator(const PowOperator&) = delete; // Copy Constructor Not Implemented - PowOperator(PowOperator&&) = delete; // Move Constructor Not Implemented - PowOperator& operator=(const PowOperator&) = delete; // Copy Assignment Not Implemented - PowOperator& operator=(PowOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp deleted file mode 100644 index cf56bbfc4b..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/RootOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -RootOperator::RootOperator() -{ - setNumberOfArguments(2); - setInfixToken("root"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -RootOperator::~RootOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void RootOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [this](double num1, double num2) -> double { return root(num1, num2); }); -} - -// ----------------------------------------------------------------------------- -RootOperator::Pointer RootOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp deleted file mode 100644 index 58b0868bd9..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/RootOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT RootOperator : public UnaryOperator -{ -public: - using Self = RootOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new RootOperator()); - } - - ~RootOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - RootOperator(); - -public: - RootOperator(const RootOperator&) = delete; // Copy Constructor Not Implemented - RootOperator(RootOperator&&) = delete; // Move Constructor Not Implemented - RootOperator& operator=(const RootOperator&) = delete; // Copy Assignment Not Implemented - RootOperator& operator=(RootOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp deleted file mode 100644 index 9484b3ce3e..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/SinOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SinOperator::SinOperator() -{ - setNumberOfArguments(1); - setInfixToken("sin"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SinOperator::~SinOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void SinOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return sin(num); }); -} - -// ----------------------------------------------------------------------------- -SinOperator::Pointer SinOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp deleted file mode 100644 index c8e8d57cf1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SinOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT SinOperator : public UnaryOperator -{ -public: - using Self = SinOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new SinOperator()); - } - - ~SinOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - SinOperator(); - -public: - SinOperator(const SinOperator&) = delete; // Copy Constructor Not Implemented - SinOperator(SinOperator&&) = delete; // Move Constructor Not Implemented - SinOperator& operator=(const SinOperator&) = delete; // Copy Assignment Not Implemented - SinOperator& operator=(SinOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp deleted file mode 100644 index 02d17072b1..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/SqrtOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SqrtOperator::SqrtOperator() -{ - setNumberOfArguments(1); - setInfixToken("sqrt"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SqrtOperator::~SqrtOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void SqrtOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayStandardUnary(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return sqrt(num); }); -} - -// ----------------------------------------------------------------------------- -SqrtOperator::Pointer SqrtOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp deleted file mode 100644 index 46a174f6f0..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SqrtOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT SqrtOperator : public UnaryOperator -{ -public: - using Self = SqrtOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new SqrtOperator()); - } - - ~SqrtOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - SqrtOperator(); - -public: - SqrtOperator(const SqrtOperator&) = delete; // Copy Constructor Not Implemented - SqrtOperator(SqrtOperator&&) = delete; // Move Constructor Not Implemented - SqrtOperator& operator=(const SqrtOperator&) = delete; // Copy Assignment Not Implemented - SqrtOperator& operator=(SqrtOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp deleted file mode 100644 index 6110ce750f..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/SubtractionOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SubtractionOperator::SubtractionOperator() -{ - setPrecedence(A_Precedence); - setInfixToken("-"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -SubtractionOperator::~SubtractionOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void SubtractionOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTwoArguments(dataStructure, units, calculatedArrayPath, executionStack, [](double num1, double num2) -> double { return num1 - num2; }); -} - -// ----------------------------------------------------------------------------- -SubtractionOperator::Pointer SubtractionOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp deleted file mode 100644 index 80b196435e..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/SubtractionOperator.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT SubtractionOperator : public BinaryOperator -{ -public: - using Self = SubtractionOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new SubtractionOperator()); - } - - ~SubtractionOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - SubtractionOperator(); - -public: - SubtractionOperator(const SubtractionOperator&) = delete; // Copy Constructor Not Implemented - SubtractionOperator(SubtractionOperator&&) = delete; // Move Constructor Not Implemented - SubtractionOperator& operator=(const SubtractionOperator&) = delete; // Copy Assignment Not Implemented - SubtractionOperator& operator=(SubtractionOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp deleted file mode 100644 index e39d1a2d44..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "SimplnxCore/utils/TanOperator.hpp" -#include "SimplnxCore/utils/CalculatorArray.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -TanOperator::TanOperator() -{ - setNumberOfArguments(1); - setInfixToken("tan"); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -TanOperator::~TanOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void TanOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - CreateNewArrayTrig(dataStructure, units, calculatedArrayPath, executionStack, [](double num) -> double { return tan(num); }); -} - -// ----------------------------------------------------------------------------- -TanOperator::Pointer TanOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp deleted file mode 100644 index 5ce8a5ca83..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/TanOperator.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "SimplnxCore/SimplnxCore_export.hpp" -#include "SimplnxCore/utils/UnaryOperator.hpp" - -namespace nx::core -{ -class CalculatorNumber; - -class SIMPLNXCORE_EXPORT TanOperator : public UnaryOperator -{ -public: - using Self = TanOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new TanOperator()); - } - - ~TanOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - -protected: - TanOperator(); - -public: - TanOperator(const TanOperator&) = delete; // Copy Constructor Not Implemented - TanOperator(TanOperator&&) = delete; // Move Constructor Not Implemented - TanOperator& operator=(const TanOperator&) = delete; // Copy Assignment Not Implemented - TanOperator& operator=(TanOperator&&) = delete; // Move Assignment Not Implemented - -private: -}; - -} // namespace nx::core diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp deleted file mode 100644 index 61cf7c7c99..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.cpp +++ /dev/null @@ -1,265 +0,0 @@ -#include "UnaryOperator.hpp" - -#include "SimplnxCore/Filters/ArrayCalculatorFilter.hpp" -#include "SimplnxCore/utils/BinaryOperator.hpp" -#include "SimplnxCore/utils/CommaSeparator.hpp" -#include "SimplnxCore/utils/LeftParenthesisItem.hpp" -#include "SimplnxCore/utils/NegativeOperator.hpp" -#include "SimplnxCore/utils/RightParenthesisItem.hpp" - -using namespace nx::core; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -UnaryOperator::UnaryOperator() -: m_NumOfArguments(-1) -{ - setPrecedence(E_Precedence); - setOperatorType(Unary); -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -UnaryOperator::~UnaryOperator() = default; - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void UnaryOperator::calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) -{ - // This should never be executed -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -CalculatorItem::ErrorCode UnaryOperator::checkValidity(std::vector infixVector, int currentIndex, std::string& errMsg) -{ - if(currentIndex - 1 >= 0) - { - // If the left value isn't a binary operator - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - // If the left value isn't a left parenthesis - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - // If the left value isn't a negative operator - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - // If the left value isn't a comma - if(nullptr == std::dynamic_pointer_cast(infixVector[currentIndex - 1])) - { - errMsg = fmt::format("The operator '{}' does not have a valid 'left' value.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoLeftValue; - } - } - } - } - } - - int index = currentIndex + 1; - int commaCount = 0; - bool hasArray = false; - if(index < infixVector.size() && nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - index++; - - // Iterate through the vector to find the matching right parenthesis - for(; index < infixVector.size(); index++) - { - if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - // We found the matching right parenthesis - if(commaCount < m_NumOfArguments - 1) - { - errMsg = fmt::format("The operator '{}' needs {} arguments. {} arguments were found.", getInfixToken(), m_NumOfArguments, commaCount + 1); - return CalculatorItem::ErrorCode::NotEnoughArguments; - } - if(!hasArray) - { - errMsg = fmt::format("The operator '{}' does not have any arguments that simplify down to a number.", getInfixToken()); - return CalculatorItem::ErrorCode::NoNumericArguments; - } - - return CalculatorItem::ErrorCode::Success; - } - if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - /* We found another left parenthesis, but we don't care what's inside this set of parentheses - (other operators' checkValidity functions will take care of these values), so just iterate - until we find the matching closing parenthesis for this opening parenthesis */ - int extraLeftPCount = 0; - index++; - while(index < infixVector.size() && (nullptr == std::dynamic_pointer_cast(infixVector[index]) || extraLeftPCount > 0)) - { - if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - hasArray = true; - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - extraLeftPCount++; - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - extraLeftPCount--; - } - - index++; - } - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - // We found a comma, so increase the comma count - commaCount++; - if(commaCount > m_NumOfArguments - 1) - { - // We found too many commas (meaning that there are too many arguments), so return false - errMsg = fmt::format("The operator '{}' needs {} arguments. {} arguments were found.", getInfixToken(), m_NumOfArguments, commaCount + 1); - return CalculatorItem::ErrorCode::TooManyArguments; - } - } - else if(nullptr != std::dynamic_pointer_cast(infixVector[index])) - { - hasArray = true; - } - } - } - else - { - errMsg = fmt::format("The operator '{}' does not have an opening parenthesis.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoOpeningParen; - } - - errMsg = fmt::format("The operator '{}' does not have a closing parenthesis.", getInfixToken()); - return CalculatorItem::ErrorCode::OperatorNoClosingParen; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -int UnaryOperator::getNumberOfArguments() -{ - return m_NumOfArguments; -} - -// ----------------------------------------------------------------------------- -// -// ----------------------------------------------------------------------------- -void UnaryOperator::setNumberOfArguments(int numOfArguments) -{ - m_NumOfArguments = numOfArguments; -} - -// ----------------------------------------------------------------------------- -UnaryOperator::Pointer UnaryOperator::NullPointer() -{ - return Pointer(static_cast(nullptr)); -} - -// ----------------------------------------------------------------------------- -void UnaryOperator::CreateNewArrayStandardUnary(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, - std::stack& executionStack, std::function op) -{ - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - if(!executionStack.empty() && nullptr != arrayPtr) - { - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - Float64Array* newArray = - Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), arrayPtr->getArray()->getTupleShape(), arrayPtr->getArray()->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = arrayPtr->getValue(index); - (*newArray)[index] = op(num); - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} - -// ----------------------------------------------------------------------------- -void UnaryOperator::CreateNewArrayTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op) -{ - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - if(!executionStack.empty() && nullptr != arrayPtr) - { - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array = arrayPtr->getArray(); - - Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = array->getValue(index); - - if(units == CalculatorParameter::AngleUnits::Degrees) - { - (*newArray)[index] = op(toRadians(num)); - } - else - { - (*newArray)[index] = op(num); - } - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} - -// ----------------------------------------------------------------------------- -void UnaryOperator::CreateNewArrayArcTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op) -{ - ICalculatorArray::Pointer arrayPtr = executionStack.top(); - if(!executionStack.empty() && nullptr != arrayPtr) - { - executionStack.pop(); - calculatedArrayPath = GetUniquePathName(dataStructure, calculatedArrayPath); - - DataArray* array = arrayPtr->getArray(); - - Float64Array* newArray = Float64Array::CreateWithStore(dataStructure, calculatedArrayPath.getTargetName(), array->getTupleShape(), array->getComponentShape()); - - usize numComps = newArray->getNumberOfComponents(); - for(usize i = 0; i < newArray->getNumberOfTuples(); i++) - { - for(usize c = 0; c < newArray->getNumberOfComponents(); c++) - { - usize index = numComps * i + c; - double num = array->getValue(index); - - if(units == CalculatorParameter::AngleUnits::Degrees) - { - (*newArray)[index] = toDegrees(op(num)); - } - else - { - (*newArray)[index] = op(num); - } - } - } - - executionStack.push(CalculatorArray::New(dataStructure, newArray, arrayPtr->getType(), true)); - return; - } -} diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp deleted file mode 100644 index a3f49a08d8..0000000000 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/utils/UnaryOperator.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include "SimplnxCore/utils/CalculatorOperator.hpp" -#include "simplnx/DataStructure/DataPath.hpp" - -#include -#include - -namespace nx::core -{ -class SIMPLNXCORE_EXPORT UnaryOperator : public CalculatorOperator -{ -public: - using Self = UnaryOperator; - using Pointer = std::shared_ptr; - using ConstPointer = std::shared_ptr; - using WeakPointer = std::weak_ptr; - using ConstWeakPointer = std::weak_ptr; - static Pointer NullPointer(); - - static Pointer New() - { - return Pointer(new UnaryOperator()); - } - - ~UnaryOperator() override; - - void calculate(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack) override; - - CalculatorItem::ErrorCode checkValidity(std::vector infixVector, int currentIndex, std::string& msg) final; - - int getNumberOfArguments(); - -protected: - UnaryOperator(); - - void setNumberOfArguments(int numOfArguments); - -private: - int m_NumOfArguments; - -public: - UnaryOperator(const UnaryOperator&) = delete; // Copy Constructor Not Implemented - UnaryOperator(UnaryOperator&&) = delete; // Move Constructor Not Implemented - UnaryOperator& operator=(const UnaryOperator&) = delete; // Copy Assignment Not Implemented - UnaryOperator& operator=(UnaryOperator&&) = delete; // Move Assignment Not Implemented - - static void CreateNewArrayStandardUnary(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); - static void CreateNewArrayTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); - static void CreateNewArrayArcTrig(DataStructure& dataStructure, CalculatorParameter::AngleUnits units, DataPath calculatedArrayPath, std::stack& executionStack, - std::function op); -}; - -} // namespace nx::core From c04883eae116948c74f8c482f71fd3c007dbc7d2 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Tue, 7 Apr 2026 17:53:23 -0400 Subject: [PATCH 16/19] DOC: Add ArrayCalculator memory optimization design spec Specifies the CalcBuffer RAII sentinel pattern for eliminating unnecessary temp DataArray allocations in the ArrayCalculator evaluator. Co-Authored-By: Claude Opus 4.6 (1M context) --- ...aycalculator-memory-optimization-design.md | 289 ++++++++++++++++++ 1 file changed, 289 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-07-arraycalculator-memory-optimization-design.md diff --git a/docs/superpowers/specs/2026-04-07-arraycalculator-memory-optimization-design.md b/docs/superpowers/specs/2026-04-07-arraycalculator-memory-optimization-design.md new file mode 100644 index 0000000000..177fadb63f --- /dev/null +++ b/docs/superpowers/specs/2026-04-07-arraycalculator-memory-optimization-design.md @@ -0,0 +1,289 @@ +# ArrayCalculator Memory Optimization Design + +## Problem + +The ArrayCalculator evaluator allocates temporary `Float64Array` objects in a scratch `DataStructure` (`m_TempDataStructure`) for every input array, every intermediate result, and the final result. None of these temporaries are freed until the parser is destroyed. For a simple expression like `a + b` with float64 inputs and float64 output, this produces 4 array-sized allocations when 0 would suffice. + +For large datasets with complex expressions, this causes memory usage to explode: an expression with N operations on an array of M elements allocates O(N * M * 8) bytes of temporaries that all stay alive simultaneously. + +### Specific waste patterns + +1. **Input float64 arrays are copied into temp Float64Arrays** even though the data is already float64 — a full O(M) allocation + O(M) copy per input reference. +2. **Every intermediate result allocates a new Float64Array** in `m_TempDataStructure`. None are freed until the parser destructs. +3. **The final result is copied element-by-element** from the temp Float64Array into the output DataArray, even when the output type is float64 — an unnecessary O(M) allocation + O(M) copy. + +## Constraints + +- **`m_TempDataStructure` must be retained.** Temporary arrays must live inside a `DataStructure` because the `DataArray`/`DataStore` abstraction is load-bearing: the project is moving to an out-of-core `DataStore` implementation where data may not be resident in memory. Raw `std::vector` or `float64*` buffers cannot replace `DataArray`. +- **No raw pointer access to DataArray data.** All element reads/writes must go through `DataArray::at()` or `operator[]`. Never use `T*` pointers obtained from `DataStore::data()` or similar. +- **Memory optimization is the first priority.** CPU computation performance is the second priority. +- **Backward compatibility.** All existing tests must continue to pass. Error codes, parameter keys, and pipeline JSON formats are unchanged by this work. + +## Solution: CalcBuffer — RAII Sentinel for Temp DataArrays + +### Overview + +Introduce a `CalcBuffer` class: a move-only RAII handle that wraps a `Float64Array` (either a temp array in `m_TempDataStructure` or a borrowed reference to an input array in the real `DataStructure`). When an owned `CalcBuffer` is destroyed, it removes its `DataArray` from the `DataStructure` via `DataStructure::removeData(DataObject::IdType)`. + +The evaluation stack changes from `std::stack` (with manual ID lookups) to `std::stack` (with automatic RAII cleanup). Intermediates are freed the instant they are consumed by an operator. + +### CalcBuffer class + +```cpp +class SIMPLNXCORE_EXPORT CalcBuffer +{ +public: + // --- Factory methods --- + + // Zero-copy reference to an existing Float64Array. Read-only. Destructor: no-op. + static CalcBuffer borrow(const Float64Array& source); + + // Allocate a temp Float64Array in tempDS, convert source data from any numeric type. + // Owned. Destructor: removes from tempDS. + static CalcBuffer convertFrom(DataStructure& tempDS, const IDataArray& source, + const std::string& name); + + // Allocate a 1-element temp Float64Array with the given scalar value. + static CalcBuffer scalar(DataStructure& tempDS, double value, const std::string& name); + + // Allocate an empty temp Float64Array with the given shape. + static CalcBuffer allocate(DataStructure& tempDS, const std::string& name, + std::vector tupleShape, std::vector compShape); + + // Wrap the output DataArray for direct writing. Destructor: no-op. + static CalcBuffer wrapOutput(DataArray& outputArray); + + // --- Move-only, non-copyable --- + CalcBuffer(CalcBuffer&& other) noexcept; + CalcBuffer& operator=(CalcBuffer&& other) noexcept; + ~CalcBuffer(); + + CalcBuffer(const CalcBuffer&) = delete; + CalcBuffer& operator=(const CalcBuffer&) = delete; + + // --- Element access --- + float64 read(usize index) const; + void write(usize index, float64 value); + void fill(float64 value); + + // --- Metadata --- + usize size() const; + usize numTuples() const; + usize numComponents() const; + std::vector tupleShape() const; + std::vector compShape() const; + bool isScalar() const; + bool isOwned() const; + bool isOutputDirect() const; + + // --- Access underlying array (for final copy to non-float64 output) --- + const Float64Array& array() const; + +private: + CalcBuffer() = default; + + enum class Storage + { + Borrowed, // const Float64Array* in real DataStructure, read-only + Owned, // Float64Array in m_TempDataStructure, read-write, cleaned up on destroy + OutputDirect // DataArray* output array, read-write, NOT cleaned up + }; + + Storage m_Storage = Storage::Owned; + + // Borrowed + const Float64Array* m_BorrowedArray = nullptr; + + // Owned + DataStructure* m_TempDS = nullptr; + DataObject::IdType m_ArrayId = 0; + Float64Array* m_OwnedArray = nullptr; + + // OutputDirect + DataArray* m_OutputArray = nullptr; + + bool m_IsScalar = false; +}; +``` + +#### Storage mode behavior + +| Mode | `read(i)` | `write(i, v)` | Destructor | +|------|-----------|---------------|------------| +| Borrowed | `m_BorrowedArray->at(i)` | assert/error | no-op | +| Owned | `m_OwnedArray->at(i)` | `(*m_OwnedArray)[i] = v` | `m_TempDS->removeData(m_ArrayId)` | +| OutputDirect | `m_OutputArray->at(i)` | `(*m_OutputArray)[i] = v` | no-op | + +#### Move semantics + +The move constructor transfers all fields and nulls out the source so the moved-from object's destructor is a no-op: + +```cpp +CalcBuffer::CalcBuffer(CalcBuffer&& other) noexcept +: m_Storage(other.m_Storage) +, m_BorrowedArray(other.m_BorrowedArray) +, m_TempDS(other.m_TempDS) +, m_ArrayId(other.m_ArrayId) +, m_OwnedArray(other.m_OwnedArray) +, m_OutputArray(other.m_OutputArray) +, m_IsScalar(other.m_IsScalar) +{ + other.m_TempDS = nullptr; // prevents other's destructor from removing the array + other.m_BorrowedArray = nullptr; + other.m_OwnedArray = nullptr; + other.m_OutputArray = nullptr; +} +``` + +### RPN item changes (data-free parser) + +`CalcValue` is deleted. `RpnItem` stores metadata only — no `DataObject::IdType`, no data allocation during parsing. + +```cpp +struct SIMPLNXCORE_EXPORT RpnItem +{ + enum class Type + { + Scalar, // Numeric literal or constant (pi, e) + ArrayRef, // Reference to a source array in the real DataStructure + Operator, // Math operator or function + ComponentExtract, // [C] on a sub-expression result + TupleComponentExtract // [T, C] on a sub-expression result + } type; + + // Scalar + float64 scalarValue = 0.0; + + // ArrayRef + DataPath arrayPath; + DataType sourceDataType = DataType::float64; + + // Operator + const OperatorDef* op = nullptr; + + // ComponentExtract / TupleComponentExtract + usize componentIndex = std::numeric_limits::max(); + usize tupleIndex = std::numeric_limits::max(); +}; +``` + +### Parser changes + +The parser becomes a pure validation + RPN construction pass with no data allocation: + +1. **`createScalarInTemp()` eliminated** — parser stores `float64 scalarValue` in RpnItem. +2. **`copyArrayToTemp()` eliminated** — parser stores `DataPath` + `DataType` from the source. +3. **`Array[C]` bracket indexing unified with `(expr)[C]`** — parser emits `ArrayRef` + `ComponentExtract` RPN items instead of extracting component data during parsing. +4. **`Array[T,C]` bracket indexing unified with `(expr)[T,C]`** — parser emits `ArrayRef` + `TupleComponentExtract`. +5. **Validation step 7b** queries source array shapes directly via `dataStructure.getDataRefAs(path)` instead of looking at temp arrays. +6. **`m_IsPreflight` flag eliminated** — parser is identical for preflight and execution. +7. **`m_TempDataStructure` removed from the parser** — it is created in the evaluator only. + +### Evaluator changes + +`m_TempDataStructure` becomes a local variable inside `evaluateInto()` (currently it is a member of `ArrayCalculatorParser`). Since the parser no longer needs it, the evaluator creates it on the stack and it is destroyed — along with any remaining temp arrays — when `evaluateInto()` returns. The eval stack is `std::stack`. + +#### Buffer creation by RPN type + +| RPN Type | CalcBuffer creation | +|----------|-------------------| +| `Scalar` | `CalcBuffer::scalar(tempDS, value, name)` | +| `ArrayRef` where `sourceDataType == float64` | `CalcBuffer::borrow(sourceFloat64Array)` | +| `ArrayRef` where `sourceDataType != float64` | `CalcBuffer::convertFrom(tempDS, source, name)` | + +#### RAII cleanup during operator evaluation + +When processing a binary operator, operands are moved out of the stack into locals. After the result is computed and pushed, the locals are destroyed at the closing brace, triggering `removeData()` for any owned temps: + +```cpp +{ + CalcBuffer right = std::move(evalStack.top()); + evalStack.pop(); + CalcBuffer left = std::move(evalStack.top()); + evalStack.pop(); + + CalcBuffer result = CalcBuffer::allocate(tempDS, name, outTupleShape, outCompShape); + + bool leftIsScalar = left.isScalar(); + bool rightIsScalar = right.isScalar(); + + for(usize i = 0; i < totalSize; i++) + { + float64 lv = left.read(leftIsScalar ? 0 : i); + float64 rv = right.read(rightIsScalar ? 0 : i); + result.write(i, op->binaryOp(lv, rv)); + } + + evalStack.push(std::move(result)); +} +// left and right destroyed here -> owned temp arrays removed from tempDS +``` + +#### Last-operator direct-write optimization + +For the last RPN operator, when the output type is `float64`: + +1. Pre-scan `m_RpnItems` to find the index of the last Operator/ComponentExtract/TupleComponentExtract. +2. When processing that item, use `CalcBuffer::wrapOutput(outputFloat64Array)` instead of `CalcBuffer::allocate()`. +3. Writes go directly into the output array via `operator[]`. +4. At the end, detect `isOutputDirect()` on the final CalcBuffer and skip the copy step. + +This eliminates the last temp array allocation entirely. + +#### Final result copy to output + +After the RPN loop, the stack has exactly one CalcBuffer: + +Checked in order (first match wins): + +| Final CalcBuffer | Output type | Action | +|-----------------|-------------|--------| +| isScalar() | any | Fill the output array with the scalar value via `DataArray::fill()` or equivalent loop | +| OutputDirect | float64 | No copy needed — data is already in the output | +| Owned or Borrowed | float64 | Element-by-element copy into output `DataArray` via `operator[]` (no type cast) | +| Owned or Borrowed | non-float64 | `CopyResultFunctor` cast-copy via `ExecuteDataFunction` | + +### CPU performance considerations + +- **`CalcBuffer::read()` branch on storage mode**: predictable per-CalcBuffer (same branch every call). Negligible cost compared to `std::function` dispatch through `op->binaryOp`/`op->unaryOp`. +- **Scalar broadcast check**: hoisted outside inner loops (`leftIsScalar`/`rightIsScalar` evaluated once before the loop). +- **OutputDirect adds a third branch to `write()`**: only applies to the single final-result CalcBuffer, so the branch predictor handles it trivially. +- **Borrowed reads via `Float64Array::at()` vs current temp array reads via `Float64Array::at()`**: identical per-element cost. Zero CPU regression for reads. + +### Memory impact analysis + +For expression `a + b + c + d + e + f` with float64 inputs and float64 output (M elements each): + +| Metric | Current | New | +|--------|---------|-----| +| Input copies | 6 arrays (6 * M * 8 bytes) | 0 (all borrowed) | +| Peak intermediate arrays | 5 (all alive simultaneously) | 1 (RAII frees consumed) | +| Final result temp | 1 array (M * 8 bytes) | 0 (OutputDirect writes to output) | +| **Total temp memory** | **12 * M * 8 bytes** | **1 * M * 8 bytes** (one intermediate) | + +For the same expression with non-float64 inputs (e.g., int32): + +| Metric | Current | New | +|--------|---------|-----| +| Input copies | 6 arrays | 6 arrays (conversion required) | +| Peak intermediate arrays | 5 | 1 | +| Final result temp | 1 | 0 (if output is float64) or 1 (if not) | +| **Total temp memory** | **12 * M * 8 bytes** | **7 * M * 8 bytes** (6 conversions + 1 intermediate) | + +### Files modified + +- `ArrayCalculator.hpp` — add `CalcBuffer` class, update `RpnItem`, remove `CalcValue`, remove `m_TempDataStructure`/`m_IsPreflight`/`createScalarInTemp`/`copyArrayToTemp` from parser, add `m_TempDataStructure` to evaluator or create locally +- `ArrayCalculator.cpp` — rewrite `parse()` to be data-free, rewrite `evaluateInto()` with CalcBuffer stack + RAII + OutputDirect, remove `CopyToFloat64Functor` (moved into `CalcBuffer::convertFrom`), update `CopyResultFunctor` for the non-float64 output path +- `ArrayCalculatorFilter.cpp` — no changes expected (parser/evaluator API stays the same) +- `ArrayCalculatorTest.cpp` — no changes expected (tests exercise the filter, not internal classes) + +### What is NOT changing + +- `OperatorDef` struct and operator registry — unchanged +- `Token` struct and `tokenize()` — unchanged +- `CalculatorErrorCode` / `CalculatorWarningCode` enums — unchanged +- `ArrayCalculatorInputValues` struct — unchanged +- `ArrayCalculator` algorithm class public API — unchanged +- `ArrayCalculatorParser::parseAndValidate()` signature — unchanged +- `ArrayCalculatorParser::evaluateInto()` signature — unchanged +- Filter parameter keys, UUID, pipeline JSON format — unchanged From a19df6c7a1055f4934d96a8c7e52e5c574b58685 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Tue, 7 Apr 2026 18:09:02 -0400 Subject: [PATCH 17/19] DOC: Add ArrayCalculator memory optimization implementation plan 7 tasks: CalcBuffer RAII class, data-free parser, evaluator rewrite with CalcBuffer stack, OutputDirect optimization, and full test verification. Co-Authored-By: Claude Opus 4.6 (1M context) --- ...-07-arraycalculator-memory-optimization.md | 1250 +++++++++++++++++ 1 file changed, 1250 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-07-arraycalculator-memory-optimization.md diff --git a/docs/superpowers/plans/2026-04-07-arraycalculator-memory-optimization.md b/docs/superpowers/plans/2026-04-07-arraycalculator-memory-optimization.md new file mode 100644 index 0000000000..a8db154391 --- /dev/null +++ b/docs/superpowers/plans/2026-04-07-arraycalculator-memory-optimization.md @@ -0,0 +1,1250 @@ +# ArrayCalculator Memory Optimization Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Eliminate unnecessary memory allocations in the ArrayCalculator evaluator by introducing a CalcBuffer RAII sentinel class, making the parser data-free, and enabling direct-write to the output array. + +**Architecture:** CalcBuffer wraps Float64Array references (borrowed or owned) with automatic cleanup via DataStructure::removeData(). The parser produces data-free RPN items (DataPath + metadata, no DataObject allocation). The evaluator creates a local DataStructure for temp arrays, uses a CalcBuffer stack where intermediates are freed via RAII when consumed, and the last operator writes directly into the output DataArray when the output type is float64. + +**Tech Stack:** C++20, simplnx DataStructure/DataArray/DataStore, Catch2 tests + +**Design spec:** `docs/superpowers/specs/2026-04-07-arraycalculator-memory-optimization-design.md` + +--- + +### Task 1: Establish Baseline — Verify All Existing Tests Pass + +**Files:** +- Read: `src/Plugins/SimplnxCore/test/ArrayCalculatorTest.cpp` + +This task ensures we have a clean starting point before making changes. + +- [ ] **Step 1: Build the project** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && cmake --build . --target SimplnxCore +``` + +Expected: Build succeeds with no errors. + +- [ ] **Step 2: Run existing ArrayCalculator tests** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && ctest -R "SimplnxCore::ArrayCalculatorFilter" --verbose +``` + +Expected: All test cases pass (Filter Execution, Tokenizer, Array Resolution, Built-in Constants, Modulo Operator, Tuple Component Indexing, Sub-expression Component Access, Multi-word Array Names, Sub-expression Tuple Component Extraction). + +--- + +### Task 2: Add CalcBuffer Class Declaration to Header + +**Files:** +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp` + +Add the CalcBuffer class declaration. This task adds new code only — nothing is removed or changed yet. + +- [ ] **Step 1: Add CalcBuffer class declaration after the OperatorDef struct (after line 133)** + +Insert the following class declaration between the `OperatorDef` struct and the `CalcValue` struct (before line 138): + +```cpp +// --------------------------------------------------------------------------- +// RAII sentinel for temporary Float64Arrays in the evaluator. +// Move-only. When an Owned CalcBuffer is destroyed, it removes its +// DataArray from the scratch DataStructure via removeData(). +// --------------------------------------------------------------------------- +class SIMPLNXCORE_EXPORT CalcBuffer +{ +public: + // --- Factory methods --- + + /** + * @brief Zero-copy reference to an existing Float64Array in the real DataStructure. + * Read-only. Destructor: no-op. + */ + static CalcBuffer borrow(const Float64Array& source); + + /** + * @brief Allocate a temp Float64Array in tempDS and convert source data from any numeric type. + * Owned. Destructor: removes the temp array from tempDS. + */ + static CalcBuffer convertFrom(DataStructure& tempDS, const IDataArray& source, const std::string& name); + + /** + * @brief Allocate a 1-element temp Float64Array with the given scalar value. + * Owned. Destructor: removes the temp array from tempDS. + */ + static CalcBuffer scalar(DataStructure& tempDS, float64 value, const std::string& name); + + /** + * @brief Allocate an empty temp Float64Array with the given shape. + * Owned. Destructor: removes the temp array from tempDS. + */ + static CalcBuffer allocate(DataStructure& tempDS, const std::string& name, std::vector tupleShape, std::vector compShape); + + /** + * @brief Wrap the output DataArray for direct writing. + * Not owned. Destructor: no-op. + */ + static CalcBuffer wrapOutput(DataArray& outputArray); + + // --- Move-only, non-copyable --- + CalcBuffer(CalcBuffer&& other) noexcept; + CalcBuffer& operator=(CalcBuffer&& other) noexcept; + ~CalcBuffer(); + + CalcBuffer(const CalcBuffer&) = delete; + CalcBuffer& operator=(const CalcBuffer&) = delete; + + // --- Element access --- + float64 read(usize index) const; + void write(usize index, float64 value); + void fill(float64 value); + + // --- Metadata --- + usize size() const; + usize numTuples() const; + usize numComponents() const; + std::vector tupleShape() const; + std::vector compShape() const; + bool isScalar() const; + bool isOwned() const; + bool isOutputDirect() const; + void markAsScalar(); + + // --- Access underlying array (for final copy to non-float64 output) --- + const Float64Array& array() const; + +private: + CalcBuffer() = default; + + enum class Storage + { + Borrowed, + Owned, + OutputDirect + }; + + Storage m_Storage = Storage::Owned; + + // Borrowed: const pointer to source Float64Array in real DataStructure + const Float64Array* m_BorrowedArray = nullptr; + + // Owned: pointer to temp Float64Array + reference to its DataStructure for cleanup + DataStructure* m_TempDS = nullptr; + DataObject::IdType m_ArrayId = 0; + Float64Array* m_OwnedArray = nullptr; + + // OutputDirect: writable pointer to output DataArray + DataArray* m_OutputArray = nullptr; + + bool m_IsScalar = false; +}; +``` + +- [ ] **Step 2: Build to verify the header compiles** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && cmake --build . --target SimplnxCore +``` + +Expected: Build succeeds. CalcBuffer is declared but not yet defined — the linker won't complain because nothing references it yet. + +- [ ] **Step 3: Commit** + +```bash +git add src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp +git commit -m "ENH: Add CalcBuffer RAII sentinel class declaration to ArrayCalculator.hpp" +``` + +--- + +### Task 3: Implement CalcBuffer in ArrayCalculator.cpp + +**Files:** +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp` + +Add the full CalcBuffer implementation. Place it after the anonymous namespace closing brace (after line 250) and before the `getOperatorRegistry()` function (line 255). This keeps it near the top of the file with other utility code. + +- [ ] **Step 1: Add CalcBuffer implementation** + +Insert the following after the anonymous namespace (after line 250, before `getOperatorRegistry()`): + +```cpp +// =========================================================================== +// CalcBuffer implementation +// =========================================================================== + +CalcBuffer::CalcBuffer(CalcBuffer&& other) noexcept +: m_Storage(other.m_Storage) +, m_BorrowedArray(other.m_BorrowedArray) +, m_TempDS(other.m_TempDS) +, m_ArrayId(other.m_ArrayId) +, m_OwnedArray(other.m_OwnedArray) +, m_OutputArray(other.m_OutputArray) +, m_IsScalar(other.m_IsScalar) +{ + other.m_TempDS = nullptr; + other.m_BorrowedArray = nullptr; + other.m_OwnedArray = nullptr; + other.m_OutputArray = nullptr; +} + +CalcBuffer& CalcBuffer::operator=(CalcBuffer&& other) noexcept +{ + if(this != &other) + { + // Clean up current state + if(m_Storage == Storage::Owned && m_TempDS != nullptr) + { + m_TempDS->removeData(m_ArrayId); + } + + m_Storage = other.m_Storage; + m_BorrowedArray = other.m_BorrowedArray; + m_TempDS = other.m_TempDS; + m_ArrayId = other.m_ArrayId; + m_OwnedArray = other.m_OwnedArray; + m_OutputArray = other.m_OutputArray; + m_IsScalar = other.m_IsScalar; + + other.m_TempDS = nullptr; + other.m_BorrowedArray = nullptr; + other.m_OwnedArray = nullptr; + other.m_OutputArray = nullptr; + } + return *this; +} + +CalcBuffer::~CalcBuffer() +{ + if(m_Storage == Storage::Owned && m_TempDS != nullptr) + { + m_TempDS->removeData(m_ArrayId); + } +} + +CalcBuffer CalcBuffer::borrow(const Float64Array& source) +{ + CalcBuffer buf; + buf.m_Storage = Storage::Borrowed; + buf.m_BorrowedArray = &source; + buf.m_IsScalar = false; + return buf; +} + +CalcBuffer CalcBuffer::convertFrom(DataStructure& tempDS, const IDataArray& source, const std::string& name) +{ + std::vector tupleShape = source.getTupleShape(); + std::vector compShape = source.getComponentShape(); + Float64Array* destArr = Float64Array::CreateWithStore(tempDS, name, tupleShape, compShape); + + usize totalElements = source.getSize(); + ExecuteDataFunction(CopyToFloat64Functor{}, source.getDataType(), source, *destArr); + + CalcBuffer buf; + buf.m_Storage = Storage::Owned; + buf.m_TempDS = &tempDS; + buf.m_ArrayId = destArr->getId(); + buf.m_OwnedArray = destArr; + buf.m_IsScalar = false; + return buf; +} + +CalcBuffer CalcBuffer::scalar(DataStructure& tempDS, float64 value, const std::string& name) +{ + Float64Array* arr = Float64Array::CreateWithStore(tempDS, name, std::vector{1}, std::vector{1}); + (*arr)[0] = value; + + CalcBuffer buf; + buf.m_Storage = Storage::Owned; + buf.m_TempDS = &tempDS; + buf.m_ArrayId = arr->getId(); + buf.m_OwnedArray = arr; + buf.m_IsScalar = true; + return buf; +} + +CalcBuffer CalcBuffer::allocate(DataStructure& tempDS, const std::string& name, std::vector tupleShape, std::vector compShape) +{ + Float64Array* arr = Float64Array::CreateWithStore(tempDS, name, tupleShape, compShape); + + CalcBuffer buf; + buf.m_Storage = Storage::Owned; + buf.m_TempDS = &tempDS; + buf.m_ArrayId = arr->getId(); + buf.m_OwnedArray = arr; + buf.m_IsScalar = false; + return buf; +} + +CalcBuffer CalcBuffer::wrapOutput(DataArray& outputArray) +{ + CalcBuffer buf; + buf.m_Storage = Storage::OutputDirect; + buf.m_OutputArray = &outputArray; + buf.m_IsScalar = false; + return buf; +} + +float64 CalcBuffer::read(usize index) const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->at(index); + case Storage::Owned: + return m_OwnedArray->at(index); + case Storage::OutputDirect: + return m_OutputArray->at(index); + } + return 0.0; +} + +void CalcBuffer::write(usize index, float64 value) +{ + switch(m_Storage) + { + case Storage::Owned: + (*m_OwnedArray)[index] = value; + return; + case Storage::OutputDirect: + (*m_OutputArray)[index] = value; + return; + case Storage::Borrowed: + return; // read-only — should not be called + } +} + +void CalcBuffer::fill(float64 value) +{ + switch(m_Storage) + { + case Storage::Owned: + m_OwnedArray->fill(value); + return; + case Storage::OutputDirect: + m_OutputArray->fill(value); + return; + case Storage::Borrowed: + return; // read-only + } +} + +usize CalcBuffer::size() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getSize(); + case Storage::Owned: + return m_OwnedArray->getSize(); + case Storage::OutputDirect: + return m_OutputArray->getSize(); + } + return 0; +} + +usize CalcBuffer::numTuples() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getNumberOfTuples(); + case Storage::Owned: + return m_OwnedArray->getNumberOfTuples(); + case Storage::OutputDirect: + return m_OutputArray->getNumberOfTuples(); + } + return 0; +} + +usize CalcBuffer::numComponents() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getNumberOfComponents(); + case Storage::Owned: + return m_OwnedArray->getNumberOfComponents(); + case Storage::OutputDirect: + return m_OutputArray->getNumberOfComponents(); + } + return 0; +} + +std::vector CalcBuffer::tupleShape() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getTupleShape(); + case Storage::Owned: + return m_OwnedArray->getTupleShape(); + case Storage::OutputDirect: + return m_OutputArray->getTupleShape(); + } + return {}; +} + +std::vector CalcBuffer::compShape() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getComponentShape(); + case Storage::Owned: + return m_OwnedArray->getComponentShape(); + case Storage::OutputDirect: + return m_OutputArray->getComponentShape(); + } + return {}; +} + +bool CalcBuffer::isScalar() const +{ + return m_IsScalar; +} + +bool CalcBuffer::isOwned() const +{ + return m_Storage == Storage::Owned; +} + +bool CalcBuffer::isOutputDirect() const +{ + return m_Storage == Storage::OutputDirect; +} + +void CalcBuffer::markAsScalar() +{ + m_IsScalar = true; +} + +const Float64Array& CalcBuffer::array() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return *m_BorrowedArray; + case Storage::Owned: + return *m_OwnedArray; + case Storage::OutputDirect: + return *m_OutputArray; + } + // Should never reach here; return owned as fallback + return *m_OwnedArray; +} +``` + +- [ ] **Step 2: Build to verify CalcBuffer compiles** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && cmake --build . --target SimplnxCore +``` + +Expected: Build succeeds. CalcBuffer is implemented but not yet used. + +- [ ] **Step 3: Run existing tests to verify no regressions** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && ctest -R "SimplnxCore::ArrayCalculatorFilter" --verbose +``` + +Expected: All tests pass (no change in behavior). + +- [ ] **Step 4: Commit** + +```bash +git add src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +git commit -m "ENH: Implement CalcBuffer RAII sentinel for ArrayCalculator temp arrays" +``` + +--- + +### Task 4: Make ParsedItem and RpnItem Data-Free + +**Files:** +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp` (RpnItem) +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp` (ParsedItem) + +Replace CalcValue-based data in ParsedItem and RpnItem with metadata-only fields. This task changes the data structures but does not yet change the parser or evaluator logic — those come next. + +- [ ] **Step 1: Update RpnItem in ArrayCalculator.hpp** + +Replace the current `RpnItem` struct (lines 152-166) with the data-free version. Also delete the `CalcValue` struct (lines 138-147): + +Delete `CalcValue`: +```cpp +// DELETE the entire CalcValue struct (lines 138-147): +// struct SIMPLNXCORE_EXPORT CalcValue { ... }; +``` + +Replace `RpnItem`: +```cpp +// --------------------------------------------------------------------------- +// A single item in the RPN (reverse-polish notation) evaluation sequence. +// Data-free: stores DataPath references and scalar values, not DataObject IDs. +// --------------------------------------------------------------------------- +struct SIMPLNXCORE_EXPORT RpnItem +{ + enum class Type + { + Scalar, + ArrayRef, + Operator, + ComponentExtract, + TupleComponentExtract + } type; + + // Scalar + float64 scalarValue = 0.0; + + // ArrayRef + DataPath arrayPath; + DataType sourceDataType = DataType::float64; + + // Operator + const OperatorDef* op = nullptr; + + // ComponentExtract / TupleComponentExtract + usize componentIndex = std::numeric_limits::max(); + usize tupleIndex = std::numeric_limits::max(); +}; +``` + +- [ ] **Step 2: Update ParsedItem in the anonymous namespace of ArrayCalculator.cpp** + +Replace the current `ParsedItem` struct (lines 26-44) with the data-free version: + +```cpp +struct ParsedItem +{ + enum class Kind + { + Scalar, + ArrayRef, + Operator, + LParen, + RParen, + Comma, + ComponentExtract, + TupleComponentExtract + } kind; + + // Scalar + float64 scalarValue = 0.0; + + // ArrayRef: metadata for validation (no data allocated) + DataPath arrayPath; + DataType sourceDataType = DataType::float64; + std::vector arrayTupleShape; + std::vector arrayCompShape; + + // Operator + const OperatorDef* op = nullptr; + bool isNegativePrefix = false; + + // ComponentExtract / TupleComponentExtract + usize componentIndex = std::numeric_limits::max(); + usize tupleIndex = std::numeric_limits::max(); +}; +``` + +- [ ] **Step 3: Update isBinaryOp helper function** + +The `isBinaryOp` function (around line 139-142) references `ParsedItem::Kind::Operator` which stays the same. No change needed to this function. + +- [ ] **Step 4: Note — do NOT build yet** + +The parser and evaluator still reference the old CalcValue and old ParsedItem/RpnItem fields. They must be updated in Tasks 5 and 6 before the code compiles. Proceed directly to Task 5. + +--- + +### Task 5: Rewrite Parser to Be Data-Free + +**Files:** +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp` (remove parser members) +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp` (rewrite parse()) + +This is the largest task. The parser's `parse()` method is rewritten so it allocates zero data — it only produces RPN items with DataPath/scalar metadata. The helper methods `createScalarInTemp()`, `copyArrayToTemp()`, and `nextScratchName()` are removed from the parser class. The `m_TempDataStructure`, `m_IsPreflight`, and `m_ScratchCounter` members are removed. The `getTempDataStructure()` method is removed. + +- [ ] **Step 1: Remove parser-only members from ArrayCalculatorParser in the header** + +In `ArrayCalculator.hpp`, remove the following from the `ArrayCalculatorParser` class: + +Remove these private method declarations: +- `std::string nextScratchName();` (line 234) +- `DataObject::IdType copyArrayToTemp(const IDataArray& sourceArray);` (line 242) +- `DataObject::IdType createScalarInTemp(double value);` (line 249) + +Remove these private member variables: +- `DataStructure m_TempDataStructure;` (line 252) +- `bool m_IsPreflight;` (line 255) +- `usize m_ScratchCounter = 0;` (line 256) + +Remove this public method: +- `DataStructure& getTempDataStructure() { ... }` (lines 217-221) + +Update the constructor signature — remove `bool isPreflight` parameter: +```cpp +ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, const std::atomic_bool& shouldCancel); +``` + +- [ ] **Step 2: Update ArrayCalculatorParser constructor implementation in .cpp** + +Replace the constructor (lines 305-312) with: + +```cpp +ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, const std::atomic_bool& shouldCancel) +: m_DataStructure(dataStructure) +, m_SelectedGroupPath(selectedGroupPath) +, m_InfixEquation(infixEquation) +, m_ShouldCancel(shouldCancel) +{ +} +``` + +- [ ] **Step 3: Delete the old helper method implementations from .cpp** + +Delete the following function bodies from ArrayCalculator.cpp: +- `ArrayCalculatorParser::nextScratchName()` (lines 443-446) +- `ArrayCalculatorParser::createScalarInTemp()` (lines 449-454) +- `ArrayCalculatorParser::copyArrayToTemp()` (lines 457-476) + +- [ ] **Step 4: Rewrite parse() — token resolution (steps 3+4)** + +This is the core change. In the token resolution loop (starting around line 595), every place that previously called `createScalarInTemp()` or `copyArrayToTemp()` must instead store metadata in the ParsedItem. + +**For numeric literals** (the `TokenType::Number` case, around line 773): +Replace: +```cpp +DataObject::IdType id = createScalarInTemp(numValue); +ParsedItem pi; +pi.kind = ParsedItem::Kind::Value; +pi.value = CalcValue{CalcValue::Kind::Number, id}; +``` +With: +```cpp +ParsedItem pi; +pi.kind = ParsedItem::Kind::Scalar; +pi.scalarValue = numValue; +``` + +**For constants `pi` and `e`** (around line 841): +Replace: +```cpp +double constValue = (tok.text == "pi") ? std::numbers::pi : std::numbers::e; +DataObject::IdType id = createScalarInTemp(constValue); +ParsedItem pi; +pi.kind = ParsedItem::Kind::Value; +pi.value = CalcValue{CalcValue::Kind::Number, id}; +``` +With: +```cpp +float64 constValue = (tok.text == "pi") ? std::numbers::pi : std::numbers::e; +ParsedItem pi; +pi.kind = ParsedItem::Kind::Scalar; +pi.scalarValue = constValue; +``` + +**For array references found via selected group** (around line 876): +Replace: +```cpp +DataObject::IdType id = copyArrayToTemp(*dataArray); +ParsedItem pi; +pi.kind = ParsedItem::Kind::Value; +pi.value = CalcValue{CalcValue::Kind::Array, id}; +``` +With: +```cpp +ParsedItem pi; +pi.kind = ParsedItem::Kind::ArrayRef; +pi.arrayPath = arrayPath; +pi.sourceDataType = dataArray->getDataType(); +pi.arrayTupleShape = dataArray->getTupleShape(); +pi.arrayCompShape = dataArray->getComponentShape(); +``` + +Apply the same pattern to **all other array resolution sites**: +- Array found via `findArraysByName()` (around line 916): same change — store DataPath, DataType, shapes +- Quoted string path resolution (around line 969): same change + +**For bracket indexing `Array[C]`** (the block starting around line 635): + +Currently this block accesses `m_TempDataStructure` to get the temp array and extract component data. Replace the entire bracket handling block. When `prevItem.kind == ParsedItem::Kind::ArrayRef`: + +For `[C]` (single bracket number): +```cpp +usize numComponents = 1; +for(usize d : prevItem.arrayCompShape) +{ + numComponents *= d; +} + +// Validate component index +if(compIdx >= numComponents) +{ + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), + fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); +} + +// Emit a ComponentExtract after the ArrayRef +ParsedItem ce; +ce.kind = ParsedItem::Kind::ComponentExtract; +ce.componentIndex = compIdx; +items.push_back(ce); +``` + +For `[T, C]` (two bracket numbers): +```cpp +usize numTuples = 1; +for(usize d : prevItem.arrayTupleShape) +{ + numTuples *= d; +} +usize numComponents = 1; +for(usize d : prevItem.arrayCompShape) +{ + numComponents *= d; +} + +if(tupleIdx >= numTuples) +{ + return MakeErrorResult(static_cast(CalculatorErrorCode::TupleOutOfRange), + fmt::format("Tuple index {} is out of range for array with {} tuples.", tupleIdx, numTuples)); +} +if(compIdx >= numComponents) +{ + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), + fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); +} + +ParsedItem tce; +tce.kind = ParsedItem::Kind::TupleComponentExtract; +tce.tupleIndex = tupleIdx; +tce.componentIndex = compIdx; +items.push_back(tce); +``` + +The `(expr)[C]` and `(expr)[T,C]` paths (when `prevItem.kind == ParsedItem::Kind::RParen`) remain unchanged — they already emit ComponentExtract/TupleComponentExtract items. + +- [ ] **Step 5: Rewrite parse() — validation step 7b** + +The validation step 7b (starting around line 1316) currently queries `m_TempDataStructure.getDataAs()` for each array value. Replace it to query `ParsedItem::arrayTupleShape` and `ParsedItem::arrayCompShape` directly: + +```cpp +// 7b: Collect array-type values and verify consistent tuple/component info +std::vector arrayTupleShape; +std::vector arrayCompShape; +usize arrayNumTuples = 0; +bool hasArray = false; +bool hasNumericValue = false; +bool tupleShapesMatch = true; + +for(const auto& item : items) +{ + if(item.kind == ParsedItem::Kind::Scalar || item.kind == ParsedItem::Kind::ArrayRef) + { + hasNumericValue = true; + } + if(item.kind == ParsedItem::Kind::ArrayRef) + { + std::vector ts = item.arrayTupleShape; + std::vector cs = item.arrayCompShape; + usize nt = 1; + for(usize d : ts) + { + nt *= d; + } + + if(hasArray) + { + if(!arrayCompShape.empty() && arrayCompShape != cs) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentCompDims), + "Attribute Array symbols in the infix expression have mismatching component dimensions."); + } + if(arrayNumTuples != 0 && nt != arrayNumTuples) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentTuples), + "Attribute Array symbols in the infix expression have mismatching number of tuples."); + } + if(!arrayTupleShape.empty() && arrayTupleShape != ts) + { + tupleShapesMatch = false; + } + } + + hasArray = true; + arrayTupleShape = ts; + arrayCompShape = cs; + arrayNumTuples = nt; + } +} +``` + +- [ ] **Step 6: Rewrite parse() — shunting-yard conversion to RPN** + +The shunting-yard loop (starting around line 1416) currently converts ParsedItems to RpnItems. Update the `Value` case to handle the new `Scalar` and `ArrayRef` kinds: + +Replace the `ParsedItem::Kind::Value` case with two cases: + +```cpp +case ParsedItem::Kind::Scalar: { + RpnItem rpn; + rpn.type = RpnItem::Type::Scalar; + rpn.scalarValue = item.scalarValue; + m_RpnItems.push_back(rpn); + break; +} + +case ParsedItem::Kind::ArrayRef: { + RpnItem rpn; + rpn.type = RpnItem::Type::ArrayRef; + rpn.arrayPath = item.arrayPath; + rpn.sourceDataType = item.sourceDataType; + m_RpnItems.push_back(rpn); + break; +} +``` + +Update the `ComponentExtract` and `TupleComponentExtract` cases similarly — they already match the new RpnItem fields. Just ensure the RpnItem type assignment uses `RpnItem::Type::ComponentExtract` / `RpnItem::Type::TupleComponentExtract` and sets `componentIndex`/`tupleIndex`. + +- [ ] **Step 7: Update constructor calls in ArrayCalculatorFilter.cpp** + +In `ArrayCalculatorFilter.cpp`, update the two places where `ArrayCalculatorParser` is constructed: + +In `preflightImpl()` (around line 88), remove the `true` (isPreflight) argument: +```cpp +ArrayCalculatorParser parser(dataStructure, pInfixEquationValue.m_SelectedGroup, pInfixEquationValue.m_Equation, m_ShouldCancel); +``` + +In `ArrayCalculator::operator()()` in ArrayCalculator.cpp (around line 1789), remove the `false` (isPreflight) argument: +```cpp +ArrayCalculatorParser parser(m_DataStructure, m_InputValues->SelectedGroup, m_InputValues->InfixEquation, m_ShouldCancel); +``` + +- [ ] **Step 8: Note — do NOT build yet** + +The evaluator (`evaluateInto()`) still references the old CalcValue-based eval stack. It must be updated in Task 6 before the code compiles. + +--- + +### Task 6: Rewrite Evaluator to Use CalcBuffer Stack + +**Files:** +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp` + +Rewrite `evaluateInto()` to use a `std::stack` with a local `DataStructure` for temps. Add the last-operator OutputDirect optimization and the final result copy logic. + +- [ ] **Step 1: Rewrite evaluateInto()** + +Replace the entire `evaluateInto()` method (starting at line 1534) with the following implementation. This is the complete new evaluator: + +```cpp +Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const DataPath& outputPath, NumericType scalarType, CalculatorParameter::AngleUnits units) +{ + // 1. Parse (populates m_RpnItems via shunting-yard) + Result<> parseResult = parse(); + if(parseResult.invalid()) + { + return parseResult; + } + + // 2. Create local temp DataStructure for intermediate arrays + DataStructure tempDS; + usize scratchCounter = 0; + auto nextScratchName = [&scratchCounter]() -> std::string { + return "_calc_" + std::to_string(scratchCounter++); + }; + + // 3. Pre-scan RPN to find the index of the last operator/extract item + // for the OutputDirect optimization + DataType outputDataType = ConvertNumericTypeToDataType(scalarType); + bool outputIsFloat64 = (outputDataType == DataType::float64); + int64 lastOpIndex = -1; + for(int64 idx = static_cast(m_RpnItems.size()) - 1; idx >= 0; --idx) + { + RpnItem::Type t = m_RpnItems[static_cast(idx)].type; + if(t == RpnItem::Type::Operator || t == RpnItem::Type::ComponentExtract || t == RpnItem::Type::TupleComponentExtract) + { + lastOpIndex = idx; + break; + } + } + + // 4. Walk the RPN items using a CalcBuffer evaluation stack + std::stack evalStack; + + for(usize rpnIdx = 0; rpnIdx < m_RpnItems.size(); ++rpnIdx) + { + if(m_ShouldCancel) + { + return {}; + } + + const RpnItem& rpnItem = m_RpnItems[rpnIdx]; + bool isLastOp = (static_cast(rpnIdx) == lastOpIndex); + + switch(rpnItem.type) + { + case RpnItem::Type::Scalar: { + evalStack.push(CalcBuffer::scalar(tempDS, rpnItem.scalarValue, nextScratchName())); + break; + } + + case RpnItem::Type::ArrayRef: { + if(rpnItem.sourceDataType == DataType::float64) + { + const auto& sourceArray = m_DataStructure.getDataRefAs(rpnItem.arrayPath); + evalStack.push(CalcBuffer::borrow(sourceArray)); + } + else + { + const auto& sourceArray = m_DataStructure.getDataRefAs(rpnItem.arrayPath); + evalStack.push(CalcBuffer::convertFrom(tempDS, sourceArray, nextScratchName())); + } + break; + } + + case RpnItem::Type::Operator: { + const OperatorDef* op = rpnItem.op; + if(op == nullptr) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: null operator in RPN evaluation."); + } + + if(op->numArgs == 1) + { + if(evalStack.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for unary operator."); + } + CalcBuffer operand = std::move(evalStack.top()); + evalStack.pop(); + + std::vector resultTupleShape = operand.tupleShape(); + std::vector resultCompShape = operand.compShape(); + usize totalSize = operand.size(); + + CalcBuffer result = (isLastOp && outputIsFloat64) + ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) + : CalcBuffer::allocate(tempDS, nextScratchName(), resultTupleShape, resultCompShape); + + for(usize i = 0; i < totalSize; i++) + { + float64 val = operand.read(i); + + if(op->trigMode == OperatorDef::ForwardTrig && units == CalculatorParameter::AngleUnits::Degrees) + { + val = val * (std::numbers::pi / 180.0); + } + + float64 res = op->unaryOp(val); + + if(op->trigMode == OperatorDef::InverseTrig && units == CalculatorParameter::AngleUnits::Degrees) + { + res = res * (180.0 / std::numbers::pi); + } + + result.write(i, res); + } + + bool wasScalar = operand.isScalar(); + if(wasScalar) + { + result.markAsScalar(); + } + // operand destroyed here, RAII cleans up + evalStack.push(std::move(result)); + } + else if(op->numArgs == 2) + { + if(evalStack.size() < 2) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for binary operator."); + } + CalcBuffer right = std::move(evalStack.top()); + evalStack.pop(); + CalcBuffer left = std::move(evalStack.top()); + evalStack.pop(); + + // Determine output shape: use the array operand's shape (broadcast scalars) + std::vector outTupleShape; + std::vector outCompShape; + if(!left.isScalar()) + { + outTupleShape = left.tupleShape(); + outCompShape = left.compShape(); + } + else + { + outTupleShape = right.tupleShape(); + outCompShape = right.compShape(); + } + + usize totalSize = 1; + for(usize d : outTupleShape) + { + totalSize *= d; + } + for(usize d : outCompShape) + { + totalSize *= d; + } + + CalcBuffer result = (isLastOp && outputIsFloat64) + ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) + : CalcBuffer::allocate(tempDS, nextScratchName(), outTupleShape, outCompShape); + + bool leftIsScalar = left.isScalar(); + bool rightIsScalar = right.isScalar(); + + for(usize i = 0; i < totalSize; i++) + { + float64 lv = left.read(leftIsScalar ? 0 : i); + float64 rv = right.read(rightIsScalar ? 0 : i); + result.write(i, op->binaryOp(lv, rv)); + } + + if(leftIsScalar && rightIsScalar) + { + result.markAsScalar(); + } + // left and right destroyed here, RAII cleans up owned temps + evalStack.push(std::move(result)); + } + else + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), + fmt::format("Internal error: operator '{}' has unsupported numArgs={}.", op->token, op->numArgs)); + } + break; + } + + case RpnItem::Type::ComponentExtract: { + if(evalStack.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for component extraction."); + } + CalcBuffer operand = std::move(evalStack.top()); + evalStack.pop(); + + usize numComps = operand.numComponents(); + usize numTuples = operand.numTuples(); + usize compIdx = rpnItem.componentIndex; + + if(compIdx >= numComps) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), + fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); + } + + CalcBuffer result = (isLastOp && outputIsFloat64) + ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) + : CalcBuffer::allocate(tempDS, nextScratchName(), operand.tupleShape(), std::vector{1}); + + for(usize t = 0; t < numTuples; ++t) + { + result.write(t, operand.read(t * numComps + compIdx)); + } + + evalStack.push(std::move(result)); + break; + } + + case RpnItem::Type::TupleComponentExtract: { + if(evalStack.empty()) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for tuple+component extraction."); + } + CalcBuffer operand = std::move(evalStack.top()); + evalStack.pop(); + + usize numComps = operand.numComponents(); + usize numTuples = operand.numTuples(); + usize tupleIdx = rpnItem.tupleIndex; + usize compIdx = rpnItem.componentIndex; + + if(tupleIdx >= numTuples) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::TupleOutOfRange), + fmt::format("Tuple index {} is out of range for array with {} tuples.", tupleIdx, numTuples)); + } + if(compIdx >= numComps) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), + fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); + } + + float64 value = operand.read(tupleIdx * numComps + compIdx); + // operand destroyed, RAII cleans up + evalStack.push(CalcBuffer::scalar(tempDS, value, nextScratchName())); + break; + } + + } // end switch + } + + // 5. Final result + if(evalStack.size() != 1) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), + fmt::format("Internal error: evaluation stack has {} items remaining; expected exactly 1.", evalStack.size())); + } + + CalcBuffer finalResult = std::move(evalStack.top()); + evalStack.pop(); + + // 6. Copy/cast result into the output array (checked in order, first match wins) + if(finalResult.isScalar()) + { + // Fill entire output with the scalar value + float64 scalarVal = finalResult.read(0); + ExecuteDataFunction(CopyResultFunctor{}, outputDataType, dataStructure, outputPath, scalarVal); + } + else if(finalResult.isOutputDirect()) + { + // Data is already in the output array — nothing to do + } + else if(outputIsFloat64) + { + // Direct float64-to-float64 copy via operator[] (no type cast) + auto& outputArray = dataStructure.getDataRefAs>(outputPath); + usize totalSize = finalResult.size(); + for(usize i = 0; i < totalSize; i++) + { + outputArray[i] = finalResult.read(i); + } + } + else + { + // Type-casting copy via CopyResultFunctor + const Float64Array& resultArray = finalResult.array(); + ExecuteDataFunction(CopyResultFunctor{}, outputDataType, dataStructure, outputPath, &resultArray, false); + } + + return parseResult; +} +``` + +- [ ] **Step 2: Update CopyResultFunctor to support scalar fill** + +The scalar fill path now passes a `float64` value directly. Add an overload or update `CopyResultFunctor` in the anonymous namespace. Replace the existing `CopyResultFunctor` (lines 230-248) with: + +```cpp +struct CopyResultFunctor +{ + // Full array copy (non-float64 output) + template + void operator()(DataStructure& ds, const DataPath& outputPath, const Float64Array* resultArray, bool /*unused*/) + { + auto& output = ds.getDataRefAs>(outputPath).getDataStoreRef(); + for(usize i = 0; i < output.getSize(); i++) + { + output[i] = static_cast(resultArray->at(i)); + } + } + + // Scalar fill + template + void operator()(DataStructure& ds, const DataPath& outputPath, float64 scalarValue) + { + auto& output = ds.getDataRefAs>(outputPath); + output.fill(static_cast(scalarValue)); + } +}; +``` + +- [ ] **Step 3: Remove old CopyToFloat64Functor** + +The `CopyToFloat64Functor` (lines 122-134) is no longer needed at the top level since its logic is now inside `CalcBuffer::convertFrom()`. However, `CalcBuffer::convertFrom()` still calls it via `ExecuteDataFunction`. Keep `CopyToFloat64Functor` in the anonymous namespace — it is still referenced by `CalcBuffer::convertFrom()`. + +- [ ] **Step 4: Build the project** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && cmake --build . --target SimplnxCore +``` + +Expected: Build succeeds. Fix any compilation errors arising from ParsedItem/RpnItem field name mismatches — common issues: +- `item.kind == ParsedItem::Kind::Value` → split into `ParsedItem::Kind::Scalar` and `ParsedItem::Kind::ArrayRef` +- `item.value.kind == CalcValue::Kind::Array` → `item.kind == ParsedItem::Kind::ArrayRef` +- References to `item.value` → `item.scalarValue` or `item.arrayPath` + +- [ ] **Step 5: Run all ArrayCalculator tests** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && ctest -R "SimplnxCore::ArrayCalculatorFilter" --verbose +``` + +Expected: All test cases pass — identical behavior to baseline. If any fail, debug by comparing the error code or output value against the expected. Common issues: +- Bracket indexing `Array[C]` now emits ArrayRef + ComponentExtract, so the evaluator must handle ComponentExtract on borrowed arrays correctly +- Scalar detection: CalcBuffer created via `CalcBuffer::scalar()` has `m_IsScalar = true`, but CalcBuffers from binary operations where both operands are scalar should also be scalar. Check that the scalar fill path triggers correctly for all-scalar expressions. + +- [ ] **Step 6: Commit** + +```bash +git add src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp \ + src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp \ + src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp +git commit -m "MEM: Rewrite ArrayCalculator parser and evaluator with CalcBuffer RAII + +Parser is now data-free: produces RPN items with DataPath/scalar metadata +instead of allocating temporary Float64Arrays. Evaluator uses a CalcBuffer +stack with RAII cleanup — intermediates are freed when consumed. Float64 +input arrays are borrowed (zero-copy). The last RPN operator writes +directly into the output DataArray when output type is float64." +``` + +--- + +### Task 7: Final Verification and Cleanup + +**Files:** +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp` (cleanup) +- Modify: `src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp` (cleanup) + +- [ ] **Step 1: Run clang-format on modified files** + +```bash +cd /Users/mjackson/Workspace7/simplnx && clang-format -i \ + src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp \ + src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp \ + src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp +``` + +- [ ] **Step 2: Build the full project (not just SimplnxCore)** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && cmake --build . --target all +``` + +Expected: Full build succeeds — no other files reference CalcValue or the removed parser members. + +- [ ] **Step 3: Run the full SimplnxCore test suite** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && ctest -R "SimplnxCore::" --verbose +``` + +Expected: All SimplnxCore tests pass. This catches any accidental regressions in other filters. + +- [ ] **Step 4: Run ArrayCalculator tests specifically and verify all assertions pass** + +```bash +cd /Users/mjackson/Workspace2/DREAM3D-Build/simplnx-Rel && ctest -R "SimplnxCore::ArrayCalculatorFilter" --verbose +``` + +Expected: All 9 test cases pass with all assertions (the test output should show the same assertion count as the baseline from Task 1). + +- [ ] **Step 5: Commit formatting changes (if any)** + +```bash +git add src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp \ + src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp \ + src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp +git commit -m "STY: Run clang-format on ArrayCalculator files after memory optimization" +``` + From 5813d0e79950a006d231f0244e17c3659dfe25a3 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Tue, 7 Apr 2026 18:52:30 -0400 Subject: [PATCH 18/19] MEM: Rewrite ArrayCalculator with CalcBuffer RAII and data-free parser Introduce CalcBuffer, a move-only RAII sentinel that wraps Float64Array references (borrowed for zero-copy, owned for temps with automatic cleanup via DataStructure::removeData()). This eliminates unnecessary memory allocations: - Parser is now data-free: produces RPN items with DataPath/scalar metadata instead of allocating temporary Float64Arrays. The m_TempDataStructure, m_IsPreflight, createScalarInTemp(), and copyArrayToTemp() members are removed from the parser class. - Evaluator uses a CalcBuffer stack with RAII cleanup: intermediates are freed the instant they are consumed by an operator. - Float64 input arrays are borrowed (zero-copy) instead of copied. - The last RPN operator writes directly into the output DataArray when the output type is float64 (OutputDirect optimization). - Array[C] bracket indexing now emits ArrayRef + ComponentExtract RPN items (unified with sub-expression indexing) instead of extracting component data during parsing. All 3,629 existing test assertions pass. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Filters/Algorithms/ArrayCalculator.cpp | 778 ++++++++++++------ .../Filters/Algorithms/ArrayCalculator.hpp | 146 +++- .../Filters/ArrayCalculatorFilter.cpp | 2 +- 3 files changed, 654 insertions(+), 272 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 19ced286db..0307d77bc6 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -28,7 +28,8 @@ struct ParsedItem { enum class Kind { - Value, + Scalar, + ArrayRef, Operator, LParen, RParen, @@ -37,11 +38,22 @@ struct ParsedItem TupleComponentExtract } kind; - CalcValue value{CalcValue::Kind::Number, 0}; + // Scalar + float64 scalarValue = 0.0; + + // ArrayRef: metadata for validation (no data allocated) + DataPath arrayPath; + DataType sourceDataType = DataType::float64; + std::vector arrayTupleShape; + std::vector arrayCompShape; + + // Operator const OperatorDef* op = nullptr; + bool isNegativePrefix = false; + + // ComponentExtract / TupleComponentExtract usize componentIndex = std::numeric_limits::max(); usize tupleIndex = std::numeric_limits::max(); - bool isNegativePrefix = false; }; // --------------------------------------------------------------------------- @@ -229,26 +241,292 @@ void wrapFunctionArguments(std::vector& items) // --------------------------------------------------------------------------- struct CopyResultFunctor { + // Full array copy (non-float64 output) template - void operator()(DataStructure& ds, const DataPath& outputPath, const Float64Array* resultArray, bool isScalar) + void operator()(DataStructure& ds, const DataPath& outputPath, const Float64Array* resultArray, bool /*unused*/) { auto& output = ds.getDataRefAs>(outputPath).getDataStoreRef(); - if(isScalar && resultArray->getSize() == 1) + for(usize i = 0; i < output.getSize(); i++) { - output.fill(static_cast(resultArray->at(0))); - } - else - { - for(usize i = 0; i < output.getSize(); i++) - { - output[i] = static_cast(resultArray->at(i)); - } + output[i] = static_cast(resultArray->at(i)); } } + + // Scalar fill + template + void operator()(DataStructure& ds, const DataPath& outputPath, float64 scalarValue) + { + auto& output = ds.getDataRefAs>(outputPath); + output.fill(static_cast(scalarValue)); + } }; } // anonymous namespace +// =========================================================================== +// CalcBuffer implementation +// =========================================================================== + +CalcBuffer::CalcBuffer(CalcBuffer&& other) noexcept +: m_Storage(other.m_Storage) +, m_BorrowedArray(other.m_BorrowedArray) +, m_TempDS(other.m_TempDS) +, m_ArrayId(other.m_ArrayId) +, m_OwnedArray(other.m_OwnedArray) +, m_OutputArray(other.m_OutputArray) +, m_IsScalar(other.m_IsScalar) +{ + other.m_TempDS = nullptr; + other.m_BorrowedArray = nullptr; + other.m_OwnedArray = nullptr; + other.m_OutputArray = nullptr; +} + +CalcBuffer& CalcBuffer::operator=(CalcBuffer&& other) noexcept +{ + if(this != &other) + { + // Clean up current state + if(m_Storage == Storage::Owned && m_TempDS != nullptr) + { + m_TempDS->removeData(m_ArrayId); + } + + m_Storage = other.m_Storage; + m_BorrowedArray = other.m_BorrowedArray; + m_TempDS = other.m_TempDS; + m_ArrayId = other.m_ArrayId; + m_OwnedArray = other.m_OwnedArray; + m_OutputArray = other.m_OutputArray; + m_IsScalar = other.m_IsScalar; + + other.m_TempDS = nullptr; + other.m_BorrowedArray = nullptr; + other.m_OwnedArray = nullptr; + other.m_OutputArray = nullptr; + } + return *this; +} + +CalcBuffer::~CalcBuffer() +{ + if(m_Storage == Storage::Owned && m_TempDS != nullptr) + { + m_TempDS->removeData(m_ArrayId); + } +} + +CalcBuffer CalcBuffer::borrow(const Float64Array& source) +{ + CalcBuffer buf; + buf.m_Storage = Storage::Borrowed; + buf.m_BorrowedArray = &source; + buf.m_IsScalar = false; + return buf; +} + +CalcBuffer CalcBuffer::convertFrom(DataStructure& tempDS, const IDataArray& source, const std::string& name) +{ + std::vector tupleShape = source.getTupleShape(); + std::vector compShape = source.getComponentShape(); + Float64Array* destArr = Float64Array::CreateWithStore(tempDS, name, tupleShape, compShape); + + ExecuteDataFunction(CopyToFloat64Functor{}, source.getDataType(), source, *destArr); + + CalcBuffer buf; + buf.m_Storage = Storage::Owned; + buf.m_TempDS = &tempDS; + buf.m_ArrayId = destArr->getId(); + buf.m_OwnedArray = destArr; + buf.m_IsScalar = false; + return buf; +} + +CalcBuffer CalcBuffer::scalar(DataStructure& tempDS, float64 value, const std::string& name) +{ + Float64Array* arr = Float64Array::CreateWithStore(tempDS, name, std::vector{1}, std::vector{1}); + (*arr)[0] = value; + + CalcBuffer buf; + buf.m_Storage = Storage::Owned; + buf.m_TempDS = &tempDS; + buf.m_ArrayId = arr->getId(); + buf.m_OwnedArray = arr; + buf.m_IsScalar = true; + return buf; +} + +CalcBuffer CalcBuffer::allocate(DataStructure& tempDS, const std::string& name, std::vector tupleShape, std::vector compShape) +{ + Float64Array* arr = Float64Array::CreateWithStore(tempDS, name, tupleShape, compShape); + + CalcBuffer buf; + buf.m_Storage = Storage::Owned; + buf.m_TempDS = &tempDS; + buf.m_ArrayId = arr->getId(); + buf.m_OwnedArray = arr; + buf.m_IsScalar = false; + return buf; +} + +CalcBuffer CalcBuffer::wrapOutput(DataArray& outputArray) +{ + CalcBuffer buf; + buf.m_Storage = Storage::OutputDirect; + buf.m_OutputArray = &outputArray; + buf.m_IsScalar = false; + return buf; +} + +float64 CalcBuffer::read(usize index) const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->at(index); + case Storage::Owned: + return m_OwnedArray->at(index); + case Storage::OutputDirect: + return m_OutputArray->at(index); + } + return 0.0; +} + +void CalcBuffer::write(usize index, float64 value) +{ + switch(m_Storage) + { + case Storage::Owned: + (*m_OwnedArray)[index] = value; + return; + case Storage::OutputDirect: + (*m_OutputArray)[index] = value; + return; + case Storage::Borrowed: + return; // read-only — should not be called + } +} + +void CalcBuffer::fill(float64 value) +{ + switch(m_Storage) + { + case Storage::Owned: + m_OwnedArray->fill(value); + return; + case Storage::OutputDirect: + m_OutputArray->fill(value); + return; + case Storage::Borrowed: + return; // read-only + } +} + +usize CalcBuffer::size() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getSize(); + case Storage::Owned: + return m_OwnedArray->getSize(); + case Storage::OutputDirect: + return m_OutputArray->getSize(); + } + return 0; +} + +usize CalcBuffer::numTuples() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getNumberOfTuples(); + case Storage::Owned: + return m_OwnedArray->getNumberOfTuples(); + case Storage::OutputDirect: + return m_OutputArray->getNumberOfTuples(); + } + return 0; +} + +usize CalcBuffer::numComponents() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getNumberOfComponents(); + case Storage::Owned: + return m_OwnedArray->getNumberOfComponents(); + case Storage::OutputDirect: + return m_OutputArray->getNumberOfComponents(); + } + return 0; +} + +std::vector CalcBuffer::tupleShape() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getTupleShape(); + case Storage::Owned: + return m_OwnedArray->getTupleShape(); + case Storage::OutputDirect: + return m_OutputArray->getTupleShape(); + } + return {}; +} + +std::vector CalcBuffer::compShape() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return m_BorrowedArray->getComponentShape(); + case Storage::Owned: + return m_OwnedArray->getComponentShape(); + case Storage::OutputDirect: + return m_OutputArray->getComponentShape(); + } + return {}; +} + +bool CalcBuffer::isScalar() const +{ + return m_IsScalar; +} + +bool CalcBuffer::isOwned() const +{ + return m_Storage == Storage::Owned; +} + +bool CalcBuffer::isOutputDirect() const +{ + return m_Storage == Storage::OutputDirect; +} + +void CalcBuffer::markAsScalar() +{ + m_IsScalar = true; +} + +const Float64Array& CalcBuffer::array() const +{ + switch(m_Storage) + { + case Storage::Borrowed: + return *m_BorrowedArray; + case Storage::Owned: + return *m_OwnedArray; + case Storage::OutputDirect: + return *m_OutputArray; + } + // Should never reach here; return owned as fallback + return *m_OwnedArray; +} + // --------------------------------------------------------------------------- // getOperatorRegistry // --------------------------------------------------------------------------- @@ -302,11 +580,10 @@ const std::vector& nx::core::getOperatorRegistry() // --------------------------------------------------------------------------- // ArrayCalculatorParser // --------------------------------------------------------------------------- -ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight, const std::atomic_bool& shouldCancel) +ArrayCalculatorParser::ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, const std::atomic_bool& shouldCancel) : m_DataStructure(dataStructure) , m_SelectedGroupPath(selectedGroupPath) , m_InfixEquation(infixEquation) -, m_IsPreflight(isPreflight) , m_ShouldCancel(shouldCancel) { } @@ -439,42 +716,6 @@ std::vector ArrayCalculatorParser::tokenize(const std::string& equation) return tokens; } -// --------------------------------------------------------------------------- -std::string ArrayCalculatorParser::nextScratchName() -{ - return "_calc_" + std::to_string(m_ScratchCounter++); -} - -// --------------------------------------------------------------------------- -DataObject::IdType ArrayCalculatorParser::createScalarInTemp(double value) -{ - auto* arr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), std::vector{1}, std::vector{1}); - (*arr)[0] = value; - return arr->getId(); -} - -// --------------------------------------------------------------------------- -DataObject::IdType ArrayCalculatorParser::copyArrayToTemp(const IDataArray& sourceArray) -{ - using EmptyDataStoreType = EmptyDataStore; - using DataStoreType = DataStore; - - auto tupleShape = sourceArray.getTupleShape(); - auto compShape = sourceArray.getComponentShape(); - std::string scratchName = nextScratchName(); - - if(m_IsPreflight) - { - auto* destArr = Float64Array::CreateWithStore(m_TempDataStructure, scratchName, tupleShape, compShape); - return destArr->getId(); - } - - auto* destArr = Float64Array::CreateWithStore(m_TempDataStructure, scratchName, tupleShape, compShape); - ExecuteDataFunction(CopyToFloat64Functor{}, sourceArray.getDataType(), sourceArray, *destArr); - - return destArr->getId(); -} - // --------------------------------------------------------------------------- // parse() -- the core parsing pipeline // --------------------------------------------------------------------------- @@ -632,17 +873,19 @@ Result<> ArrayCalculatorParser::parse() ParsedItem& prevItem = items.back(); - if(prevItem.kind == ParsedItem::Kind::Value && prevItem.value.kind == CalcValue::Kind::Array) + if(prevItem.kind == ParsedItem::Kind::ArrayRef) { // Case A: Array[C] or Array[T, C] - auto* tempArr = m_TempDataStructure.getDataAs(prevItem.value.arrayId); - if(tempArr == nullptr) + usize numComponents = 1; + for(usize d : prevItem.arrayCompShape) { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find temporary array for bracket indexing."); + numComponents *= d; + } + usize numTuples = 1; + for(usize d : prevItem.arrayTupleShape) + { + numTuples *= d; } - - usize numComponents = tempArr->getNumberOfComponents(); - usize numTuples = tempArr->getNumberOfTuples(); if(bracketNumbers.size() == 1) { @@ -662,20 +905,11 @@ Result<> ArrayCalculatorParser::parse() return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); } - if(numComponents > 1) - { - // Create new single-component array by extracting component C - auto* newArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), tempArr->getTupleShape(), std::vector{1}); - if(!m_IsPreflight) - { - for(usize t = 0; t < numTuples; ++t) - { - (*newArr)[t] = (*tempArr)[t * numComponents + compIdx]; - } - } - prevItem.value.arrayId = newArr->getId(); - } - // If already single-component, leave as-is + // Emit a ComponentExtract after the ArrayRef + ParsedItem ce; + ce.kind = ParsedItem::Kind::ComponentExtract; + ce.componentIndex = compIdx; + items.push_back(ce); } else if(bracketNumbers.size() == 2) { @@ -700,13 +934,11 @@ Result<> ArrayCalculatorParser::parse() return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComponents)); } - double extractedValue = 0.0; - if(!m_IsPreflight) - { - extractedValue = (*tempArr)[tupleIdx * numComponents + compIdx]; - } - DataObject::IdType id = createScalarInTemp(extractedValue); - prevItem.value = CalcValue{CalcValue::Kind::Number, id}; + ParsedItem tce; + tce.kind = ParsedItem::Kind::TupleComponentExtract; + tce.tupleIndex = tupleIdx; + tce.componentIndex = compIdx; + items.push_back(tce); } else { @@ -779,15 +1011,13 @@ Result<> ArrayCalculatorParser::parse() { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), fmt::format("Invalid numeric value '{}'.", tok.text)); } - DataObject::IdType id = createScalarInTemp(numValue); ParsedItem pi; - pi.kind = ParsedItem::Kind::Value; - pi.value = CalcValue{CalcValue::Kind::Number, id}; + pi.kind = ParsedItem::Kind::Scalar; + pi.scalarValue = numValue; items.push_back(pi); // Ambiguous name warning - if(m_IsPreflight) { bool arrayExists = false; if(!m_SelectedGroupPath.empty()) @@ -813,7 +1043,6 @@ Result<> ArrayCalculatorParser::parse() const OperatorDef* opDef = findOperatorByToken(tok.text); if(opDef != nullptr) { - if(m_IsPreflight) { bool arrayExists = false; if(!m_SelectedGroupPath.empty()) @@ -840,15 +1069,13 @@ Result<> ArrayCalculatorParser::parse() } else if(tok.text == "pi" || tok.text == "e") { - double constValue = (tok.text == "pi") ? std::numbers::pi : std::numbers::e; - DataObject::IdType id = createScalarInTemp(constValue); + float64 constValue = (tok.text == "pi") ? std::numbers::pi : std::numbers::e; ParsedItem pi; - pi.kind = ParsedItem::Kind::Value; - pi.value = CalcValue{CalcValue::Kind::Number, id}; + pi.kind = ParsedItem::Kind::Scalar; + pi.scalarValue = constValue; items.push_back(pi); - if(m_IsPreflight) { bool arrayExists = false; if(!m_SelectedGroupPath.empty()) @@ -879,11 +1106,13 @@ Result<> ArrayCalculatorParser::parse() { return MakeErrorResult(static_cast(CalculatorErrorCode::UnrecognizedItem), fmt::format("Could not access array '{}' in selected group.", tok.text)); } - DataObject::IdType id = copyArrayToTemp(*dataArray); ParsedItem pi; - pi.kind = ParsedItem::Kind::Value; - pi.value = CalcValue{CalcValue::Kind::Array, id}; + pi.kind = ParsedItem::Kind::ArrayRef; + pi.arrayPath = arrayPath; + pi.sourceDataType = dataArray->getDataType(); + pi.arrayTupleShape = dataArray->getTupleShape(); + pi.arrayCompShape = dataArray->getComponentShape(); items.push_back(pi); } else @@ -913,11 +1142,13 @@ Result<> ArrayCalculatorParser::parse() { return MakeErrorResult(static_cast(CalculatorErrorCode::UnrecognizedItem), fmt::format("Could not access array '{}'.", tok.text)); } - DataObject::IdType id = copyArrayToTemp(*dataArray); ParsedItem pi; - pi.kind = ParsedItem::Kind::Value; - pi.value = CalcValue{CalcValue::Kind::Array, id}; + pi.kind = ParsedItem::Kind::ArrayRef; + pi.arrayPath = foundPaths[0]; + pi.sourceDataType = dataArray->getDataType(); + pi.arrayTupleShape = dataArray->getTupleShape(); + pi.arrayCompShape = dataArray->getComponentShape(); items.push_back(pi); } } @@ -966,11 +1197,13 @@ Result<> ArrayCalculatorParser::parse() { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidArrayName), fmt::format("The item '\"{}\"' is not a valid array path in the DataStructure.", tok.text)); } - DataObject::IdType id = copyArrayToTemp(*dataArray); ParsedItem pi; - pi.kind = ParsedItem::Kind::Value; - pi.value = CalcValue{CalcValue::Kind::Array, id}; + pi.kind = ParsedItem::Kind::ArrayRef; + pi.arrayPath = quotedPath; + pi.sourceDataType = dataArray->getDataType(); + pi.arrayTupleShape = dataArray->getTupleShape(); + pi.arrayCompShape = dataArray->getComponentShape(); items.push_back(pi); break; } @@ -988,7 +1221,6 @@ Result<> ArrayCalculatorParser::parse() } // Check if the operator symbol is also the name of an array - if(m_IsPreflight) { bool arrayExists = false; if(!m_SelectedGroupPath.empty()) @@ -1135,7 +1367,7 @@ Result<> ArrayCalculatorParser::parse() { ++commaCount; } - else if(depth >= 1 && (items[j].kind == ParsedItem::Kind::Value || (items[j].kind == ParsedItem::Kind::Operator && items[j].op != nullptr))) + else if(depth >= 1 && (items[j].kind == ParsedItem::Kind::Scalar || items[j].kind == ParsedItem::Kind::ArrayRef || (items[j].kind == ParsedItem::Kind::Operator && items[j].op != nullptr))) { hasValueInside = true; } @@ -1233,7 +1465,8 @@ Result<> ArrayCalculatorParser::parse() if(i > 0) { const auto& prev = items[i - 1]; - if(prev.kind == ParsedItem::Kind::Value || prev.kind == ParsedItem::Kind::RParen) + if(prev.kind == ParsedItem::Kind::Scalar || prev.kind == ParsedItem::Kind::ArrayRef || prev.kind == ParsedItem::Kind::RParen || prev.kind == ParsedItem::Kind::ComponentExtract || + prev.kind == ParsedItem::Kind::TupleComponentExtract) { hasLeft = true; } @@ -1247,7 +1480,7 @@ Result<> ArrayCalculatorParser::parse() if(i + 1 < items.size()) { const auto& next = items[i + 1]; - if(next.kind == ParsedItem::Kind::Value || next.kind == ParsedItem::Kind::LParen) + if(next.kind == ParsedItem::Kind::Scalar || next.kind == ParsedItem::Kind::ArrayRef || next.kind == ParsedItem::Kind::LParen) { hasRight = true; } @@ -1272,7 +1505,7 @@ Result<> ArrayCalculatorParser::parse() if(i + 1 < items.size()) { const auto& next = items[i + 1]; - if(next.kind == ParsedItem::Kind::Value || next.kind == ParsedItem::Kind::LParen) + if(next.kind == ParsedItem::Kind::Scalar || next.kind == ParsedItem::Kind::ArrayRef || next.kind == ParsedItem::Kind::LParen) { hasRight = true; } @@ -1321,42 +1554,57 @@ Result<> ArrayCalculatorParser::parse() bool hasNumericValue = false; bool tupleShapesMatch = true; - for(const auto& item : items) + for(size_t vi = 0; vi < items.size(); ++vi) { - if(item.kind == ParsedItem::Kind::Value) + const auto& item = items[vi]; + if(item.kind == ParsedItem::Kind::Scalar || item.kind == ParsedItem::Kind::ArrayRef) { hasNumericValue = true; - if(item.value.kind == CalcValue::Kind::Array) + } + if(item.kind == ParsedItem::Kind::ArrayRef) + { + std::vector ts = item.arrayTupleShape; + std::vector cs = item.arrayCompShape; + + // If this ArrayRef is immediately followed by ComponentExtract or + // TupleComponentExtract, adjust the effective shape accordingly. + if(vi + 1 < items.size() && items[vi + 1].kind == ParsedItem::Kind::ComponentExtract) { - auto* arr = m_TempDataStructure.getDataAs(item.value.arrayId); - if(arr != nullptr) - { - auto ts = arr->getTupleShape(); - auto cs = arr->getComponentShape(); - usize nt = arr->getNumberOfTuples(); + cs = {1}; + } + else if(vi + 1 < items.size() && items[vi + 1].kind == ParsedItem::Kind::TupleComponentExtract) + { + // TupleComponentExtract reduces to a scalar — skip this array from + // shape consistency checks entirely (it won't contribute shape). + continue; + } - if(hasArray) - { - if(!arrayCompShape.empty() && arrayCompShape != cs) - { - return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentCompDims), "Attribute Array symbols in the infix expression have mismatching component dimensions."); - } - if(arrayNumTuples != 0 && nt != arrayNumTuples) - { - return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentTuples), "Attribute Array symbols in the infix expression have mismatching number of tuples."); - } - if(!arrayTupleShape.empty() && arrayTupleShape != ts) - { - tupleShapesMatch = false; - } - } + usize nt = 1; + for(usize d : ts) + { + nt *= d; + } - hasArray = true; - arrayTupleShape = ts; - arrayCompShape = cs; - arrayNumTuples = nt; + if(hasArray) + { + if(!arrayCompShape.empty() && arrayCompShape != cs) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentCompDims), "Attribute Array symbols in the infix expression have mismatching component dimensions."); + } + if(arrayNumTuples != 0 && nt != arrayNumTuples) + { + return MakeErrorResult(static_cast(CalculatorErrorCode::InconsistentTuples), "Attribute Array symbols in the infix expression have mismatching number of tuples."); + } + if(!arrayTupleShape.empty() && arrayTupleShape != ts) + { + tupleShapesMatch = false; } } + + hasArray = true; + arrayTupleShape = ts; + arrayCompShape = cs; + arrayNumTuples = nt; } } @@ -1417,8 +1665,20 @@ Result<> ArrayCalculatorParser::parse() { switch(item.kind) { - case ParsedItem::Kind::Value: { - m_RpnItems.push_back(RpnItem{RpnItem::Type::Value, item.value, nullptr, std::numeric_limits::max()}); + case ParsedItem::Kind::Scalar: { + RpnItem rpn; + rpn.type = RpnItem::Type::Scalar; + rpn.scalarValue = item.scalarValue; + m_RpnItems.push_back(rpn); + break; + } + + case ParsedItem::Kind::ArrayRef: { + RpnItem rpn; + rpn.type = RpnItem::Type::ArrayRef; + rpn.arrayPath = item.arrayPath; + rpn.sourceDataType = item.sourceDataType; + m_RpnItems.push_back(rpn); break; } @@ -1432,7 +1692,10 @@ Result<> ArrayCalculatorParser::parse() while(!opStack.empty() && opStack.back().kind != ParsedItem::Kind::LParen) { const auto& top = opStack.back(); - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, std::numeric_limits::max()}); + RpnItem rpn; + rpn.type = RpnItem::Type::Operator; + rpn.op = top.op; + m_RpnItems.push_back(rpn); opStack.pop_back(); } if(opStack.empty()) @@ -1450,7 +1713,10 @@ Result<> ArrayCalculatorParser::parse() while(!opStack.empty() && opStack.back().kind != ParsedItem::Kind::LParen) { const auto& top = opStack.back(); - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, top.op, std::numeric_limits::max()}); + RpnItem rpn; + rpn.type = RpnItem::Type::Operator; + rpn.op = top.op; + m_RpnItems.push_back(rpn); opStack.pop_back(); } break; @@ -1469,7 +1735,10 @@ Result<> ArrayCalculatorParser::parse() if(topPrec > incomingPrec || (topPrec == incomingPrec && isLeftAssoc)) { - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, std::numeric_limits::max()}); + RpnItem rpn; + rpn.type = RpnItem::Type::Operator; + rpn.op = topOp; + m_RpnItems.push_back(rpn); opStack.pop_back(); } else @@ -1483,16 +1752,19 @@ Result<> ArrayCalculatorParser::parse() } case ParsedItem::Kind::ComponentExtract: { - m_RpnItems.push_back(RpnItem{RpnItem::Type::ComponentExtract, CalcValue{CalcValue::Kind::Number, 0}, nullptr, item.componentIndex}); + RpnItem rpn; + rpn.type = RpnItem::Type::ComponentExtract; + rpn.componentIndex = item.componentIndex; + m_RpnItems.push_back(rpn); break; } case ParsedItem::Kind::TupleComponentExtract: { - RpnItem tce; - tce.type = RpnItem::Type::TupleComponentExtract; - tce.tupleIndex = item.tupleIndex; - tce.componentIndex = item.componentIndex; - m_RpnItems.push_back(tce); + RpnItem rpn; + rpn.type = RpnItem::Type::TupleComponentExtract; + rpn.tupleIndex = item.tupleIndex; + rpn.componentIndex = item.componentIndex; + m_RpnItems.push_back(rpn); break; } @@ -1508,7 +1780,10 @@ Result<> ArrayCalculatorParser::parse() return MakeErrorResult(static_cast(CalculatorErrorCode::MismatchedParentheses), fmt::format("One or more parentheses are mismatched in the chosen infix expression '{}'.", m_InfixEquation)); } const OperatorDef* topOp = top.isNegativePrefix ? &getUnaryNegativeOp() : top.op; - m_RpnItems.push_back(RpnItem{RpnItem::Type::Operator, CalcValue{CalcValue::Kind::Number, 0}, topOp, std::numeric_limits::max()}); + RpnItem rpn; + rpn.type = RpnItem::Type::Operator; + rpn.op = topOp; + m_RpnItems.push_back(rpn); opStack.pop_back(); } @@ -1533,26 +1808,66 @@ Result<> ArrayCalculatorParser::parseAndValidate(std::vector& outTupleSha // --------------------------------------------------------------------------- Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const DataPath& outputPath, NumericType scalarType, CalculatorParameter::AngleUnits units) { - // 1. Parse (which now populates m_RpnItems via shunting-yard) + // 1. Parse (populates m_RpnItems via shunting-yard) Result<> parseResult = parse(); if(parseResult.invalid()) { return parseResult; } - // 2. Walk the RPN items using an evaluation stack - std::stack evalStack; + // 2. Create local temp DataStructure for intermediate arrays + DataStructure tempDS; + usize scratchCounter = 0; + auto nextScratchName = [&scratchCounter]() -> std::string { + return "_calc_" + std::to_string(scratchCounter++); + }; + + // 3. Pre-scan RPN to find the index of the last operator/extract item + // for the OutputDirect optimization + DataType outputDataType = ConvertNumericTypeToDataType(scalarType); + bool outputIsFloat64 = (outputDataType == DataType::float64); + int64 lastOpIndex = -1; + for(int64 idx = static_cast(m_RpnItems.size()) - 1; idx >= 0; --idx) + { + RpnItem::Type t = m_RpnItems[static_cast(idx)].type; + if(t == RpnItem::Type::Operator || t == RpnItem::Type::ComponentExtract || t == RpnItem::Type::TupleComponentExtract) + { + lastOpIndex = idx; + break; + } + } + + // 4. Walk the RPN items using a CalcBuffer evaluation stack + std::stack evalStack; - for(const auto& rpnItem : m_RpnItems) + for(usize rpnIdx = 0; rpnIdx < m_RpnItems.size(); ++rpnIdx) { if(m_ShouldCancel) { return {}; } + + const RpnItem& rpnItem = m_RpnItems[rpnIdx]; + bool isLastOp = (static_cast(rpnIdx) == lastOpIndex); + switch(rpnItem.type) { - case RpnItem::Type::Value: { - evalStack.push(rpnItem.value); + case RpnItem::Type::Scalar: { + evalStack.push(CalcBuffer::scalar(tempDS, rpnItem.scalarValue, nextScratchName())); + break; + } + + case RpnItem::Type::ArrayRef: { + if(rpnItem.sourceDataType == DataType::float64) + { + const auto& sourceArray = m_DataStructure.getDataRefAs(rpnItem.arrayPath); + evalStack.push(CalcBuffer::borrow(sourceArray)); + } + else + { + const auto& sourceArray = m_DataStructure.getDataRefAs(rpnItem.arrayPath); + evalStack.push(CalcBuffer::convertFrom(tempDS, sourceArray, nextScratchName())); + } break; } @@ -1565,103 +1880,101 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const if(op->numArgs == 1) { - // Unary operator / 1-arg function if(evalStack.empty()) { return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for unary operator."); } - CalcValue operand = evalStack.top(); + CalcBuffer operand = std::move(evalStack.top()); evalStack.pop(); - auto* operandArr = m_TempDataStructure.getDataAs(operand.arrayId); - if(operandArr == nullptr) - { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand array during evaluation."); - } + std::vector resultTupleShape = operand.tupleShape(); + std::vector resultCompShape = operand.compShape(); + usize totalSize = operand.size(); - auto tupleShape = operandArr->getTupleShape(); - auto compShape = operandArr->getComponentShape(); - auto* resultArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), tupleShape, compShape); + CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) + : CalcBuffer::allocate(tempDS, nextScratchName(), resultTupleShape, resultCompShape); - usize totalSize = operandArr->getSize(); for(usize i = 0; i < totalSize; i++) { - double val = operandArr->at(i); + float64 val = operand.read(i); - // Handle trig angle unit conversions if(op->trigMode == OperatorDef::ForwardTrig && units == CalculatorParameter::AngleUnits::Degrees) { val = val * (std::numbers::pi / 180.0); } - double res = op->unaryOp(val); + float64 res = op->unaryOp(val); if(op->trigMode == OperatorDef::InverseTrig && units == CalculatorParameter::AngleUnits::Degrees) { res = res * (180.0 / std::numbers::pi); } - (*resultArr)[i] = res; + result.write(i, res); } - evalStack.push(CalcValue{operand.kind, resultArr->getId()}); + bool wasScalar = operand.isScalar(); + if(wasScalar) + { + result.markAsScalar(); + } + // operand destroyed here, RAII cleans up + evalStack.push(std::move(result)); } else if(op->numArgs == 2) { - // Binary operator / 2-arg function if(evalStack.size() < 2) { return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for binary operator."); } - CalcValue rightVal = evalStack.top(); + CalcBuffer right = std::move(evalStack.top()); evalStack.pop(); - CalcValue leftVal = evalStack.top(); + CalcBuffer left = std::move(evalStack.top()); evalStack.pop(); - auto* leftArr = m_TempDataStructure.getDataAs(leftVal.arrayId); - auto* rightArr = m_TempDataStructure.getDataAs(rightVal.arrayId); - if(leftArr == nullptr || rightArr == nullptr) - { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand arrays during evaluation."); - } - - // Determine output shape: use array operand's shape (broadcast scalars) + // Determine output shape: use the array operand's shape (broadcast scalars) std::vector outTupleShape; std::vector outCompShape; - if(leftVal.kind == CalcValue::Kind::Array) + if(!left.isScalar()) { - outTupleShape = leftArr->getTupleShape(); - outCompShape = leftArr->getComponentShape(); + outTupleShape = left.tupleShape(); + outCompShape = left.compShape(); } else { - outTupleShape = rightArr->getTupleShape(); - outCompShape = rightArr->getComponentShape(); + outTupleShape = right.tupleShape(); + outCompShape = right.compShape(); } - usize numTuples = 1; - for(auto d : outTupleShape) + usize totalSize = 1; + for(usize d : outTupleShape) { - numTuples *= d; + totalSize *= d; } - usize numComps = 1; - for(auto d : outCompShape) + for(usize d : outCompShape) { - numComps *= d; + totalSize *= d; } - usize totalSize = numTuples * numComps; - auto* resultArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), outTupleShape, outCompShape); + CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) + : CalcBuffer::allocate(tempDS, nextScratchName(), outTupleShape, outCompShape); + + bool leftIsScalar = left.isScalar(); + bool rightIsScalar = right.isScalar(); for(usize i = 0; i < totalSize; i++) { - double lv = (leftVal.kind == CalcValue::Kind::Array) ? leftArr->at(i) : leftArr->at(0); - double rv = (rightVal.kind == CalcValue::Kind::Array) ? rightArr->at(i) : rightArr->at(0); - (*resultArr)[i] = op->binaryOp(lv, rv); + float64 lv = left.read(leftIsScalar ? 0 : i); + float64 rv = right.read(rightIsScalar ? 0 : i); + result.write(i, op->binaryOp(lv, rv)); } - CalcValue::Kind resultKind = (leftVal.kind == CalcValue::Kind::Array || rightVal.kind == CalcValue::Kind::Array) ? CalcValue::Kind::Array : CalcValue::Kind::Number; - evalStack.push(CalcValue{resultKind, resultArr->getId()}); + if(leftIsScalar && rightIsScalar) + { + result.markAsScalar(); + } + // left and right destroyed here, RAII cleans up owned temps + evalStack.push(std::move(result)); } else { @@ -1675,17 +1988,11 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const { return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for component extraction."); } - CalcValue operand = evalStack.top(); + CalcBuffer operand = std::move(evalStack.top()); evalStack.pop(); - auto* operandArr = m_TempDataStructure.getDataAs(operand.arrayId); - if(operandArr == nullptr) - { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand array for component extraction."); - } - - usize numComps = operandArr->getNumberOfComponents(); - usize numTuples = operandArr->getNumberOfTuples(); + usize numComps = operand.numComponents(); + usize numTuples = operand.numTuples(); usize compIdx = rpnItem.componentIndex; if(compIdx >= numComps) @@ -1693,13 +2000,15 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); } - auto* newArr = Float64Array::CreateWithStore(m_TempDataStructure, nextScratchName(), operandArr->getTupleShape(), std::vector{1}); + CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) + : CalcBuffer::allocate(tempDS, nextScratchName(), operand.tupleShape(), std::vector{1}); + for(usize t = 0; t < numTuples; ++t) { - (*newArr)[t] = operandArr->at(t * numComps + compIdx); + result.write(t, operand.read(t * numComps + compIdx)); } - evalStack.push(CalcValue{operand.kind, newArr->getId()}); + evalStack.push(std::move(result)); break; } @@ -1708,17 +2017,11 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const { return MakeErrorResult(static_cast(CalculatorErrorCode::NotEnoughArguments), "Not enough arguments for tuple+component extraction."); } - CalcValue operand = evalStack.top(); + CalcBuffer operand = std::move(evalStack.top()); evalStack.pop(); - auto* operandArr = m_TempDataStructure.getDataAs(operand.arrayId); - if(operandArr == nullptr) - { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find operand array for tuple+component extraction."); - } - - usize numComps = operandArr->getNumberOfComponents(); - usize numTuples = operandArr->getNumberOfTuples(); + usize numComps = operand.numComponents(); + usize numTuples = operand.numTuples(); usize tupleIdx = rpnItem.tupleIndex; usize compIdx = rpnItem.componentIndex; @@ -1731,34 +2034,51 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); } - double value = operandArr->at(tupleIdx * numComps + compIdx); - DataObject::IdType scalarId = createScalarInTemp(value); - evalStack.push(CalcValue{CalcValue::Kind::Number, scalarId}); + float64 value = operand.read(tupleIdx * numComps + compIdx); + // operand destroyed, RAII cleans up + evalStack.push(CalcBuffer::scalar(tempDS, value, nextScratchName())); break; } } // end switch } - // 3. Final result + // 5. Final result if(evalStack.size() != 1) { return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), fmt::format("Internal error: evaluation stack has {} items remaining; expected exactly 1.", evalStack.size())); } - CalcValue finalVal = evalStack.top(); + CalcBuffer finalResult = std::move(evalStack.top()); evalStack.pop(); - auto* resultArr = m_TempDataStructure.getDataAs(finalVal.arrayId); - if(resultArr == nullptr) + // 6. Copy/cast result into the output array (checked in order, first match wins) + if(finalResult.isScalar()) { - return MakeErrorResult(static_cast(CalculatorErrorCode::InvalidEquation), "Internal error: could not find final result array."); + // Fill entire output with the scalar value + float64 scalarVal = finalResult.read(0); + ExecuteDataFunction(CopyResultFunctor{}, outputDataType, dataStructure, outputPath, scalarVal); + } + else if(finalResult.isOutputDirect()) + { + // Data is already in the output array — nothing to do + } + else if(outputIsFloat64) + { + // Direct float64-to-float64 copy via operator[] (no type cast) + auto& outputArray = dataStructure.getDataRefAs>(outputPath); + usize totalSize = finalResult.size(); + for(usize i = 0; i < totalSize; i++) + { + outputArray[i] = finalResult.read(i); + } + } + else + { + // Type-casting copy via CopyResultFunctor + const Float64Array& resultArray = finalResult.array(); + ExecuteDataFunction(CopyResultFunctor{}, outputDataType, dataStructure, outputPath, &resultArray, false); } - - // 4. Copy/cast result into the output array - DataType outputDataType = ConvertNumericTypeToDataType(scalarType); - bool isScalar = (finalVal.kind == CalcValue::Kind::Number); - ExecuteDataFunction(CopyResultFunctor{}, outputDataType, dataStructure, outputPath, resultArr, isScalar); return parseResult; } @@ -1786,6 +2106,6 @@ const std::atomic_bool& ArrayCalculator::getCancel() // --------------------------------------------------------------------------- Result<> ArrayCalculator::operator()() { - ArrayCalculatorParser parser(m_DataStructure, m_InputValues->SelectedGroup, m_InputValues->InfixEquation, false, m_ShouldCancel); + ArrayCalculatorParser parser(m_DataStructure, m_InputValues->SelectedGroup, m_InputValues->InfixEquation, m_ShouldCancel); return parser.evaluateInto(m_DataStructure, m_InputValues->CalculatedArray, m_InputValues->ScalarType, m_InputValues->Units); } diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp index 61def9b296..63674307b9 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.hpp @@ -2,6 +2,7 @@ #include "SimplnxCore/SimplnxCore_export.hpp" +#include "simplnx/DataStructure/DataArray.hpp" #include "simplnx/DataStructure/DataPath.hpp" #include "simplnx/DataStructure/DataStructure.hpp" #include "simplnx/DataStructure/IDataArray.hpp" @@ -133,34 +134,124 @@ struct SIMPLNXCORE_EXPORT OperatorDef }; // --------------------------------------------------------------------------- -// A value that lives on the evaluation stack (either a scalar or an array) +// RAII sentinel for temporary Float64Arrays in the evaluator. +// Move-only. When an Owned CalcBuffer is destroyed, it removes its +// DataArray from the scratch DataStructure via removeData(). // --------------------------------------------------------------------------- -struct SIMPLNXCORE_EXPORT CalcValue +class SIMPLNXCORE_EXPORT CalcBuffer { - enum class Kind +public: + // --- Factory methods --- + + /** + * @brief Zero-copy reference to an existing Float64Array in the real DataStructure. + * Read-only. Destructor: no-op. + */ + static CalcBuffer borrow(const Float64Array& source); + + /** + * @brief Allocate a temp Float64Array in tempDS and convert source data from any numeric type. + * Owned. Destructor: removes the temp array from tempDS. + */ + static CalcBuffer convertFrom(DataStructure& tempDS, const IDataArray& source, const std::string& name); + + /** + * @brief Allocate a 1-element temp Float64Array with the given scalar value. + * Owned. Destructor: removes the temp array from tempDS. + */ + static CalcBuffer scalar(DataStructure& tempDS, float64 value, const std::string& name); + + /** + * @brief Allocate an empty temp Float64Array with the given shape. + * Owned. Destructor: removes the temp array from tempDS. + */ + static CalcBuffer allocate(DataStructure& tempDS, const std::string& name, std::vector tupleShape, std::vector compShape); + + /** + * @brief Wrap the output DataArray for direct writing. + * Not owned. Destructor: no-op. + */ + static CalcBuffer wrapOutput(DataArray& outputArray); + + // --- Move-only, non-copyable --- + CalcBuffer(CalcBuffer&& other) noexcept; + CalcBuffer& operator=(CalcBuffer&& other) noexcept; + ~CalcBuffer(); + + CalcBuffer(const CalcBuffer&) = delete; + CalcBuffer& operator=(const CalcBuffer&) = delete; + + // --- Element access --- + float64 read(usize index) const; + void write(usize index, float64 value); + void fill(float64 value); + + // --- Metadata --- + usize size() const; + usize numTuples() const; + usize numComponents() const; + std::vector tupleShape() const; + std::vector compShape() const; + bool isScalar() const; + bool isOwned() const; + bool isOutputDirect() const; + void markAsScalar(); + + // --- Access underlying array (for final copy to non-float64 output) --- + const Float64Array& array() const; + +private: + CalcBuffer() = default; + + enum class Storage { - Number, - Array - } kind; + Borrowed, + Owned, + OutputDirect + }; + + Storage m_Storage = Storage::Owned; + + // Borrowed: const pointer to source Float64Array in real DataStructure + const Float64Array* m_BorrowedArray = nullptr; + + // Owned: pointer to temp Float64Array + reference to its DataStructure for cleanup + DataStructure* m_TempDS = nullptr; + DataObject::IdType m_ArrayId = 0; + Float64Array* m_OwnedArray = nullptr; + + // OutputDirect: writable pointer to output DataArray + DataArray* m_OutputArray = nullptr; - DataObject::IdType arrayId; + bool m_IsScalar = false; }; // --------------------------------------------------------------------------- -// A single item in the RPN (reverse-polish notation) evaluation sequence +// A single item in the RPN (reverse-polish notation) evaluation sequence. +// Data-free: stores DataPath references and scalar values, not DataObject IDs. // --------------------------------------------------------------------------- struct SIMPLNXCORE_EXPORT RpnItem { enum class Type { - Value, + Scalar, + ArrayRef, Operator, ComponentExtract, TupleComponentExtract } type; - CalcValue value; + // Scalar + float64 scalarValue = 0.0; + + // ArrayRef + DataPath arrayPath; + DataType sourceDataType = DataType::float64; + + // Operator const OperatorDef* op = nullptr; + + // ComponentExtract / TupleComponentExtract usize componentIndex = std::numeric_limits::max(); usize tupleIndex = std::numeric_limits::max(); }; @@ -188,7 +279,7 @@ struct SIMPLNXCORE_EXPORT ArrayCalculatorInputValues class SIMPLNXCORE_EXPORT ArrayCalculatorParser { public: - ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, bool isPreflight, const std::atomic_bool& shouldCancel); + ArrayCalculatorParser(const DataStructure& dataStructure, const DataPath& selectedGroupPath, const std::string& infixEquation, const std::atomic_bool& shouldCancel); ~ArrayCalculatorParser() noexcept = default; ArrayCalculatorParser(const ArrayCalculatorParser&) = delete; @@ -214,48 +305,19 @@ class SIMPLNXCORE_EXPORT ArrayCalculatorParser */ static std::vector tokenize(const std::string& equation); - // Expose temp DataStructure for evaluator (Task 1e will use this) - DataStructure& getTempDataStructure() - { - return m_TempDataStructure; - } - private: /** * @brief Runs the full parsing pipeline (tokenize, merge identifiers, * resolve, bracket indexing, minus disambiguation, wrap function args, - * validate) and populates m_ParsedItems. + * validate) and populates m_RpnItems. */ Result<> parse(); - /** - * @brief Creates a unique scratch name for temporary arrays. - */ - std::string nextScratchName(); - - /** - * @brief Creates a Float64Array in m_TempDataStructure from a source - * IDataArray, converting all values to double. When m_IsPreflight is - * true the array is allocated but data is not copied. - * @return the DataObject::IdType of the newly created array - */ - DataObject::IdType copyArrayToTemp(const IDataArray& sourceArray); - - /** - * @brief Creates a 1-element Float64Array in m_TempDataStructure with the - * given scalar value. - * @return the DataObject::IdType of the newly created array - */ - DataObject::IdType createScalarInTemp(double value); - const DataStructure& m_DataStructure; - DataStructure m_TempDataStructure; DataPath m_SelectedGroupPath; std::string m_InfixEquation; - bool m_IsPreflight; - usize m_ScratchCounter = 0; - // Populated by parse(); consumed by evaluateInto() (Task 1e) + // Populated by parse(); consumed by evaluateInto() std::vector m_RpnItems; // Shape info determined during validation diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp index 226d62e732..e32d10c8a5 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/ArrayCalculatorFilter.cpp @@ -85,7 +85,7 @@ IFilter::PreflightResult ArrayCalculatorFilter::preflightImpl(const DataStructur // Parse and validate the expression const std::atomic_bool m_ShouldCancel(false); - ArrayCalculatorParser parser(dataStructure, pInfixEquationValue.m_SelectedGroup, pInfixEquationValue.m_Equation, true, m_ShouldCancel); + ArrayCalculatorParser parser(dataStructure, pInfixEquationValue.m_SelectedGroup, pInfixEquationValue.m_Equation, m_ShouldCancel); std::vector calculatedTupleShape; std::vector calculatedComponentShape; Result<> parseResult = parser.parseAndValidate(calculatedTupleShape, calculatedComponentShape); From 07508d54c4686831f2e7a8da579666f5e165e264 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Tue, 7 Apr 2026 19:03:05 -0400 Subject: [PATCH 19/19] BUG: Add error on write/fill to borrowed CalcBuffer, fix unreachable fallback Replace silent no-ops with std::runtime_error throws when write() or fill() is called on a read-only Borrowed CalcBuffer. Replace null pointer dereference fallback in array() with a throw. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Filters/Algorithms/ArrayCalculator.cpp | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp index 0307d77bc6..31f52bccdd 100644 --- a/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp +++ b/src/Plugins/SimplnxCore/src/SimplnxCore/Filters/Algorithms/ArrayCalculator.cpp @@ -11,6 +11,7 @@ #include #include #include +#include using namespace nx::core; @@ -403,7 +404,7 @@ void CalcBuffer::write(usize index, float64 value) (*m_OutputArray)[index] = value; return; case Storage::Borrowed: - return; // read-only — should not be called + throw std::runtime_error("CalcBuffer::write() called on a read-only Borrowed buffer"); } } @@ -418,7 +419,7 @@ void CalcBuffer::fill(float64 value) m_OutputArray->fill(value); return; case Storage::Borrowed: - return; // read-only + throw std::runtime_error("CalcBuffer::fill() called on a read-only Borrowed buffer"); } } @@ -523,8 +524,7 @@ const Float64Array& CalcBuffer::array() const case Storage::OutputDirect: return *m_OutputArray; } - // Should never reach here; return owned as fallback - return *m_OwnedArray; + throw std::runtime_error("CalcBuffer::array() called on buffer with unknown storage mode"); } // --------------------------------------------------------------------------- @@ -1818,9 +1818,7 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const // 2. Create local temp DataStructure for intermediate arrays DataStructure tempDS; usize scratchCounter = 0; - auto nextScratchName = [&scratchCounter]() -> std::string { - return "_calc_" + std::to_string(scratchCounter++); - }; + auto nextScratchName = [&scratchCounter]() -> std::string { return "_calc_" + std::to_string(scratchCounter++); }; // 3. Pre-scan RPN to find the index of the last operator/extract item // for the OutputDirect optimization @@ -1891,8 +1889,8 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const std::vector resultCompShape = operand.compShape(); usize totalSize = operand.size(); - CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) - : CalcBuffer::allocate(tempDS, nextScratchName(), resultTupleShape, resultCompShape); + CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) : + CalcBuffer::allocate(tempDS, nextScratchName(), resultTupleShape, resultCompShape); for(usize i = 0; i < totalSize; i++) { @@ -1956,8 +1954,8 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const totalSize *= d; } - CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) - : CalcBuffer::allocate(tempDS, nextScratchName(), outTupleShape, outCompShape); + CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) : + CalcBuffer::allocate(tempDS, nextScratchName(), outTupleShape, outCompShape); bool leftIsScalar = left.isScalar(); bool rightIsScalar = right.isScalar(); @@ -2000,8 +1998,8 @@ Result<> ArrayCalculatorParser::evaluateInto(DataStructure& dataStructure, const return MakeErrorResult(static_cast(CalculatorErrorCode::ComponentOutOfRange), fmt::format("Component index {} is out of range for array with {} components.", compIdx, numComps)); } - CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) - : CalcBuffer::allocate(tempDS, nextScratchName(), operand.tupleShape(), std::vector{1}); + CalcBuffer result = (isLastOp && outputIsFloat64) ? CalcBuffer::wrapOutput(dataStructure.getDataRefAs>(outputPath)) : + CalcBuffer::allocate(tempDS, nextScratchName(), operand.tupleShape(), std::vector{1}); for(usize t = 0; t < numTuples; ++t) {