NAMESPACE_UPP enum SetOpCode { SET_OP2_NOP, // empty set SET_OP2_LEFT, // left set SET_OP2_RIGHT, // right set SET_OP2_LADD, // left addition - duplicates are kept in left set SET_OP2_RADD, // right additions - duplicates are kept in right set SET_OP2_AND, // intersection (left set order) SET_OP2_LSUB, // left subtraction (left - right) SET_OP2_RSUB, // right subtraction (right - left) SET_OP2_XOR, // symmetrical difference }; template <> inline unsigned UPP::GetHashValue(const SetOpCode& c) { return c; } NTL_MOVEABLE(SetOpCode); template Index SetGetIndex(I begin, I end) { Index result; while(begin != end) result.FindAdd(*begin++); return result; } template C SetLAdd(I begin1, I end1, I begin2, I end2) { typedef typename C::ValueType V; C result; if(begin1 == end1) // left set is empty Append(result, begin2, end2); else { Append(result, begin1, end1); if(begin2 != end2) { Index hash = SetGetIndex(begin1, end1); for(; begin2 != end2; begin2++) if(hash.Find(*begin2) < 0) result.Add(*begin2); } } return result; } template C SetRAdd(I begin1, I end1, I begin2, I end2) { typedef typename C::ValueType V; C result; if(begin2 == end2) Append(result, begin1, end1); else { if(begin1 != end1) { Index hash = SetGetIndex(begin2, end2); while(begin1 != end1) { if(hash.Find(*begin1) < 0) result.Add(*begin1); begin1++; } } Append(result, begin2, end2); } return result; } template C SetAnd(I begin1, I end1, I begin2, I end2) { typedef typename C::ValueType V; C result; int count1 = end1 - begin1; int count2 = end2 - begin2; if(count1 == 0 || count2 == 0) return result; // empty intersection if(count1 > count2) { // 1st is longer, generate hash on 2nd Index hash = SetGetIndex(begin2, end2); while(begin1 != end1) { if(hash.Find(*begin1) >= 0) result.Add(*begin1); begin1++; } } else { // 1st is shorter, generate hash on 1st Index hash = SetGetIndex(begin1, end1); while(begin2 != end2) { if(hash.Find(*begin2) >= 0) result.Add(*begin2); begin2++; } } return result; } template C SetSub(I begin1, I end1, I begin2, I end2) { typedef typename C::ValueType V; C result; if(begin1 == end1) ; // no-op - empty set else if(begin2 == end2) Append(result, begin1, end1); else { Index hash = SetGetIndex(begin2, end2); while(begin1 != end1) { if(hash.Find(*begin1) < 0) result.Add(*begin1); begin1++; } } return result; } template C SetXor(I begin1, I end1, I begin2, I end2) { typedef typename C::ValueType V; C result; if(begin1 == end1) Append(result, begin2, end2); else if(begin2 == end2) Append(result, begin1, end1); else { Index hash = SetGetIndex(begin2, end2); for(I temp = begin1; temp != end1; temp++) if(hash.Find(*temp) < 0) result.Add(*temp); hash = SetGetIndex(begin1, end1); while(begin2 != end2) { if(hash.Find(*begin2) < 0) result.Add(*begin2); begin2++; } } return result; } template C SetOperation(I begin1, I end1, I begin2, I end2, SetOpCode op) { C result; switch(op) { default: NEVER(); case SET_OP2_NOP: break; case SET_OP2_LEFT: Append(result, begin1, end1); break; case SET_OP2_RIGHT: Append(result, begin2, end2); break; case SET_OP2_LADD: return SetLAdd(begin1, end1, begin2, end2); case SET_OP2_RADD: return SetRAdd(begin1, end1, begin2, end2); case SET_OP2_AND: return SetAnd(begin1, end1, begin2, end2); case SET_OP2_LSUB: return SetSub(begin1, end1, begin2, end2); case SET_OP2_RSUB: return SetSub(begin2, end2, begin1, end1); case SET_OP2_XOR: return SetXor(begin1, end1, begin2, end2); } return result; } template T SetOperation(const T& set1, const T& set2, SetOpCode op) { return SetOperation(set1.Begin(), set1.End(), set2.Begin(), set2.End(), op); } template T SetLAdd(const T& set1, const T& set2) { return SetLAdd(set1.Begin(), set1.End(), set2.Begin(), set2.End()); } template T SetRAdd(const T& set1, const T& set2) { return SetRAdd(set1.Begin(), set1.End(), set2.Begin(), set2.End()); } template T SetAnd (const T& set1, const T& set2) { return SetAnd(set1.Begin(), set1.End(), set2.Begin(), set2.End()); } template T SetSub (const T& set1, const T& set2) { return SetSub(set1.Begin(), set1.End(), set2.Begin(), set2.End()); } template T SetXor (const T& set1, const T& set2) { return SetXor(set1.Begin(), set1.End(), set2.Begin(), set2.End()); } END_UPP_NAMESPACE