internal CharacterSet/*!*/ Union(CharacterSet/*!*/ set) {
if (IsEmpty) {
return set;
} else if (set.IsEmpty) {
return this;
}
if (_negated) {
if (set._negated) {
// ^A or ^B == ^(A and B)
return Complement().Intersect(set.Complement()).Complement();
} else {
// ^A or B == ^(A \ B)
return Complement().Subtract(set).Complement();
}
} else if (set._negated) {
// A or ^B == ^(B \ A)
return set.Complement().Subtract(this).Complement();
}
// (a \ B) or (c \ D) == (a or c) \ ((D \ a) or (B \ c) or (B and D))
//
// Proof:
// (a \ B) or (c \ D) ==
// (a and ^B) or (c and ^D) ==
// (a or c) and (a or ^D) and (^B or c) and (^B or ^D) ==
// (a or c) \ (^(a or ^D) or ^(^B or c) or ^(^B or ^D)) ==
// (a or c) \ ((D \ a) or (B \ c) or (B and D)) QED
return new CharacterSet(_include + set._include,
set._exclude.Subtract(GetIncludedSet()).
Union(this._exclude.Subtract(set.GetIncludedSet())).
Union(this._exclude.Intersect(set._exclude))
);
}