3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-03 04:41:21 +00:00

Merge branch 'unstable' of https://git01.codeplex.com/z3 into unstable

This commit is contained in:
Christoph M. Wintersteiger 2014-04-04 17:57:57 +01:00
commit dee21c6656
15 changed files with 11110 additions and 10967 deletions

3
.gitattributes vendored
View file

@ -1 +1,4 @@
# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto
src/api/dotnet/Properties/AssemblyInfo.cs text eol=crlf src/api/dotnet/Properties/AssemblyInfo.cs text eol=crlf

File diff suppressed because it is too large Load diff

View file

@ -1,134 +1,134 @@
/*++ /*++
Copyright (c) 2011 Microsoft Corporation Copyright (c) 2011 Microsoft Corporation
Module Name: Module Name:
duality_profiling.cpp duality_profiling.cpp
Abstract: Abstract:
collection performance information for duality collection performance information for duality
Author: Author:
Ken McMillan (kenmcmil) Ken McMillan (kenmcmil)
Revision History: Revision History:
--*/ --*/
#include <map> #include <map>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef _WINDOWS #ifdef _WINDOWS
#pragma warning(disable:4996) #pragma warning(disable:4996)
#pragma warning(disable:4800) #pragma warning(disable:4800)
#pragma warning(disable:4267) #pragma warning(disable:4267)
#endif #endif
#include "duality_wrapper.h" #include "duality_wrapper.h"
#include "iz3profiling.h" #include "iz3profiling.h"
namespace Duality { namespace Duality {
void show_time(){ void show_time(){
output_time(std::cout,current_time()); output_time(std::cout,current_time());
std::cout << "\n"; std::cout << "\n";
} }
typedef std::map<const char*, struct node> nmap; typedef std::map<const char*, struct node> nmap;
struct node { struct node {
std::string name; std::string name;
clock_t time; clock_t time;
clock_t start_time; clock_t start_time;
nmap sub; nmap sub;
struct node *parent; struct node *parent;
node(); node();
} top; } top;
node::node(){ node::node(){
time = 0; time = 0;
parent = 0; parent = 0;
} }
struct node *current; struct node *current;
struct init { struct init {
init(){ init(){
top.name = "TOTAL"; top.name = "TOTAL";
current = &top; current = &top;
} }
} initializer; } initializer;
struct time_entry { struct time_entry {
clock_t t; clock_t t;
time_entry(){t = 0;}; time_entry(){t = 0;};
void add(clock_t incr){t += incr;} void add(clock_t incr){t += incr;}
}; };
struct ltstr struct ltstr
{ {
bool operator()(const char* s1, const char* s2) const bool operator()(const char* s1, const char* s2) const
{ {
return strcmp(s1, s2) < 0; return strcmp(s1, s2) < 0;
} }
}; };
typedef std::map<const char*, time_entry, ltstr> tmap; typedef std::map<const char*, time_entry, ltstr> tmap;
static std::ostream *pfs; static std::ostream *pfs;
void print_node(node &top, int indent, tmap &totals){ void print_node(node &top, int indent, tmap &totals){
for(int i = 0; i < indent; i++) (*pfs) << " "; for(int i = 0; i < indent; i++) (*pfs) << " ";
(*pfs) << top.name; (*pfs) << top.name;
int dots = 70 - 2 * indent - top.name.size(); int dots = 70 - 2 * indent - top.name.size();
for(int i = 0; i <dots; i++) (*pfs) << "."; for(int i = 0; i <dots; i++) (*pfs) << ".";
output_time(*pfs, top.time); output_time(*pfs, top.time);
(*pfs) << std::endl; (*pfs) << std::endl;
if(indent != 0)totals[top.name.c_str()].add(top.time); if(indent != 0)totals[top.name.c_str()].add(top.time);
for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++) for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++)
print_node(it->second,indent+1,totals); print_node(it->second,indent+1,totals);
} }
void print_profile(std::ostream &os) { void print_profile(std::ostream &os) {
pfs = &os; pfs = &os;
top.time = 0; top.time = 0;
for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++) for(nmap::iterator it = top.sub.begin(); it != top.sub.end(); it++)
top.time += it->second.time; top.time += it->second.time;
tmap totals; tmap totals;
print_node(top,0,totals); print_node(top,0,totals);
(*pfs) << "TOTALS:" << std::endl; (*pfs) << "TOTALS:" << std::endl;
for(tmap::iterator it = totals.begin(); it != totals.end(); it++){ for(tmap::iterator it = totals.begin(); it != totals.end(); it++){
(*pfs) << (it->first) << " "; (*pfs) << (it->first) << " ";
output_time(*pfs, it->second.t); output_time(*pfs, it->second.t);
(*pfs) << std::endl; (*pfs) << std::endl;
} }
profiling::print(os); // print the interpolation stats profiling::print(os); // print the interpolation stats
} }
void timer_start(const char *name){ void timer_start(const char *name){
node &child = current->sub[name]; node &child = current->sub[name];
if(child.name.empty()){ // a new node if(child.name.empty()){ // a new node
child.parent = current; child.parent = current;
child.name = name; child.name = name;
} }
child.start_time = current_time(); child.start_time = current_time();
current = &child; current = &child;
} }
void timer_stop(const char *name){ void timer_stop(const char *name){
if(current->name != name || !current->parent){ if(current->name != name || !current->parent){
std::cerr << "imbalanced timer_start and timer_stop"; std::cerr << "imbalanced timer_start and timer_stop";
exit(1); exit(1);
} }
current->time += (current_time() - current->start_time); current->time += (current_time() - current->start_time);
current = current->parent; current = current->parent;
} }
} }

View file

@ -1,38 +1,38 @@
/*++ /*++
Copyright (c) 2011 Microsoft Corporation Copyright (c) 2011 Microsoft Corporation
Module Name: Module Name:
duality_profiling.h duality_profiling.h
Abstract: Abstract:
collection performance information for duality collection performance information for duality
Author: Author:
Ken McMillan (kenmcmil) Ken McMillan (kenmcmil)
Revision History: Revision History:
--*/ --*/
#ifndef DUALITYPROFILING_H #ifndef DUALITYPROFILING_H
#define DUALITYPROFILING_H #define DUALITYPROFILING_H
#include <ostream> #include <ostream>
namespace Duality { namespace Duality {
/** Start a timer with given name */ /** Start a timer with given name */
void timer_start(const char *); void timer_start(const char *);
/** Stop a timer with given name */ /** Stop a timer with given name */
void timer_stop(const char *); void timer_stop(const char *);
/** Print out timings */ /** Print out timings */
void print_profile(std::ostream &s); void print_profile(std::ostream &s);
/** Show the current time. */ /** Show the current time. */
void show_time(); void show_time();
} }
#endif #endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -340,6 +340,12 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
params p; params p;
return simplify(p); return simplify(p);
} }
expr context::make_var(int idx, const sort &s){
::sort * a = to_sort(s.raw());
return cook(m().mk_var(idx,a));
}
expr expr::qe_lite() const { expr expr::qe_lite() const {
::qe_lite qe(m()); ::qe_lite qe(m());
@ -374,6 +380,12 @@ expr context::make_quant(decl_kind op, const std::vector<sort> &_sorts, const st
return q.ctx().cook(q.m().update_quantifier(thing, is_forall, num_patterns, &_patterns[0], to_expr(b.raw()))); return q.ctx().cook(q.m().update_quantifier(thing, is_forall, num_patterns, &_patterns[0], to_expr(b.raw())));
} }
expr clone_quantifier(decl_kind dk, const expr &q, const expr &b){
quantifier *thing = to_quantifier(q.raw());
bool is_forall = dk == Forall;
return q.ctx().cook(q.m().update_quantifier(thing, is_forall, to_expr(b.raw())));
}
void expr::get_patterns(std::vector<expr> &pats) const { void expr::get_patterns(std::vector<expr> &pats) const {
quantifier *thing = to_quantifier(raw()); quantifier *thing = to_quantifier(raw());
unsigned num_patterns = thing->get_num_patterns(); unsigned num_patterns = thing->get_num_patterns();

File diff suppressed because it is too large Load diff

View file

@ -1,195 +1,195 @@
/*++ /*++
Copyright (c) 2011 Microsoft Corporation Copyright (c) 2011 Microsoft Corporation
Module Name: Module Name:
iz3base.h iz3base.h
Abstract: Abstract:
Base class for interpolators. Includes an AST manager and a scoping Base class for interpolators. Includes an AST manager and a scoping
object as bases. object as bases.
Author: Author:
Ken McMillan (kenmcmil) Ken McMillan (kenmcmil)
Revision History: Revision History:
--*/ --*/
#ifndef IZ3BASE_H #ifndef IZ3BASE_H
#define IZ3BASE_H #define IZ3BASE_H
#include "iz3mgr.h" #include "iz3mgr.h"
#include "iz3scopes.h" #include "iz3scopes.h"
namespace hash_space { namespace hash_space {
template <> template <>
class hash<func_decl *> { class hash<func_decl *> {
public: public:
size_t operator()(func_decl * const &s) const { size_t operator()(func_decl * const &s) const {
return (size_t) s; return (size_t) s;
} }
}; };
} }
/* Base class for interpolators. Includes an AST manager and a scoping /* Base class for interpolators. Includes an AST manager and a scoping
object as bases. */ object as bases. */
class iz3base : public iz3mgr, public scopes { class iz3base : public iz3mgr, public scopes {
public: public:
/** Get the range in which an expression occurs. This is the /** Get the range in which an expression occurs. This is the
smallest subtree containing all occurrences of the smallest subtree containing all occurrences of the
expression. */ expression. */
range &ast_range(ast); range &ast_range(ast);
/** Get the scope of an expression. This is the set of tree nodes in /** Get the scope of an expression. This is the set of tree nodes in
which all of the expression's symbols are in scope. */ which all of the expression's symbols are in scope. */
range &ast_scope(ast); range &ast_scope(ast);
/** Get the range of a symbol. This is the smallest subtree containing /** Get the range of a symbol. This is the smallest subtree containing
all occurrences of the symbol. */ all occurrences of the symbol. */
range &sym_range(symb); range &sym_range(symb);
/** Is an expression local (in scope in some frame)? */ /** Is an expression local (in scope in some frame)? */
bool is_local(ast node){ bool is_local(ast node){
return !range_is_empty(ast_scope(node)); return !range_is_empty(ast_scope(node));
} }
/** Simplify an expression */ /** Simplify an expression */
ast simplify(ast); ast simplify(ast);
/** Constructor */ /** Constructor */
iz3base(ast_manager &_m_manager, iz3base(ast_manager &_m_manager,
const std::vector<ast> &_cnsts, const std::vector<ast> &_cnsts,
const std::vector<int> &_parents, const std::vector<int> &_parents,
const std::vector<ast> &_theory) const std::vector<ast> &_theory)
: iz3mgr(_m_manager), scopes(_parents) { : iz3mgr(_m_manager), scopes(_parents) {
initialize(_cnsts,_parents,_theory); initialize(_cnsts,_parents,_theory);
weak = false; weak = false;
} }
iz3base(const iz3mgr& other, iz3base(const iz3mgr& other,
const std::vector<ast> &_cnsts, const std::vector<ast> &_cnsts,
const std::vector<int> &_parents, const std::vector<int> &_parents,
const std::vector<ast> &_theory) const std::vector<ast> &_theory)
: iz3mgr(other), scopes(_parents) { : iz3mgr(other), scopes(_parents) {
initialize(_cnsts,_parents,_theory); initialize(_cnsts,_parents,_theory);
weak = false; weak = false;
} }
iz3base(const iz3mgr& other, iz3base(const iz3mgr& other,
const std::vector<std::vector<ast> > &_cnsts, const std::vector<std::vector<ast> > &_cnsts,
const std::vector<int> &_parents, const std::vector<int> &_parents,
const std::vector<ast> &_theory) const std::vector<ast> &_theory)
: iz3mgr(other), scopes(_parents) { : iz3mgr(other), scopes(_parents) {
initialize(_cnsts,_parents,_theory); initialize(_cnsts,_parents,_theory);
weak = false; weak = false;
} }
iz3base(const iz3mgr& other) iz3base(const iz3mgr& other)
: iz3mgr(other), scopes() { : iz3mgr(other), scopes() {
weak = false; weak = false;
} }
/* Set our options */ /* Set our options */
void set_option(const std::string &name, const std::string &value){ void set_option(const std::string &name, const std::string &value){
if(name == "weak" && value == "1") weak = true; if(name == "weak" && value == "1") weak = true;
} }
/* Are we doing weak interpolants? */ /* Are we doing weak interpolants? */
bool weak_mode(){return weak;} bool weak_mode(){return weak;}
/** Print interpolation problem to an SMTLIB format file */ /** Print interpolation problem to an SMTLIB format file */
void print(const std::string &filename); void print(const std::string &filename);
/** Check correctness of a solutino to this problem. */ /** Check correctness of a solutino to this problem. */
void check_interp(const std::vector<ast> &itps, std::vector<ast> &theory); void check_interp(const std::vector<ast> &itps, std::vector<ast> &theory);
/** For convenience -- is this formula SAT? */ /** For convenience -- is this formula SAT? */
bool is_sat(const std::vector<ast> &consts, ast &_proof); bool is_sat(const std::vector<ast> &consts, ast &_proof);
/** Interpolator for clauses, to be implemented */ /** Interpolator for clauses, to be implemented */
virtual void interpolate_clause(std::vector<ast> &lits, std::vector<ast> &itps){ virtual void interpolate_clause(std::vector<ast> &lits, std::vector<ast> &itps){
throw "no interpolator"; throw "no interpolator";
} }
ast get_proof_check_assump(range &rng){ ast get_proof_check_assump(range &rng){
std::vector<ast> cs(theory); std::vector<ast> cs(theory);
cs.push_back(cnsts[rng.hi]); cs.push_back(cnsts[rng.hi]);
return make(And,cs); return make(And,cs);
} }
int frame_of_assertion(const ast &ass){ int frame_of_assertion(const ast &ass){
stl_ext::hash_map<ast,int>::iterator it = frame_map.find(ass); stl_ext::hash_map<ast,int>::iterator it = frame_map.find(ass);
if(it == frame_map.end()) if(it == frame_map.end())
throw "unknown assertion"; throw "unknown assertion";
return it->second; return it->second;
} }
void to_parents_vec_representation(const std::vector<ast> &_cnsts, void to_parents_vec_representation(const std::vector<ast> &_cnsts,
const ast &tree, const ast &tree,
std::vector<ast> &cnsts, std::vector<ast> &cnsts,
std::vector<int> &parents, std::vector<int> &parents,
std::vector<ast> &theory, std::vector<ast> &theory,
std::vector<int> &pos_map, std::vector<int> &pos_map,
bool merge = false bool merge = false
); );
protected: protected:
std::vector<ast> cnsts; std::vector<ast> cnsts;
std::vector<ast> theory; std::vector<ast> theory;
private: private:
struct ranges { struct ranges {
range rng; range rng;
range scp; range scp;
bool scope_computed; bool scope_computed;
ranges(){scope_computed = false;} ranges(){scope_computed = false;}
}; };
stl_ext::hash_map<symb,range> sym_range_hash; stl_ext::hash_map<symb,range> sym_range_hash;
stl_ext::hash_map<ast,ranges> ast_ranges_hash; stl_ext::hash_map<ast,ranges> ast_ranges_hash;
stl_ext::hash_map<ast,ast> simplify_memo; stl_ext::hash_map<ast,ast> simplify_memo;
stl_ext::hash_map<ast,int> frame_map; // map assertions to frames stl_ext::hash_map<ast,int> frame_map; // map assertions to frames
int frames; // number of frames int frames; // number of frames
protected: protected:
void add_frame_range(int frame, ast t); void add_frame_range(int frame, ast t);
private: private:
void initialize(const std::vector<ast> &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory); void initialize(const std::vector<ast> &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory);
void initialize(const std::vector<std::vector<ast> > &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory); void initialize(const std::vector<std::vector<ast> > &_parts, const std::vector<int> &_parents, const std::vector<ast> &_theory);
bool is_literal(ast n); bool is_literal(ast n);
void gather_conjuncts_rec(ast n, std::vector<ast> &conjuncts, stl_ext::hash_set<ast> &memo); void gather_conjuncts_rec(ast n, std::vector<ast> &conjuncts, stl_ext::hash_set<ast> &memo);
void gather_conjuncts(ast n, std::vector<ast> &conjuncts); void gather_conjuncts(ast n, std::vector<ast> &conjuncts);
ast simplify_and(std::vector<ast> &conjuncts); ast simplify_and(std::vector<ast> &conjuncts);
ast simplify_with_lit_rec(ast n, ast lit, stl_ext::hash_map<ast,ast> &memo, int depth); ast simplify_with_lit_rec(ast n, ast lit, stl_ext::hash_map<ast,ast> &memo, int depth);
ast simplify_with_lit(ast n, ast lit); ast simplify_with_lit(ast n, ast lit);
void find_children(const stl_ext::hash_set<ast> &cnsts_set, void find_children(const stl_ext::hash_set<ast> &cnsts_set,
const ast &tree, const ast &tree,
std::vector<ast> &cnsts, std::vector<ast> &cnsts,
std::vector<int> &parents, std::vector<int> &parents,
std::vector<ast> &conjuncts, std::vector<ast> &conjuncts,
std::vector<int> &children, std::vector<int> &children,
std::vector<int> &pos_map, std::vector<int> &pos_map,
bool merge bool merge
); );
bool weak; bool weak;
}; };
#endif #endif

View file

@ -464,7 +464,9 @@ namespace hash_space {
Value &operator[](const Key& key) { Value &operator[](const Key& key) {
std::pair<Key,Value> kvp(key,Value()); std::pair<Key,Value> kvp(key,Value());
return lookup(kvp,true)->val.second; return
hashtable<std::pair<Key,Value>,Key,HashFun,proj1<Key,Value>,EqFun>::
lookup(kvp,true)->val.second;
} }
}; };

View file

@ -814,6 +814,10 @@ class iz3proof_itp_impl : public iz3proof_itp {
ast equa = sep_cond(arg(pf,0),cond); ast equa = sep_cond(arg(pf,0),cond);
if(is_equivrel_chain(equa)){ if(is_equivrel_chain(equa)){
ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove ast lhs,rhs; eq_from_ineq(arg(neg_equality,0),lhs,rhs); // get inequality we need to prove
if(!rewrites_from_to(equa,lhs,rhs)){
lhs = arg(arg(neg_equality,0),0); // the equality proved is ambiguous, sadly
rhs = arg(arg(neg_equality,0),1);
}
LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs); LitType lhst = get_term_type(lhs), rhst = get_term_type(rhs);
if(lhst != LitMixed && rhst != LitMixed) if(lhst != LitMixed && rhst != LitMixed)
return unmixed_eq2ineq(lhs, rhs, op(arg(neg_equality,0)), equa, cond); return unmixed_eq2ineq(lhs, rhs, op(arg(neg_equality,0)), equa, cond);
@ -1671,9 +1675,20 @@ class iz3proof_itp_impl : public iz3proof_itp {
return head; return head;
} }
// split a rewrite chain into head and tail at last non-mixed term bool has_mixed_summands(const ast &e){
if(op(e) == Plus){
int nargs = num_args(e);
for(int i = 0; i < nargs; i++)
if(has_mixed_summands(arg(e,i)))
return true;
return false;
}
return get_term_type(e) == LitMixed;
}
// split a rewrite chain into head and tail at last sum with no mixed sumands
ast get_right_movers(const ast &chain, const ast &rhs, ast &tail, ast &mid){ ast get_right_movers(const ast &chain, const ast &rhs, ast &tail, ast &mid){
if(is_true(chain) || get_term_type(rhs) != LitMixed){ if(is_true(chain) || !has_mixed_summands(rhs)){
mid = rhs; mid = rhs;
tail = mk_true(); tail = mk_true();
return chain; return chain;
@ -1686,11 +1701,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
return res; return res;
} }
// split a rewrite chain into head and tail at first non-mixed term // split a rewrite chain into head and tail at first sum with no mixed sumands
ast get_left_movers(const ast &chain, const ast &lhs, ast &tail, ast &mid){ ast get_left_movers(const ast &chain, const ast &lhs, ast &tail, ast &mid){
if(is_true(chain)){ if(is_true(chain)){
mid = lhs; mid = lhs;
if(get_term_type(lhs) != LitMixed){ if(!has_mixed_summands(lhs)){
tail = mk_true(); tail = mk_true();
return chain; return chain;
} }
@ -1790,10 +1805,21 @@ class iz3proof_itp_impl : public iz3proof_itp {
} }
bool rewrites_from_to(const ast &chain, const ast &lhs, const ast &rhs){
if(is_true(chain))
return lhs == rhs;
ast last = chain_last(chain);
ast rest = chain_rest(chain);
ast mid = subst_in_pos(rhs,rewrite_pos(last),rewrite_lhs(last));
return rewrites_from_to(rest,lhs,mid);
}
struct bad_ineq_inference {};
ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){ ast chain_ineqs(opr comp_op, LitType t, const ast &chain, const ast &lhs, const ast &rhs){
if(is_true(chain)){ if(is_true(chain)){
if(lhs != rhs) if(lhs != rhs)
throw "bad ineq inference"; throw bad_ineq_inference();
return make(Leq,make_int(rational(0)),make_int(rational(0))); return make(Leq,make_int(rational(0)),make_int(rational(0)));
} }
ast last = chain_last(chain); ast last = chain_last(chain);
@ -2656,9 +2682,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
pf = make_refl(e); // proof that e = e pf = make_refl(e); // proof that e = e
prover::range erng = pv->ast_scope(e); prover::range erng = pv->ast_scope(e);
#if 0
if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){ if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){
return e; // this term occurs in range, so it's O.K. return e; // this term occurs in range, so it's O.K.
} }
#endif
hash_map<ast,ast>::iterator it = localization_map.find(e); hash_map<ast,ast>::iterator it = localization_map.find(e);

View file

@ -1,321 +1,321 @@
/*++ /*++
Copyright (c) 2011 Microsoft Corporation Copyright (c) 2011 Microsoft Corporation
Module Name: Module Name:
iz3scopes.cpp iz3scopes.cpp
Abstract: Abstract:
Calculations with scopes, for both sequence and tree interpolation. Calculations with scopes, for both sequence and tree interpolation.
Author: Author:
Ken McMillan (kenmcmil) Ken McMillan (kenmcmil)
Revision History: Revision History:
--*/ --*/
#include <assert.h> #include <assert.h>
#include <algorithm> #include <algorithm>
#include "iz3scopes.h" #include "iz3scopes.h"
/** computes the least common ancestor of two nodes in the tree, or SHRT_MAX if none */ /** computes the least common ancestor of two nodes in the tree, or SHRT_MAX if none */
int scopes::tree_lca(int n1, int n2){ int scopes::tree_lca(int n1, int n2){
if(!tree_mode()) if(!tree_mode())
return std::max(n1,n2); return std::max(n1,n2);
if(n1 == SHRT_MIN) return n2; if(n1 == SHRT_MIN) return n2;
if(n2 == SHRT_MIN) return n1; if(n2 == SHRT_MIN) return n1;
if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX; if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX;
while(n1 != n2){ while(n1 != n2){
if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX; if(n1 == SHRT_MAX || n2 == SHRT_MAX) return SHRT_MAX;
assert(n1 >= 0 && n2 >= 0 && n1 < (int)parents.size() && n2 < (int)parents.size()); assert(n1 >= 0 && n2 >= 0 && n1 < (int)parents.size() && n2 < (int)parents.size());
if(n1 < n2) n1 = parents[n1]; if(n1 < n2) n1 = parents[n1];
else n2 = parents[n2]; else n2 = parents[n2];
} }
return n1; return n1;
} }
/** computes the greatest common descendant two nodes in the tree, or SHRT_MIN if none */ /** computes the greatest common descendant two nodes in the tree, or SHRT_MIN if none */
int scopes::tree_gcd(int n1, int n2){ int scopes::tree_gcd(int n1, int n2){
if(!tree_mode()) if(!tree_mode())
return std::min(n1,n2); return std::min(n1,n2);
int foo = tree_lca(n1,n2); int foo = tree_lca(n1,n2);
if(foo == n1) return n2; if(foo == n1) return n2;
if(foo == n2) return n1; if(foo == n2) return n1;
return SHRT_MIN; return SHRT_MIN;
} }
#ifndef FULL_TREE #ifndef FULL_TREE
/** test whether a tree node is contained in a range */ /** test whether a tree node is contained in a range */
bool scopes::in_range(int n, const range &rng){ bool scopes::in_range(int n, const range &rng){
return tree_lca(rng.lo,n) == n && tree_gcd(rng.hi,n) == n; return tree_lca(rng.lo,n) == n && tree_gcd(rng.hi,n) == n;
} }
/** test whether two ranges of tree nodes intersect */ /** test whether two ranges of tree nodes intersect */
bool scopes::ranges_intersect(const range &rng1, const range &rng2){ bool scopes::ranges_intersect(const range &rng1, const range &rng2){
return tree_lca(rng1.lo,rng2.hi) == rng2.hi && tree_lca(rng1.hi,rng2.lo) == rng1.hi; return tree_lca(rng1.lo,rng2.hi) == rng2.hi && tree_lca(rng1.hi,rng2.lo) == rng1.hi;
} }
bool scopes::range_contained(const range &rng1, const range &rng2){ bool scopes::range_contained(const range &rng1, const range &rng2){
return tree_lca(rng2.lo,rng1.lo) == rng1.lo return tree_lca(rng2.lo,rng1.lo) == rng1.lo
&& tree_lca(rng1.hi,rng2.hi) == rng2.hi; && tree_lca(rng1.hi,rng2.hi) == rng2.hi;
} }
scopes::range scopes::range_lub(const range &rng1, const range &rng2){ scopes::range scopes::range_lub(const range &rng1, const range &rng2){
range res; range res;
res.lo = tree_gcd(rng1.lo,rng2.lo); res.lo = tree_gcd(rng1.lo,rng2.lo);
res.hi = tree_lca(rng1.hi,rng2.hi); res.hi = tree_lca(rng1.hi,rng2.hi);
return res; return res;
} }
scopes::range scopes::range_glb(const range &rng1, const range &rng2){ scopes::range scopes::range_glb(const range &rng1, const range &rng2){
range res; range res;
res.lo = tree_lca(rng1.lo,rng2.lo); res.lo = tree_lca(rng1.lo,rng2.lo);
res.hi = tree_gcd(rng1.hi,rng2.hi); res.hi = tree_gcd(rng1.hi,rng2.hi);
return res; return res;
} }
#else #else
namespace std { namespace std {
template <> template <>
class hash<scopes::range_lo > { class hash<scopes::range_lo > {
public: public:
size_t operator()(const scopes::range_lo &p) const { size_t operator()(const scopes::range_lo &p) const {
return p.lo + (size_t)p.next; return p.lo + (size_t)p.next;
} }
}; };
} }
template <> inline template <> inline
size_t stdext::hash_value<scopes::range_lo >(const scopes::range_lo& p) size_t stdext::hash_value<scopes::range_lo >(const scopes::range_lo& p)
{ {
std::hash<scopes::range_lo> h; std::hash<scopes::range_lo> h;
return h(p); return h(p);
} }
namespace std { namespace std {
template <> template <>
class less<scopes::range_lo > { class less<scopes::range_lo > {
public: public:
bool operator()(const scopes::range_lo &x, const scopes::range_lo &y) const { bool operator()(const scopes::range_lo &x, const scopes::range_lo &y) const {
return x.lo < y.lo || x.lo == y.lo && (size_t)x.next < (size_t)y.next; return x.lo < y.lo || x.lo == y.lo && (size_t)x.next < (size_t)y.next;
} }
}; };
} }
struct range_op { struct range_op {
scopes::range_lo *x, *y; scopes::range_lo *x, *y;
int hi; int hi;
range_op(scopes::range_lo *_x, scopes::range_lo *_y, int _hi){ range_op(scopes::range_lo *_x, scopes::range_lo *_y, int _hi){
x = _x; y = _y; hi = _hi; x = _x; y = _y; hi = _hi;
} }
}; };
namespace std { namespace std {
template <> template <>
class hash<range_op > { class hash<range_op > {
public: public:
size_t operator()(const range_op &p) const { size_t operator()(const range_op &p) const {
return (size_t) p.x + (size_t)p.y + p.hi; return (size_t) p.x + (size_t)p.y + p.hi;
} }
}; };
} }
template <> inline template <> inline
size_t stdext::hash_value<range_op >(const range_op& p) size_t stdext::hash_value<range_op >(const range_op& p)
{ {
std::hash<range_op> h; std::hash<range_op> h;
return h(p); return h(p);
} }
namespace std { namespace std {
template <> template <>
class less<range_op > { class less<range_op > {
public: public:
bool operator()(const range_op &x, const range_op &y) const { bool operator()(const range_op &x, const range_op &y) const {
return (size_t)x.x < (size_t)y.x || x.x == y.x && return (size_t)x.x < (size_t)y.x || x.x == y.x &&
((size_t)x.y < (size_t)y.y || x.y == y.y && x.hi < y.hi); ((size_t)x.y < (size_t)y.y || x.y == y.y && x.hi < y.hi);
} }
}; };
} }
struct range_tables { struct range_tables {
hash_map<scopes::range_lo, scopes::range_lo *> unique; hash_map<scopes::range_lo, scopes::range_lo *> unique;
hash_map<range_op,scopes::range_lo *> lub; hash_map<range_op,scopes::range_lo *> lub;
hash_map<range_op,scopes::range_lo *> glb; hash_map<range_op,scopes::range_lo *> glb;
}; };
scopes::range_lo *scopes::find_range_lo(int lo, range_lo *next){ scopes::range_lo *scopes::find_range_lo(int lo, range_lo *next){
range_lo foo(lo,next); range_lo foo(lo,next);
std::pair<range_lo,range_lo *> baz(foo,(range_lo *)0); std::pair<range_lo,range_lo *> baz(foo,(range_lo *)0);
std::pair<hash_map<range_lo,scopes::range_lo *>::iterator,bool> bar = rt->unique.insert(baz); std::pair<hash_map<range_lo,scopes::range_lo *>::iterator,bool> bar = rt->unique.insert(baz);
if(bar.second) if(bar.second)
bar.first->second = new range_lo(lo,next); bar.first->second = new range_lo(lo,next);
return bar.first->second; return bar.first->second;
//std::pair<hash_set<scopes::range_lo>::iterator,bool> bar = rt->unique.insert(foo); //std::pair<hash_set<scopes::range_lo>::iterator,bool> bar = rt->unique.insert(foo);
// const range_lo *baz = &*(bar.first); // const range_lo *baz = &*(bar.first);
// return (range_lo *)baz; // exit const hell // return (range_lo *)baz; // exit const hell
} }
scopes::range_lo *scopes::range_lub_lo(range_lo *rng1, range_lo *rng2){ scopes::range_lo *scopes::range_lub_lo(range_lo *rng1, range_lo *rng2){
if(!rng1) return rng2; if(!rng1) return rng2;
if(!rng2) return rng1; if(!rng2) return rng1;
if(rng1->lo > rng2->lo) if(rng1->lo > rng2->lo)
std::swap(rng1,rng2); std::swap(rng1,rng2);
std::pair<range_op,range_lo *> foo(range_op(rng1,rng2,0),(range_lo *)0); std::pair<range_op,range_lo *> foo(range_op(rng1,rng2,0),(range_lo *)0);
std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->lub.insert(foo); std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->lub.insert(foo);
range_lo *&res = bar.first->second; range_lo *&res = bar.first->second;
if(!bar.second) return res; if(!bar.second) return res;
if(!(rng1->next && rng1->next->lo <= rng2->lo)){ if(!(rng1->next && rng1->next->lo <= rng2->lo)){
for(int lo = rng1->lo; lo <= rng2->lo; lo = parents[lo]) for(int lo = rng1->lo; lo <= rng2->lo; lo = parents[lo])
if(lo == rng2->lo) if(lo == rng2->lo)
{rng2 = rng2->next; break;} {rng2 = rng2->next; break;}
} }
range_lo *baz = range_lub_lo(rng1->next,rng2); range_lo *baz = range_lub_lo(rng1->next,rng2);
res = find_range_lo(rng1->lo,baz); res = find_range_lo(rng1->lo,baz);
return res; return res;
} }
scopes::range_lo *scopes::range_glb_lo(range_lo *rng1, range_lo *rng2, int hi){ scopes::range_lo *scopes::range_glb_lo(range_lo *rng1, range_lo *rng2, int hi){
if(!rng1) return rng1; if(!rng1) return rng1;
if(!rng2) return rng2; if(!rng2) return rng2;
if(rng1->lo > rng2->lo) if(rng1->lo > rng2->lo)
std::swap(rng1,rng2); std::swap(rng1,rng2);
std::pair<range_op,range_lo *> cand(range_op(rng1,rng2,hi),(range_lo *)0); std::pair<range_op,range_lo *> cand(range_op(rng1,rng2,hi),(range_lo *)0);
std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->glb.insert(cand); std::pair<hash_map<range_op,scopes::range_lo *>::iterator,bool> bar = rt->glb.insert(cand);
range_lo *&res = bar.first->second; range_lo *&res = bar.first->second;
if(!bar.second) return res; if(!bar.second) return res;
range_lo *foo; range_lo *foo;
if(!(rng1->next && rng1->next->lo <= rng2->lo)){ if(!(rng1->next && rng1->next->lo <= rng2->lo)){
int lim = hi; int lim = hi;
if(rng1->next) lim = std::min(lim,rng1->next->lo); if(rng1->next) lim = std::min(lim,rng1->next->lo);
int a = rng1->lo, b = rng2->lo; int a = rng1->lo, b = rng2->lo;
while(a != b && b <= lim){ while(a != b && b <= lim){
a = parents[a]; a = parents[a];
if(a > b)std::swap(a,b); if(a > b)std::swap(a,b);
} }
if(a == b && b <= lim){ if(a == b && b <= lim){
foo = range_glb_lo(rng1->next,rng2->next,hi); foo = range_glb_lo(rng1->next,rng2->next,hi);
foo = find_range_lo(b,foo); foo = find_range_lo(b,foo);
} }
else else
foo = range_glb_lo(rng2,rng1->next,hi); foo = range_glb_lo(rng2,rng1->next,hi);
} }
else foo = range_glb_lo(rng1->next,rng2,hi); else foo = range_glb_lo(rng1->next,rng2,hi);
res = foo; res = foo;
return res; return res;
} }
/** computes the lub (smallest containing subtree) of two ranges */ /** computes the lub (smallest containing subtree) of two ranges */
scopes::range scopes::range_lub(const range &rng1, const range &rng2){ scopes::range scopes::range_lub(const range &rng1, const range &rng2){
int hi = tree_lca(rng1.hi,rng2.hi); int hi = tree_lca(rng1.hi,rng2.hi);
if(hi == SHRT_MAX) return range_full(); if(hi == SHRT_MAX) return range_full();
range_lo *lo = range_lub_lo(rng1.lo,rng2.lo); range_lo *lo = range_lub_lo(rng1.lo,rng2.lo);
return range(hi,lo); return range(hi,lo);
} }
/** computes the glb (intersection) of two ranges */ /** computes the glb (intersection) of two ranges */
scopes::range scopes::range_glb(const range &rng1, const range &rng2){ scopes::range scopes::range_glb(const range &rng1, const range &rng2){
if(rng1.hi == SHRT_MAX) return rng2; if(rng1.hi == SHRT_MAX) return rng2;
if(rng2.hi == SHRT_MAX) return rng1; if(rng2.hi == SHRT_MAX) return rng1;
int hi = tree_gcd(rng1.hi,rng2.hi); int hi = tree_gcd(rng1.hi,rng2.hi);
range_lo *lo = hi == SHRT_MIN ? 0 : range_glb_lo(rng1.lo,rng2.lo,hi); range_lo *lo = hi == SHRT_MIN ? 0 : range_glb_lo(rng1.lo,rng2.lo,hi);
if(!lo) hi = SHRT_MIN; if(!lo) hi = SHRT_MIN;
return range(hi,lo); return range(hi,lo);
} }
/** is this range empty? */ /** is this range empty? */
bool scopes::range_is_empty(const range &rng){ bool scopes::range_is_empty(const range &rng){
return rng.hi == SHRT_MIN; return rng.hi == SHRT_MIN;
} }
/** return an empty range */ /** return an empty range */
scopes::range scopes::range_empty(){ scopes::range scopes::range_empty(){
return range(SHRT_MIN,0); return range(SHRT_MIN,0);
} }
/** return a full range */ /** return a full range */
scopes::range scopes::range_full(){ scopes::range scopes::range_full(){
return range(SHRT_MAX,0); return range(SHRT_MAX,0);
} }
/** return the maximal element of a range */ /** return the maximal element of a range */
int scopes::range_max(const range &rng){ int scopes::range_max(const range &rng){
return rng.hi; return rng.hi;
} }
/** return a minimal (not necessarily unique) element of a range */ /** return a minimal (not necessarily unique) element of a range */
int scopes::range_min(const range &rng){ int scopes::range_min(const range &rng){
if(rng.hi == SHRT_MAX) return SHRT_MIN; if(rng.hi == SHRT_MAX) return SHRT_MIN;
return rng.lo ? rng.lo->lo : SHRT_MAX; return rng.lo ? rng.lo->lo : SHRT_MAX;
} }
/** return range consisting of downward closure of a point */ /** return range consisting of downward closure of a point */
scopes::range scopes::range_downward(int _hi){ scopes::range scopes::range_downward(int _hi){
std::vector<bool> descendants(parents.size()); std::vector<bool> descendants(parents.size());
for(int i = descendants.size() - 1; i >= 0 ; i--) for(int i = descendants.size() - 1; i >= 0 ; i--)
descendants[i] = i == _hi || parents[i] < parents.size() && descendants[parents[i]]; descendants[i] = i == _hi || parents[i] < parents.size() && descendants[parents[i]];
for(unsigned i = 0; i < descendants.size() - 1; i++) for(unsigned i = 0; i < descendants.size() - 1; i++)
if(parents[i] < parents.size()) if(parents[i] < parents.size())
descendants[parents[i]] = false; descendants[parents[i]] = false;
range_lo *foo = 0; range_lo *foo = 0;
for(int i = descendants.size() - 1; i >= 0; --i) for(int i = descendants.size() - 1; i >= 0; --i)
if(descendants[i]) foo = find_range_lo(i,foo); if(descendants[i]) foo = find_range_lo(i,foo);
return range(_hi,foo); return range(_hi,foo);
} }
/** add an element to a range */ /** add an element to a range */
void scopes::range_add(int i, range &n){ void scopes::range_add(int i, range &n){
range foo = range(i, find_range_lo(i,0)); range foo = range(i, find_range_lo(i,0));
n = range_lub(foo,n); n = range_lub(foo,n);
} }
/** Choose an element of rng1 that is near to rng2 */ /** Choose an element of rng1 that is near to rng2 */
int scopes::range_near(const range &rng1, const range &rng2){ int scopes::range_near(const range &rng1, const range &rng2){
int frame; int frame;
int thing = tree_lca(rng1.hi,rng2.hi); int thing = tree_lca(rng1.hi,rng2.hi);
if(thing != rng1.hi) return rng1.hi; if(thing != rng1.hi) return rng1.hi;
range line = range(rng1.hi,find_range_lo(rng2.hi,(range_lo *)0)); range line = range(rng1.hi,find_range_lo(rng2.hi,(range_lo *)0));
line = range_glb(line,rng1); line = range_glb(line,rng1);
return range_min(line); return range_min(line);
} }
/** test whether a tree node is contained in a range */ /** test whether a tree node is contained in a range */
bool scopes::in_range(int n, const range &rng){ bool scopes::in_range(int n, const range &rng){
range r = range_empty(); range r = range_empty();
range_add(n,r); range_add(n,r);
r = range_glb(rng,r); r = range_glb(rng,r);
return !range_is_empty(r); return !range_is_empty(r);
} }
/** test whether two ranges of tree nodes intersect */ /** test whether two ranges of tree nodes intersect */
bool scopes::ranges_intersect(const range &rng1, const range &rng2){ bool scopes::ranges_intersect(const range &rng1, const range &rng2){
range r = range_glb(rng1,rng2); range r = range_glb(rng1,rng2);
return !range_is_empty(r); return !range_is_empty(r);
} }
bool scopes::range_contained(const range &rng1, const range &rng2){ bool scopes::range_contained(const range &rng1, const range &rng2){
range r = range_glb(rng1,rng2); range r = range_glb(rng1,rng2);
return r.hi == rng1.hi && r.lo == rng1.lo; return r.hi == rng1.hi && r.lo == rng1.lo;
} }
#endif #endif

View file

@ -1,197 +1,197 @@
/*++ /*++
Copyright (c) 2011 Microsoft Corporation Copyright (c) 2011 Microsoft Corporation
Module Name: Module Name:
iz3scopes.h iz3scopes.h
Abstract: Abstract:
Calculations with scopes, for both sequence and tree interpolation. Calculations with scopes, for both sequence and tree interpolation.
Author: Author:
Ken McMillan (kenmcmil) Ken McMillan (kenmcmil)
Revision History: Revision History:
--*/ --*/
#ifndef IZ3SOPES_H #ifndef IZ3SOPES_H
#define IZ3SOPES_H #define IZ3SOPES_H
#include <vector> #include <vector>
#include <limits.h> #include <limits.h>
class scopes { class scopes {
public: public:
/** Construct from parents vector. */ /** Construct from parents vector. */
scopes(const std::vector<int> &_parents){ scopes(const std::vector<int> &_parents){
parents = _parents; parents = _parents;
} }
scopes(){ scopes(){
} }
void initialize(const std::vector<int> &_parents){ void initialize(const std::vector<int> &_parents){
parents = _parents; parents = _parents;
} }
/** The parents vector defining the tree structure */ /** The parents vector defining the tree structure */
std::vector<int> parents; std::vector<int> parents;
// #define FULL_TREE // #define FULL_TREE
#ifndef FULL_TREE #ifndef FULL_TREE
struct range { struct range {
range(){ range(){
lo = SHRT_MAX; lo = SHRT_MAX;
hi = SHRT_MIN; hi = SHRT_MIN;
} }
short lo, hi; short lo, hi;
}; };
/** computes the lub (smallest containing subtree) of two ranges */ /** computes the lub (smallest containing subtree) of two ranges */
range range_lub(const range &rng1, const range &rng2); range range_lub(const range &rng1, const range &rng2);
/** computes the glb (intersection) of two ranges */ /** computes the glb (intersection) of two ranges */
range range_glb(const range &rng1, const range &rng2); range range_glb(const range &rng1, const range &rng2);
/** is this range empty? */ /** is this range empty? */
bool range_is_empty(const range &rng){ bool range_is_empty(const range &rng){
return rng.hi < rng.lo; return rng.hi < rng.lo;
} }
/** return an empty range */ /** return an empty range */
range range_empty(){ range range_empty(){
range res; range res;
res.lo = SHRT_MAX; res.lo = SHRT_MAX;
res.hi = SHRT_MIN; res.hi = SHRT_MIN;
return res; return res;
} }
/** return an empty range */ /** return an empty range */
range range_full(){ range range_full(){
range res; range res;
res.lo = SHRT_MIN; res.lo = SHRT_MIN;
res.hi = SHRT_MAX; res.hi = SHRT_MAX;
return res; return res;
} }
/** return the maximal element of a range */ /** return the maximal element of a range */
int range_max(const range &rng){ int range_max(const range &rng){
return rng.hi; return rng.hi;
} }
/** return a minimal (not necessarily unique) element of a range */ /** return a minimal (not necessarily unique) element of a range */
int range_min(const range &rng){ int range_min(const range &rng){
return rng.lo; return rng.lo;
} }
/** return range consisting of downward closure of a point */ /** return range consisting of downward closure of a point */
range range_downward(int _hi){ range range_downward(int _hi){
range foo; range foo;
foo.lo = SHRT_MIN; foo.lo = SHRT_MIN;
foo.hi = _hi; foo.hi = _hi;
return foo; return foo;
} }
void range_add(int i, range &n){ void range_add(int i, range &n){
#if 0 #if 0
if(i < n.lo) n.lo = i; if(i < n.lo) n.lo = i;
if(i > n.hi) n.hi = i; if(i > n.hi) n.hi = i;
#else #else
range rng; rng.lo = i; rng.hi = i; range rng; rng.lo = i; rng.hi = i;
n = range_lub(rng,n); n = range_lub(rng,n);
#endif #endif
} }
/** Choose an element of rng1 that is near to rng2 */ /** Choose an element of rng1 that is near to rng2 */
int range_near(const range &rng1, const range &rng2){ int range_near(const range &rng1, const range &rng2){
int frame; int frame;
int thing = tree_lca(rng1.lo,rng2.hi); int thing = tree_lca(rng1.lo,rng2.hi);
if(thing == rng1.lo) frame = rng1.lo; if(thing == rng1.lo) frame = rng1.lo;
else frame = tree_gcd(thing,rng1.hi); else frame = tree_gcd(thing,rng1.hi);
return frame; return frame;
} }
#else #else
struct range_lo { struct range_lo {
int lo; int lo;
range_lo *next; range_lo *next;
range_lo(int _lo, range_lo *_next){ range_lo(int _lo, range_lo *_next){
lo = _lo; lo = _lo;
next = _next; next = _next;
} }
}; };
struct range { struct range {
int hi; int hi;
range_lo *lo; range_lo *lo;
range(int _hi, range_lo *_lo){ range(int _hi, range_lo *_lo){
hi = _hi; hi = _hi;
lo = _lo; lo = _lo;
} }
range(){ range(){
hi = SHRT_MIN; hi = SHRT_MIN;
lo = 0; lo = 0;
} }
}; };
range_tables *rt; range_tables *rt;
/** computes the lub (smallest containing subtree) of two ranges */ /** computes the lub (smallest containing subtree) of two ranges */
range range_lub(const range &rng1, const range &rng2); range range_lub(const range &rng1, const range &rng2);
/** computes the glb (intersection) of two ranges */ /** computes the glb (intersection) of two ranges */
range range_glb(const range &rng1, const range &rng2); range range_glb(const range &rng1, const range &rng2);
/** is this range empty? */ /** is this range empty? */
bool range_is_empty(const range &rng); bool range_is_empty(const range &rng);
/** return an empty range */ /** return an empty range */
range range_empty(); range range_empty();
/** return a full range */ /** return a full range */
range range_full(); range range_full();
/** return the maximal element of a range */ /** return the maximal element of a range */
int range_max(const range &rng); int range_max(const range &rng);
/** return a minimal (not necessarily unique) element of a range */ /** return a minimal (not necessarily unique) element of a range */
int range_min(const range &rng); int range_min(const range &rng);
/** return range consisting of downward closure of a point */ /** return range consisting of downward closure of a point */
range range_downward(int _hi); range range_downward(int _hi);
/** add an element to a range */ /** add an element to a range */
void range_add(int i, range &n); void range_add(int i, range &n);
/** Choose an element of rng1 that is near to rng2 */ /** Choose an element of rng1 that is near to rng2 */
int range_near(const range &rng1, const range &rng2); int range_near(const range &rng1, const range &rng2);
range_lo *find_range_lo(int lo, range_lo *next); range_lo *find_range_lo(int lo, range_lo *next);
range_lo *range_lub_lo(range_lo *rng1, range_lo *rng2); range_lo *range_lub_lo(range_lo *rng1, range_lo *rng2);
range_lo *range_glb_lo(range_lo *rng1, range_lo *rng2, int lim); range_lo *range_glb_lo(range_lo *rng1, range_lo *rng2, int lim);
#endif #endif
/** test whether a tree node is contained in a range */ /** test whether a tree node is contained in a range */
bool in_range(int n, const range &rng); bool in_range(int n, const range &rng);
/** test whether two ranges of tree nodes intersect */ /** test whether two ranges of tree nodes intersect */
bool ranges_intersect(const range &rng1, const range &rng2); bool ranges_intersect(const range &rng1, const range &rng2);
/** test whether range rng1 contained in range rng2 */ /** test whether range rng1 contained in range rng2 */
bool range_contained(const range &rng1, const range &rng2); bool range_contained(const range &rng1, const range &rng2);
private: private:
int tree_lca(int n1, int n2); int tree_lca(int n1, int n2);
int tree_gcd(int n1, int n2); int tree_gcd(int n1, int n2);
bool tree_mode(){return parents.size() != 0;} bool tree_mode(){return parents.size() != 0;}
}; };
#endif #endif

View file

@ -464,7 +464,7 @@ public:
for(int i = 0; i < 2; i++){ // try the second equality both ways for(int i = 0; i < 2; i++){ // try the second equality both ways
if(match_op(eq_ops_r[0],Select,sel_ops,2)) if(match_op(eq_ops_r[0],Select,sel_ops,2))
if(match_op(sel_ops[0],Store,sto_ops,3)) if(match_op(sel_ops[0],Store,sto_ops,3))
if(match_op(eq_ops_r[1],Select,sel_ops2,2)) if(match_op(eq_ops_r[1],Select,sel_ops2,2))
for(int j = 0; j < 2; j++){ // try the first equality both ways for(int j = 0; j < 2; j++){ // try the first equality both ways
if(eq_ops_l[0] == sto_ops[1] if(eq_ops_l[0] == sto_ops[1]
&& eq_ops_l[1] == sel_ops[1] && eq_ops_l[1] == sel_ops[1]
@ -482,8 +482,8 @@ public:
// int frame = range_min(ast_scope(res)); TODO // int frame = range_min(ast_scope(res)); TODO
// antes.push_back(std::pair<ast,int>(res,frame)); // antes.push_back(std::pair<ast,int>(res,frame));
return; return;
} }
std::swap(eq_ops_l[0],eq_ops_l[1]); std::swap(eq_ops_l[0],eq_ops_l[1]);
} }
std::swap(eq_ops_r[0],eq_ops_r[1]); std::swap(eq_ops_r[0],eq_ops_r[1]);
} }

View file

@ -484,7 +484,7 @@ public:
for(int i = 0; i < 2; i++){ // try the second equality both ways for(int i = 0; i < 2; i++){ // try the second equality both ways
if(match_op(eq_ops_r[0],Select,sel_ops,2)) if(match_op(eq_ops_r[0],Select,sel_ops,2))
if(match_op(sel_ops[0],Store,sto_ops,3)) if(match_op(sel_ops[0],Store,sto_ops,3))
if(match_op(eq_ops_r[1],Select,sel_ops2,2)) if(match_op(eq_ops_r[1],Select,sel_ops2,2))
for(int j = 0; j < 2; j++){ // try the first equality both ways for(int j = 0; j < 2; j++){ // try the first equality both ways
if(eq_ops_l[0] == sto_ops[1] if(eq_ops_l[0] == sto_ops[1]
&& eq_ops_l[1] == sel_ops[1] && eq_ops_l[1] == sel_ops[1]
@ -502,8 +502,8 @@ public:
int frame = range_min(ast_scope(res)); int frame = range_min(ast_scope(res));
antes.push_back(std::pair<ast,int>(res,frame)); antes.push_back(std::pair<ast,int>(res,frame));
return; return;
} }
std::swap(eq_ops_l[0],eq_ops_l[1]); std::swap(eq_ops_l[0],eq_ops_l[1]);
} }
std::swap(eq_ops_r[0],eq_ops_r[1]); std::swap(eq_ops_r[0],eq_ops_r[1]);
} }