1*a65addddSAndroid Build Coastguard Worker /* 2*a65addddSAndroid Build Coastguard Worker * Copyright 2014 Google Inc. All rights reserved. 3*a65addddSAndroid Build Coastguard Worker * 4*a65addddSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*a65addddSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*a65addddSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*a65addddSAndroid Build Coastguard Worker * 8*a65addddSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*a65addddSAndroid Build Coastguard Worker * 10*a65addddSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*a65addddSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*a65addddSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*a65addddSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*a65addddSAndroid Build Coastguard Worker * limitations under the License. 15*a65addddSAndroid Build Coastguard Worker */ 16*a65addddSAndroid Build Coastguard Worker 17*a65addddSAndroid Build Coastguard Worker #ifndef FRUIT_META_SET_H 18*a65addddSAndroid Build Coastguard Worker #define FRUIT_META_SET_H 19*a65addddSAndroid Build Coastguard Worker 20*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/fruit_assert.h> 21*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/immutable_set.h> 22*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/pair.h> 23*a65addddSAndroid Build Coastguard Worker #include <fruit/impl/meta/vector.h> 24*a65addddSAndroid Build Coastguard Worker 25*a65addddSAndroid Build Coastguard Worker namespace fruit { 26*a65addddSAndroid Build Coastguard Worker namespace impl { 27*a65addddSAndroid Build Coastguard Worker namespace meta { 28*a65addddSAndroid Build Coastguard Worker 29*a65addddSAndroid Build Coastguard Worker // Set ::= Vector<Ts...>, with no duplicates. 30*a65addddSAndroid Build Coastguard Worker 31*a65addddSAndroid Build Coastguard Worker using EmptySet = Vector<>; 32*a65addddSAndroid Build Coastguard Worker 33*a65addddSAndroid Build Coastguard Worker template <typename T> 34*a65addddSAndroid Build Coastguard Worker using ToSet1 = Vector<T>; 35*a65addddSAndroid Build Coastguard Worker 36*a65addddSAndroid Build Coastguard Worker template <typename T, typename U> 37*a65addddSAndroid Build Coastguard Worker using ToSet2 = Vector<T, U>; 38*a65addddSAndroid Build Coastguard Worker 39*a65addddSAndroid Build Coastguard Worker using IsInSet = IsInVector; 40*a65addddSAndroid Build Coastguard Worker 41*a65addddSAndroid Build Coastguard Worker // If S is a set with elements (T1, ..., Tn) this calculates 42*a65addddSAndroid Build Coastguard Worker // F(InitialValue, F(T1, F(..., F(Tn) ...))). 43*a65addddSAndroid Build Coastguard Worker // If S is EmptySet this returns InitialValue. 44*a65addddSAndroid Build Coastguard Worker using FoldSet = FoldVector; 45*a65addddSAndroid Build Coastguard Worker 46*a65addddSAndroid Build Coastguard Worker // If S is a set with elements (T1, ..., Tn) this calculates 47*a65addddSAndroid Build Coastguard Worker // Combine(F(T1), Combine(F(T2),..., F(Tn) ...)). 48*a65addddSAndroid Build Coastguard Worker // 49*a65addddSAndroid Build Coastguard Worker // `Combine' must be associative, and CombineIdentity must be an identity value wrt Combine. 50*a65addddSAndroid Build Coastguard Worker // Use this instead of FoldSet when possible, it shares more sub-instances when invoked multiple 51*a65addddSAndroid Build Coastguard Worker // times with similar sets. 52*a65addddSAndroid Build Coastguard Worker struct FoldSetWithCombine { 53*a65addddSAndroid Build Coastguard Worker template <typename S, typename F, typename Combine, typename CombineIdentity> 54*a65addddSAndroid Build Coastguard Worker struct apply { 55*a65addddSAndroid Build Coastguard Worker using type = FoldVector(TransformVector(S, F), Combine, CombineIdentity); 56*a65addddSAndroid Build Coastguard Worker }; 57*a65addddSAndroid Build Coastguard Worker }; 58*a65addddSAndroid Build Coastguard Worker 59*a65addddSAndroid Build Coastguard Worker // Converts a set (T1,...,Tn) to a set (F(T1), ..., F(Tn)). 60*a65addddSAndroid Build Coastguard Worker // F(T1), ..., F(Tn) must be distinct. 61*a65addddSAndroid Build Coastguard Worker using TransformSet = TransformVector; 62*a65addddSAndroid Build Coastguard Worker 63*a65addddSAndroid Build Coastguard Worker using SetSize = VectorSize; 64*a65addddSAndroid Build Coastguard Worker 65*a65addddSAndroid Build Coastguard Worker using AddToSetUnchecked = PushFront; 66*a65addddSAndroid Build Coastguard Worker 67*a65addddSAndroid Build Coastguard Worker struct AddToSet { 68*a65addddSAndroid Build Coastguard Worker template <typename S, typename T> 69*a65addddSAndroid Build Coastguard Worker struct apply { 70*a65addddSAndroid Build Coastguard Worker using type = If(IsInSet(T, S), S, AddToSetUnchecked(S, T)); 71*a65addddSAndroid Build Coastguard Worker }; 72*a65addddSAndroid Build Coastguard Worker }; 73*a65addddSAndroid Build Coastguard Worker 74*a65addddSAndroid Build Coastguard Worker // Checks if S1 is contained in S2. 75*a65addddSAndroid Build Coastguard Worker struct IsContained { 76*a65addddSAndroid Build Coastguard Worker template <typename S1, typename S2> 77*a65addddSAndroid Build Coastguard Worker struct apply { 78*a65addddSAndroid Build Coastguard Worker struct Helper { 79*a65addddSAndroid Build Coastguard Worker template <typename CurrentResult, typename T> 80*a65addddSAndroid Build Coastguard Worker struct apply { 81*a65addddSAndroid Build Coastguard Worker using type = And(CurrentResult, IsInSet(T, S2)); 82*a65addddSAndroid Build Coastguard Worker }; 83*a65addddSAndroid Build Coastguard Worker }; 84*a65addddSAndroid Build Coastguard Worker 85*a65addddSAndroid Build Coastguard Worker using type = FoldVector(S1, Helper, Bool<true>); 86*a65addddSAndroid Build Coastguard Worker }; 87*a65addddSAndroid Build Coastguard Worker }; 88*a65addddSAndroid Build Coastguard Worker 89*a65addddSAndroid Build Coastguard Worker // Checks if S1 is disjoint from S2. 90*a65addddSAndroid Build Coastguard Worker struct IsDisjoint { 91*a65addddSAndroid Build Coastguard Worker template <typename S1, typename S2> 92*a65addddSAndroid Build Coastguard Worker struct apply { 93*a65addddSAndroid Build Coastguard Worker struct Helper { 94*a65addddSAndroid Build Coastguard Worker template <typename CurrentResult, typename T> 95*a65addddSAndroid Build Coastguard Worker struct apply { 96*a65addddSAndroid Build Coastguard Worker using type = Or(CurrentResult, IsInSet(T, S2)); 97*a65addddSAndroid Build Coastguard Worker }; 98*a65addddSAndroid Build Coastguard Worker }; 99*a65addddSAndroid Build Coastguard Worker 100*a65addddSAndroid Build Coastguard Worker using type = Not(FoldVector(S1, Helper, Bool<false>)); 101*a65addddSAndroid Build Coastguard Worker }; 102*a65addddSAndroid Build Coastguard Worker }; 103*a65addddSAndroid Build Coastguard Worker 104*a65addddSAndroid Build Coastguard Worker struct IsEmptySet { 105*a65addddSAndroid Build Coastguard Worker template <typename S> 106*a65addddSAndroid Build Coastguard Worker struct apply { 107*a65addddSAndroid Build Coastguard Worker using type = Bool<false>; 108*a65addddSAndroid Build Coastguard Worker }; 109*a65addddSAndroid Build Coastguard Worker }; 110*a65addddSAndroid Build Coastguard Worker 111*a65addddSAndroid Build Coastguard Worker template <> 112*a65addddSAndroid Build Coastguard Worker struct IsEmptySet::apply<Vector<>> { 113*a65addddSAndroid Build Coastguard Worker using type = Bool<true>; 114*a65addddSAndroid Build Coastguard Worker }; 115*a65addddSAndroid Build Coastguard Worker 116*a65addddSAndroid Build Coastguard Worker using SetToVector = Identity; 117*a65addddSAndroid Build Coastguard Worker 118*a65addddSAndroid Build Coastguard Worker // The vector must have no duplicates. 119*a65addddSAndroid Build Coastguard Worker using VectorToSetUnchecked = Identity; 120*a65addddSAndroid Build Coastguard Worker 121*a65addddSAndroid Build Coastguard Worker struct SetDifference { 122*a65addddSAndroid Build Coastguard Worker template <typename S1, typename S2> 123*a65addddSAndroid Build Coastguard Worker struct apply { 124*a65addddSAndroid Build Coastguard Worker struct Helper { 125*a65addddSAndroid Build Coastguard Worker template <typename CurrentResult, typename T> 126*a65addddSAndroid Build Coastguard Worker struct apply { 127*a65addddSAndroid Build Coastguard Worker using type = If(IsInSet(T, S2), CurrentResult, AddToSetUnchecked(CurrentResult, T)); 128*a65addddSAndroid Build Coastguard Worker }; 129*a65addddSAndroid Build Coastguard Worker }; 130*a65addddSAndroid Build Coastguard Worker 131*a65addddSAndroid Build Coastguard Worker using type = FoldSet(S1, Helper, EmptySet); 132*a65addddSAndroid Build Coastguard Worker }; 133*a65addddSAndroid Build Coastguard Worker }; 134*a65addddSAndroid Build Coastguard Worker 135*a65addddSAndroid Build Coastguard Worker struct SetIntersection { 136*a65addddSAndroid Build Coastguard Worker template <typename S1, typename S2> 137*a65addddSAndroid Build Coastguard Worker struct apply { 138*a65addddSAndroid Build Coastguard Worker struct Helper { 139*a65addddSAndroid Build Coastguard Worker template <typename CurrentResult, typename T> 140*a65addddSAndroid Build Coastguard Worker struct apply { 141*a65addddSAndroid Build Coastguard Worker using type = If(IsInSet(T, S2), AddToSetUnchecked(CurrentResult, T), CurrentResult); 142*a65addddSAndroid Build Coastguard Worker }; 143*a65addddSAndroid Build Coastguard Worker }; 144*a65addddSAndroid Build Coastguard Worker 145*a65addddSAndroid Build Coastguard Worker using type = If(GreaterThan(SetSize(S1), SetSize(S2)), SetIntersection(S2, S1), FoldSet(S1, Helper, EmptySet)); 146*a65addddSAndroid Build Coastguard Worker }; 147*a65addddSAndroid Build Coastguard Worker }; 148*a65addddSAndroid Build Coastguard Worker 149*a65addddSAndroid Build Coastguard Worker struct SetUnion { 150*a65addddSAndroid Build Coastguard Worker template <typename S1, typename S2> 151*a65addddSAndroid Build Coastguard Worker struct apply { 152*a65addddSAndroid Build Coastguard Worker using type = If(GreaterThan(SetSize(S1), SetSize(S2)), SetUnion(S2, S1), 153*a65addddSAndroid Build Coastguard Worker FoldSet(SetDifference(S1, S2), AddToSetUnchecked, S2)); 154*a65addddSAndroid Build Coastguard Worker }; 155*a65addddSAndroid Build Coastguard Worker }; 156*a65addddSAndroid Build Coastguard Worker 157*a65addddSAndroid Build Coastguard Worker using SetUncheckedUnion = ConcatVectors; 158*a65addddSAndroid Build Coastguard Worker 159*a65addddSAndroid Build Coastguard Worker struct IsSameSet { 160*a65addddSAndroid Build Coastguard Worker template <typename S1, typename S2> 161*a65addddSAndroid Build Coastguard Worker struct apply { 162*a65addddSAndroid Build Coastguard Worker using type = And(IsContained(S1, S2), IsContained(S2, S1)); 163*a65addddSAndroid Build Coastguard Worker }; 164*a65addddSAndroid Build Coastguard Worker }; 165*a65addddSAndroid Build Coastguard Worker 166*a65addddSAndroid Build Coastguard Worker // Returns an arbitrary element from the given set (that must be non-empty). 167*a65addddSAndroid Build Coastguard Worker struct GetArbitrarySetElement { 168*a65addddSAndroid Build Coastguard Worker template <typename S> 169*a65addddSAndroid Build Coastguard Worker struct apply; 170*a65addddSAndroid Build Coastguard Worker 171*a65addddSAndroid Build Coastguard Worker template <typename T, typename... Ts> 172*a65addddSAndroid Build Coastguard Worker struct apply<Vector<T, Ts...>> { 173*a65addddSAndroid Build Coastguard Worker using type = T; 174*a65addddSAndroid Build Coastguard Worker }; 175*a65addddSAndroid Build Coastguard Worker }; 176*a65addddSAndroid Build Coastguard Worker 177*a65addddSAndroid Build Coastguard Worker } // namespace meta 178*a65addddSAndroid Build Coastguard Worker } // namespace impl 179*a65addddSAndroid Build Coastguard Worker } // namespace fruit 180*a65addddSAndroid Build Coastguard Worker 181*a65addddSAndroid Build Coastguard Worker #endif // FRUIT_META_SET_H 182