inline Set<hybrid>* set_intersect(Set<hybrid> *C_in,const Set<hybrid> *A_in,const Set<hybrid> *B_in){ if(A_in->cardinality == 0 || B_in->cardinality == 0){ C_in->cardinality = 0; C_in->number_of_bytes = 0; return C_in; } switch (A_in->type) { case type::UINTEGER: switch (B_in->type) { case type::UINTEGER: #ifdef STATS debug::num_uint_uint++; #endif return (Set<hybrid>*)set_intersect((Set<uinteger>*)C_in,(const Set<uinteger>*)A_in,(const Set<uinteger>*)B_in); break; case type::BITSET: #ifdef STATS type::num_uint_bs++; #endif return (Set<hybrid>*)set_intersect((Set<uinteger>*)C_in,(const Set<uinteger>*)A_in,(const Set<bitset>*)B_in); break; default: break; } break; case type::BITSET: switch (B_in->type) { case type::UINTEGER: #ifdef STATS debug::num_uint_bs++; #endif return (Set<hybrid>*)set_intersect((Set<uinteger>*)C_in,(const Set<uinteger>*)B_in,(const Set<bitset>*)A_in); break; case type::BITSET: #ifdef STATS debug::num_bs_bs++; #endif return (Set<hybrid>*)set_intersect((Set<bitset>*)C_in,(const Set<bitset>*)A_in,(const Set<bitset>*)B_in); break; default: break; } break; default: break; } std::cout << "ERROR" << std::endl; return C_in; }
static void test_ops(void) { Set *s1 = set_create(); Set *s2 = set_create(); Set *s3 = set_create(); if (s1 == 0 || s2 == 0 || s3 == 0) err_syserr("Out of memory\n"); load_set(s1, 1, 3, 4, 6); dump_set("S1", s1); load_set(s2, 2, 5, 7, 9); dump_set("S2", s2); set_union(s1, s2, s3); dump_set("S1 union S2", s3); set_empty(s3); set_intersect(s1, s2, s3); dump_set("S1 intersect S2", s3); set_empty(s3); set_difference(s1, s2, s3); dump_set("S1 minus S2", s3); set_empty(s3); set_difference(s2, s1, s3); dump_set("S2 minus S1", s3); set_destroy(s1); set_destroy(s2); set_destroy(s3); }
std::pair<std::set<T>,std::set<T> > set_partition(const std::set<T>& s, const std::set<T>& partition) { std::set<T> a, b; a = set_intersect(s, partition); b = set_difference(s, partition); return std::make_pair(a, b); }
//! Returns the number of variable values for which both finite_assignments //! agree. inline size_t assignment_agreement(const finite_assignment &fa1, const finite_assignment &fa2) { finite_domain allvars = set_intersect(keys(fa1), keys(fa2)); size_t count = 0; foreach(finite_variable *v, allvars) { count += (safe_get(fa1, v) == safe_get(fa2, v)); } return count; }
/** * Calculate dst = prev(src, rel) intersected with univ */ static void set_prev(vset_t dst, vset_t src, vrel_t rel, vset_t univ) { LACE_ME; assert(dst->projection == src->projection); sylvan_deref(dst->bdd); dst->bdd = sylvan_ref(sylvan_relprod_paired_prev(src->bdd, rel->bdd, rel->all_variables)); set_intersect(dst, univ); }
range* range_from_inter(range_request* rr, const range* r1, const range* r2) { range* r3 = range_new(rr); apr_pool_t* pool = range_request_pool(rr); r3->nodes = set_intersect(pool, r1->nodes, r2->nodes); r3->quoted = r1->quoted || r2->quoted; return r3; }
STATIC mp_obj_t set_binary_op(int op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_t args[] = {lhs, rhs}; switch (op) { case RT_BINARY_OP_OR: return set_union(lhs, rhs); case RT_BINARY_OP_XOR: return set_symmetric_difference(lhs, rhs); case RT_BINARY_OP_AND: return set_intersect(lhs, rhs); case RT_BINARY_OP_SUBTRACT: return set_diff(2, args); case RT_BINARY_OP_INPLACE_OR: return set_union(lhs, rhs); case RT_BINARY_OP_INPLACE_XOR: return set_symmetric_difference(lhs, rhs); case RT_BINARY_OP_INPLACE_AND: return set_intersect(lhs, rhs); case RT_BINARY_OP_INPLACE_SUBTRACT: return set_diff(2, args); case RT_BINARY_OP_LESS: return set_issubset_proper(lhs, rhs); case RT_BINARY_OP_MORE: return set_issuperset_proper(lhs, rhs); case RT_BINARY_OP_EQUAL: return set_equal(lhs, rhs); case RT_BINARY_OP_LESS_EQUAL: return set_issubset(lhs, rhs); case RT_BINARY_OP_MORE_EQUAL: return set_issuperset(lhs, rhs); case RT_BINARY_OP_NOT_EQUAL: return MP_BOOL(set_equal(lhs, rhs) == mp_const_false); case RT_BINARY_OP_IN: { mp_obj_set_t *o = lhs; mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP); return MP_BOOL(elem != NULL); } default: // op not supported return NULL; } }
// increase the belt size of the given diamond // O(log n) void t_dir_graph::increase_diamond(const t_diamond& diam){ map<t_diamond, uint>::iterator d_iter = diamond_set.find(diam); // cout << "increasing diamond-belt of "<<diam<<"\n"; if(d_iter != diamond_set.end()){ d_iter->second++; } else {// if its not there, maybe it should be inserted... // this intersection can be calced in O(1), otherwise, diam would have been in diamond_set ! set<t_vertex> belt = set_intersect(get_successors(diam.first), get_predecessors(diam.second)); // cout << "oops, not yet there, "<<diam<<" is "<<(belt.size()>1?"":"not ")<<"inserted (size "<<belt.size()<<")\n"; if(belt.size() > 1) diamond_set.insert(pair<t_diamond,uint>(diam, belt.size())); } }
// mark an arc forbidden/permanent, // note that, if adjacent arcs are also forbidden/permanent, this mark may cascade bool t_dir_graph::mark_arc(const t_arc& a, const uint mark){ if(successors.find(a.first) == successors.end()) return false; // dont mark edges that are not in VxV if(successors.find(a.second) == successors.end()) return false; // dont mark edges that are not in VxV dbgcout << "marking " << a << (mark==MRK_NONE?"none":(mark==MRK_FORBIDDEN?"forbidden":"permanent")) << "\n"; bool result = true; switch(mark){ case MRK_NONE: return (forbidden_arcs.erase(a) || permanent_arcs.erase(a)); break; case MRK_FORBIDDEN: if((!contains_arc(a)) && (forbidden_arcs.find(a) == forbidden_arcs.end()) && forbidden_arcs.insert(a).second) { set<t_vertex> belt = set_intersect(get_successors(a.first), get_predecessors(a.second)); for(set<t_vertex>::iterator u = belt.begin(); u != belt.end(); u++){ if(permanent_arcs.find(t_arc(a.first, *u)) != permanent_arcs.end()) result &= mark_arc(t_arc(*u, a.second), MRK_FORBIDDEN); if(permanent_arcs.find(t_arc(*u, a.second)) != permanent_arcs.end()) result &= mark_arc(t_arc(a.first, *u), MRK_FORBIDDEN); } return result; } else return false; break; case MRK_PERMANENT: if(contains_arc(a) && (permanent_arcs.find(a) == permanent_arcs.end()) && permanent_arcs.insert(a).second) { set<t_vertex> pred = get_predecessors(a.first); for(set<t_vertex>::iterator u = pred.begin(); u != pred.end(); u++){ if(permanent_arcs.find(t_arc(*u, a.first)) != permanent_arcs.end()) result &= mark_arc(t_arc(*u, a.second), MRK_PERMANENT); } pred = set_substract(get_vertices(), get_predecessors(a.second)); for(set<t_vertex>::iterator u = pred.begin(); u != pred.end(); u++){ if(forbidden_arcs.find(t_arc(*u, a.second)) != forbidden_arcs.end()) result &= mark_arc(t_arc(*u, a.second), MRK_FORBIDDEN); } set<t_vertex> succ = get_successors(a.second); for(set<t_vertex>::iterator u = succ.begin(); u != succ.end(); u++){ if(permanent_arcs.find(t_arc(a.second, *u)) != permanent_arcs.end()) result &= mark_arc(t_arc(a.first, *u), MRK_PERMANENT); } succ = set_substract(get_vertices(), get_successors(a.first)); for(set<t_vertex>::iterator u = succ.begin(); u != succ.end(); u++){ if(forbidden_arcs.find(t_arc(a.first, *u)) != forbidden_arcs.end()) result &= mark_arc(t_arc(a.second, *u), MRK_FORBIDDEN); } return result; } else return false; break; default: return false; } }
// insert an arc // O(n log n) bool t_dir_graph::insert_arc(const t_arc& a, const bool permanent){ if(successors.find(a.second) == successors.end()) return false; // dont insert edges that are not in VxV if(predecessors.find(a.first) == predecessors.end()) return false; // dont insert edges that are not in VxV if(forbidden_arcs.find(a) != forbidden_arcs.end()) return false; // dont insert if the arc is forbidden t_adjtable::iterator i = successors.find(a.first); t_adjtable::iterator j = predecessors.find(a.second); if((i != successors.end()) && (j != predecessors.end())) if(i->second.insert(a.second).second) if(j->second.insert(a.first).second){ if(permanent) mark_arc(a, MRK_PERMANENT); // update p3_set and diamond_set // first, remove all p3 destroyed by a set<t_vertex> belt = set_intersect(i->second,j->second); for(set<t_vertex>::const_iterator u = belt.begin(); u != belt.end(); u++) p3_set.erase(t_3path(t_arc(a.first, *u),t_arc(*u, a.second))); diamond_set.erase(t_diamond(a.first, a.second)); // second, add new P3 and diamonds // u -> a.first -> a.second set<t_vertex> pred = set_substract(get_predecessors(a.first), j->second); pred.erase(a.second); for(set<t_vertex>::const_iterator u = pred.begin(); u != pred.end(); u++){ increase_diamond(t_diamond(*u, a.second)); p3_set.insert(t_3path(t_arc(*u,a.first),a)); } // a.first -> a.second -> u set<t_vertex> succ = set_substract(get_successors(a.second), i->second); succ.erase(a.first); for(set<t_vertex>::const_iterator u = succ.begin(); u != succ.end(); u++){ increase_diamond(t_diamond(a.first, *u)); p3_set.insert(t_3path(a,t_arc(a.second, *u))); } return true; } else {// avoid inconsistency i->second.erase(a.second); return false; } else return false; else return false; }
// delete an arc // O(n log n) bool t_dir_graph::delete_arc(const t_arc& a, const bool forbidden){ if(permanent_arcs.find(a) != permanent_arcs.end()) return false; // dont delete if the arc is permanent t_adjtable::iterator i = successors.find(a.first); t_adjtable::iterator j = predecessors.find(a.second); if((i != successors.end()) && (j != predecessors.end())) if(i->second.erase(a.second)) if(j->second.erase(a.first)){ if(forbidden) mark_arc(a, MRK_FORBIDDEN); // update p3_set and diamond_set // first, remove all p3 destroyed by a // u -> a.first -> a.second set<t_vertex> pred = set_substract(get_predecessors(a.first), j->second); pred.erase(a.second); for(set<t_vertex>::const_iterator u = pred.begin(); u != pred.end(); u++){ decrease_diamond(t_diamond(*u,a.second)); p3_set.erase(t_3path(t_arc(*u,a.first),t_arc(a.first, a.second))); } // a.first -> a.second -> u set<t_vertex> succ = set_substract(get_successors(a.second), i->second); succ.erase(a.first); for(set<t_vertex>::const_iterator u = succ.begin(); u != succ.end(); u++){ decrease_diamond(t_diamond(a.first, *u)); p3_set.erase(t_3path(t_arc(a.first, a.second),t_arc(a.second, *u))); } // second, add new P3 and diamonds set<t_vertex> belt = set_intersect(i->second,j->second); for(set<t_vertex>::const_iterator u = belt.begin(); u != belt.end(); u++) p3_set.insert(t_3path(t_arc(a.first, *u),t_arc(*u, a.second))); if(belt.size()>1) diamond_set.insert( pair<t_diamond,uint>(t_diamond(a.first,a.second),belt.size()) ); return true; } else return false; else return false; else return false; }
/** * Get inode list from query tree. The returned list is allocated with malloc() * and should be freed with free(). * * @param query The root of the query tree to calculate the inode list for. * @param count The number of inodes in the returned list. * @param neg True if the query results should be negated. * @returns The list of inodes available given the query tree, or NULL on error * or if count is zero. */ fileptr *query_to_inodes(const qelem * const query, int * const count, int * const neg) { DEBUG("Function entry"); if (!query) { PMSG(LOG_ERR, "Query was null"); return NULL; } if (!count) { PMSG(LOG_ERR, "Count was null"); return NULL; } if (!neg) { PMSG(LOG_ERR, "Neg was null"); return NULL; } switch (query->type) { case QUERY_IS_ANY: /* IS_ANY node, output set is the set of limbo inodes, with internal * negation flag set to false */ DEBUG("IS_ANY: creating list of limbo inodes, negation 0"); *neg=0; *count = inode_get_all(0, NULL, 0); if (*count>0) { fileptr *inodes = calloc(*count, sizeof(fileptr)); inode_get_all(0, inodes, *count); return inodes; } else if (*count==0) { /* empty return list to avoid error; must still be freed though */ return calloc(1, sizeof(fileptr)); } else if (*count<0) { DEBUG("Error calling inode_get_all(): %s", strerror(-*count)); return NULL; } break; case QUERY_IS: /* IS node, the output set is the recursive union of the inodes belonging * to that tag and its subtags, with internal negation flag set to false */ { fileptr dblock = get_tag(query->tag); DEBUG("IS: fetching recursive list of inodes from block %lu, negation 0", dblock); *neg=0; fileptr *inodes = inode_get_all_recurse(dblock, count); DEBUG("IS: %d inodes in block %lu", *count, dblock); if (inodes && *count>=0) { return inodes; } else { if (inodes) ifree(inodes); DEBUG("Error calling inode_get_all(): %s", strerror(-*count)); return NULL; } } break; case QUERY_IS_NOSUB: /* IS_NOSUB node, the output set is the set of inodes belonging tag, with * internal negation flag set to false */ { fileptr dblock = get_tag(query->tag); DEBUG("IS_NOSUB: creating list of inodes from block %lu, negation 0", dblock); *neg=0; *count = inode_get_all(dblock, NULL, 0); DEBUG("IS_NOSUB: %d inodes in block %lu", *count, dblock); if (*count>0) { fileptr *inodes = calloc(*count, sizeof(fileptr)); inode_get_all(dblock, inodes, *count); return inodes; } else if (*count==0) { /* empty return list to avoid error; must still be freed though */ return calloc(1, sizeof(fileptr)); } else if (*count<0) { DEBUG("Error calling inode_get_all(): %s", strerror(-*count)); return NULL; } } break; case QUERY_IS_INODE: /* IS_INODE node, the output set contains a single element: the inode. */ { fileptr *ret = calloc(1, sizeof(fileptr)); DEBUG("IS_INODE: single inode 0x%08lx, negation 0", query->inode); *count=1; *neg=0; *ret=query->inode; return ret; } break; case QUERY_NOT: if (query->tag) { /* IS_NOT node with a tag, the output set is the same as for an IS * node, with an internal negation flag set to true */ PMSG(LOG_ERR, "Unhandled type of NOT query! Tag is available."); return NULL; } else if (query->next[0]) { /* IS_NOT node with a subquery, the output set is identical to the * subquery resultset, with an internal negation flag inverted */ fileptr *res = query_to_inodes(query, count, neg); *neg = !*neg; return res; } else { PMSG(LOG_ERR, "Unknown type of NOT query! Both tag and next[0] are null."); return NULL; } break; case QUERY_AND: /* AND node output depends on the negation flags of its subqueries: * * Both false: output is the set intersection of its subqueries, with * negation flag clear * * Both true: output is union of subqueries, with negation flag set * * Otherwise: output is set difference, with the negation-true set * removed from the negation-false set, and the negation flag cleared */ { DEBUG("AND: Conjunction of two query subtrees"); int count1=0, count2=0, neg1=0, neg2=0; fileptr *res1 = query_to_inodes(query->next[0], &count1, &neg1); if (!res1) { DEBUG("Error in left branch"); return NULL; } if (!count1 && !neg1) { /* short-circuit query evaluation */ DEBUG("Short-circuit: first branch yielded no results"); *count=0; *neg=neg1; return res1; } fileptr *res2 = query_to_inodes(query->next[1], &count2, &neg2); if (!res2) { DEBUG("Error in right branch"); ifree(res1); return NULL; } if (!count2 && !neg2) { /* no need to perform set operations */ DEBUG("Short-circuit: second branch yielded no results"); *count=0; *neg=neg2; ifree(res1); return res2; } /* both subtrees returned results */ if (!neg1 && !neg2) { fileptr *res = calloc(MIN(count1, count2), sizeof(fileptr)); if (!res) { PMSG(LOG_ERR, "Failed to allocate memory for return array"); ifree(res1); ifree(res2); return NULL; } /* output is the intersection of subqueries, with negation flag clear */ *neg=0; *count=set_intersect(res1, res2, res, count1, count2, MIN(count1, count2), sizeof(fileptr), inodecmp); if (*count < 0) { PMSG(LOG_ERR, "Error in set intersection operation."); ifree(res1); ifree(res2); ifree(res); return NULL; } else { DEBUG("Set intersection succeeded; %d results", *count); ifree(res1); ifree(res2); return res; } /* } else if (neg1 && neg2) { */ /* output is union of subqueries, with negation flag set */ /* } else { */ /* output is set difference, with the negation-true set removed from * the negation-false set, and the negation flag cleared */ } else { PMSG(LOG_ERR, "Unhandled case in AND"); ifree(res1); ifree(res2); return NULL; } } break; case QUERY_OR: /* OR node output depends on the negation flags of its subqueries: * * Both false: output is union of subquery results, with negation flag * clear * * Both true: output is intersection of subquery results, with * negation flag set * * Otherwise: output is ??? */ { PMSG(LOG_ERR, "Cannot handle OR queries yet!"); return NULL; DEBUG("OR: Disjunction of two query subtrees"); int count1=0, count2=0, neg1=0, neg2=0; fileptr *res1 = query_to_inodes(query->next[0], &count1, &neg1); if (!res1) { DEBUG("Error in left branch"); return NULL; } fileptr *res2 = query_to_inodes(query->next[1], &count2, &neg2); if (!res2) { DEBUG("Error in right branch"); ifree(res1); return NULL; } if (!count1 && !neg1) { /* no need to perform set operations */ DEBUG("Short-circuit: first branch yielded no results"); *count=0; *neg=neg2; ifree(res1); return res2; } if (!count2 && !neg2) { /* no need to perform set operations */ DEBUG("Short-circuit: second branch yielded no results"); *count=0; *neg=neg1; ifree(res2); return res1; } /* both subtrees returned results */ if (!neg1 && !neg2) { fileptr *res = calloc(count1 + count2, sizeof(fileptr)); if (!res) { PMSG(LOG_ERR, "Failed to allocate memory for return array"); ifree(res1); ifree(res2); return NULL; } /* output is the union of subqueries, with negation flag clear */ *neg=0; *count=set_union(res1, res2, res, count1, count2, MIN(count1, count2), sizeof(fileptr), inodecmp); if (*count < 0) { PMSG(LOG_ERR, "Error in set union operation."); ifree(res1); ifree(res2); ifree(res); return NULL; } else { DEBUG("Set union succeeded; %d results", *count); ifree(res1); ifree(res2); return res; } /* } else if (neg1 && neg2) { */ /* output is union of subqueries, with negation flag set */ /* } else { */ /* output is set difference, with the negation-true set removed from * the negation-false set, and the negation flag cleared */ } else { PMSG(LOG_ERR, "Unhandled case in AND"); ifree(res1); ifree(res2); return NULL; } } break; default: PMSG(LOG_ERR, "Unknown query tree element type %d!", query->type); return NULL; } return NULL; }
inline Set<uinteger>* set_intersect(Set<uinteger> *C_in,const Set<bitset> *A_in,const Set<uinteger> *B_in){ return set_intersect(C_in,B_in,A_in); }
void test(string args) { args = splitArg(args, 1); if(streql(args, "") || streql(args, "-H")) { print("\nThis file is in charge of testing the data types embedded in Q-OS.",black); print("\nAccepted Arguments:\n-list\tTests the list.c file\n-set \ttests the set.c file", black); print("\n-strb\ttests the strbuilder.c file\n-y \tshould return the current year...",black); } else if(streql(args, "-LIST"))//For testing lists { newline(); list_t test_list = list_init(); test_list.autoShrink = true; for(uint8 i = 0; i < 4; i++) { list_add(&test_list, "1"); list_add(&test_list, "2"); list_add(&test_list, "3"); list_add(&test_list, "4"); list_add(&test_list, "5"); list_add(&test_list, "6"); list_add(&test_list, "7"); list_add(&test_list, "8"); list_add(&test_list, "9"); list_add(&test_list, "10"); list_add(&test_list, "11"); list_add(&test_list, "12"); list_add(&test_list, "13"); list_add(&test_list, "14"); list_add(&test_list, "15"); list_add(&test_list, "16"); } list_add(&test_list, "Pointless"); println("Done sizing up", white); printint(test_list.capt, white); element_t t; for(uint8 i = 0; i < 64; i++) { t = list_shift(&test_list); } println("\nLast item deleted should be \"16\"", white); println(t.udata.strdata, white); println("\nDeleting all but element \"Pointless\"", white); for(uint8 i = 0; i < test_list.size; i++) { println(list_get(test_list, i), white); } println("Done resizing up", white); printint(test_list.capt, white); list_destroy(&test_list); } else if(streql(args,"-SET")) { set_t test_set = set_init(); for(uint8 i = 0; i < 4; i++) { set_add(&test_set, "0"); set_add(&test_set, "1"); set_add(&test_set, "2"); set_add(&test_set, "3"); set_add(&test_set, "4"); set_add(&test_set, "5"); set_add(&test_set, "6"); set_add(&test_set, "7"); set_add(&test_set, "8"); set_add(&test_set, "9"); set_add(&test_set, "10"); set_add(&test_set, "11"); set_add(&test_set, "12"); set_add(&test_set, "13"); set_add(&test_set, "14"); set_add(&test_set, "15"); set_add(&test_set, "16"); print("\nIteration: ", white); printint(i, white); } println("\n\nInsertion::Output should be 17", white); printint(test_set.size, white); set_t tmp = set_init(); set_add(&tmp, "Union item"); set_union(&test_set, &tmp); println("\n\nUnion::Output should be 18", white); printint(test_set.size, white); set_intersect(&test_set, &tmp); println("\n\nIntersect::Output should be 1", white); printint(test_set.size, white); println("\n\nPreparing for diff test", white); set_add(&test_set, "1"); set_add(&test_set, "2"); set_add(&test_set, "3"); set_add(&tmp, "2"); set_add(&tmp, "3"); set_add(&tmp, "4"); set_diff(&test_set, &tmp); println("Diff::Output should be 2", white); printint(test_set.size, white); set_destroy(&tmp); set_destroy(&test_set); } else if(streql(args, "-STRB")) { static const string bak = "Hello, world "; static const uint32 bln = 13; strbuilder_t test_strb = strbuilder_init(); strbuilder_append(&test_strb, bak); strbuilder_append(&test_strb, "Hello, 2nd world"); println("\nTesting backup text. Output should 1", red); printint(streql(bak, test_strb.prevTxt), green); println("\nOutput should be \"Hello, world Hello, 2nd world\"", red); println(strbuilder_tostr(test_strb), green); println("\nRemoving greeters from first world", red); strbuilder_delete(&test_strb, 0, bln); println("\nOutput should be \"Hello, 2nd world\"", red); println(strbuilder_tostr(test_strb), green); strbuilder_flip(&test_strb); println("\nOutput should be \"dlrow dn2 ,olleH\"", red); println(strbuilder_tostr(test_strb), green); list_t tmp = strbuilder_split(test_strb, " "); println("\nOutput should be last str split by spaces", red); for(uint8 i = 0; i < tmp.size; i++) { println(list_get(tmp, i), white); } list_destroy(&tmp); strbuilder_destroy(&test_strb); } else if(streql(args,"-Y")) { //getTime() test printint(getTime("year"),white); } }
STATIC mp_obj_t set_binary_op(mp_binary_op_t op, mp_obj_t lhs, mp_obj_t rhs) { mp_obj_t args[] = {lhs, rhs}; #if MICROPY_PY_BUILTINS_FROZENSET bool update = MP_OBJ_IS_TYPE(lhs, &mp_type_set); #else bool update = true; #endif if (op != MP_BINARY_OP_CONTAINS && !is_set_or_frozenset(rhs)) { // For all ops except containment the RHS must be a set/frozenset return MP_OBJ_NULL; } switch (op) { case MP_BINARY_OP_OR: return set_union(lhs, rhs); case MP_BINARY_OP_XOR: return set_symmetric_difference(lhs, rhs); case MP_BINARY_OP_AND: return set_intersect(lhs, rhs); case MP_BINARY_OP_SUBTRACT: return set_diff(2, args); case MP_BINARY_OP_INPLACE_OR: if (update) { set_update(2, args); return lhs; } else { return set_union(lhs, rhs); } case MP_BINARY_OP_INPLACE_XOR: if (update) { set_symmetric_difference_update(lhs, rhs); return lhs; } else { return set_symmetric_difference(lhs, rhs); } case MP_BINARY_OP_INPLACE_AND: rhs = set_intersect_int(lhs, rhs, update); if (update) { return lhs; } else { return rhs; } case MP_BINARY_OP_INPLACE_SUBTRACT: return set_diff_int(2, args, update); case MP_BINARY_OP_LESS: return set_issubset_proper(lhs, rhs); case MP_BINARY_OP_MORE: return set_issuperset_proper(lhs, rhs); case MP_BINARY_OP_EQUAL: return set_equal(lhs, rhs); case MP_BINARY_OP_LESS_EQUAL: return set_issubset(lhs, rhs); case MP_BINARY_OP_MORE_EQUAL: return set_issuperset(lhs, rhs); case MP_BINARY_OP_CONTAINS: { mp_obj_set_t *o = MP_OBJ_TO_PTR(lhs); mp_obj_t elem = mp_set_lookup(&o->set, rhs, MP_MAP_LOOKUP); return mp_obj_new_bool(elem != MP_OBJ_NULL); } default: return MP_OBJ_NULL; // op not supported } }