From 48482b294d84fee52bb2acbdcdb817ca72bd6c79 Mon Sep 17 00:00:00 2001
From: Bartosz Broda <bartosz.broda@gmail.com>
Date: Fri, 10 Jun 2011 09:24:26 +0200
Subject: [PATCH] fix set intersect with Tomek

---
 libwccl/ops/functions/setops.h | 52 +++++++++++++++++++++++-----------
 tests/data/setops.ccl          | 10 +++++++
 2 files changed, 45 insertions(+), 17 deletions(-)
 create mode 100644 tests/data/setops.ccl

diff --git a/libwccl/ops/functions/setops.h b/libwccl/ops/functions/setops.h
index bdf2059..d53cedc 100644
--- a/libwccl/ops/functions/setops.h
+++ b/libwccl/ops/functions/setops.h
@@ -6,6 +6,7 @@
 #include <libwccl/values/strset.h>
 
 namespace Wccl {
+	typedef boost::shared_ptr<StrSet> StrSetPtr;
 
 template<class T>
 class SetListOperator : public ListOperator<T>
@@ -84,12 +85,9 @@ FunctionBase::BaseRetValPtr SetUnion<StrSet>::apply_internal(const FunExecContex
 	boost::shared_ptr<StrSet> out = boost::make_shared<StrSet>();
 	if (expressions_->empty()) return out;
 	const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[0]->apply(context);
-	const boost::shared_ptr<const StrSet>& set2 = (*expressions_)[1]->apply(context);
-	std::set_union(set1->contents().begin(), set1->contents().end(),
-		set2->contents().begin(), set2->contents().end(),
-		std::inserter(out->contents(), out->contents().begin()));
+	out->contents() = set1->contents();
 
-	for (size_t i = 2; i < expressions_->size(); ++i) {
+	for (size_t i = 1; i < expressions_->size(); ++i) {
 		const boost::shared_ptr<const StrSet>& seti = (*expressions_)[i]->apply(context);
 		foreach (const UnicodeString& s, seti->contents()) {
 			out->insert(s);
@@ -116,20 +114,40 @@ FunctionBase::BaseRetValPtr SetIntersection<StrSet>::apply_internal(const FunExe
 	if (expressions_->size() == 1) return expressions_->front()->apply(context);
 	boost::shared_ptr<StrSet> out = boost::make_shared<StrSet>();
 	if (expressions_->empty()) return out;
-	const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[0]->apply(context);
-	const boost::shared_ptr<const StrSet>& set2 = (*expressions_)[1]->apply(context);
-	std::set_intersection(set1->contents().begin(), set1->contents().end(),
-		set2->contents().begin(), set2->contents().end(),
-		std::inserter(out->contents(), out->contents().begin()));
 
-	for (size_t i = 2; i < expressions_->size(); ++i) {
-		boost::shared_ptr<StrSet> out2 = boost::make_shared<StrSet>();
-		const boost::shared_ptr<const StrSet>& seti = (*expressions_)[i]->apply(context);
-		std::set_intersection(seti->contents().begin(), seti->contents().end(),
-			out->contents().begin(), out->contents().end(),
-			std::inserter(out->contents(), out2->contents().begin()));
-		out->contents().swap(out2->contents());
+
+	//find smallest set
+	size_t smallest = 0;
+	size_t smallest_size = (std::numeric_limits<size_t>::max)();
+	for (size_t i = 0; i < expressions_->size(); ++i) {
+		const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[i]->apply(context);
+		size_t ssize = set1->size();
+		if(ssize < smallest_size){
+			smallest = i;
+			smallest_size = ssize;
+		}
+	}
+
+	const boost::shared_ptr<const StrSet>& smallest_set = (*expressions_)[smallest]->apply(context);
+	//for each element in smallest set
+	foreach (const UnicodeString& s, smallest_set->contents()) {
+		bool everywhere = true;
+		// find if every other set contains this element
+		for (size_t i = 0; i < expressions_->size() && everywhere; ++i) {
+			if (i == smallest)
+				continue;
+			const boost::shared_ptr<const StrSet>& set1 = (*expressions_)[i]->apply(context);
+
+			if(set1->contents().find(s) == set1->contents().end())
+				everywhere = false;
+		}
+		if(everywhere)
+			out->insert(s);
 	}
+
+
+
+
 	return out;
 }
 
diff --git a/tests/data/setops.ccl b/tests/data/setops.ccl
new file mode 100644
index 0000000..a295b1b
--- /dev/null
+++ b/tests/data/setops.ccl
@@ -0,0 +1,10 @@
+---
+intersection(["ala","ma","kota"], ["kota", "kij"])
+
+["kota"]
+---
+
+inter(union(["ala","ma","kota"], ["kota", "kij"]), ["ala", "ma", "kota", "kij"])
+
+True
+---
-- 
GitLab