Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
DisjointRange.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Traversal_DisjointRange_h_
5#define _Stroika_Foundation_Traversal_DisjointRange_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
10#include "Stroika/Foundation/Common/Common.h"
11#include "Stroika/Foundation/Containers/Sequence.h"
13
14/**
15 * \file
16 *
17 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
18 *
19 * TODO:
20 * @todo better document thread-safety stuff and use AssertExternallyLocked locker crap to assert/assure only used at same time
21 * from multiple threads.
22 *
23 * @todo Properly handle edge conditions for open/closed stuff - adding open/closed intervals and doing unions properly.
24 * I think all the bugs in MergeIn_();
25 *
26 * @todo Add overload of Contains() taking RANGETYPE, and ensure it does more than test Contains of the endpoints
27 * (contains all points in range).
28 *
29 * THEN use that in Ensure() at end of DisjointRange<T, RANGE_TYPE>::MergeIn_();
30 *
31 * And have Contains() overload that takes DisjointRange(), as alias for Intersects(); I think?
32 * Maybe Contains ALWAYS is just alias for Intersects?
33 *
34 * DOCUMENT that Contains() is ContainsOrEquals () - not proper containment.
35 */
36
37namespace Stroika::Foundation::Traversal {
38
39 /**
40 * \brief A DisjointRange is NOT a range, but a collection of non-overlapping (except at the edges) Ranges. It its BOUNDs (GetBounds) form a Range.
41 *
42 * DiscreteRange<> is an immutable type (once constructed, will never change), except for allowing operator=.
43 *
44 * \note <a href="Design-Overview.md#Comparisons">Comparisons</a>:
45 * o operator==, operator!= supported, but this assumes operator== is defined on 'T'
46 */
47 template <typename T, typename RANGE_TYPE = Range<T>>
49 public:
50 /**
51 * \brief a Disjoint range collection of (disjoint) ranges of this type.
52 */
53 using RangeType = RANGE_TYPE;
54
55 public:
56 /**
57 * \brief Range::value_type is the type of the contained elements of the range (say range of integers, value_type=int)
58 */
59 using value_type = typename RangeType::value_type;
60
61 public:
62 /**
63 * You can pass in empty Ranges, ranges out of order, and overlapping ranges, and the constructor
64 * always filters out empty ranges, and re-order so subranges well-ordered and disjoint.
65 */
66 DisjointRange () = default;
67 DisjointRange (const DisjointRange&) = default;
68 DisjointRange (const RangeType& from);
69 DisjointRange (const initializer_list<RangeType>& from);
70 template <typename CONTAINER_OF_RANGE_OF_T>
71 explicit DisjointRange (const CONTAINER_OF_RANGE_OF_T& from);
72 template <typename COPY_FROM_ITERATOR_OF_RANGE_OF_T, sentinel_for<remove_cvref_t<COPY_FROM_ITERATOR_OF_RANGE_OF_T>> COPY_FROM_ITERATOR_OF_RANGE_OF_T2>
73 explicit DisjointRange (COPY_FROM_ITERATOR_OF_RANGE_OF_T&& start, COPY_FROM_ITERATOR_OF_RANGE_OF_T2&& end);
74
75 public:
76 nonvirtual DisjointRange& operator= (const DisjointRange& rhs) = default;
77
78 public:
79 /**
80 */
81 static DisjointRange FullRange ();
82
83 public:
84 /**
85 * A disjoint range is made up of a finite number of disjoint (non-overlapping) subranges, which are arranged
86 * following the natural ordering intrinsic to the value_type. This returns those subranges.
87 */
89
90 public:
91 /**
92 * Containing no points (same as containing no subranges).
93 */
94 nonvirtual bool empty () const;
95
96 public:
97 /**
98 * Same as *this = DisjointRange ()
99 */
100 nonvirtual void clear ();
101
102 public:
103 /**
104 * @see Range::Contains.
105 *
106 * This returns true if r is contained in some sub-element range. This is only the smae as
107 * GetBounds().Contains() if SubRanges ().size () <= 1.
108 */
109 nonvirtual bool Contains (value_type elt) const;
110 nonvirtual bool Contains (const RangeType& rhs) const;
111
112 public:
113 /**
114 * if empty, returns empty range()
115 *
116 * \note the resulting BOUNDS should captures the openness flags from the LHS and RHS bounds
117 *
118 * // @todo need constexpr check if RangeType gas this CTOR (careful of case when used with DicreteRange)
119 */
120 nonvirtual RangeType GetBounds () const;
121
122 public:
123 /**
124 * \brief like GetBounds (), but always returns a closed range
125 *
126 * // @todo need constexpr check if RangeType gas this CTOR (careful of case when used with DicreteRange)
127 */
128 nonvirtual RangeType Closure () const;
129
130 public:
131 /**
132 * This returns true if the constituent subranges are all equal. This amounts to checking
133 * if the 'covered points' are all equal.
134 */
135 constexpr bool operator== (const DisjointRange& rhs) const;
136
137 public:
138 /**
139 */
140 nonvirtual bool Intersects (const RangeType& rhs) const;
141 nonvirtual bool Intersects (const DisjointRange& rhs) const;
142
143 public:
144 /**
145 */
146 nonvirtual DisjointRange Intersection (const RangeType& rhs) const;
147 nonvirtual DisjointRange Intersection (const DisjointRange& rhs) const;
148
149 public:
150 /**
151 */
152 nonvirtual DisjointRange Union (const DisjointRange& rhs) const;
153
154 public:
155 /**
156 */
157 nonvirtual RangeType UnionBounds (const DisjointRange& rhs) const;
158
159 public:
160 /**
161 */
162 nonvirtual Characters::String ToString (const function<Characters::String (T)>& elt2String = [] (T x) -> Characters::String {
163 return Characters::ToString (x);
164 }) const;
165
166 private:
167 nonvirtual void MergeIn_ (const RangeType& r); // non-const method, but only called during construction
168
169 private:
170 nonvirtual void AssertInternalRepValid_ () const;
171
172 private:
174
175 private:
176 static constexpr bool sNoisyDebugTrace_ = false;
177 };
178
179 /**
180 */
181 template <typename T, typename RANGE_TYPE>
182 DisjointRange<T, RANGE_TYPE> operator+ (const DisjointRange<T, RANGE_TYPE>& lhs, const DisjointRange<T, RANGE_TYPE>& rhs);
183
184 /**
185 */
186 template <typename T, typename RANGE_TYPE>
187 DisjointRange<T, RANGE_TYPE> operator^ (const DisjointRange<T, RANGE_TYPE>& lhs, const DisjointRange<T, RANGE_TYPE>& rhs);
188
189}
190
191/*
192 ********************************************************************************
193 ******************************* Implementation Details *************************
194 ********************************************************************************
195 */
196#include "DisjointRange.inl"
197
198#endif /*_Stroika_Foundation_Traversal_DisjointRange_h_ */
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Definition Sequence.h:187
A DisjointRange is NOT a range, but a collection of non-overlapping (except at the edges) Ranges....
typename RangeType::value_type value_type
Range::value_type is the type of the contained elements of the range (say range of integers,...
nonvirtual RangeType Closure() const
like GetBounds (), but always returns a closed range
constexpr bool operator==(const DisjointRange &rhs) const
nonvirtual Containers::Sequence< RangeType > SubRanges() const
nonvirtual bool Contains(value_type elt) const
RANGE_TYPE RangeType
a Disjoint range collection of (disjoint) ranges of this type.
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
Definition ToString.inl:465