IntervalSet IntervalSet::Or(const std::vector<IntervalSet> &sets) { IntervalSet result; for (auto &s : sets) { result.addAll(s); } return result; }
TEST(IntervalTest, IntervalIteration) { IntervalSet<int> set; set += (Bound<int>::closed(0), Bound<int>::closed(1)); set += (Bound<int>::open(2), Bound<int>::open(4)); set += (Bound<int>::closed(5), Bound<int>::open(7)); set += (Bound<int>::open(7), Bound<int>::closed(9)); EXPECT_EQ(4u, set.intervalCount()); int index = 0; foreach (const Interval<int>& interval, set) { if (index == 0) { EXPECT_EQ(0, interval.lower()); EXPECT_EQ(2, interval.upper()); } else if (index == 1) { EXPECT_EQ(3, interval.lower()); EXPECT_EQ(4, interval.upper()); } else if (index == 2) { EXPECT_EQ(5, interval.lower()); EXPECT_EQ(7, interval.upper()); } else if (index == 3) { EXPECT_EQ(8, interval.lower()); EXPECT_EQ(10, interval.upper()); } index++; } }
/** * @brief clip a ray by a Cone. * @param ray_ the ray to clip * @param bounds ray sorted bounds of the resulting clipping segment. * @return true if ray was clipped. bounds parameter is filld by this method * * For simple convex objects, there is two values in bounds that represent in and out events. * An in event is whe the ray enters the geometry, an out is when the ray leaves the geometry. * * Adapted from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrLine3Cone3.cpp * */ bool clip(Ray& ray_, IntervalSet &bounds) const { Diff_Geom ipoints[2]; float t[2]; int numintersection = get_clip_points(ray_, ipoints, t); if (numintersection == 0) return false; else if (numintersection == 2) { Diff_Geom *in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), t[0]); Diff_Geom *out = new Diff_Geom(ipoints[1].pos(), ipoints[1].normal(), t[1]); bounds.add(in, out); return true; } else { Diff_Geom *in, *out; IntervalSet capset; // check with cap plane Plane cap(m_vertex + m_axis * m_height, m_axis); if (cap.clip(ray_, capset) ) { /* Beuark mais ca facilite la gestion mémoire ... */ Diff_Geom *tmp =capset.bounds()[0].data; in = new Diff_Geom(*tmp); if (in->t()< t[0]) { out = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), t[0]); } else { out = in; in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), t[0]); } bounds.add(in, out); return true; } else { return false; } } }
XHMM::xhmmInputManager::IntervalSet* XHMM::xhmmInputManager::readIntervalsFromFile(string intervalsFile, const set<char>& excludeLinesStartingWith) { HMM_PP::istreamLineReader* intervalsStream = HMM_PP::utils::getIstreamLineReaderFromFile(intervalsFile); if (intervalsStream == NULL) throw new Exception("Unable to read table from file '" + intervalsFile + "'"); IntervalSet* intervSet = new IntervalSet(); while (!intervalsStream->eof()) { string* line = new string(); *intervalsStream >> *line; if (line->empty()) { delete line; continue; } char firstChar = (*line)[0]; if (firstChar != NO_EXCLUDE_CHAR && excludeLinesStartingWith.find(firstChar) != excludeLinesStartingWith.end()) { delete line; continue; } stringstream* lineStream = new stringstream(*line); delete line; intervSet->insert(Interval(*lineStream)); delete lineStream; } delete intervalsStream; return intervSet; }
// Initialize intervals, one for each unique attribute value void initialize_intervals(int dimIndex) { g_intervals.clear(); IntervalSet interval; TupleVec::iterator it = g_data.begin(), end = g_data.end(), next; int index = 0; for ( ; it != end; ++it, ++index) { next = it+1; // Add element (index) to interval interval.insert(index); bool insertInterval = (next == end) || ( (next->first)[dimIndex] != (it->first)[dimIndex] ); if (insertInterval) { // Insert interval into list if // (a) end of sequence or // (b) next element is not the same as current element g_intervals.push_back(interval); interval.clear(); } } // Debug print_all_intervals(); }
void print_set(const IntervalSet &s) { for(IntervalSet::const_iterator i=s.begin(); i!=s.end(); ++i) { printf("%i-%i ", (int)i->start, (int)i->end); } printf("\n"); }
typename IntervalSet<DomainT,Interval,Compare,Alloc>::interval_type enclosure(const IntervalSet<DomainT,Interval,Compare,Alloc>& object) { typedef IntervalSet<DomainT,Interval,Compare,Alloc> IntervalSetT; typedef typename IntervalSetT::interval_type interval_type; return object.empty() ? neutron<interval_type>::value() : (*object.begin()).span(*object.rbegin()); }
TEST(IntervalTest, Intersection) { IntervalSet<int> set; set += (Bound<int>::closed(1), Bound<int>::closed(3)); EXPECT_TRUE(set.contains(1)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(3u, set.size()); set &= (Bound<int>::open(1), Bound<int>::open(5)); EXPECT_FALSE(set.contains(1)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(2u, set.size()); IntervalSet<int> set2; set2 += 6; set &= set2; EXPECT_TRUE(set.empty()); EXPECT_EQ(0u, set.intervalCount()); }
XHMM::xhmmInputManager::LoadedReadDepths XHMM::xhmmInputManager::loadReadDepthsFromFile(string readDepthFile, IntervalSet* excludeTargets, StringSet* excludeTargetChromosomes, StringSet* excludeSamples, const ullint minTargetSize, const ullint maxTargetSize) { HMM_PP::DoubleMat* rdMat = MatrixReader<double>::readMatrixFromFile(readDepthFile); StringSet* excludedSamples = new StringSet(); IntervalSet* excludedTargets = new IntervalSet(); set<ullint>* excludeSampleIndices = new set<ullint>(); if (excludeSamples != NULL) { for (ullint row = 0; row < rdMat->nrow(); ++row) { string samp = rdMat->rowName(row); if (excludeSamples->find(samp) != excludeSamples->end()) { cerr << "Excluded sample " << samp << endl; excludedSamples->insert(samp); excludeSampleIndices->insert(row); } } } set<ullint>* excludeTargetIndices = new set<ullint>(); if (excludeTargets != NULL || excludeTargetChromosomes != NULL || minTargetSize > 0 || maxTargetSize < ULLINT_INFINITY) { for (ullint j = 0; j < rdMat->ncol(); ++j) { const Interval targJ(rdMat->colName(j)); const ullint targLen = targJ.span(); bool targLenFails = (targLen < minTargetSize || targLen > maxTargetSize); if ((excludeTargets != NULL && excludeTargets->find(targJ) != excludeTargets->end()) || (excludeTargetChromosomes != NULL && excludeTargetChromosomes->find(targJ.getChr()) != excludeTargetChromosomes->end()) || targLenFails) { cerr << "Excluded target " << targJ; if (targLenFails) cerr << " of length " << targLen; cerr << endl; excludeTargetIndices->insert(j); excludedTargets->insert(targJ); } } } if (!excludeSampleIndices->empty() || !excludeTargetIndices->empty()) { HMM_PP::DoubleMat* newRdMat = rdMat->deleteRowsAndColumns(excludeSampleIndices, excludeTargetIndices); delete rdMat; rdMat = newRdMat; } delete excludeSampleIndices; delete excludeTargetIndices; return LoadedReadDepths(rdMat, excludedTargets, excludedSamples); }
pair<DataType, DataType> get_range(IntervalSet& interval, int dimIndex) { assert(!interval.empty()); int beginIndex = *interval.begin(); IntervalSet::iterator end = interval.end(); --end; int endIndex = *end; assert(beginIndex >= 0 && beginIndex < (int)g_data.size()); assert(endIndex >= 0 && endIndex < (int)g_data.size()); return make_pair( g_data[beginIndex].first[dimIndex], g_data[endIndex].first[dimIndex]); }
bool is_disjoint ( interval_base_set<SubType,DomainT,Interval,Compare,Alloc>& object, const IntervalSet <DomainT,Interval,Compare,Alloc>& operand ) { typedef interval_base_set<SubType,DomainT,Interval,Compare,Alloc> object_type; typedef IntervalSet <DomainT,Interval,Compare,Alloc> operand_type; object_type intersection; if(operand.empty()) return true; typename operand_type::const_iterator common_lwb; typename operand_type::const_iterator common_upb; if(!Set::common_range(common_lwb, common_upb, operand, object)) return true; typename operand_type::const_iterator it = common_lwb; while(it != common_upb) { object.add_intersection(intersection, *it++); if(!intersection.empty()) return false; } return true; }
IntervalSet IntervalSet::And(const IntervalSet &other) const { IntervalSet intersection; size_t i = 0; size_t j = 0; // iterate down both interval lists looking for nondisjoint intervals while (i < _intervals.size() && j < other._intervals.size()) { Interval mine = _intervals[i]; Interval theirs = other._intervals[j]; if (mine.startsBeforeDisjoint(theirs)) { // move this iterator looking for interval that might overlap i++; } else if (theirs.startsBeforeDisjoint(mine)) { // move other iterator looking for interval that might overlap j++; } else if (mine.properlyContains(theirs)) { // overlap, add intersection, get next theirs intersection.add(mine.intersection(theirs)); j++; } else if (theirs.properlyContains(mine)) { // overlap, add intersection, get next mine intersection.add(mine.intersection(theirs)); i++; } else if (!mine.disjoint(theirs)) { // overlap, add intersection intersection.add(mine.intersection(theirs)); // Move the iterator of lower range [a..b], but not // the upper range as it may contain elements that will collide // with the next iterator. So, if mine=[0..115] and // theirs=[115..200], then intersection is 115 and move mine // but not theirs as theirs may collide with the next range // in thisIter. // move both iterators to next ranges if (mine.startsAfterNonDisjoint(theirs)) { j++; } else if (theirs.startsAfterNonDisjoint(mine)) { i++; } } } return intersection; }
// Compute $\chi^2$ value for an interval float chisquared_interval(IntervalSet& interval) { // Count instances of each class map<ClassType, int> classCount; IntervalSet::iterator it = interval.begin(), end = interval.end(); for ( ; it != end; ++it) { int index = *it; ClassType classType = g_data[index].second; classCount[classType]++; } // Keep track of summation float chichiri = 0.0f; set<ClassType>::iterator sit = g_classTypes.begin(), send = g_classTypes.end(); for ( ; sit != send; ++sit) { ClassType classType = *sit; // Uses notation from section 4.2.1, // "Discretization: An Enabling Technique" by H. Liu et al. float A_ij = static_cast<float>(classCount[classType]); float R_i = static_cast<float>(interval.size()); float C_j = static_cast<float>(g_globalClassCount[classType]); float N = static_cast<float>(g_data.size()); float E_ij = (R_i * C_j) / N; float top = (A_ij - E_ij); chichiri += top*top / E_ij; } cout << "{" << chichiri << "} + "; return chichiri; }
int main() { IntervalSet s; s.insert(Interval<size_t>(1,10)); s.insert(Interval<size_t>(10,20)); s.insert(Interval<size_t>(20,30)); s.insert(Interval<size_t>(30,40)); print_set(s); printf("Matching intervals:\n"); std::pair<IntervalSet::const_iterator,IntervalSet::const_iterator> ir = intersecting_intervals(s, Interval<size_t>(10,25)); for(IntervalSet::const_iterator i=ir.first; i!=ir.second; ++i) { printf("%i-%i ", (int)i->start, (int)i->end); } printf("\n"); intervalset_merge(s, Interval<size_t>(25, 50)); print_set(s); }
bool clip(Ray& ray_, IntervalSet &bounds) const { Diff_Geom ipoints[2]; float t[2]; int numintersection = get_clip_points(ray_, ipoints, t); if (numintersection == 0) return false; else if (numintersection == 2) { Diff_Geom *in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), ipoints[0].dNdx(), ipoints[0].dNdy(), t[0], ipoints[0].dPdx(), ipoints[0].dPdy(), ipoints[0].dDdx(), ipoints[0].dDdy(), ipoints[0].u(), ipoints[0].v(), ipoints[0].dTdx(), ipoints[0].dTdy(), true); Diff_Geom *out = new Diff_Geom(ipoints[1].pos(), ipoints[1].normal(), ipoints[1].dNdx(), ipoints[1].dNdy(), t[1], ipoints[1].dPdx(), ipoints[1].dPdy(), ipoints[1].dDdx(), ipoints[1].dDdy(), ipoints[1].u(), ipoints[1].v(), ipoints[1].dTdx(), ipoints[1].dTdy(), false); bounds.add(in, out); return true; } else { Diff_Geom *in, *out; IntervalSet capset; // check with cap plane Plane cap(m_vertex + m_axis * m_height, m_axis); if (cap.clip(ray_, capset) ) { in = capset.bounds()[0].data; in->set_u(in->u()/(PSCALE*m_radius)); in->set_v(in->v()/(PSCALE*m_radius)); in->set_dTdx(in->dTdx()* (1.f/(PSCALE*m_radius))); in->set_dTdy(in->dTdy()* (1.f/(PSCALE*m_radius))); if (in->t()< t[0]) { //if (p_diff_geom_in_->t() < t[0]) { out = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), ipoints[0].dNdx(), ipoints[0].dNdy(), t[0], ipoints[0].dPdx(), ipoints[0].dPdy(), ipoints[0].dDdx(), ipoints[0].dDdy(), ipoints[0].u(), ipoints[0].v(), ipoints[0].dTdx(), ipoints[0].dTdy(), false); } else { out = in; out->set_in(false); in = new Diff_Geom(ipoints[0].pos(), ipoints[0].normal(), ipoints[0].dNdx(), ipoints[0].dNdy(), t[0], ipoints[0].dPdx(), ipoints[0].dPdy(), ipoints[0].dDdx(), ipoints[0].dDdy(), ipoints[0].u(), ipoints[0].v(), ipoints[0].dTdx(), ipoints[0].dTdy(), true); } delete (capset.bounds()[1].data); bounds.add(in, out); return true; } else { return false; } } }
TEST(IntervalTest, LargeInterval) { IntervalSet<int> set; set += (Bound<int>::open(1), Bound<int>::open(100)); set += (Bound<int>::closed(100), Bound<int>::closed(1000000000)); EXPECT_FALSE(set.contains(1)); EXPECT_TRUE(set.contains(5)); EXPECT_TRUE(set.contains(100)); EXPECT_TRUE(set.contains(100000)); EXPECT_TRUE(set.contains(1000000000)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(999999999u, set.size()); }
int main() { using namespace ch10; using namespace std; IntervalSet intervals; intervals.insert(1); intervals.insert(100); intervals.insert(200); intervals.insert(300); intervals.insert(400); intervals.insert(500); intervals.insert(600); intervals.insert(700); intervals.insert(800); intervals.insert(900); intervals.insert(1000); Histogram hist(intervals); cout << "Uniform distribution:" << endl; UniformRandomGenerator gen1(1, 1000); for(int i = 0; i < 100; i++) { hist.add(gen1.draw()); } hist.print_formatted(cout); cout << "Exponential distribution:" << endl; ExponentialRandomGenerator gen2(1,200); hist = Histogram(intervals); for(int i = 0; i < 100; i++) { int result = gen2.draw(); if(result >= 1 && result < 1000) hist.add(result); } hist.print_formatted(cout); cout << "Normal distribution:" << endl; NormalRandomGenerator gen3(500, 200); hist = Histogram(intervals); for(int i = 0; i < 100; i++) { int result = gen3.draw(); if(result >= 1 && result < 1000) hist.add(result); } hist.print_formatted(cout); }
int main() { using namespace ch10; using namespace std; try { IntervalSet intervals; intervals.insert(1); intervals.insert(10); intervals.insert(20); intervals.insert(30); intervals.insert(40); intervals.insert(50); intervals.insert(60); intervals.insert(70); intervals.insert(80); intervals.insert(90); intervals.insert(100); Histogram hist(intervals); cout << "Histogram output with fixed numbers:" << endl; hist.add(1).add(10).add(11).add(19).add(20).add(11).add(89).add(89).add(89).add(90).add(95).add(100); hist.print_formatted(std::cout); cout << endl << "Histogram with random numbers:" << endl; hist = Histogram(intervals); srand(clock()); for(int i = 0; i < 100; i++) { hist.add(rand() % 100 + 1); } hist.print_formatted(std::cout); } catch(Histogram::OutOfRangeError) { cerr << "The value was out of range." << endl; } catch(Histogram::InvalidIntervalSetError) { cerr << "Invalid interval." << endl; } }
int get_clip_points(Ray& ray_, Diff_Geom ipoints[2], float t[2]) const{ int numintersection = 0; Vector3D E = ray_.ori() - m_vertex; float AdD = m_axis.dot(ray_.dir()); float cosSqr = m_costheta*m_costheta; float AdE = m_axis.dot(E); float DdE = ray_.dir().dot(E); float EdE = E.dot(E); float c2 = AdD*AdD-cosSqr; float c1 = AdD*AdE - cosSqr*DdE; float c0 = AdE*AdE - cosSqr*EdE; float dot; Vector3D zero; if (std::fabs(c2)>0) { float discr = c1*c1 - c0*c2; float invC2 = 1.f/c2; if (discr < 0) { // No intersection return 0; } else if (discr > 0) { // two distinct intersections float root = std::sqrt(discr); // entry point t[numintersection] = (-c1 + root) * invC2; E = ray_.at(t[numintersection]) - m_vertex; dot = E.dot(m_axis); if ( (dot > 0) && (dot <= m_height)) { fillConicalDiffGeom(ipoints[numintersection], ray_, t[numintersection], true); ++numintersection; } // exit point t[numintersection] = (-c1 - root) * invC2; E = ray_.at(t[numintersection]) - m_vertex; dot = E.dot(m_axis); if ( (dot > 0) && (dot <= m_height)) { fillConicalDiffGeom(ipoints[numintersection], ray_, t[numintersection], false); ++numintersection; } return numintersection; } else { // one reapeated intersection : ray is tangent to the cone // may be return 0 instead of an intersection ? return 0; t[numintersection] = -c1 * invC2; E = ray_.at(t[numintersection]) - m_vertex; dot = E.dot(m_axis); if ( (dot > 0) && (dot <= m_height)) { fillConicalDiffGeom(ipoints[numintersection], ray_, t[numintersection], true); ++numintersection; } return numintersection; } } else if (std::fabs(c1) > 0) { // the ray is on the boundary of the cone // we consider no intersection // TODO : check this for CSG return 0; } else { //return false; // Cone contains ray V+tD // The ray intersect the cone exactly at its vertex :( // TODO : manage this particular case in another function ipoints[numintersection].set_pos(m_vertex); ipoints[numintersection].set_normal(-m_axis); ipoints[numintersection].set_u(1.f); ipoints[numintersection].set_v(0.f); E = ray_.ori() - m_vertex; t[numintersection] = ( (E.dot(ray_.dir())<0) ? std::sqrt(EdE) : -std::sqrt(EdE) ) ; ipoints[numintersection].set_t(t[numintersection]); ipoints[numintersection].set_in(true); ipoints[numintersection].set_u(0.f); ipoints[numintersection].set_v(1.f); // todo : compute here normal derivatives (according to x and y directions on the image plane) ipoints[numintersection].set_dNdx(zero); ipoints[numintersection].set_dNdy(zero); ++numintersection; // check with cap plane Plane cap(m_vertex + m_axis * m_height, m_axis); IntervalSet capset; if (cap.clip(ray_, capset)) { if (capset.bounds()[0].t < t[numintersection-1]) { t[numintersection] = t[numintersection-1]; ipoints[numintersection] = ipoints[numintersection-1]; --numintersection; } else { capset.bounds()[0].data->set_in(false); } ipoints[numintersection] = *(capset.bounds()[0].data); // TODO : update u, v dTdx and dTdy ipoints[numintersection].set_u(ipoints[numintersection].u()/(PSCALE*m_radius)); ipoints[numintersection].set_v(ipoints[numintersection].v()/(PSCALE*m_radius)); ipoints[numintersection].set_dTdx(ipoints[numintersection].dTdx()* (1.f/(PSCALE*m_radius))); ipoints[numintersection].set_dTdy(ipoints[numintersection].dTdy()* (1.f/(PSCALE*m_radius))); delete capset.bounds()[0].data; delete capset.bounds()[1].data; return 2; } else { // must never reach this point ! assert(false); return 0; } } }
/** * @brief clip a ray by a Box3D. * @param ray_ the ray to clip * @param bounds ray sorted bounds of the resulting clipping segment. * @return true if ray was clipped. bounds parameter is filld by this method * * For simple convex objects, there is two values in bounds that represent in and out events. * An in event is whe the ray enters the geometry, an out is when the ray leaves the geometry. * * @todo Factorize code shared by Box3D::intersect() * * Adapted from http://www.geometrictools.com/LibMathematics/Intersection/Wm5IntrLine3Box3.cpp * */ bool clip(Ray& ray_, IntervalSet &bounds) const { float t0 = std::numeric_limits<float>::min(); float t1 = std::numeric_limits<float>::max(); // Convert linear component to box coordinates. Vector3D diff = ray_.ori() - m_center; Vector3D BOrigin( diff.dot(m_axis[0]), diff.dot(m_axis[1]), diff.dot(m_axis[2]) ); Vector3D BDirection( ray_.dir().dot(m_axis[0]), ray_.dir().dot(m_axis[1]), ray_.dir().dot(m_axis[2]) ); float saveT0 = t0, saveT1 = t1; bool notAllClipped; unsigned char updated; int nt0, nt1; notAllClipped = clip(+BDirection.x(), -BOrigin.x()-m_extent[0], t0, t1, updated); if (updated == 1) nt0 = 0; else if (updated == 2) nt1 = 0; notAllClipped = notAllClipped && clip(-BDirection.x(), +BOrigin.x()-m_extent[0], t0, t1, updated); if (updated == 1) nt0 = 1; else if (updated == 2) nt1 = 1; notAllClipped = notAllClipped && clip(+BDirection.y(), -BOrigin.y()-m_extent[1], t0, t1, updated); if (updated == 1) nt0 = 2; else if (updated == 2) nt1 = 2; notAllClipped = notAllClipped && clip(-BDirection.y(), +BOrigin.y()-m_extent[1], t0, t1, updated); if (updated == 1) nt0 = 3; else if (updated == 2) nt1 = 3; notAllClipped = notAllClipped && clip(+BDirection.z(), -BOrigin.z()-m_extent[2], t0, t1, updated); if (updated == 1) nt0 = 4; else if (updated == 2) nt1 = 4; notAllClipped = notAllClipped && clip(-BDirection.z(), +BOrigin.z()-m_extent[2], t0, t1, updated); if (updated == 1) nt0 = 5; else if (updated == 2) nt1 = 5; if (notAllClipped && (t0 != saveT0 || t1 != saveT1)) { if (t1 > t0) { Vector3D normal = m_axis[nt0/2]; if (nt0%2) normal = -normal; Diff_Geom *in = new Diff_Geom(ray_.at(t0), normal, t0); normal = m_axis[nt1/2]; if (nt1%2) normal = -normal; Diff_Geom *out = new Diff_Geom(ray_.at(t1), normal, t1); bounds.add(in, out); return true; } else { return false; } } else { return false; } }
// Debugging -- print one interval void print_interval_set(IntervalSet& indices) { copy(indices.begin(), indices.end(), ostream_iterator<int>(cout, ", ")); cout << endl; }
IntervalSet IntervalSet::Or(const IntervalSet &a) const { IntervalSet result; result.addAll(*this); result.addAll(a); return result; }
IntervalSet IntervalSet::subtract(const IntervalSet &left, const IntervalSet &right) { if (left.isEmpty()) { return IntervalSet(); } if (right.isEmpty()) { // right set has no elements; just return the copy of the current set return left; } IntervalSet result(left); size_t resultI = 0; size_t rightI = 0; while (resultI < result._intervals.size() && rightI < right._intervals.size()) { Interval &resultInterval = result._intervals[resultI]; const Interval &rightInterval = right._intervals[rightI]; // operation: (resultInterval - rightInterval) and update indexes if (rightInterval.b < resultInterval.a) { rightI++; continue; } if (rightInterval.a > resultInterval.b) { resultI++; continue; } Interval beforeCurrent; Interval afterCurrent; if (rightInterval.a > resultInterval.a) { beforeCurrent = Interval(resultInterval.a, rightInterval.a - 1); } if (rightInterval.b < resultInterval.b) { afterCurrent = Interval(rightInterval.b + 1, resultInterval.b); } if (beforeCurrent.a > -1) { // -1 is the default value if (afterCurrent.a > -1) { // split the current interval into two result._intervals[resultI] = beforeCurrent; result._intervals.insert(result._intervals.begin() + resultI + 1, afterCurrent); resultI++; rightI++; } else { // replace the current interval result._intervals[resultI] = beforeCurrent; resultI++; } } else { if (afterCurrent.a > -1) { // replace the current interval result._intervals[resultI] = afterCurrent; rightI++; } else { // remove the current interval (thus no need to increment resultI) result._intervals.erase(result._intervals.begin() + resultI); } } } // If rightI reached right.intervals.size(), no more intervals to subtract from result. // If resultI reached result.intervals.size(), we would be subtracting from an empty set. // Either way, we are done. return result; }
IntervalSet IntervalSet::complement(const IntervalSet &vocabulary) const { return vocabulary.subtract(*this); }
TEST(IntervalTest, Contains) { IntervalSet<int> set; set += (Bound<int>::closed(1), Bound<int>::closed(10)); EXPECT_TRUE(set.contains(1)); EXPECT_TRUE(set.contains(10)); EXPECT_FALSE(set.contains(11)); EXPECT_FALSE(set.contains(0)); EXPECT_TRUE(set.contains((Bound<int>::closed(2), Bound<int>::closed(10)))); EXPECT_TRUE(set.contains((Bound<int>::closed(2), Bound<int>::open(11)))); EXPECT_TRUE(set.contains((Bound<int>::open(2), Bound<int>::open(4)))); EXPECT_FALSE(set.contains((Bound<int>::closed(5), Bound<int>::closed(11)))); EXPECT_FALSE(set.contains((Bound<int>::open(0), Bound<int>::closed(20)))); IntervalSet<int> set2; set2 += (Bound<int>::open(4), Bound<int>::open(10)); EXPECT_TRUE(set.contains(set2)); EXPECT_FALSE(set2.contains(set)); IntervalSet<int> set3; EXPECT_TRUE(set.contains(set3)); EXPECT_FALSE(set3.contains(set2)); }
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "misc/MurmurHash.h" #include "Lexer.h" #include "Exceptions.h" #include "Vocabulary.h" #include "misc/IntervalSet.h" using namespace antlr4; using namespace antlr4::misc; IntervalSet const IntervalSet::COMPLETE_CHAR_SET = []() { IntervalSet complete = IntervalSet::of(Lexer::MIN_CHAR_VALUE, Lexer::MAX_CHAR_VALUE); complete.setReadOnly(true); return complete; }(); IntervalSet const IntervalSet::EMPTY_SET = []() { IntervalSet empty; empty.setReadOnly(true); return empty; }(); IntervalSet::IntervalSet() { InitializeInstanceFields(); } IntervalSet::IntervalSet(const std::vector<Interval> &intervals) : IntervalSet() {
TEST(IntervalTest, EmptyInterval) { Interval<int> i1 = (Bound<int>::closed(1), Bound<int>::open(0)); EXPECT_EQ(1, i1.lower()); EXPECT_EQ(0, i1.upper()); Interval<int> i2 = (Bound<int>::open(1), Bound<int>::closed(0)); EXPECT_EQ(2, i2.lower()); EXPECT_EQ(1, i2.upper()); Interval<int> i3 = (Bound<int>::open(0), Bound<int>::open(0)); EXPECT_EQ(1, i3.lower()); EXPECT_EQ(0, i3.upper()); Interval<int> i4 = (Bound<int>::closed(3), Bound<int>::closed(2)); EXPECT_EQ(3, i4.lower()); EXPECT_EQ(3, i4.upper()); IntervalSet<int> set; set += i1; EXPECT_TRUE(set.empty()); EXPECT_EQ(0u, set.intervalCount()); set += i2; EXPECT_TRUE(set.empty()); EXPECT_EQ(0u, set.intervalCount()); set += i3; EXPECT_TRUE(set.empty()); EXPECT_EQ(0u, set.intervalCount()); set += i4; EXPECT_TRUE(set.empty()); EXPECT_EQ(0u, set.intervalCount()); set += (Bound<int>::closed(2), Bound<int>::closed(2)); EXPECT_TRUE(set.contains(2)); EXPECT_EQ(1u, set.size()); EXPECT_EQ(1u, set.intervalCount()); set += (Bound<int>::closed(0), Bound<int>::open(1)); EXPECT_TRUE(set.contains(0)); EXPECT_TRUE(set.contains(2)); EXPECT_EQ(2u, set.size()); EXPECT_EQ(2u, set.intervalCount()); }
TEST(IntervalTest, Interval) { Interval<int> i1 = (Bound<int>::open(1), Bound<int>::closed(3)); EXPECT_EQ(2, i1.lower()); EXPECT_EQ(4, i1.upper()); Interval<int> i2 = (Bound<int>::open(3), Bound<int>::open(5)); EXPECT_EQ(4, i2.lower()); EXPECT_EQ(5, i2.upper()); Interval<int> i3 = (Bound<int>::closed(5), Bound<int>::open(6)); EXPECT_EQ(5, i3.lower()); EXPECT_EQ(6, i3.upper()); Interval<int> i4 = (Bound<int>::closed(6), Bound<int>::closed(7)); EXPECT_EQ(6, i4.lower()); EXPECT_EQ(8, i4.upper()); IntervalSet<int> set; set += i1; EXPECT_FALSE(set.contains(1)); EXPECT_TRUE(set.contains(2)); EXPECT_TRUE(set.contains(3)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(2u, set.size()); set += i2; EXPECT_TRUE(set.contains(4)); EXPECT_FALSE(set.contains(5)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(3u, set.size()); set += i3; EXPECT_TRUE(set.contains(5)); EXPECT_FALSE(set.contains(6)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(4u, set.size()); set += i4; EXPECT_TRUE(set.contains(6)); EXPECT_TRUE(set.contains(7)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(6u, set.size()); }
TEST(IntervalTest, Addition) { IntervalSet<int> set; set += 1; set += 2; set += 3; EXPECT_TRUE(set.contains(1)); EXPECT_TRUE(set.contains(2)); EXPECT_TRUE(set.contains(3)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(3u, set.size()); set += (Bound<int>::closed(5), Bound<int>::closed(6)); EXPECT_FALSE(set.contains(4)); EXPECT_TRUE(set.contains(5)); EXPECT_TRUE(set.contains(6)); EXPECT_EQ(2u, set.intervalCount()); EXPECT_EQ(5u, set.size()); set += (Bound<int>::open(2), Bound<int>::open(5)); EXPECT_TRUE(set.contains(4)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(6u, set.size()); IntervalSet<int> set2; set2 += (Bound<int>::closed(8), Bound<int>::closed(9)); set += set2; EXPECT_TRUE(set.contains(8)); EXPECT_TRUE(set.contains(9)); EXPECT_EQ(2u, set.intervalCount()); EXPECT_EQ(8u, set.size()); }
TEST(IntervalTest, Subtraction) { IntervalSet<int> set; set += (Bound<int>::closed(1), Bound<int>::closed(10)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(10u, set.size()); set -= 5; EXPECT_FALSE(set.contains(5)); EXPECT_EQ(2u, set.intervalCount()); EXPECT_EQ(9u, set.size()); set -= (Bound<int>::closed(2), Bound<int>::closed(8)); EXPECT_FALSE(set.contains(2)); EXPECT_FALSE(set.contains(8)); EXPECT_EQ(2u, set.intervalCount()); EXPECT_EQ(3u, set.size()); set -= (Bound<int>::open(0), Bound<int>::open(2)); EXPECT_FALSE(set.contains(1)); EXPECT_EQ(1u, set.intervalCount()); EXPECT_EQ(2u, set.size()); IntervalSet<int> set2; set2 += (Bound<int>::open(5), Bound<int>::closed(10)); set -= set2; EXPECT_TRUE(set.empty()); EXPECT_EQ(0u, set.intervalCount()); }