// Returns true if a and b have parameter and return types. static bool eq_fn_type(const fn_type& a, const fn_type& b) { return a.get_specifiers() == b.get_specifiers() && equivalent(a.get_return_type(), b.get_return_type()) && equivalent(a.get_parameter_types(), b.get_parameter_types()); }
void run( const testcase *tests, size_t tests_size, std::vector<std::pair<const char*,func_t>> f_intersection, std::vector<std::pair<const char*,func_t>> f_union, std::vector<std::pair<const char*,func_t>> f_difference ){ //for(const auto &t : tests){ for(size_t i=0; i<tests_size; ++i){ const auto &t = tests[i]; uint32_t *res = (uint32_t*)aligned_alloc(64, (t.size1+t.size2)*sizeof(uint32_t)); for(const auto &f : f_intersection){ size_t size_res = f.second(t.list1, t.size1, t.list2, t.size2, res); if(!equivalent(res, size_res, t.res_intersection, t.size_intersection)){ //TODO printf("test \"%s\", intersection \"%s\" wrong\nlist1 : ", t.name, f.first); for(size_t i=0; i<t.size1; ++i) printf("%i, ", t.list1[i]); printf("\nlist2 : "); for(size_t i=0; i<t.size2; ++i) printf("%i, ", t.list2[i]); printf("\nresult: "); for(size_t i=0; i<size_res; ++i) printf("%i, ", res[i]); printf("\nexpect: "); for(size_t i=0; i<t.size_intersection; ++i) printf("%i, ", t.res_intersection[i]); printf("\n"); } } for(const auto &f : f_union){ size_t size_res = f.second(t.list1, t.size1, t.list2, t.size2, res); if(!equivalent(res, size_res, t.res_union, t.size_union)){ //TODO printf("test \"%s\", union \"%s\" wrong\nlist1 : ", t.name, f.first); for(size_t i=0; i<t.size1; ++i) printf("%i, ", t.list1[i]); printf("\nlist2 : "); for(size_t i=0; i<t.size2; ++i) printf("%i, ", t.list2[i]); printf("\nresult: "); for(size_t i=0; i<size_res; ++i) printf("%i, ", res[i]); printf("\nexpect: "); for(size_t i=0; i<t.size_union; ++i) printf("%i, ", t.res_union[i]); printf("\n"); } } for(const auto &f : f_difference){ size_t size_res = f.second(t.list1, t.size1, t.list2, t.size2, res); if(!equivalent(res, size_res, t.res_difference, t.size_difference)){ //TODO printf("test \"%s\", difference \"%s\" wrong\nlist1 : ", t.name, f.first); for(size_t i=0; i<t.size1; ++i) printf("%i, ", t.list1[i]); printf("\nlist2 : "); for(size_t i=0; i<t.size2; ++i) printf("%i, ", t.list2[i]); printf("\nresult: "); for(size_t i=0; i<size_res; ++i) printf("%i, ", res[i]); printf("\nexpect: "); for(size_t i=0; i<t.size_difference; ++i) printf("%i, ", t.res_difference[i]); printf("\n"); } } free(res); } }
/** * Returns true if the domain of the factor matches the vertex / vertices. */ bool valid() const { for (vertex_type v : this->vertices()) { if (!equivalent(arguments(v), node_domain_type({v}))) { return false; } } for (edge_type e : this->edges()) { edge_domain_type dom({e.source(), e.target()}); if (!equivalent(arguments(e), dom)) { return false; } } return true; }
bool ts::server::is_builtin_asset(const utf8_string& path_string) { boost::filesystem::path data = config::data_directory; boost::filesystem::path sounds = config::sound_directory; for (boost::filesystem::path path = path_string.string(); !path.empty(); path = path.parent_path()) { if (equivalent(path, data) || equivalent(path, sounds)) { return true; } } return false; }
rb_tree_node* __find_node(const key_type& key) const { rb_tree_node* iter = root_; for (; !__isnil(iter) && !equivalent(iter->value.first, key);) iter = (less(key, iter->value.first)) ? iter->l_child : iter->r_child; return iter; }
int Asset::operator==(Asset &asset) { return equivalent(asset, 1, 1); }
PRIVATE HTChildAnchor * HTAnchor_findChild ARGS2 (HTParentAnchor *,parent, CONST char *,tag) { HTChildAnchor *child; HTList *kids; if (! parent) { if (TRACE) printf ("HTAnchor_findChild called with NULL parent.\n"); return NULL; } if (kids = parent->children) { /* parent has children : search them */ if (tag && *tag) { /* TBL */ while (child = HTList_nextObject (kids)) { if (equivalent(child->tag, tag)) { /* Case sensitive 920226 */ if (TRACE) printf ( "Child anchor %p of parent %p with name `%s' already exists.\n", child, parent, tag); return child; } } } /* end if tag is void */ } else /* parent doesn't have any children yet : create family */ parent->children = HTList_new (); child = HTChildAnchor_new (); if (TRACE) fprintf(stderr, "new Anchor %p named `%s' is child of %p\n", child, (int)tag ? tag : (CONST char *)"" , parent); /* int for apollo */ HTList_addObject (parent->children, child); child->parent = parent; StrAllocCopy(child->tag, tag); return child; }
size_t SymbolTable::map_operand(bh_instruction& instr, size_t operand_idx) { size_t arg_idx = ++(nsymbols_); // Candidate arg_idx if not reused if (bh_is_constant(&instr.operand[operand_idx])) { // Constants if (BH_R123 != instr.constant.type) { // Regular constants table_[arg_idx].const_data = &(instr.constant.value); table_[arg_idx].etype = bhtype_to_etype(instr.constant.type); } else { // "Special" for BH_R123 table_[arg_idx].etype = UINT64; if (1 == operand_idx) { table_[arg_idx].const_data = &(instr.constant.value.r123.start); } else if (2 == operand_idx) { table_[arg_idx].const_data = &(instr.constant.value.r123.key); } else { throw runtime_error("THIS SHOULD NEVER HAPPEN!"); } } table_[arg_idx].data = &table_[arg_idx].const_data; table_[arg_idx].nelem = 1; table_[arg_idx].ndim = 1; table_[arg_idx].start = 0; table_[arg_idx].shape = instr.operand[operand_idx].shape; table_[arg_idx].shape[0] = 1; table_[arg_idx].stride = instr.operand[operand_idx].shape; table_[arg_idx].stride[0] = 0; table_[arg_idx].layout = SCALAR_CONST; table_[arg_idx].base = NULL; } else { table_[arg_idx].const_data= NULL; table_[arg_idx].data = &(bh_base_array(&instr.operand[operand_idx])->data); table_[arg_idx].etype = bhtype_to_etype(bh_base_array(&instr.operand[operand_idx])->type); table_[arg_idx].nelem = bh_base_array(&instr.operand[operand_idx])->nelem; table_[arg_idx].ndim = instr.operand[operand_idx].ndim; table_[arg_idx].start = instr.operand[operand_idx].start; table_[arg_idx].shape = instr.operand[operand_idx].shape; table_[arg_idx].stride = instr.operand[operand_idx].stride; table_[arg_idx].layout = determine_layout(table_[arg_idx]); table_[arg_idx].base = instr.operand[operand_idx].base; } // // Reuse operand identifiers: Detect if we have seen it before and reuse the name. // This is done by comparing the currently investigated operand (arg_idx) // with all other operands in the current scope [1,arg_idx[ // Do remember that 0 is is not a valid operand and we therefore index from 1. // Also we do not want to compare with selv, that is when i == arg_idx. for(size_t i=1; i<arg_idx; ++i) { if (!equivalent(table_[i], table_[arg_idx])) { continue; // Not equivalent, continue search. } // Found one! Use it instead of the incremented identifier. --nsymbols_; arg_idx = i; break; } return arg_idx; }
void sooty::lexing::detail::fold_impl(std::set<base_lexer_ptr> visited_nodes, const base_lexer_ptr& lhs, const base_lexer_ptr& rhs) { if (!lhs || !rhs) return; if (visited_nodes.find(lhs) != visited_nodes.end()) return; visited_nodes.insert(lhs); if (lhs->type == base_lexer::lexer_type::marker) { fold_impl(visited_nodes, lhs->on_success, rhs); } else if (rhs->type == base_lexer::lexer_type::marker) { base_lexer_ptr saved_lhs = clone_tree(lhs); *lhs = *rhs; fold_impl(visited_nodes, lhs->on_success, saved_lhs); } // if lhs is partially equivalent to rhs, then we need to try rhs // if it fails, but try the one /after/ rhs if it succeeds else if ( partially_equivalent(lhs, rhs) ) { if (lhs->on_failure) append_failure(lhs->on_failure, rhs); else lhs->on_failure = rhs; if (lhs->on_success) fold_impl(visited_nodes, lhs->on_success, rhs->on_success); else lhs->on_success = rhs->on_success; } // rhs is partially equivalent to lhs, which means that we have to // test rhs first, *then* lhs. else if ( partially_equivalent(rhs, lhs) ) { base_lexer_ptr lhs_copy = clone_tree(lhs); *lhs = *rhs; visited_nodes.erase(lhs); fold_impl(visited_nodes, lhs, lhs_copy); } else if ( equivalent(lhs, rhs) ) { if (lhs->on_success) fold_impl(visited_nodes, lhs->on_success, rhs->on_success); else { lhs->on_success = rhs->on_success; if (lhs->on_failure) { append_failure(lhs->on_success, lhs->on_failure); lhs->on_failure = base_lexer_ptr(); } } } else { if (lhs->on_failure) fold_impl(visited_nodes, lhs->on_failure, rhs); else lhs->on_failure = rhs; } }
int main() { bignumber<> a(1), b(1); //使用默认参数,"<>"不能省略 std::cout << equivalent(a, b) << std::endl; //函数模板参数自动推导 std::cout << equivalent<double>(1, 2) << std::endl; std::cin.get(); return 0; }
data_type& operator[](const key_type& k) { iterator i = std::lower_bound(m_impl->begin(), m_impl->end(), k, Compare()); if (i != m_impl->end() && equivalent(i->first, k)) { return i->second; } return (*(m_impl->insert(i, value_type(k, data_type())))).second; }
HTAnchor * HTAnchor_findAddress ARGS1 (CONST char *,address) { char *tag = HTParse (address, "", PARSE_ANCHOR); /* Anchor tag specified ? */ /* If the address represents a sub-anchor, we recursively load its parent, then we create a child anchor within that document. */ if (tag && *tag) { char *docAddress = HTParse(address, "", PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION); HTParentAnchor * foundParent = (HTParentAnchor *) HTAnchor_findAddress (docAddress); HTChildAnchor * foundAnchor = HTAnchor_findChild (foundParent, tag); free (docAddress); free (tag); return (HTAnchor *) foundAnchor; } else { /* If the address has no anchor tag, check whether we have this node */ int hash; CONST char *p; HTList * adults; HTList *grownups; HTParentAnchor * foundAnchor; if (tag && *tag) free (tag); /* Select list from hash table */ for(p=address, hash=0; *p; p++) hash = (hash * 3 + *p) % HASH_SIZE; if (!adult_table) adult_table = (HTList**) calloc(HASH_SIZE, sizeof(HTList*)); if (!adult_table[hash]) adult_table[hash] = HTList_new(); adults = adult_table[hash]; /* Search list for anchor */ grownups = adults; while (foundAnchor = HTList_nextObject (grownups)) { if (equivalent(foundAnchor->address, address)) { if (TRACE) fprintf(stderr, "Anchor %p with address `%s' already exists.\n", foundAnchor, address); return (HTAnchor *) foundAnchor; } } /* Node not found : create new anchor */ foundAnchor = HTParentAnchor_new (); if (TRACE) fprintf(stderr, "New anchor %p has hash %d and address `%s'\n", foundAnchor, hash, address); StrAllocCopy(foundAnchor->address, address); HTList_addObject (adults, foundAnchor); return (HTAnchor *) foundAnchor; } }
inline bool equivalent (const std::vector<T> &a, const std::vector<T> &b) { if (a.size() != b.size()) return false; typename std::vector<T>::const_iterator ai, ae, bi; for (ai = a.begin(), ae = a.end(), bi = b.begin(); ai != ae; ++ai, ++bi) if (! equivalent(*ai, *bi)) return false; return true; }
iterator find(const key_type& x) { iterator pos = std::lower_bound(m_impl->begin(), m_impl->end(), x, Compare()); if (pos != m_impl->end() && equivalent(pos->first, x)) { return pos; } else { return m_impl->end(); } }
std::pair<iterator, bool> insert(const value_type& x) { iterator i = std::lower_bound(m_impl->begin(), m_impl->end(), x, Compare()); if (i != m_impl->end() && equivalent(i->first, x.first)) { return std::pair<iterator, bool>(i, false); } else { return std::pair<iterator, bool>(m_impl->insert(i, x), true); } }
size_type erase(const key_type& x) { iterator i = std::lower_bound(m_impl->begin(), m_impl->end(), x, Compare()); if (i != m_impl->end() && equivalent(i->first, x)) { m_impl->erase(i); return 1; } else { return 0; } }
void EDL::set_outpoint(double position) { if(equivalent(local_session->get_outpoint(), position) && local_session->get_outpoint() >= 0) { local_session->unset_outpoint(); } else { local_session->set_outpoint(align_to_frame(position, 0)); if(local_session->get_inpoint() >= local_session->get_outpoint()) local_session->unset_inpoint(); } }
BOOST_FIXTURE_TEST_CASE(test_marginal, basic_fixture) { decomposable<ptable> model; model *= factors; domain<var> dom = {lvfailure, history, cvp, pcwp, hypovolemia}; ptable marginal = model.marginal(dom); BOOST_CHECK_CLOSE(marginal.entropy(), 4.27667, 1e-3); BOOST_CHECK_EQUAL(marginal.arguments(), dom); decomposable<ptable> marginal_model; model.marginal(dom, marginal_model); BOOST_CHECK(equivalent(domain<var>(marginal_model.arguments()), dom)); BOOST_CHECK_CLOSE(marginal_model.entropy(), 4.27667, 1e-3); }
static int found_override(const char *top, const char *bottom) { _cleanup_free_ char *dest = NULL; int k; pid_t pid; assert(top); assert(bottom); if (null_or_empty_path(top) > 0) { notify_override_masked(top, bottom); return 0; } k = readlink_malloc(top, &dest); if (k >= 0) { if (equivalent(dest, bottom) > 0) notify_override_equivalent(top, bottom); else notify_override_redirected(top, bottom); return 0; } notify_override_overridden(top, bottom); if (!arg_diff) return 0; putchar('\n'); fflush(stdout); pid = fork(); if (pid < 0) { log_error("Failed to fork off diff: %m"); return -errno; } else if (pid == 0) { execlp("diff", "diff", "-us", "--", bottom, top, NULL); log_error("Failed to execute diff: %m"); _exit(1); } wait_for_terminate(pid, NULL); putchar('\n'); return 0; }
static int found_override(const char *top, const char *bottom) { _cleanup_free_ char *dest = NULL; int k; pid_t pid; assert(top); assert(bottom); if (null_or_empty_path(top) > 0) return notify_override_masked(top, bottom); k = readlink_malloc(top, &dest); if (k >= 0) { if (equivalent(dest, bottom) > 0) return notify_override_equivalent(top, bottom); else return notify_override_redirected(top, bottom); } k = notify_override_overridden(top, bottom); if (!arg_diff) return k; putchar('\n'); fflush(stdout); pid = fork(); if (pid < 0) return log_error_errno(errno, "Failed to fork off diff: %m"); else if (pid == 0) { (void) reset_all_signal_handlers(); (void) reset_signal_mask(); assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); execlp("diff", "diff", "-us", "--", bottom, top, NULL); log_error_errno(errno, "Failed to execute diff: %m"); _exit(EXIT_FAILURE); } wait_for_terminate_and_warn("diff", pid, false); putchar('\n'); return k; }
void SkPictureRecord::addBitmap(const SkBitmap& bitmap) { // First see if we already have this bitmap. This deduplication should really // only be important for our tests, where bitmaps tend not to be tagged immutable. // In Chrome (and hopefully Android?) they're typically immutable. for (int i = 0; i < fBitmaps.count(); i++) { if (equivalent(fBitmaps[i], bitmap)) { this->addInt(i); // Unlike the rest, bitmap indices are 0-based. return; } } // Don't have it. We'll add it to our list, making sure it's tagged as immutable. if (bitmap.isImmutable()) { // Shallow copies of bitmaps are cheap, so immutable == fast. fBitmaps.push_back(bitmap); } else { // If you see this block on a memory profile, it's a good opportunity to reduce RAM usage. SkBitmap copy; bitmap.copyTo(©); copy.setImmutable(); fBitmaps.push_back(copy); } this->addInt(fBitmaps.count()-1); // Remember, 0-based. }
void OSLCompilerImpl::write_oso_const_value (const ConstantSymbol *sym) const { ASSERT (sym); TypeDesc type = sym->typespec().simpletype(); TypeDesc elemtype = type.elementtype(); int nelements = std::max (1, type.arraylen); if (elemtype == TypeDesc::STRING) for (int i = 0; i < nelements; ++i) oso ("\"%s\"%s", sym->strval(i).c_str(), nelements>1 ? " " : ""); else if (elemtype == TypeDesc::INT) for (int i = 0; i < nelements; ++i) oso ("%d%s", sym->intval(i), nelements>1 ? " " : ""); else if (elemtype == TypeDesc::FLOAT) for (int i = 0; i < nelements; ++i) oso ("%.8g%s", sym->floatval(i), nelements>1 ? " " : ""); else if (equivalent (elemtype, TypeDesc::TypeVector)) for (int i = 0; i < nelements; ++i) oso ("%.8g %.8g %.8g%s", sym->vecval(i)[0], sym->vecval(i)[1], sym->vecval(i)[2], nelements>1 ? " " : ""); else { ASSERT (0 && "Don't know how to output this constant type"); } }
/* Recursively create symbolic links from the current directory to the "from" directory. Assumes that files described by fs and ts are directories. */ static int dodir (char *fn, /* name of "from" directory, either absolute or relative to cwd */ struct stat *fs, struct stat *ts, /* stats for the "from" directory and cwd */ int rel) /* if true, prepend "../" to fn before using */ { DIR *df; struct dirent *dp; char buf[MAXPATHLEN + 1], *p; char symbuf[MAXPATHLEN + 1]; char basesym[MAXPATHLEN + 1]; struct stat sb, sc; int n_dirs; int symlen; int basesymlen = -1; char *ocurdir; if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) { msg ("%s: From and to directories are identical!", fn); return 1; } if (rel) strcpy (buf, "../"); else buf[0] = '\0'; strcat (buf, fn); if (!(df = opendir (buf))) { msg ("%s: Cannot opendir", buf); return 1; } p = buf + strlen (buf); if (*(p - 1) != '/') *p++ = '/'; n_dirs = fs->st_nlink; while ((dp = readdir (df))) { if (dp->d_name[strlen(dp->d_name) - 1] == '~') continue; #ifdef __DARWIN__ /* Ignore these Mac OS X Finder data files */ if (!strcmp(dp->d_name, ".DS_Store") || !strcmp(dp->d_name, "._.DS_Store")) continue; #endif strcpy (p, dp->d_name); if (n_dirs > 0) { if (lstat (buf, &sb) < 0) { mperror (buf); continue; } #ifdef S_ISDIR if(S_ISDIR(sb.st_mode)) #else if ((sb.st_mode & S_IFMT) == S_IFDIR) #endif { /* directory */ n_dirs--; if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) continue; if (!with_revinfo) { if (!strcmp (dp->d_name, "BitKeeper")) continue; if (!strcmp (dp->d_name, "RCS")) continue; if (!strcmp (dp->d_name, "SCCS")) continue; if (!strcmp (dp->d_name, "CVS")) continue; if (!strcmp (dp->d_name, "CVS.adm")) continue; if (!strcmp (dp->d_name, ".svn")) continue; } ocurdir = rcurdir; rcurdir = buf; curdir = silent ? buf : (char *)0; if (!silent) printf ("%s:\n", buf); if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) { if (mkdir (dp->d_name, 0777) < 0 || stat (dp->d_name, &sc) < 0) { mperror (dp->d_name); curdir = rcurdir = ocurdir; continue; } } if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) { msg ("%s: is a link instead of a directory", dp->d_name); curdir = rcurdir = ocurdir; continue; } if (chdir (dp->d_name) < 0) { mperror (dp->d_name); curdir = rcurdir = ocurdir; continue; } dodir (buf, &sb, &sc, (buf[0] != '/')); if (chdir ("..") < 0) quiterr (1, ".."); curdir = rcurdir = ocurdir; continue; } } /* non-directory */ symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1); if (symlen >= 0) symbuf[symlen] = '\0'; /* The option to ignore links exists mostly because checking for them slows us down by 10-20%. But it is off by default because this really is a useful check. */ if (!ignore_links) { /* see if the file in the base tree was a symlink */ basesymlen = readlink(buf, basesym, sizeof(basesym) - 1); if (basesymlen >= 0) basesym[basesymlen] = '\0'; } if (symlen >= 0) { /* Link exists in new tree. Print message if it doesn't match. */ if (!equivalent (basesymlen>=0 ? basesym : buf, symbuf, basesymlen>=0 ? (char **) 0 : &p)) msg ("%s: %s", dp->d_name, symbuf); } else { char *sympath; if (basesymlen>=0) { if ((buf[0] == '.') && (buf[1] == '.') && (buf[2] == '/') && (basesym[0] == '.') && (basesym[1] == '.') && (basesym[2] == '/')) { /* It becomes very tricky here. We have ../../bar/foo symlinked to ../xxx/yyy. We can't just use ../xxx/yyy. We have to use ../../bar/foo/../xxx/yyy. */ int i; char *start, *end; strcpy (symbuf, buf); /* Find the first char after "../" in symbuf. */ start = symbuf; do { start += 3; } while ((start[0] == '.') && (start[1] == '.') && (start[2] == '/')); /* Then try to eliminate "../"s in basesym. */ i = 0; end = strrchr (symbuf, '/'); if (start < end) { do { i += 3; end--; while ((*end != '/') && (end != start)) end--; if (end == start) break; } while ((basesym[i] == '.') && (basesym[i + 1] == '.') && (basesym[i + 2] == '/')); } if (*end == '/') end++; strcpy (end, &basesym[i]); sympath = symbuf; } else sympath = basesym; } else sympath = buf; if (symlink (sympath, dp->d_name) < 0) mperror (dp->d_name); } } closedir (df); return 0; }
// Returns true if a and b have equivalent reference types. static inline bool eq_ref_type(const ref_type& a, const ref_type& b) { return equivalent(a.get_object_type(), b.get_object_type()); }
namespace Geometry { UnitTest::Suite AxisTestSuite { "Euclid::Geometry::Axis", {"Construction", [](UnitTest::Examiner & examiner) { auto a1 = Axis<RealT>{IDENTITY}; examiner << "Identity axis has zero translation." << std::endl; examiner.check(a1.translation().equivalent(0)); examiner << "Identity axis has zero rotation." << std::endl; examiner.check(a1.rotation().angle().equivalent(0_deg)); auto a2 = Axis<RealT>{{1, 2, 3}, rotate<Z>(R90)}; examiner << "Axis has correct translation." << std::endl; examiner.check(a2.translation().equivalent({1, 2, 3})); examiner << "Axis has correct rotation." << std::endl; examiner.check(a2.rotation().equivalent((Quat)rotate<Z>(R90))); // This transform should move any points from axis-space to origin-space auto p1 = a2.to_origin() * Vec3(1, 2, 3); /// This transform should move any points from origin-space to axis-space auto p2 = a2.from_origin() * Vec3(0); examiner << "Point is transformed to origin." << std::endl; examiner.check(p1.equivalent(0)); examiner << "Point is transformed from origin." << std::endl; examiner.check(p2.equivalent({1, 2, 3})); auto p3 = a2.to_origin() * Vec3(2, 2, 3); examiner << "Point is rotated correctly around Z." << std::endl; examiner.check(p3.equivalent({0, 1, 0})); } }, {"Axis-Axis Mating", [](UnitTest::Examiner & examiner) { auto a1 = Axis<RealT>({10, 10, 10}, IDENTITY); auto a2 = Axis<RealT>({-5, -5, -5}, rotate<Z>(R90)); auto m1 = a1.mate_with(a2); auto p1 = m1 * Vec3(10, 10, 10); examiner << "Point is translated." << std::endl; examiner.check(p1.equivalent({-5, -5, -5})); auto p2 = m1 * Vec3(10, 10, 15); examiner << "Point is translated." << std::endl; examiner.check(p2.equivalent({-5, -5, 0})); auto p3 = m1 * Vec3(10, 15, 10); examiner << "Point is translated and rotated." << std::endl; examiner.check(p3.equivalent({-10, -5, -5})); auto m2 = a1.mate_with(a2, translate(Vec3{1, 1, 1})); auto p4 = m2 * Vec3(10, 10, 10); examiner << "Point is transformed with intermediate translation." << std::endl; examiner.check(p4.equivalent({-6, -4, -4})); } }, }; }
TypeSpec ASTbinary_expression::typecheck (TypeSpec expected) { typecheck_children (expected); TypeSpec l = left()->typespec(); TypeSpec r = right()->typespec(); // No binary ops work on structs or arrays if (l.is_structure() || r.is_structure() || l.is_array() || r.is_array()) { error ("Not allowed: '%s %s %s'", type_c_str(l), opname(), type_c_str(r)); return TypeSpec (); } // Special for closures -- just a few cases to worry about if (l.is_color_closure() || r.is_color_closure()) { if (m_op == Add) { if (l.is_color_closure() && r.is_color_closure()) return m_typespec = l; } if (m_op == Mul) { if (l.is_color_closure() && (r.is_color() || r.is_int_or_float())) return m_typespec = l; if (r.is_color_closure() && (l.is_color() || l.is_int_or_float())) { // N.B. Reorder so that it's always r = closure * k, // not r = k * closure. See codegen for why this helps. std::swap (m_children[0], m_children[1]); return m_typespec = r; } } // If we got this far, it's an op that's not allowed error ("Not allowed: '%s %s %s'", type_c_str(l), opname(), type_c_str(r)); return TypeSpec (); } switch (m_op) { case Sub : case Add : case Mul : case Div : // Add/Sub/Mul/Div work for any equivalent types, and // combination of int/float and other numeric types, but do not // work with strings. Add/Sub don't work with matrices, but // Mul/Div do. // FIXME -- currently, equivalent types combine to make the // left type. But maybe we should be more careful, for example // point-point -> vector, etc. if (l.is_string() || r.is_string()) break; // Dispense with strings trivially if ((m_op == Sub || m_op == Add) && (l.is_matrix() || r.is_matrix())) break; // Matrices don't combine for + and - if (equivalent (l, r) || (l.is_numeric() && r.is_int_or_float()) || (l.is_int_or_float() && r.is_numeric())) return m_typespec = higherprecision (l.simpletype(), r.simpletype()); break; case Mod : // Mod only works with ints, and return ints. if (l.is_int() && r.is_int()) return m_typespec = TypeDesc::TypeInt; break; case Equal : case NotEqual : // Any equivalent types can be compared with == and !=, also a // float or int can be compared to any other numeric type. // Result is always an int. if (equivalent (l, r) || (l.is_numeric() && r.is_int_or_float()) || (l.is_int_or_float() && r.is_numeric())) return m_typespec = TypeDesc::TypeInt; break; case Greater : case Less : case GreaterEqual : case LessEqual : // G/L comparisons only work with floats or ints, and always // return int. if (l.is_int_or_float() && r.is_int_or_float()) return m_typespec = TypeDesc::TypeInt; break; case BitAnd : case BitOr : case Xor : case ShiftLeft : case ShiftRight : // Bitwise ops only work with ints, and return ints. if (l.is_int() && r.is_int()) return m_typespec = TypeDesc::TypeInt; break; case And : case Or : // Logical ops work on any simple type (since they test for // nonzeroness), but always return int. return m_typespec = TypeDesc::TypeInt; default: error ("unknown binary operator"); } // If we got this far, it's an op that's not allowed error ("Not allowed: '%s %s %s'", type_c_str(l), opname(), type_c_str(r)); return TypeSpec (); }
int main() { // valid programs are equivalent to themselves CHECK(equivalent("add r0,r1;", "add r0,r1;")); CHECK(equivalent("sub r0,r1;", "sub r0,r1;")); CHECK(equivalent("inc r0;", "inc r0;")); CHECK(equivalent("dec r0;", "dec r0;")); CHECK(equivalent("neg r0;", "neg r0;")); CHECK(equivalent("and r0,r1;", "and r0,r1;")); CHECK(equivalent("or r0,r1;", "or r0,r1;")); CHECK(equivalent("xor r0,r1;", "xor r0,r1;")); CHECK(equivalent("not r0;", "not r0;")); CHECK(equivalent("mov r0,r1;", "mov r0,r1;")); // programs with different output registers are not equivalent CHECK(!equivalent("add r0,r1;", "add r1,r0;")); CHECK(!equivalent("sub r0,r1;", "sub r1,r0;")); CHECK(!equivalent("inc r0;", "inc r1;")); CHECK(!equivalent("dec r0;", "dec r1;")); CHECK(!equivalent("neg r0;", "neg r1;")); CHECK(!equivalent("and r0,r1;", "and r1,r0;")); CHECK(!equivalent("or r0,r1;", "or r1,r0;")); CHECK(!equivalent("xor r0,r1;", "xor r1,r0;")); CHECK(!equivalent("not r0;", "not r1;")); CHECK(!equivalent("mov r0,r1;", "mov r1,r0;")); // sanity check: obvious non-equivalence CHECK(!equivalent("add r0,r1;", "sub r0,r1;")); CHECK(!equivalent("and r0,r1;", "or r0,r1;")); CHECK(!equivalent("inc r0;", "dec r0;")); // ((r0 + r1) + r2) + r3 is equivalent to (r0 + r1) + (r2 + 3) CHECK(equivalent("add r0,r1; add r0,r2; add r0,r3;", "add r0,r1; add r2,r3; add r0,r2;")); // (r0 - r1) - r2 is equivalent to r0 - (r1 + r2) CHECK(equivalent("sub r0,r1; sub r0,r2;", "add r1,r2; sub r0,r1;")); // ~(r0 & r1) is equivalent to ~r0 | ~r1 (De Morgan) CHECK(equivalent("and r0,r1; not r0;", "not r0; not r1; or r0,r1;")); // two ways to clear r0 CHECK(equivalent("sub r0,r0;", "xor r0,r0;")); // a few cases where cmov can be replaced by mov CHECK(equivalent("stc; cmovc r0,r1;", "mov r0,r1;")); CHECK(equivalent("clc; cmovnc r0,r1;", "mov r0,r1;")); CHECK(equivalent("cmp r0,r1; cmovnz r0,r1;", "mov r0,r1;")); // add != adc, sub != sbb CHECK(!equivalent("add r0,r1; add r0,r2;", "add r0,r1; adc r0,r2;")); CHECK(!equivalent("sub r0,r1; sub r0,r2;", "sub r0,r1; sbb r0,r2;")); // l != le, g != ge, a != ae (nc), b (c) != be // a probabilistic equivalence checker that uses only random input states will probably fail here CHECK(!equivalent("cmp r0,r1; cmovl r2,r3;", "cmp r0,r1; cmovle r2,r3;")); CHECK(!equivalent("cmp r0,r1; cmovg r2,r3;", "cmp r0,r1; cmovge r2,r3;")); CHECK(!equivalent("cmp r0,r1; cmova r2,r3;", "cmp r0,r1; cmovnc r2,r3;")); CHECK(!equivalent("cmp r0,r1; cmovc r2,r3;", "cmp r0,r1; cmovbe r2,r3;")); // the venerable sign program, r3 = sign(r3) CHECK(equivalent("xor r0,r0; xor r1,r1; xor r2,r2; inc r1; dec r2; cmp r3,r0; cmovg r3,r1; cmovl r3,r2;", "add r3,r3; sbb r0,r0; sub r0,r3; adc r3,r0;")); // an incorrect variant of the sign program, which misbehaves when r3 == 0 CHECK(!equivalent("xor r0,r0; xor r1,r1; xor r2,r2; inc r1; dec r2; cmp r3,r0; cmovg r3,r1; cmovl r3,r2;", "add r3,r3; sbb r3,r3; add r3,r3; inc r3;")); // -x is equivalent to 0-x CHECK(equivalent("neg r0;", "mov r1,r0; xor r0,r0; sub r0,r1;")); CHECK(equivalent("mov r1,r0; neg r1;", "xor r1,r1; sub r1,r0;")); return EXIT_SUCCESS; }
MStatus geometrySurfaceConstraint::compute( const MPlug& plug, MDataBlock& block ) { MStatus returnStatus; if ( plug == geometrySurfaceConstraint::constraintGeometry ) { // block.inputValue(constraintParentInverseMatrix); // MArrayDataHandle targetArray = block.inputArrayValue( compoundTarget ); unsigned int targetArrayCount = targetArray.elementCount(); double weight,selectedWeight = 0; if ( weightType == geometrySurfaceConstraintCommand::kSmallestWeight ) selectedWeight = FLT_MAX; MObject selectedMesh; unsigned int i; for ( i = 0; i < targetArrayCount; i++ ) { MDataHandle targetElement = targetArray.inputValue(); weight = targetElement.child(targetWeight).asDouble(); if ( !equivalent(weight,0.0)) { if ( weightType == geometrySurfaceConstraintCommand::kLargestWeight ) { if ( weight > selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh(); if ( !mesh.isNull() ) { selectedMesh = mesh; selectedWeight = weight; } } } else { if ( weight < selectedWeight ) { MObject mesh = targetElement.child(targetGeometry).asMesh(); if ( !mesh.isNull() ) { selectedMesh = mesh; selectedWeight = weight; } } } } targetArray.next(); } // if ( selectedMesh.isNull() ) { block.setClean(plug); } else { // The transform node via the geometry attribute will take care of // updating the location of the constrained geometry. MDataHandle outputConstraintGeometryHandle = block.outputValue(constraintGeometry); outputConstraintGeometryHandle.setMObject(selectedMesh); } } else { return MS::kUnknownParameter; } return MS::kSuccess; }
bool ShaderInstance::mergeable (const ShaderInstance &b, const ShaderGroup &g) const { // Must both be instances of the same master -- very fast early-out // for most potential pair comparisons. if (master() != b.master()) return false; // If the shaders haven't been optimized yet, they don't yet have // their own symbol tables and instructions (they just refer to // their unoptimized master), but they may have an "instance // override" vector that describes which parameters have // instance-specific values or connections. bool optimized = (m_instsymbols.size() != 0 || m_instops.size() != 0); // Same instance overrides if (m_instoverrides.size() || b.m_instoverrides.size()) { ASSERT (! optimized); // should not be post-opt ASSERT (m_instoverrides.size() == b.m_instoverrides.size()); for (size_t i = 0, e = m_instoverrides.size(); i < e; ++i) { if ((m_instoverrides[i].valuesource() == Symbol::DefaultVal || m_instoverrides[i].valuesource() == Symbol::InstanceVal) && (b.m_instoverrides[i].valuesource() == Symbol::DefaultVal || b.m_instoverrides[i].valuesource() == Symbol::InstanceVal)) { // If both params are defaults or instances, let the // instance parameter value checking below handle // things. No need to reject default-vs-instance // mismatches if the actual values turn out to be the // same later. continue; } if (! (equivalent(m_instoverrides[i], b.m_instoverrides[i]))) { const Symbol *sym = mastersymbol(i); // remember, it's pre-opt if (! sym->everused()) continue; return false; } } } // Make sure that the two nodes have the same parameter values. If // the group has already been optimized, it's got an // instance-specific symbol table to check; but if it hasn't been // optimized, we check the symbol table int he master. for (int i = firstparam(); i < lastparam(); ++i) { const Symbol *sym = optimized ? symbol(i) : mastersymbol(i); if (! sym->everused()) continue; if (sym->typespec().is_closure()) continue; // Closures can't have instance override values if ((sym->valuesource() == Symbol::InstanceVal || sym->valuesource() == Symbol::DefaultVal) && memcmp (param_storage(i), b.param_storage(i), sym->typespec().simpletype().size())) { return false; } } if (m_run_lazily != b.m_run_lazily) { return false; } // The connection list need to be the same for the two shaders. if (m_connections.size() != b.m_connections.size()) { return false; } if (m_connections != b.m_connections) { return false; } // If there are no "local" ops or symbols, this instance hasn't been // optimized yet. In that case, we've already done enough checking, // since the masters being the same and having the same instance // params and connections is all it takes. The rest (below) only // comes into play after instances are more fully elaborated from // their masters in order to be optimized. if (!optimized) { return true; } // Same symbol table if (! equivalent (m_instsymbols, b.m_instsymbols)) { return false; } // Same opcodes to run if (! equivalent (m_instops, b.m_instops)) { return false; } // Same arguments to the ops if (m_instargs != b.m_instargs) { return false; } // Parameter and code ranges if (m_firstparam != b.m_firstparam || m_lastparam != b.m_lastparam || m_maincodebegin != b.m_maincodebegin || m_maincodeend != b.m_maincodeend || m_Psym != b.m_Psym || m_Nsym != b.m_Nsym) { return false; } // Nothing left to check, they must be identical! return true; }
String NamespaceableNode::getQualifiedName() const { return (equivalent(xmlnamespace, Namespace::DefaultNamespace())) ? name : xmlnamespace->getPrefix() + ':' + name; }