UpdateQuery::operator LITESQL_String() const { LITESQL_String q = LITESQL_L("UPDATE ") + table + LITESQL_L(" SET "); Split sets; for (size_t i = 0; i < fields.size(); i++) sets.push_back(fields[i] + LITESQL_L("=") + values[i]); q += sets.join(LITESQL_L(",")); if (_where.size()) q += LITESQL_L(" WHERE ") + _where; return q; }
void ActivityInTTS::link(const litesql::Database& db, const pomotuxdatabase::Activity& o0, const pomotuxdatabase::TodoTodaySheet& o1) { Record values; Split fields; fields.push_back(Activity.name()); values.push_back(o0.id); fields.push_back(TodoTodaySheet.name()); values.push_back(o1.id); db.insert(table__, values, fields); }
SelectQuery selectObjectQuery(const std::vector<FieldType>& fdatas, const Expr& e) { SelectQuery sel; Split tables; std::set<LITESQL_String> tableSet; for (size_t i = 0; i < fdatas.size(); i++) if (tableSet.find(fdatas[i].table()) == tableSet.end()) { tables.push_back(fdatas[i].table()); tableSet.insert(fdatas[i].table()); } Split tableFilters; tableFilters.resize(tables.size()-1); for (size_t i = 1; i < tables.size(); i++) tableFilters[i-1] = tables[i-1] + LITESQL_L(".id_ = ") + tables[i] + LITESQL_L(".id_"); tableSet.clear(); for (size_t i = 0; i < tables.size(); i++) { sel.source(tables[i]); tableSet.insert(tables[i]); } if (tables.size() > 1) sel.where((e && RawExpr(tableFilters.join(LITESQL_L(" AND ")))).asString()); else sel.where(e.asString()); for (size_t i = 0; i < fdatas.size(); i++) sel.result(fdatas[i].table() + LITESQL_L(".") + fdatas[i].name()); return sel; }
bool QuasarDB::validate(const Split& split) { for (unsigned int i = 0; i < split.allocations().size(); ++i) { const AllocLine& line = split.allocations()[i]; Store store; if (!lookup(line.store_id, store)) return error("Store doesn't exist"); } return validate((Gltx&)split); }
Split *Split::extractSubSplit(Split &taxa_mask) { assert(taxa_mask.getNTaxa() == getNTaxa()); Split *sp = new Split(taxa_mask.countTaxa()); int id = 0; for (int tax = 0; tax < ntaxa; tax++) if (taxa_mask.containTaxon(tax)) { if (containTaxon(tax)) sp->addTaxon(id); id++; } assert(id == sp->getNTaxa()); return sp; }
int rightmost_location(Split in) { string S = in.get_read_string(); char t = in.get_rightmost_val(); for (int i = (S.size() - 1); i >= 0; i--) { if (S[i] == t) { return i; } } return -1; // return -1 if not in the string }
bool Split::subsetOf (Split &sp) { assert(ntaxa == sp.ntaxa); for (iterator it = begin(), it2 = sp.begin(); it != end(); it++, it2++) if ( ((*it) & (*it2)) != (*it) ) return false; return true; }
bool Split::operator==(const Split &sp) const{ if (ntaxa != sp.ntaxa) return false; for (const_iterator it = begin(), it2 = sp.begin(); it != end(); it++, it2++) if ((*it) != (*it2)) return false; return true; }
void Splitter<Heuristic>::split_spatial(const TaskScheduler::ThreadInfo& thread, PrimRefAlloc* alloc, const BuildTriangle* triangles, const Vec3fa* vertices, atomic_set<PrimRefBlock>& prims, const PrimInfo& pinfo, const Split& split) { Heuristic lheuristic(split.linfo,triangles,vertices); Heuristic rheuristic(split.rinfo,triangles,vertices); atomic_set<PrimRefBlock>::item* lblock = lprims.insert(alloc->malloc(thread)); atomic_set<PrimRefBlock>::item* rblock = rprims.insert(alloc->malloc(thread)); while (atomic_set<PrimRefBlock>::item* block = prims.take()) { for (size_t i=0; i<block->size(); i++) { const PrimRef& prim = block->at(i); PrimRef lprim, rprim; split.split(prim,lprim,rprim); if (lprim.id() != size_t(-1) && !lblock->insert(lprim)) { lheuristic.bin(lblock->base(),lblock->size()); lblock = lprims.insert(alloc->malloc(thread)); lblock->insert(lprim); } if (rprim.id() != size_t(-1) && !rblock->insert(rprim)) { rheuristic.bin(rblock->base(),rblock->size()); rblock = rprims.insert(alloc->malloc(thread)); rblock->insert(rprim); } } alloc->free(thread,block); } lheuristic.bin(lblock->base(),lblock->size()); linfo = split.linfo; lheuristic.best(lsplit); rheuristic.bin(rblock->base(),rblock->size()); rinfo = split.rinfo; rheuristic.best(rsplit); }
MultiThreadedSplitter<Heuristic,PrimRefBlockList>::MultiThreadedSplitter(size_t threadIndex, size_t threadCount, TaskScheduler::Event* event, PrimRefAlloc* alloc, const RTCGeometry* geom, PrimRefBlockList& prims_i, const PrimInfo& pinfo, const Split& split, TaskScheduler::completeFunction cfun, void* cptr) : alloc(alloc), prims(prims_i), pinfo(pinfo), split(split), geom(geom), cfun(cfun), cptr(cptr) { /* if split was not successfull enforce some split */ if (unlikely(split.linfo.size() == 0 || split.rinfo.size() == 0)) { FallBackSplitter<Heuristic,PrimRefBlockList>::split(threadIndex,alloc,geom,prims,pinfo,lprims,linfo,lsplit,rprims,rinfo,rsplit); cfun(cptr,threadIndex,threadCount,event); } /* perform spatial split */ else if (unlikely(split.spatial())) { new (&task) TaskScheduler::Task(event, _task_split_parallel_spatial,this,numTasks, _task_split_parallel_reduce,this, "build::parsplit"); TaskScheduler::addTask(threadIndex,TaskScheduler::GLOBAL_FRONT,&task); } /* otherwise perform normal split */ else { new (&task) TaskScheduler::Task(event, _task_split_parallel, this,numTasks, _task_split_parallel_reduce,this, "build::parsplit"); TaskScheduler::addTask(threadIndex,TaskScheduler::GLOBAL_FRONT,&task); } }
void Splitter<Heuristic>::split(size_t thread, PrimRefAlloc* alloc, const RTCGeometry* geom, atomic_set<PrimRefBlock>& prims, const PrimInfo& pinfo, const Split& split) { Heuristic lheuristic(split.linfo,geom); Heuristic rheuristic(split.rinfo,geom); atomic_set<PrimRefBlock>::item* lblock = lprims.insert(alloc->malloc(thread)); atomic_set<PrimRefBlock>::item* rblock = rprims.insert(alloc->malloc(thread)); while (atomic_set<PrimRefBlock>::item* block = prims.take()) { for (size_t i=0; i<block->size(); i++) { const PrimRef& prim = block->at(i); if (split.left(prim)) { if (likely(lblock->insert(prim))) continue; lheuristic.bin(lblock->base(),lblock->size()); lblock = lprims.insert(alloc->malloc(thread)); lblock->insert(prim); } else { if (likely(rblock->insert(prim))) continue; rheuristic.bin(rblock->base(),rblock->size()); rblock = rprims.insert(alloc->malloc(thread)); rblock->insert(prim); } } alloc->free(thread,block); } lheuristic.bin(lblock->base(),lblock->size()); linfo = split.linfo; lheuristic.best(lsplit); rheuristic.bin(rblock->base(),rblock->size()); rinfo = split.rinfo; rheuristic.best(rsplit); }
bool Split::overlap(Split &sp) { assert(ntaxa == sp.ntaxa); iterator it, it2; for (it = begin(), it2 = sp.begin(); it != end(); it++, it2++) if ((*it) & (*it2)) return true; return false; }
void CandidateSet::addCandidateSplits(string treeString) { vector<string> taxaNames = aln->getSeqNames(); MTree tree(treeString, taxaNames, Params::getInstance().is_rooted); SplitGraph allSplits; tree.convertSplits(allSplits); for (SplitGraph::iterator splitIt = allSplits.begin(); splitIt != allSplits.end(); splitIt++) { int value; Split *sp = candSplits.findSplit(*splitIt, value); if (sp != NULL) { sp->setWeight(value + 1); candSplits.setValue(sp, value + 1); } else { sp = new Split(*(*splitIt)); sp->setWeight(1); candSplits.insertSplit(sp, 1); } } candSplits.setNumTree(candSplits.getNumTree() + 1); }
// Returns a vector of Splits. bool QuasarDB::select(vector<Split>& splits, const SplitSelect& conditions) { splits.clear(); QString cmd = gltxCmd("split", "split_id", "account_id," "split.amount,transfer_id", conditions); Statement stmt(connection(), cmd); if (!execute(stmt)) return false; while (stmt.next()) { Split split; int next = 1; selectData(split, stmt, next); selectGltx(split, stmt, next); split.setAccountId(stmtGetId(stmt, next++)); split.setAmount(stmtGetFixed(stmt, next++)); split.setTransferAccount(stmtGetId(stmt, next++)); splits.push_back(split); } QString cmd1 = "select store_id,amount from split_alloc where " "split_id = ? order by seq_num"; Statement stmt1(connection(), cmd1); for (unsigned int i = 0; i < splits.size(); ++i) { Id gltx_id = splits[i].id(); GLTX_ACCOUNTS(splits); stmtSetId(stmt1, gltx_id); if (!execute(stmt1)) return false; while (stmt1.next()) { AllocLine line; line.store_id = stmtGetId(stmt1, 1); line.amount = stmtGetFixed(stmt1, 2); splits[i].allocations().push_back(line); } } commit(); return true; }
/** @param taxa_set set of taxa @return true if this split is preserved in the set taxa_set */ bool Split::preserved(Split &taxa_set) { // be sure that the two split has the same size assert(taxa_set.size() == size() && taxa_set.ntaxa == ntaxa); int time_zero = 0, time_notzero = 0; for (iterator it = begin(), sit = taxa_set.begin(); it != end(); it++, sit++) { UINT res = (*it) & (*sit); if (res != 0 && res != (*sit)) return true; if (*sit != 0) { if (res == 0) time_zero++; else time_notzero++; if (res == 0 && time_notzero > 0) return true; if (res != 0 && time_zero > 0) return true; } } return false; }
// Delete a Split bool QuasarDB::remove(const Split& split) { if (split.id() == INVALID_ID) return false; if (!sqlDeleteLines(split)) return false; if (!remove((Gltx&)split)) return false; commit(); dataSignal(DataEvent::Delete, split); return true; }
bool QuasarDB::sqlCreateLines(const Split& split) { QString cmd = insertText("split_alloc", "split_id", "seq_num,store_id," "amount"); Statement stmt(connection(), cmd); const vector<AllocLine>& lines = split.allocations(); for (unsigned int line = 0; line < lines.size(); ++line) { Id store_id = lines[line].store_id; fixed amount = lines[line].amount; stmtSetId(stmt, split.id()); stmtSetInt(stmt, line); stmtSetId(stmt, store_id); stmtSetFixed(stmt, amount); if (!execute(stmt)) return false; } return true; }
// Update a Split bool QuasarDB::update(const Split& orig, Split& split) { if (orig.id() == INVALID_ID || split.id() == INVALID_ID) return false; if (!validate(split)) return false; if (!update(orig, (Gltx&)split)) return false; // Update the split tables QString cmd = updateText("split", "split_id", "account_id," "amount,transfer_id"); Statement stmt(connection(), cmd); stmtSetId(stmt, split.accountId()); stmtSetFixed(stmt, split.amount()); stmtSetId(stmt, split.transferAccount()); stmtSetId(stmt, split.id()); if (!execute(stmt)) return false; if (!sqlDeleteLines(orig)) return false; if (!sqlCreateLines(split)) return false; commit(); dataSignal(DataEvent::Update, orig); return true; }
// Create a Split bool QuasarDB::create(Split& split) { if (!validate(split)) return false; if (!create((Gltx&)split)) return false; QString cmd = insertText("split", "split_id", "account_id," "amount,transfer_id"); Statement stmt(connection(), cmd); stmtSetId(stmt, split.id()); stmtSetId(stmt, split.accountId()); stmtSetFixed(stmt, split.amount()); stmtSetId(stmt, split.transferAccount()); if (!execute(stmt)) return false; if (!sqlCreateLines(split)) return false; commit(); dataSignal(DataEvent::Insert, split); return true; }
int CandidateSet::computeSplitOccurences(double supportThreshold) { candSplits.clear(); candSplits.setNumTree(size()); /* Store all splits in the best trees in candSplits. * The variable numTree in SpitInMap is the number of trees, from which the splits are converted. */ CandidateSet::iterator treeIt; //vector<string> taxaNames = aln->getSeqNames(); for (treeIt = begin(); treeIt != end(); treeIt++) { MTree tree(treeIt->second.tree, Params::getInstance().is_rooted); SplitGraph splits; tree.convertSplits(splits); SplitGraph::iterator itg; for (itg = splits.begin(); itg != splits.end(); itg++) { int value; Split *sp = candSplits.findSplit(*itg, value); if (sp != NULL) { int newHashWeight = value + 1; double newSupport = (double) newHashWeight / (double) candSplits.getNumTree(); sp->setWeight(newSupport); candSplits.setValue(sp, newHashWeight); } else { sp = new Split(*(*itg)); sp->setWeight(1.0 / (double) candSplits.getNumTree()); candSplits.insertSplit(sp, 1); } } } int newNumStableSplits = countStableSplits(supportThreshold); if (verbose_mode >= VB_MED) { cout << ((double) newNumStableSplits / (aln->getNSeq() - 3)) * 100; cout << " % of the splits are stable (support threshold " << supportThreshold; cout << " from " << candSplits.getNumTree() << " trees)" << endl; } return numStableSplits; }
int main(int argc, char* argv[]) { ifstream file; string input; file.open(argv[1]); if (file.fail()) { cout << "error opening file\n"; return -1; } while (getline(file, input)) { Split output; output.set_values(input); int right_most = rightmost_location(output); cout << right_most << endl; } file.close(); return 0; }
void CandidateSet::removeCandidateSplits(string treeString) { vector<string> taxaNames = aln->getSeqNames(); MTree tree(treeString, taxaNames, Params::getInstance().is_rooted); SplitGraph allSplits; tree.convertSplits(allSplits); for (SplitGraph::iterator splitIt = allSplits.begin(); splitIt != allSplits.end(); splitIt++) { int value = 0; Split *sp; sp = candSplits.findSplit(*splitIt, value); if (value == 0) { cout << "Cannot find split: "; (*splitIt)->report(cout); exit(1); } else { assert(sp->getWeight() >= 1); if (sp->getWeight() > 1) { sp->setWeight(value - 1); } else { candSplits.eraseSplit(*splitIt); } } } candSplits.setNumTree(candSplits.getNumTree() - 1); }
/** @param sp the other split @return true if this split is compatible with sp */ bool Split::compatible(Split &sp) { // be sure that the two split has the same size assert(sp.size() == size() && sp.ntaxa == ntaxa); UINT res = 0, res2 = 0, res3 = 0, res4 = 0; for (iterator it = begin(), sit = sp.begin(); it != end(); it++, sit++) { int num_bits = (it+1 == end()) ? ntaxa % UINT_BITS : UINT_BITS; UINT it2 = (1 << (num_bits-1)) - 1 + (1 << (num_bits-1)) - (*it); UINT sit2 = (1 << (num_bits-1)) - 1 + (1 << (num_bits-1)) - (*sit); res |= (*it) & (*sit); res2 |= (it2) & (sit2); res3 |= (*it) & (sit2); res4 |= (it2) & (*sit); if (res != 0 && res2 != 0 && res3 != 0 && res4 != 0) return false; //if (res != 0 && res != (*it) && res != (*sit) && res2 != 0) //return false; } return true; //return (res == 0) || (res2 == 0) || (res3 == 0) || (res4 == 0); }
void Input(){ //world and location data for current area game_world = gsmRef->getAdventure()->getWorld(); //get command entered getline(cin, input); //separate words in the command args = s.split(input, ' '); //process CommandManager cm(game_world); cm.Process(args); game_world = cm.UpdatedWorld(); }
vector<std::pair<string, Expr>> compute_loop_bounds_after_split(const Split &split, string prefix) { // Define the bounds on the split dimensions using the bounds // on the function args. If it is a purify, we should use the bounds // from the dims instead. vector<std::pair<string, Expr>> let_stmts; Expr old_var_extent = Variable::make(Int(32), prefix + split.old_var + ".loop_extent"); Expr old_var_max = Variable::make(Int(32), prefix + split.old_var + ".loop_max"); Expr old_var_min = Variable::make(Int(32), prefix + split.old_var + ".loop_min"); if (split.is_split()) { Expr inner_extent = split.factor; Expr outer_extent = (old_var_max - old_var_min + split.factor)/split.factor; let_stmts.push_back({ prefix + split.inner + ".loop_min", 0 }); let_stmts.push_back({ prefix + split.inner + ".loop_max", inner_extent-1 }); let_stmts.push_back({ prefix + split.inner + ".loop_extent", inner_extent }); let_stmts.push_back({ prefix + split.outer + ".loop_min", 0 }); let_stmts.push_back({ prefix + split.outer + ".loop_max", outer_extent-1 }); let_stmts.push_back({ prefix + split.outer + ".loop_extent", outer_extent }); } else if (split.is_fuse()) { // Define bounds on the fused var using the bounds on the inner and outer Expr inner_extent = Variable::make(Int(32), prefix + split.inner + ".loop_extent"); Expr outer_extent = Variable::make(Int(32), prefix + split.outer + ".loop_extent"); Expr fused_extent = inner_extent * outer_extent; let_stmts.push_back({ prefix + split.old_var + ".loop_min", 0 }); let_stmts.push_back({ prefix + split.old_var + ".loop_max", fused_extent - 1 }); let_stmts.push_back({ prefix + split.old_var + ".loop_extent", fused_extent }); } else if (split.is_rename()) { let_stmts.push_back({ prefix + split.outer + ".loop_min", old_var_min }); let_stmts.push_back({ prefix + split.outer + ".loop_max", old_var_max }); let_stmts.push_back({ prefix + split.outer + ".loop_extent", old_var_extent }); } // Do nothing for purify return let_stmts; }
Splitter<Heuristic>::Splitter (const TaskScheduler::ThreadInfo& thread, PrimRefAlloc* alloc, const BuildTriangle* triangles, const Vec3fa* vertices, atomic_set<PrimRefBlock>& prims, const PrimInfo& pinfo, const Split& psplit) { /* if split was not successfull enforce some split */ if (unlikely(psplit.linfo.size() == 0 || psplit.rinfo.size() == 0)) { FallBackSplitter<Heuristic,atomic_set<PrimRefBlock> >::split(thread,alloc,triangles,vertices,prims,pinfo,lprims,linfo,lsplit,rprims,rinfo,rsplit); } /* split with support for duplications */ else if (unlikely(psplit.spatial())) { split_spatial(thread,alloc,triangles,vertices,prims,pinfo,psplit); } /* otherwise perform normal split */ else { split(thread,alloc,triangles,vertices,prims,pinfo,psplit); } }
Splitter<Heuristic>::Splitter (size_t thread, PrimRefAlloc* alloc, const RTCGeometry* geom, atomic_set<PrimRefBlock>& prims, const PrimInfo& pinfo, const Split& psplit) { /* if split was not successfull enforce some split */ if (unlikely(psplit.linfo.size() == 0 || psplit.rinfo.size() == 0)) { FallBackSplitter<Heuristic,atomic_set<PrimRefBlock> >::split(thread,alloc,geom,prims,pinfo,lprims,linfo,lsplit,rprims,rinfo,rsplit); } /* split with support for duplications */ else if (unlikely(psplit.spatial())) { split_spatial(thread,alloc,geom,prims,pinfo,psplit); } /* otherwise perform normal split */ else { split(thread,alloc,geom,prims,pinfo,psplit); } assert(linfo.size()); assert(rinfo.size()); }
string OCILib::getSQLType(AT_field_type fieldType, const string& length) const { Split s; switch(fieldType) { case A_field_type_integer: return "INTEGER"; case A_field_type_bigint: return "BIGINT"; case A_field_type_string: s.push_back("VARCHAR("); (length.size()>0)?(s.push_back(length)):(s.push_back("4000")); s.push_back(")"); return s.join(""); case A_field_type_float: return "BINARY_FLOAT"; case A_field_type_double: return "BINARY_DOUBLE"; case A_field_type_boolean: return "INTEGER"; case A_field_type_date: return "INTEGER"; case A_field_type_time: return "INTEGER"; case A_field_type_datetime: return "INTEGER"; case A_field_type_blob: return "BLOB"; default: return ""; } }
void QA::applyOptions(bool isPost) { enablePostProc=isPost; // the first loop for items with higher precedence for( size_t i=0 ; i < optStr.size() ; ++i) { Split split(optStr[i], "="); if( split[0] == "pP" || split[0] == "postProc" || split[0] == "post_proc") { enablePostProc=true; break; } } for( size_t i=0 ; i < optStr.size() ; ++i) { Split split(optStr[i], "="); if( split[0] == "cM" || split[0] == "checkMode" || split[0] == "check_mode" ) { if( split.size() == 2 ) setCheckMode(split[1]); continue; } if( split[0] == "dIP" || split[0] == "dataInProduction" || split[0] == "data_in_production" ) { // effects completeness test in testPeriod() isFileComplete=false; continue; } if( split[0] == "dP" || split[0] == "dataPath" || split[0] == "data_path" ) { if( split.size() == 2 ) // path to the directory where the execution takes place qaFile.setPath(split[1]); continue; } if( split[0] == "f" ) { if( split.size() == 2 ) qaFile.setFile(split[1]); continue; } if( split[0] == "fS" || split[0] == "FileSequence" || split[0] == "file_sequence" ) { if( split.size() == 2 ) fileSequenceState=split[1][0]; continue; } if( split[0] == "oT" || split[0] == "outlierTest" || split[0] == "outlier_test" ) { if( enablePostProc && split.size() == 2 ) outlierOpts.push_back(split[1]); continue; } if( split[0] == "qNF" || split[0] == "qaNcfileFlags" || split[0] == "qa_ncfile_flags" ) { if( split.size() == 2 ) qaNcfileFlags=split[1]; continue; } if( split[0] == "rR" || split[0] == "replicatedRecord" || split[0] == "replicated_record" ) { if( split.size() > 1 ) { // input could be: ..., only_groups=num // then num would be in split[2] std::string tmp( split[1] ); if( split.size() == 3 ) { tmp += '=' ; tmp += split[2] ; } Split csv ; csv.setSeparator(","); BraceOP groups(tmp); while ( groups.next(tmp) ) { csv = tmp; for( size_t i=0 ; i < csv.size() ; ++i ) replicationOpts.push_back(csv[i]); } continue; } } } return; }
vector<ApplySplitResult> apply_split(const Split &split, bool is_update, string prefix, map<string, Expr> &dim_extent_alignment) { vector<ApplySplitResult> result; Expr outer = Variable::make(Int(32), prefix + split.outer); Expr outer_max = Variable::make(Int(32), prefix + split.outer + ".loop_max"); if (split.is_split()) { Expr inner = Variable::make(Int(32), prefix + split.inner); Expr old_max = Variable::make(Int(32), prefix + split.old_var + ".loop_max"); Expr old_min = Variable::make(Int(32), prefix + split.old_var + ".loop_min"); Expr old_extent = Variable::make(Int(32), prefix + split.old_var + ".loop_extent"); dim_extent_alignment[split.inner] = split.factor; Expr base = outer * split.factor + old_min; string base_name = prefix + split.inner + ".base"; Expr base_var = Variable::make(Int(32), base_name); string old_var_name = prefix + split.old_var; Expr old_var = Variable::make(Int(32), old_var_name); map<string, Expr>::iterator iter = dim_extent_alignment.find(split.old_var); TailStrategy tail = split.tail; internal_assert(tail != TailStrategy::Auto) << "An explicit tail strategy should exist at this point\n"; if ((iter != dim_extent_alignment.end()) && is_zero(simplify(iter->second % split.factor))) { // We have proved that the split factor divides the // old extent. No need to adjust the base or add an if // statement. dim_extent_alignment[split.outer] = iter->second / split.factor; } else if (is_negative_const(split.factor) || is_zero(split.factor)) { user_error << "Can't split " << split.old_var << " by " << split.factor << ". Split factors must be strictly positive\n"; } else if (is_one(split.factor)) { // The split factor trivially divides the old extent, // but we know nothing new about the outer dimension. } else if (tail == TailStrategy::GuardWithIf) { // It's an exact split but we failed to prove that the // extent divides the factor. Use predication. // Make a var representing the original var minus its // min. It's important that this is a single Var so // that bounds inference has a chance of understanding // what it means for it to be limited by the if // statement's condition. Expr rebased = outer * split.factor + inner; string rebased_var_name = prefix + split.old_var + ".rebased"; Expr rebased_var = Variable::make(Int(32), rebased_var_name); result.push_back(ApplySplitResult( prefix + split.old_var, rebased_var + old_min, ApplySplitResult::Substitution)); // Tell Halide to optimize for the case in which this // condition is true by partitioning some outer loop. Expr cond = likely(rebased_var < old_extent); result.push_back(ApplySplitResult(cond)); result.push_back(ApplySplitResult(rebased_var_name, rebased, ApplySplitResult::LetStmt)); } else if (tail == TailStrategy::ShiftInwards) { // Adjust the base downwards to not compute off the // end of the realization. // We'll only mark the base as likely (triggering a loop // partition) if we're at or inside the innermost // non-trivial loop. base = likely_if_innermost(base); base = Min::make(base, old_max + (1 - split.factor)); } else { internal_assert(tail == TailStrategy::RoundUp); } // Substitute in the new expression for the split variable ... result.push_back(ApplySplitResult(old_var_name, base_var + inner, ApplySplitResult::Substitution)); // ... but also define it as a let for the benefit of bounds inference. result.push_back(ApplySplitResult(old_var_name, base_var + inner, ApplySplitResult::LetStmt)); result.push_back(ApplySplitResult(base_name, base, ApplySplitResult::LetStmt)); } else if (split.is_fuse()) { // Define the inner and outer in terms of the fused var Expr fused = Variable::make(Int(32), prefix + split.old_var); Expr inner_min = Variable::make(Int(32), prefix + split.inner + ".loop_min"); Expr outer_min = Variable::make(Int(32), prefix + split.outer + ".loop_min"); Expr inner_extent = Variable::make(Int(32), prefix + split.inner + ".loop_extent"); // If the inner extent is zero, the loop will never be // entered, but the bounds expressions lifted out might // contain divides or mods by zero. In the cases where // simplification of inner and outer matter, inner_extent // is a constant, so the max will simplify away. Expr factor = max(inner_extent, 1); Expr inner = fused % factor + inner_min; Expr outer = fused / factor + outer_min; result.push_back(ApplySplitResult(prefix + split.inner, inner, ApplySplitResult::Substitution)); result.push_back(ApplySplitResult(prefix + split.outer, outer, ApplySplitResult::Substitution)); result.push_back(ApplySplitResult(prefix + split.inner, inner, ApplySplitResult::LetStmt)); result.push_back(ApplySplitResult(prefix + split.outer, outer, ApplySplitResult::LetStmt)); // Maintain the known size of the fused dim if // possible. This is important for possible later splits. map<string, Expr>::iterator inner_dim = dim_extent_alignment.find(split.inner); map<string, Expr>::iterator outer_dim = dim_extent_alignment.find(split.outer); if (inner_dim != dim_extent_alignment.end() && outer_dim != dim_extent_alignment.end()) { dim_extent_alignment[split.old_var] = inner_dim->second*outer_dim->second; } } else { // rename or purify result.push_back(ApplySplitResult(prefix + split.old_var, outer, ApplySplitResult::Substitution)); result.push_back(ApplySplitResult(prefix + split.old_var, outer, ApplySplitResult::LetStmt)); } return result; }