finalyze moving

This commit is contained in:
2025-03-12 14:28:04 +03:00
parent f840006398
commit 033bbce220
774 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,811 @@
#include "../Utils/leak_detector.h"
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <string>
#include <algorithm>
#include "DvmhDirective.h"
#include "../Distribution/Array.h"
#include "../Distribution/Arrays.h"
#include "../Distribution/GraphCSR.h"
#include "../Utils/errors.h"
#include "../Utils/utils.h"
#include "../GraphCall/graph_calls_func.h"
using std::vector;
using std::tuple;
using std::get;
using std::string;
using std::pair;
using std::set;
using std::map;
using std::set_union;
using std::make_pair;
using std::min;
using std::max;
template<typename setT>
static void uniteSets(const set<setT> &first, const set<setT> &second, set<setT> &result)
{
vector<setT> unitedVector(first.size() + second.size());
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
unitedVector.resize(it - unitedVector.begin());
for (int i = 0; i < (int)unitedVector.size(); ++i)
result.insert(unitedVector[i]);
}
template<typename keyT, typename valT>
static void uniteSets(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
{
vector<pair<keyT, valT>> unitedVector(first.size() + second.size());
auto it = set_union(first.begin(), first.end(), second.begin(), second.end(), unitedVector.begin());
unitedVector.resize(it - unitedVector.begin());
for (int i = 0; i < (int)unitedVector.size(); ++i)
result.insert(unitedVector[i]);
}
template<typename keyT, typename valT>
static void uniteReduction(const map<keyT, valT> &first, const map<keyT, valT> &second, map<keyT, valT> &result)
{
auto itF = first.begin();
for (auto &redList : result)
{
auto itFound = second.find(redList.first);
if (itFound != second.end())
uniteSets(itF->second, itFound->second, redList.second);
++itF;
}
for (auto redList : second)
{
auto itFound = result.find(redList.first);
if (itFound == result.end())
result.insert(itFound, redList);
}
}
template<typename vTuples>
static vTuples uniteOnRules(const vTuples &first, const vTuples &second)
{
vTuples result(first.size());
for (int i = 0; i < (int)first.size(); ++i)
{
bool firstStar = first[i].first == "*";
bool secondStar = second[i].first == "*";
if (firstStar && secondStar)
result[i].first = "*";
else if (firstStar)
result[i] = second[i];
else
result[i] = first[i];
}
return result;
}
template<typename vTuples>
static bool hasConflictUniteOnRules(const vTuples& first, const vTuples& second)
{
if (first.size() != second.size())
return true;
for (int i = 0; i < (int)first.size(); ++i)
{
bool firstStar = first[i].first == "*";
bool secondStar = second[i].first == "*";
if (!firstStar && !secondStar)
return true;
}
return false;
}
ParallelDirective* operator+(const ParallelDirective &left, const ParallelDirective &right)
{
const ParallelDirective *first = &left;
const ParallelDirective *second = &right;
ParallelDirective *result = NULL;
checkNull(first, convertFileName(__FILE__).c_str(), __LINE__);
checkNull(second, convertFileName(__FILE__).c_str(), __LINE__);
bool condition = first->arrayRef == second->arrayRef;
if (sharedMemoryParallelization)
condition = !hasConflictUniteOnRules(first->on, second->on) && !hasConflictUniteOnRules(first->on2, second->on2);
if (condition)
{
if (first->on.size() != second->on.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
result = new ParallelDirective();
result->langType = first->langType;
result->file = first->file;
result->line = first->line;
result->col = first->col;
result->arrayRef = first->arrayRef;
result->arrayRef2 = first->arrayRef2;
result->parallel = vector<string>(first->parallel.size() + second->parallel.size());
result->on = vector<pair<string, pair<int, int>>>(first->on.size());
for (int i = 0; i < (int)first->parallel.size(); ++i)
result->parallel[i] = first->parallel[i];
for (int i = 0; i < (int)second->parallel.size(); ++i)
result->parallel[i + first->parallel.size()] = second->parallel[i];
result->on = uniteOnRules(first->on, second->on);
result->on2 = uniteOnRules(first->on2, second->on2);
uniteVectors(first->across, second->across, result->across);
uniteVectors(first->shadowRenew, second->shadowRenew, result->shadowRenew);
uniteSets(first->privates, second->privates, result->privates);
uniteSets(first->remoteAccess, second->remoteAccess, result->remoteAccess);
result->reduction = first->reduction;
result->reductionLoc = first->reductionLoc;
uniteReduction(first->reduction, second->reduction, result->reduction);
uniteReduction(first->reductionLoc, second->reductionLoc, result->reductionLoc);
}
else
result = new ParallelDirective(left);
return result;
}
static inline int findRule(const int alingDim, const vector<tuple<DIST::Array*, int, pair<int, int>>> &rule, pair<int, pair<int, int>> &retVal)
{
for (int i = 0; i < rule.size(); ++i)
{
if (get<1>(rule[i]) == alingDim)
{
retVal = make_pair(alingDim, get<2>(rule[i]));
return 0;
}
}
return -1;
}
static inline bool isNonDistributedDim(const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForOn,
const vector<tuple<DIST::Array*, int, pair<int, int>>> &ruleForShadow,
const int dimN,
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
const vector<pair<string, pair<int, int>>> &parallelOnRule)
{
if (ruleForShadow.size() <= dimN)
return false;
if (get<0>(ruleForShadow[dimN]) == NULL)
return true;
//check for distributed in declaration or in redistr. rules
const tuple<DIST::Array*, int, pair<int, int>> &toCheck = ruleForShadow[dimN];
const int dimInTepml = get<1>(toCheck);
for (auto &templ : distribution)
{
if (templ.first == get<0>(toCheck))
{
if (templ.second->distRule[dimInTepml] == NONE)
return true;
}
}
//check for distributed in loop
if (dimInTepml >= 0 && dimInTepml < parallelOnRule.size())
if (parallelOnRule[dimInTepml].first == "*")
return true;
return false;
}
vector<tuple<DIST::Array*, int, pair<int, int>>>
getAlignRuleWithTemplate(DIST::Array *array, const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls,
DIST::GraphCSR<int, double, attrType> &reducedG, const DIST::Arrays<int> &allArrays,
const uint64_t regionId)
{
vector<tuple<DIST::Array*, int, pair<int, int>>> retVal;
set<DIST::Array*> realRefs;
getRealArrayRefs(array, array, realRefs, arrayLinksByFuncCalls);
vector<vector<tuple<DIST::Array*, int, pair<int, int>>>> allRuleForShadow(realRefs.size());
int idx = 0;
for (auto &array : realRefs)
reducedG.GetAlignRuleWithTemplate(array, allArrays, allRuleForShadow[idx++], regionId);
if (realRefs.size() == 1)
retVal = allRuleForShadow[0];
else
{
bool eq = isAllRulesEqual(allRuleForShadow);
if (eq == false)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
else
retVal = allRuleForShadow[0];
}
return retVal;
}
bool needCorner(const DIST::Array* currArray, const vector<map<pair<int, int>, int>>& shiftsByAccess, const vector<vector<pair<int, int>>>& refsInLoop)
{
for (auto& access : refsInLoop)
{
int countOfShadows = 0;
if (access.size() < currArray->GetDimSize())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < currArray->GetDimSize(); ++i)
{
const pair<int, int>& coef = access[i];
auto it = shiftsByAccess[i].find(coef);
if (it != shiftsByAccess[i].end())
if (it->second != 0)
countOfShadows++;
}
if (countOfShadows > 1)
return true;
}
return false;
}
static inline string calculateShifts(DIST::GraphCSR<int, double, attrType> &reducedG,
const DIST::Arrays<int> &allArrays,
DIST::Array *arrayRef, DIST::Array *calcForArray,
pair<pair<string, string>, vector<pair<int, int>>> &coeffs,
vector<pair<int, int>> &shifts,
vector<map<pair<int, int>, int>> &shiftsByAccess,
map<DIST::Array*, vector<ArrayOp>>& remoteRegularReads,
const vector<pair<string, pair<int, int>>> baseOnRule,
const vector<pair<string, pair<int, int>>> parallelOnRule,
const map<DIST::Array*, pair<vector<ArrayOp>, vector<bool>>> &readOps, const bool isAcross,
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
const uint64_t regionId,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls)
{
vector<tuple<DIST::Array*, int, pair<int, int>>> ruleForOn, ruleForShadow;
if (!sharedMemoryParallelization)
{
ruleForOn = getAlignRuleWithTemplate(arrayRef, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
ruleForShadow = getAlignRuleWithTemplate(calcForArray, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
}
string out = "";
// check for distributed and not mapped dims -> zero them out ('coeffs.second')
set<DIST::Array*> refs;
getRealArrayRefs(calcForArray, calcForArray, refs, arrayLinksByFuncCalls);
//TODO: need to correct errors
/*if (!sharedMemoryParallelization)
{
for (auto& array : refs)
{
DIST::Array* tmpl = array->GetTemplateArray(regionId);
checkNull(tmpl, convertFileName(__FILE__).c_str(), __LINE__);
auto align = array->GetLinksWithTemplate(regionId);
bool found = false;
for (auto& t : distribution)
{
if (t.first == tmpl)
{
found = true;
for (int aDim = 0; aDim < align.size(); ++aDim)
{
int link = align[aDim];
if (link != -1)
{
int tLink = link;
if (!arrayRef->IsTemplate())
{
auto alignMain = arrayRef->GetLinksWithTemplate(regionId);
for (int z = 0; z < alignMain.size(); ++z)
if (alignMain[z] == tLink)
tLink = z;
}
if (t.second->distRule[link] == dist::BLOCK && baseOnRule[aDim].first == "*")
{
for (int z = 0; z < coeffs.second.size(); ++z)
coeffs.second[z].first = coeffs.second[z].second = 0;
return out;
}
}
}
}
}
if (!found)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
}*/
const pair<vector<ArrayOp>, vector<bool>> *currReadOp = NULL;
auto readIt = readOps.find(calcForArray);
if (readIt != readOps.end())
currReadOp = &(readIt->second);
if(!sharedMemoryParallelization)
{
findAndReplaceDimentions(ruleForOn, allArrays);
findAndReplaceDimentions(ruleForShadow, allArrays);
}
const int len = (int)coeffs.second.size();
vector<pair<int, int>> shift(len);
bool allZero = true;
for (int k = 0; k < len; ++k)
{
shiftsByAccess.push_back(map<pair<int, int>, int>());
shift[k].first = shift[k].second = 0;
if (k != 0)
out += ",";
char buf[256];
// calculate correct shifts from readOp info
if (currReadOp)
{
// no unrecognized read operations
if (currReadOp->second[k] == false)
{
if (sharedMemoryParallelization)
{
for (auto& coefs : currReadOp->first[k].coefficients)
{
auto currAccess = coefs.first;
const int currShift = coefs.first.second;
auto itFound = shiftsByAccess[k].find(currAccess);
if (itFound == shiftsByAccess[k].end())
itFound = shiftsByAccess[k].insert(itFound, make_pair(currAccess, currShift));
}
}
else if (get<0>(ruleForShadow[k]) != NULL)
{
const pair<int, int> currRuleShadow = get<2>(ruleForShadow[k]);
pair<int, pair<int, int>> currRuleOn;
int err = findRule(get<1>(ruleForShadow[k]), ruleForOn, currRuleOn);
if (err == 0)
{
if (currRuleOn.first >= parallelOnRule.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
const pair<int, int> loopRule = DIST::Fx(parallelOnRule[currRuleOn.first].second, currRuleOn.second);
if (loopRule.first != 0)
{
int minShift = 9999999;
int maxShift = -9999999;
for (auto &coefs : currReadOp->first[k].coefficients)
{
auto currAccess = coefs.first;
auto result = DIST::Fx(currAccess, currRuleShadow);
if (result.first == loopRule.first)
{
const int absShift = abs(result.second - loopRule.second);
const int signShift = (result.second - loopRule.second) > 0 ? 1 : -1;
const int currShift = signShift * (absShift / currRuleShadow.first + ((absShift % currRuleShadow.first) != 0));
minShift = std::min(minShift, currShift);
maxShift = std::max(maxShift, currShift);
auto itFound = shiftsByAccess[k].find(currAccess);
if (itFound == shiftsByAccess[k].end())
itFound = shiftsByAccess[k].insert(itFound, make_pair(currAccess, currShift));
}
else // remote_access
{
auto it = remoteRegularReads.find(calcForArray);
if (it == remoteRegularReads.end())
it = remoteRegularReads.insert(it, make_pair(calcForArray, vector<ArrayOp>(calcForArray->GetDimSize())));
it->second[k].coefficients.insert(coefs);
}
}
// inconsistent -> may be remote will add later...
// or SINGLE position
if (minShift == 9999999 && maxShift == -9999999)
minShift = maxShift = 0;
if (minShift == maxShift)
{
if (minShift == 0)
{
if (parallelOnRule[currRuleOn.first].first != "SINGLE")
{
shift[k].first = -coeffs.second[k].first;
shift[k].second = -coeffs.second[k].second;
}
}
else
{
shift[k].first = -minShift;
shift[k].second = minShift;
if (shift[k].first > 0 && shift[k].second < 0)
shift[k].second = 0;
else if (shift[k].first < 0 && shift[k].second > 0)
shift[k].first = 0;
shift[k].first -= coeffs.second[k].first;
shift[k].second -= coeffs.second[k].second;
}
}
else if (currReadOp->first[k].coefficients.size() > 0)
{
if (minShift > 0 && maxShift > 0)
{
shift[k].first = 0;
shift[k].second = std::abs(maxShift) - coeffs.second[k].second;
}
else if (minShift < 0 && maxShift < 0)
{
shift[k].first = std::abs(minShift) - coeffs.second[k].first;
shift[k].second = 0;
}
else
{
shift[k].first = std::abs(minShift) - coeffs.second[k].first;
shift[k].second = std::abs(maxShift) - coeffs.second[k].second;
}
}
}
}
}
}
}
if(!sharedMemoryParallelization)
{
if (coeffs.second[k].first + shift[k].first < 0)
shift[k].first = -coeffs.second[k].first;
if (coeffs.second[k].second + shift[k].second < 0)
shift[k].second = -coeffs.second[k].second;
if (isAcross)
{
if (coeffs.second[k] == make_pair(0, 0))
shift[k] = make_pair(0, 0);
}
else if (isNonDistributedDim(ruleForOn, ruleForShadow, k, distribution, parallelOnRule))
{
shift[k].first = -coeffs.second[k].first;
shift[k].second = -coeffs.second[k].second;
shiftsByAccess[k].clear();
}
}
sprintf(buf, "%d:%d", coeffs.second[k].first + shift[k].first, coeffs.second[k].second + shift[k].second);
shifts[k] = shift[k];
if (coeffs.second[k].first + shift[k].first != 0 || coeffs.second[k].second + shift[k].second != 0)
allZero = false;
out += buf;
}
if (allZero)
return "";
else
return out;
}
string ParallelDirective::genBounds(pair<pair<string, string>, vector<pair<int, int>>> &shadowOp,
vector<pair<int, int>> &shadowOpShift,
DIST::GraphCSR<int, double, attrType> &reducedG,
DIST::Arrays<int> &allArrays, DIST::Array* shadowArray,
map<DIST::Array*, vector<ArrayOp>>& remoteRegularReads,
const map<DIST::Array*, pair<vector<ArrayOp>, vector<bool>>> &readOps,
const bool isAcross,
const uint64_t regionId,
const vector<pair<DIST::Array*, const DistrVariant*>> &distribution,
set<DIST::Array*> &arraysInAcross,
vector<map<pair<int, int>, int>> &shiftsByAccess,
const map<DIST::Array*, set<DIST::Array*>> &arrayLinksByFuncCalls) const
{
checkNull(shadowArray, convertFileName(__FILE__).c_str(), __LINE__);
auto on_ext = on;
if(!sharedMemoryParallelization)
{
//replace to template align ::on
if (arrayRef->IsTemplate() == false)
{
vector<tuple<DIST::Array*, int, pair<int, int>>> ruleForRef =
getAlignRuleWithTemplate(arrayRef, arrayLinksByFuncCalls, reducedG, allArrays, regionId);
findAndReplaceDimentions(ruleForRef, allArrays);
on_ext.clear();
for (int i = 0; i < ruleForRef.size(); ++i)
{
if (get<0>(ruleForRef[i]))
{
on_ext.resize(get<0>(ruleForRef[i])->GetDimSize());
break;
}
}
if (on_ext.size() == 0)
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
std::fill(on_ext.begin(), on_ext.end(), make_pair("*", make_pair(0, 0)));
for (int i = 0; i < ruleForRef.size(); ++i)
if (get<0>(ruleForRef[i]))
on_ext[get<1>(ruleForRef[i])] = on[i];
}
//replace single dim to key word 'SINGLE'
for (int i = 0; i < on_ext.size(); ++i)
{
if (on_ext[i].first != "*")
{
if (std::find(parallel.begin(), parallel.end(), on_ext[i].first) == parallel.end())
on_ext[i].first = "SINGLE";
}
}
}
string ret = "";
if (isAcross)
{
arraysInAcross.insert(shadowArray);
ret = calculateShifts(reducedG, allArrays, arrayRef, shadowArray, shadowOp, shadowOpShift, shiftsByAccess, remoteRegularReads, on, on_ext, readOps, isAcross, distribution, regionId, arrayLinksByFuncCalls);
}
else
{
if (arraysInAcross.find(shadowArray) == arraysInAcross.end())
ret = calculateShifts(reducedG, allArrays, arrayRef, shadowArray, shadowOp, shadowOpShift, shiftsByAccess, remoteRegularReads, on, on_ext, readOps, isAcross, distribution, regionId, arrayLinksByFuncCalls);
}
return ret;
}
static void genVariants(const int dimNum, vector<dist> &currDist, std::vector<DistrVariant> &currdist)
{
if (dimNum == 1)
{
DistrVariant var1(currDist);
var1.distRule.push_back(dist::NONE);
DistrVariant var2(currDist);
var2.distRule.push_back(dist::BLOCK);
currdist.push_back(var1);
currdist.push_back(var2);
}
else
{
vector<dist> next(currDist);
next.push_back(dist::NONE);
genVariants(dimNum - 1, next, currdist);
next.back() = dist::BLOCK;
genVariants(dimNum - 1, next, currdist);
}
}
void DataDirective::createDirstributionVariants(const vector<DIST::Array*> &arraysToDist)
{
for (int i = 0; i < arraysToDist.size(); ++i)
{
vector<DistrVariant> currdist;
vector<dist> currDist;
genVariants(arraysToDist[i]->GetDimSize(), currDist, currdist);
//deprecate by dims
for (auto &variant : currdist)
{
for (int z = 0; z < arraysToDist[i]->GetDimSize(); ++z)
if (arraysToDist[i]->IsDimDepracated(z) || !arraysToDist[i]->IsDimMapped(z))
variant.distRule[z] = dist::NONE;
}
distrRules.push_back(make_pair(arraysToDist[i], currdist));
}
}
string DistrVariantBase::GenRuleBase(const vector<int> &newOrder) const
{
string retVal = "";
retVal += "(";
for (int i = 0; i < distRule.size(); ++i)
{
if (newOrder.size() == 0)
{
if (distRule[i] == dist::NONE)
retVal += "*";
else if (distRule[i] == dist::BLOCK)
retVal += "BLOCK";
}
else
{
if (distRule[newOrder[i]] == dist::NONE)
retVal += "*";
else if (distRule[newOrder[i]] == dist::BLOCK)
retVal += "BLOCK";
}
if (i != distRule.size() - 1)
retVal += ",";
}
retVal += ")";
return retVal;
}
vector<string> DataDirective::GenRule(const vector<int> &rules) const
{
vector<string> retVal;
if (distrRules.size() < rules.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < rules.size(); ++i)
{
if (rules[i] < distrRules[i].second.size())
{
string tmp = distrRules[i].first->GetShortName();
tmp += distrRules[i].second[rules[i]].GenRuleBase(distrRules[i].first->GetNewTemplateDimsOrder());
retVal.push_back(tmp);
}
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
return retVal;
}
vector<vector<dist>> DataDirective::GenRule(const vector<int> &rules, int) const
{
vector<vector<dist>> retVal;
if (distrRules.size() < rules.size())
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
for (int i = 0; i < rules.size(); ++i)
{
if (rules[i] < distrRules[i].second.size())
retVal.push_back(distrRules[i].second[rules[i]].distRule);
else
printInternalError(convertFileName(__FILE__).c_str(), __LINE__);
}
return retVal;
}
vector<string> DataDirective::GenAlignsRules() const
{
vector<string> retVal;
for (int i = 0; i < alignRules.size(); ++i)
retVal.push_back(alignRules[i].GenRuleBase());
return retVal;
}
string AlignRuleBase::GenRuleBase() const
{
string retVal = "";
retVal += "ALIGN " + alignArray->GetShortName() + "(";
for (int i = 0; i < alignRule.size(); ++i)
{
retVal += genStringExpr(alignNames[i], alignRule[i]);
if (i != alignRule.size() - 1)
retVal += ",";
}
retVal += ") WITH " + alignWith->GetShortName() + "(";
vector<string> alignEachDim(alignWith->GetDimSize());
for (int i = 0; i < alignWith->GetDimSize(); ++i)
alignEachDim[i] = "*";
for (int i = 0; i < alignRuleWith.size(); ++i)
if (alignRuleWith[i].first != -1)
alignEachDim[alignRuleWith[i].first] = genStringExpr(alignNames[i], alignRuleWith[i].second);
auto newOrder = alignWith->GetNewTemplateDimsOrder();
if (newOrder.size() != 0)
{
vector<string> alignEachDimNew(alignEachDim);
for (int z = 0; z < newOrder.size(); ++z)
alignEachDim[z] = alignEachDimNew[newOrder[z]];
}
for (int i = 0; i < alignWith->GetDimSize(); ++i)
{
retVal += alignEachDim[i];
if (i != alignWith->GetDimSize() - 1)
retVal += ",";
}
retVal += ")";
return retVal;
}
string AlignRuleBase::toString()
{
string retVal = "";
if (alignArray)
retVal += "#" + std::to_string((long long)alignArray);
else
retVal += "#-1";
if (alignWith)
retVal += "#" + std::to_string((long long)alignWith);
else
retVal += "#-1";
retVal += "#" + std::to_string(alignRule.size());
for (int i = 0; i < alignRule.size(); ++i)
retVal += "#" + std::to_string(alignRule[i].first) + "#" + std::to_string(alignRule[i].second);
retVal += "#" + std::to_string(alignRuleWith.size());
for (int i = 0; i < alignRuleWith.size(); ++i)
retVal += "#" + std::to_string(alignRuleWith[i].first)
+ "#" + std::to_string(alignRuleWith[i].second.first)
+ "#" + std::to_string(alignRuleWith[i].second.second);
return retVal;
}
pair<string, string> convertDigitToPositive(const int digit)
{
char buf[16];
string sign = " + ";
if (digit < 0)
{
sign = " - ";
int val = -digit;
sprintf(buf, "%d", val);
}
else
sprintf(buf, "%d", digit);
return make_pair(sign, buf);
}
string genStringExpr(const string &letter, const pair<int, int> expr)
{
string retVal = "";
if (expr.first == 0 && expr.second == 0)
retVal = "*";
else if (expr.second == 0)
{
if (expr.first == 1)
retVal = letter;
else
{
pair<string, string> digit2 = convertDigitToPositive(expr.first);
if (digit2.first == " - ")
digit2.second = "(-" + digit2.second + ")";
retVal = digit2.second + string(" * ") + letter;
}
}
else
{
pair<string, string> digit1 = convertDigitToPositive(expr.second);
if (expr.first == 1)
retVal = letter + digit1.first + digit1.second;
else
{
pair<string, string> digit2 = convertDigitToPositive(expr.first);
if (digit2.first == " - ")
digit2.second = "(-" + digit2.second + ")";
retVal = digit2.second + string(" * ") + letter + digit1.first + digit1.second;
}
}
return retVal;
}
const std::vector<std::string> AlignRuleBase::alignNames = { "iEX1", "iEX2", "iEX3", "iEX4", "iEX5", "iEX6", "iEX7" };