template<typename numericType> MAKERCLASS(cinterval) { public: using numeric_type = numericType; using this_type = cinterval<numeric_type>; FRIENDINSERTION(cinterval) using interval_type = this_type; numeric_type low, high; cinterval(numeric_type _low, numeric_type _high) : low(_low), high(_high) { ASSERTINVARIANT(DATANAMEVALUEA(_low), DATANAMEVALUEA(_high)); } numeric_type begin() const { return low; } numeric_type end() const { return high +1; } numeric_type width() const { return high +1 - low; } bool operator < (const interval_type& rhs) const { return high < rhs.low; } bool operator > (const interval_type& rhs) const { return rhs.high < low; } bool operator == (const interval_type& rhs) const { return low == rhs.low && high == rhs.high; } bool operator != (const interval_type& rhs) const { return !operator == (rhs); } this_type& operator += (const interval_type& rhs) { assert(contiguous(*this, rhs)); if (*this < rhs) high = rhs.high; else low = rhs.low; return *this; } void shift_right(numeric_type d) { low += d; high += d; } void shift_left(numeric_type d) { low -= d; high -= d; } bool assert_invariant() const { return low <= high; } TOBASICOSTREAMSIGNATURE { TOBASICOSTREAMPREAMBLE auto lbracket = get_left_bracket<char_type>(); auto rbracket = get_right_bracket<char_type>(); auto lparen = get_left_paren<char_type>(); auto rparen = get_right_paren<char_type>(); DELIMITERCOLOR << lbracket; INTERVALCOLOR << XFormatNumber<char_type>(low); CONSOLEDEFAULTCOLOR(bos) << space; INTERVALCOLOR << XFormatNumber<char_type>(high); DELIMITERCOLOR << rbracket; DELIMITERCOLOR << lparen; INTERVALCOLOR << XFormatNumber<char_type>(width()); DELIMITERCOLOR << rparen; CONSOLEDEFAULTCOLOR(bos); } static bool overlap(const interval_type& lhs, const interval_type& rhs) { return lhs.low <= rhs.high && rhs.low <= lhs.high; } static bool overlap(numeric_type lhs, const interval_type& rhs) { return lhs >= rhs.low && lhs <= rhs.high; } static bool contiguous(const interval_type& lhs, const interval_type& rhs) { return lhs.high + 1 == rhs.low || rhs.high + 1 == lhs.low; } // ---lhs--- // | | // ------- | [1] case // ------------ [2] // --------------- [3] // --- | [4] // --------- [5] // ------------ [6] // | --- | [7] // | ------ [8] // | --------- [9] enum overlap_case_etype { overlap_case_1 = 1, overlap_case_2, overlap_case_3, overlap_case_4, overlap_case_5, overlap_case_6, overlap_case_7, overlap_case_8, overlap_case_9 }; static overlap_case_etype OVERLAPCASE(const interval_type& lhs, const interval_type& rhs) { overlap_case_etype overlap_case = [&]() { if(lhs.low < rhs.low) // [7] [8] [9] { if(lhs.high < rhs.high) // [9] return interval_type::overlap_case_9; else if(lhs.high == rhs.high) // [8] return overlap_case_8; else // [7] return overlap_case_7; } else if(lhs.low == rhs.low) /
template<typename numericType> MAKERCLASS(cinterval) { public: using numeric_type = numericType; using this_type = cinterval<numeric_type>; FRIENDINSERTION(cinterval) using interval_type = this_type; numeric_type low, high; cinterval(numeric_type _low, numeric_type _high) : low(_low), high(_high) { ASSERTINVARIANT(DATANAMEVALUEA(_low), DATANAMEVALUEA(_high)); } numeric_type begin() const { return low; } numeric_type end() const { return high +1; } numeric_type width() const { return high +1 - low; } bool operator < (const interval_type& rhs) const { return high < rhs.low; } bool operator > (const interval_type& rhs) const { return rhs.high < low; } bool operator == (const interval_type& rhs) const { return low == rhs.low && high == rhs.high; } bool operator != (const interval_type& rhs) const { return !operator == (rhs); } this_type& operator += (const interval_type& rhs) { assert(contiguous(*this, rhs)); if (*this < rhs) high = rhs.high; else low = rhs.low; return *this; } void shift_right(numeric_type d) { low += d; high += d; } void shift_left(numeric_type d) { low -= d; high -= d; } bool assert_invariant() const { return low <= high; } TOBASICOSTREAMSIGNATURE { TOBASICOSTREAMPREAMBLE auto lbracket = get_left_bracket<char_type>(); auto rbracket = get_right_bracket<char_type>(); auto lparen = get_left_paren<char_type>(); auto rparen = get_right_paren<char_type>(); DELIMITERCOLOR << lbracket; INTERVALCOLOR << XFormatNumber<char_type>(low); CONSOLEDEFAULTCOLOR(bos) << space; INTERVALCOLOR << XFormatNumber<char_type>(high); DELIMITERCOLOR << rbracket; DELIMITERCOLOR << lparen; INTERVALCOLOR << XFormatNumber<char_type>(width()); DELIMITERCOLOR << rparen; CONSOLEDEFAULTCOLOR(bos); } static bool overlap(const interval_type& lhs, const interval_type& rhs) { return lhs.low <= rhs.high && rhs.low <= lhs.high; } static bool overlap(numeric_type lhs, const interval_type& rhs) { return lhs >= rhs.low && lhs <= rhs.high; } static bool contiguous(const interval_type& lhs, const interval_type& rhs) { return lhs.high + 1 == rhs.low || rhs.high + 1 == lhs.low; } // ---lhs--- // | | // ------- | [1] case // ------------ [2] // --------------- [3] // --- | [4] // --------- [5] // ------------ [6] // | --- | [7] // | ------ [8] // | --------- [9] enum overlap_case_etype { overlap_case_1 = 1, overlap_case_2, overlap_case_3, overlap_case_4, overlap_case_5, overlap_case_6, overlap_case_7, overlap_case_8, overlap_case_9 }; static overlap_case_etype OVERLAPCASE(const interval_type& lhs, const interval_type& rhs) { overlap_case_etype overlap_case = [&]() { if(lhs.low < rhs.low) // [7] [8] [9] { if(lhs.high < rhs.high) // [9] return interval_type::overlap_case_9; else if(lhs.high == rhs.high) // [8] return overlap_case_8; else // [7] return overlap_case_7; } else if(lhs.low == rhs.low) //