Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*!
- * Work in Progress....
- * (C) WhiZTiM, 25Nov, 2014
- * Based on, http://www.nairaland.com/2011411/open-source-mathematics-c-class
- * RATIONALE:
- * MathSet can be instantiated with any type; and any container can be easily specialized for it as an underlying container
- * Currently, only std::vector and std::unordered_set has been explicitly specialized by the author;
- * Choosing the underlying container can be done manually(supply more arguments) or automatically based on:
- * * For small datatypes (sizeof() less than 8 bytes) and aren't heavy to construct, we use
- * an std::vector because its CPU Cache-local and thus, extremely high perfomant.
- * With this we can store several thousands of doubles that will fit into L1 cache!! which means
- * Deletion and Searching will almost always be faster than an unordered_set!
- *
- * * For larger datatypes, with more than 8 bytes, an unordered_set is used because the container overhead
- * with respect to the data is the same (64bit Architecture) or smaller.
- *
- */
- #include <vector>
- #include <algorithm>
- #include <type_traits>
- #include <unordered_set>
- namespace detail
- {
- //Compile time type_trait function
- template<typename Type>
- constexpr bool is_8bytes_or_less(){
- return sizeof(Type) <= 8;
- }
- //Blank Adaptor Class... should trigger an error if used
- template<typename ValueType, typename ContainerType>
- struct ContainerAdaptor {};
- //Specialization for std::vector
- template<typename ValueType>
- struct ContainerAdaptor<ValueType, std::vector<ValueType>>
- {
- using ContainerType = std::vector<ValueType>;
- bool SortLastElement(){
- std::partial_sort(c.rbegin(), c.rend(), c.rbegin() + 1);
- }
- bool AddElement(const ValueType& element){
- if(std::binary_search(c.begin(), c.end(), element))
- return false;
- c.push_back(element);
- SortLastElement();
- return true;
- }
- void RemoveElement(const ValueType& element){
- auto iter = std::find(c.begin(), c.end(), element);
- if(iter != c.end()){
- c.erase(iter);
- return true;
- }
- return false;
- }
- bool Contains(const ValueType& element){
- return std::binary_search(c.begin(), c.end(), element);
- }
- bool IsSuperSetOf(const ContainerType& other){
- return std::includes(c.cbegin(), c.cend(), other.cbegin(), other.cend());
- }
- bool IsSubSetOf(const ContainerType& other){
- return std::includes(other.cbegin(), other.cend(), c.cbegin(), c.cend());
- }
- void EnsureReservation(int sz){
- c.reserve(sz);
- }
- private:
- ContainerType c;
- };
- // Not yet implemented
- template<typename ValueType>
- struct ContainerAdaptor<std::unordered_set<ValueType>, ValueType>
- {
- };
- }
- // The MathSet, just supply T, and the rest is generated...
- // ..uses std::vector if sizeof(T) <= 8 bytes, else, it uses std::unordered_set
- // ..uses an Adaptor class to access and operate on its underlying container, i.e
- // ..std::vector, std::unordered_set or what ever is supplied as second template argument
- template<
- typename T,
- typename Container_Type = typename std::conditional<
- detail::is_8bytes_or_less<T>() and std::is_trivial<T>::value,
- std::unordered_set<T>,
- std::vector<T>
- >::type,
- typename Container_Adaptor = typename detail::ContainerAdaptor<typename ContainerType::value_type, ContainerType>
- >
- class MathSet : private Container_Adaptor
- {
- public:
- using ContainerType = Container_Type;
- using value_type = T;
- MathSet(const std::string& name = std::string());
- bool AddElement(const T& element);
- bool RemoveElement(const T& element);
- bool EnsureReservation(int elements);
- bool IsEmptySet() const;
- bool Contains(const T& element) const;
- bool IsSubSetOf(const MathSet<T>& mathset) const;
- bool IsSuperSetOf(const MathSet<T>& mathset) const;
- static MathSet<T> Difference(const MathSet<T>& first, const MathSet<T>& second);
- static MathSet<T> Union(const MathSet<T>& first, const MathSet<T>& second);
- static MathSet<T> Intersection(const MathSet<T>& first, const MathSet<T>& second);
- private:
- ContainerType container;
- std::string name_;
- };
- template<typename T>
- class MathSetCollection
- {
- };
- //*/
- //! Intended Usage format
- void example()
- {
- MathSet<int> s1();
- s1.AddElement(9);
- s1.AddElement(3);
- s1.AddElement(5);
- s1.RemoveElement(3);
- MathSet<int> s2();
- s2.AddElement(5);
- s2.AddElement(7);
- s2.AddElement(8);
- s2.AddElement(9);
- MathsSet<int> s3 = MathSet<int>::Union(s1, s2); // 3, 5, 6, 7, 8, 9
- MathsSet<int> s4 = MathSet<int>::Difference(s1, s2); // 3, 6, 7, 8
- MathsSet<int> s5 = MathSet<int>::Intersection(s1, s2); // 5, 9
- bool b1 = s1.IsSuperSetOf(s5) // true
- bool b2 = s2.IsSuperSetOf(s5) // true
- bool b3 = s3.IsSuperSetOf(s1) // true
- bool b4 = s3.IsSubSetOf(s2) // false
- bool b5 = s4.IsSubsetOf(s3) // true
- //....etc
- }
Add Comment
Please, Sign In to add comment