Skip to content

Commit

Permalink
refactor formula generator
Browse files Browse the repository at this point in the history
  • Loading branch information
ckrause committed Jan 3, 2024
1 parent 46e03fc commit c52c4af
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 36 deletions.
65 changes: 31 additions & 34 deletions src/form/formula_gen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
#include "oeis/oeis_sequence.hpp"
#include "sys/log.hpp"

FormulaGenerator::FormulaGenerator()
: interpreter(settings), incEval(interpreter) {}

std::string FormulaGenerator::newName() {
std::string name = "a" + std::to_string(freeNameIndex);
freeNameIndex++;
Expand Down Expand Up @@ -169,21 +172,20 @@ int64_t getNumInitialTermsNeeded(int64_t cell, const std::string fname,
return terms_needed;
}

void FormulaGenerator::initFormula(int64_t numCells, bool use_ie,
const IncrementalEvaluator& ie) {
void FormulaGenerator::initFormula(int64_t numCells, bool useIncEval) {
formula.clear();
for (int64_t cell = 0; cell < numCells; cell++) {
auto key = operandToExpression(Operand(Operand::Type::DIRECT, cell));
if (use_ie) {
if (cell == ie.getSimpleLoop().counter) {
if (useIncEval) {
if (cell == incEval.getSimpleLoop().counter) {
formula.entries[key] = ExpressionUtil::newParameter();
} else if (ie.getInputDependentCells().find(cell) ==
ie.getInputDependentCells().end()) {
} else if (incEval.getInputDependentCells().find(cell) ==
incEval.getInputDependentCells().end()) {
formula.entries[key] = key;
Expression prev(
Expression::Type::SUM, "",
{ExpressionUtil::newParameter(),
ExpressionUtil::newConstant(-ie.getLoopCounterDecrement())});
ExpressionUtil::newConstant(-incEval.getLoopCounterDecrement())});
formula.entries[key].replaceAll(ExpressionUtil::newParameter(), prev);
}
} else {
Expand All @@ -200,11 +202,7 @@ bool FormulaGenerator::generateSingle(const Program& p) {
return false;
}
const int64_t numCells = ProgramUtil::getLargestDirectMemoryCell(p) + 1;

Settings settings;
Interpreter interpreter(settings);
IncrementalEvaluator ie(interpreter);
const bool use_ie = ie.init(p, true); // skip input transformations
const bool useIncEval = incEval.init(p, true); // skip input transformations

// initialize function names for memory cells
cellNames.clear();
Expand All @@ -213,32 +211,32 @@ bool FormulaGenerator::generateSingle(const Program& p) {
}

// initialize expressions for memory cells
initFormula(numCells, false, ie);
initFormula(numCells, false);
std::map<int64_t, Expression> preloop_exprs;
if (use_ie) {
if (useIncEval) {
// TODO: remove this limitation
if (ie.getInputDependentCells().size() > 1 &&
ProgramUtil::numOps(ie.getSimpleLoop().body, Operation::Type::MOV) >
0) {
if (incEval.getInputDependentCells().size() > 1 &&
ProgramUtil::numOps(incEval.getSimpleLoop().body,
Operation::Type::MOV) > 0) {
return false;
}
// update formula based on pre-loop code
if (!update(ie.getSimpleLoop().pre_loop)) {
if (!update(incEval.getSimpleLoop().pre_loop)) {
return false;
}
for (auto cell : ie.getInputDependentCells()) {
for (auto cell : incEval.getInputDependentCells()) {
auto op = Operand(Operand::Type::DIRECT, Number(cell));
auto param = operandToExpression(op);
preloop_exprs[cell] = formula.entries[param];
}
initFormula(numCells, true, ie);
initFormula(numCells, true);
}
Log::get().debug("Initialized formula to " + formula.toString());

// update formula based on main program / loop body
Program main;
if (use_ie) {
main = ie.getSimpleLoop().body;
if (useIncEval) {
main = incEval.getSimpleLoop().body;
} else {
main = p;
}
Expand All @@ -248,12 +246,12 @@ bool FormulaGenerator::generateSingle(const Program& p) {
Log::get().debug("Updated formula: " + formula.toString());

// additional work for IE programs
if (use_ie) {
if (useIncEval) {
// determine number of initial terms needed
std::map<std::string, int64_t> numTerms;
for (int64_t cell = 0; cell < numCells; cell++) {
auto name = getCellName(cell);
numTerms[name] = getNumInitialTermsNeeded(cell, name, formula, ie);
numTerms[name] = getNumInitialTermsNeeded(cell, name, formula, incEval);
}

// find and choose alternative function definitions
Expand All @@ -269,12 +267,12 @@ bool FormulaGenerator::generateSingle(const Program& p) {
// evaluate program and add initial terms to formula
for (int64_t offset = 0; offset < maxNumTerms; offset++) {
try {
ie.next(true, true); // skip final iteration and post loop code
incEval.next(true, true); // skip final iteration and post loop code
} catch (const std::exception&) {
Log::get().debug("Cannot generate initial terms");
return false;
}
const auto state = ie.getLoopStates().at(ie.getPreviousSlice());
const auto state = incEval.getLoopStates().at(incEval.getPreviousSlice());
for (int64_t cell = 0; cell < numCells; cell++) {
auto name = getCellName(cell);
if (offset < numTerms[name]) {
Expand All @@ -289,23 +287,23 @@ bool FormulaGenerator::generateSingle(const Program& p) {
}

// prepare post-loop processing
auto preloop_counter = preloop_exprs.at(ie.getSimpleLoop().counter);
auto preloop_counter = preloop_exprs.at(incEval.getSimpleLoop().counter);
for (int64_t cell = 0; cell < numCells; cell++) {
auto name = newName();
auto left = ExpressionUtil::newFunction(name);
Expression right;
if (cell == ie.getSimpleLoop().counter) {
if (cell == incEval.getSimpleLoop().counter) {
auto last = ExpressionUtil::newConstant(0);
if (ie.getLoopCounterDecrement() > 1) {
if (incEval.getLoopCounterDecrement() > 1) {
auto loop_dec =
ExpressionUtil::newConstant(ie.getLoopCounterDecrement());
ExpressionUtil::newConstant(incEval.getLoopCounterDecrement());
last = Expression(Expression::Type::MODULUS, "",
{preloop_counter, loop_dec});
}
right = Expression(Expression::Type::FUNCTION, "min",
{preloop_counter, last});
} else if (ie.getInputDependentCells().find(cell) !=
ie.getInputDependentCells().end()) {
} else if (incEval.getInputDependentCells().find(cell) !=
incEval.getInputDependentCells().end()) {
right = preloop_exprs.at(cell);
} else {
auto safe_param = preloop_counter;
Expand All @@ -323,8 +321,7 @@ bool FormulaGenerator::generateSingle(const Program& p) {
Log::get().debug("Prepared post-loop: " + formula.toString());

// handle post-loop code
auto post = ie.getSimpleLoop().post_loop;
if (!update(post)) {
if (!update(incEval.getSimpleLoop().post_loop)) {
return false;
}
Log::get().debug("Processed post-loop: " + formula.toString());
Expand Down
9 changes: 7 additions & 2 deletions src/form/formula_gen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@
*/
class FormulaGenerator {
public:
FormulaGenerator();

bool generate(const Program& p, int64_t id, Formula& result, bool withDeps);

private:
bool generateSingle(const Program& p);

void initFormula(int64_t numCells, bool use_ie,
const IncrementalEvaluator& ie);
void initFormula(int64_t numCells, bool useIncEval);

bool update(const Operation& op);

Expand All @@ -45,6 +46,10 @@ class FormulaGenerator {

void simplifyFunctionNames();

Settings settings;
Interpreter interpreter;
IncrementalEvaluator incEval;

Formula formula;
std::map<int64_t, std::string> cellNames;
size_t freeNameIndex;
Expand Down

0 comments on commit c52c4af

Please sign in to comment.