Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Stroika::Foundation::Traversal::Range< T, TRAITS > Class Template Reference

#include <Range.h>

Inheritance diagram for Stroika::Foundation::Traversal::Range< T, TRAITS >:
Stroika::Foundation::Traversal::DiscreteRange< T, TRAITS >

Public Types

using value_type = T
 Range::value_type is the type of the contained elements of the range (say range of integers, value_type=int)
 

Public Member Functions

constexpr Range ()
 
constexpr Range ReplaceStart (Common::ArgByValueType< T > start) const
 Construct a new Range from this, but with the given start.
 
constexpr Range ReplaceEnd (Common::ArgByValueType< T > end) const
 Construct a new Range from this, but with the given end.
 
constexpr bool empty () const
 
constexpr operator bool () const
 equivalent to not this->empty ();
 
constexpr UnsignedDifferenceType GetDistanceSpanned () const
 
constexpr T GetMidpoint () const
 
constexpr T Pin (T v) const
 
constexpr bool Contains (Common::ArgByValueType< T > r) const
 
nonvirtual constexpr Range Closure () const
 
constexpr bool operator== (const Range &rhs) const
 
constexpr optional< bool > DefinitelyLessThan (const Range &rhs) const
 Compute a less-like notion for Range.
 
template<typename T2 , typename TRAITS2 >
constexpr bool Intersects (const Range< T2, TRAITS2 > &rhs) const
 
constexpr Range Intersection (const Range &rhs) const
 
nonvirtual DisjointRange< T, RangeUnion (const Range &rhs) const
 
constexpr Range UnionBounds (const Range &rhs) const
 
constexpr Range Extend (Common::ArgByValueType< T > value) const
 
constexpr T GetLowerBound () const
 
constexpr T GetUpperBound () const
 
constexpr Range Offset (SignedDifferenceType o) const
 
constexpr Range Times (T o) const
 
nonvirtual Characters::String ToString (const function< Characters::String(const T &)> &elt2String=[](const T &x) -> Characters::String { return Characters::ToString(x);}) const
 

Static Public Member Functions

static constexpr Range Ball (Common::ArgByValueType< T > center, Common::ArgByValueType< UnsignedDifferenceType > radius, Openness lhsOpen=TRAITS::kLowerBoundOpenness, Openness rhsOpen=TRAITS::kUpperBoundOpenness)
 returns a range centered around center, with the given radius (and optionally argument openness).
 
static constexpr Range ContainedRange (Common::ArgByValueType< T > begin, Common::ArgByValueType< T > end)
 
static constexpr Range FullRange ()
 

Detailed Description

template<typename T, typename TRAITS = RangeTraits::Default<T>>
class Stroika::Foundation::Traversal::Range< T, TRAITS >

A Range<> is analogous to a mathematical range. It's left and and its right sides can be optionally open or closed.

Range<> is an immutable type (once constructed, will never change), except for allowing operator=.

A range always has a lower and upper bound (if not specified in CTOR, its specified by the type traits) so no unbounded ranges).

For a range to contain a single point, min=max, and both sides must be closed (else its a require error)

This Range<> template is similar to Ruby range, and fairly DIFFERENT from the std::range<> template.

This notion of range is NOT THE SAME as std::range, though is similar (obviously from the name).

Somewhat inspired by, and at least influenced by, the definition in http://ruby-doc.org/core-2.0/Range.html However - where Ruby has one type "Range" - we have "Range" and DiscreteRange" - and some ruby Range methods/properties are expressed only in DiscreteRange<>. Also Stroika Range has openness as an optional/configurable feature of both endpoints, whereas in Ruby, the LHS is always closed and its RHS is optionally open. Note - you can do Range<float>, but cannot do DiscreteRange<float> - but can do DiscreteRange<int>. A note about an empty range. All empty ranges (of the same type) are equal to one another. It is illegal to ask for the start or end of an empty range. Empty ranges contain no points. It is illegal to call: Range<int>{1,1, Openness::eOpen, Openness::eOpen} since this would produce an empty range. Range<int>{1,1, Openness::eClosed, Openness::eClosed} != Range<int>{3,3, Openness::eClosed, Openness::eClosed} would be true, since neither is empty and they contain different points (1 vs 3). \note The default OPENNESS for Default varies by TYPE T. Integer and enums are both fully closed by default, and other arithmetic types (floats) are half open [) \note <a href="Design-Overview.md#Comparisons">Comparisons: o Standard Stroika Comparison support (operator==, operator<=>, etc); o Depends on operator==/operator<=> being defined on T

See also
DiscreteRange
DisjointRange
DisjointDiscreteRange

Definition at line 276 of file Range.h.

Constructor & Destructor Documentation

◆ Range()

template<typename T , typename TRAITS >
constexpr Stroika::Foundation::Traversal::Range< T, TRAITS >::Range ( )
explicitconstexpr

Range{} creates an empty range (note all empty () ranges of the same type are equal to each other).

optional values - if omitted - are replaced with the TRAITS::kLowerBound and TRAITS::kUpperBound values (as well as 'TRAITs' default openness). Constructors with actual numeric values (begin/end) MUST construct non-empty ranges (begin == end ==> both sides closed).

Precondition
begin <= end (after substitution of optional values)
begin < end or LHS/RHS CLOSED (after substitution of optional values)
Example Usage
Range<double> r1{3, 5};
Assert (r1.Contains (3) and not r1.Contains (3)); // because default arithmetic traits have [) half open
Range<double> r2{ 3, 5, Openness::eOpen, Openness::eOpen };
Assert (not r2.Contains (3));

Definition at line 69 of file Range.inl.

Member Function Documentation

◆ ReplaceStart()

template<typename T , typename TRAITS >
constexpr auto Stroika::Foundation::Traversal::Range< T, TRAITS >::ReplaceStart ( Common::ArgByValueType< T >  start) const
constexpr

Construct a new Range from this, but with the given start.

Precondition
start <= GetUpperBound ()

Definition at line 114 of file Range.inl.

◆ ReplaceEnd()

template<typename T , typename TRAITS >
constexpr auto Stroika::Foundation::Traversal::Range< T, TRAITS >::ReplaceEnd ( Common::ArgByValueType< T >  end) const
constexpr

Construct a new Range from this, but with the given end.

Precondition
GetLowerBound () <= end

Definition at line 120 of file Range.inl.

◆ ContainedRange()

template<typename T , typename TRAITS >
constexpr Range< T, TRAITS > Stroika::Foundation::Traversal::Range< T, TRAITS >::ContainedRange ( Common::ArgByValueType< T >  begin,
Common::ArgByValueType< T >  end 
)
staticconstexpr

This returns begin>end? EMPTY else Range<T, TRAITS> (begin, end);

The Range(begin/end) CTOR REQUIRES begin<=end). This does not, and just produces an empty range in that case.

Definition at line 132 of file Range.inl.

◆ FullRange()

template<typename T , typename TRAITS >
constexpr Range< T, TRAITS > Stroika::Foundation::Traversal::Range< T, TRAITS >::FullRange ( )
staticconstexpr

This returns Range{ TraitsType::kLowerBound, TraitsType::kUpperBound, TraitsType::kLowerBoundOpenness, TraitsType::kUpperBoundOpenness };

Definition at line 138 of file Range.inl.

◆ empty()

template<typename T , typename TRAITS >
constexpr bool Stroika::Foundation::Traversal::Range< T, TRAITS >::empty ( ) const
constexpr

A Range is considered empty if it contains no points. If GetLowerBound () < GetUpperBound (), then clearly this is non-empty. If created with Range/0() - then the range this is empty.

But if GetLowerBound () == GetUpperBound () - this is a trickier case. With both ends CLOSED - that means the GetLowerBound () value is contained in the range, so that is not empty.

if GetLowerBound () == GetUpperBound (), and both ends open, then there are no points contained.

But if GetLowerBound () == GetUpperBound (), and one one side is open, and the other closed, the one closed point endpoint is in the range, so the range is non-empty.

Definition at line 143 of file Range.inl.

◆ GetDistanceSpanned()

template<typename T , typename TRAITS >
constexpr Range< T, TRAITS >::UnsignedDifferenceType Stroika::Foundation::Traversal::Range< T, TRAITS >::GetDistanceSpanned ( ) const
constexpr

GetUpperBound ()-GetLowerBound (), or distance from GetLowerBound () to end of the range. If this is empty (), then GetDistanceSpanned () will be zero but the GetDistanceSpanned CAN be zero without the range being empty (if both ends are closed).

Note
this just uses TraitsType::Difference ()
For discrete Ranges, this does NOT correspond to the number of points (this is one less)

Definition at line 160 of file Range.inl.

◆ GetMidpoint()

template<typename T , typename TRAITS >
constexpr T Stroika::Foundation::Traversal::Range< T, TRAITS >::GetMidpoint ( ) const
constexpr
Precondition
not empty ()

Definition at line 168 of file Range.inl.

◆ Pin()

template<typename T , typename TRAITS >
constexpr T Stroika::Foundation::Traversal::Range< T, TRAITS >::Pin ( v) const
constexpr

Compare v with the upper and lower bounds of this range, and return a value as close as possible to v but in range.

If 'v' is not in range, and this Range is open, GetNext or GetPrevious maybe used to find a value in range.

Precondition
not empty ()
See also
std::clamp

Definition at line 174 of file Range.inl.

◆ Contains()

template<typename T , typename TRAITS >
constexpr bool Stroika::Foundation::Traversal::Range< T, TRAITS >::Contains ( Common::ArgByValueType< T >  r) const
constexpr

This corresponds to the mathematical set containment. When comparing with the edges of the range, we check <= if the edge is closed, and < if the edge is open.

Definition at line 193 of file Range.inl.

◆ Closure()

template<typename T , typename TRAITS >
constexpr Range< T, TRAITS > Stroika::Foundation::Traversal::Range< T, TRAITS >::Closure ( ) const
constexpr

Returns an identical Range to this, but including its end points.

Precondition
not empty ();

Definition at line 252 of file Range.inl.

◆ operator==()

template<typename T , typename TRAITS >
constexpr bool Stroika::Foundation::Traversal::Range< T, TRAITS >::operator== ( const Range< T, TRAITS > &  rhs) const
constexpr
Note
All empty ranges (of the same type) are equal to each other.

Definition at line 452 of file Range.inl.

◆ DefinitelyLessThan()

template<typename T , typename TRAITS = RangeTraits::Default<T>>
constexpr optional< bool > Stroika::Foundation::Traversal::Range< T, TRAITS >::DefinitelyLessThan ( const Range< T, TRAITS > &  rhs) const
constexpr

Compute a less-like notion for Range.

There is no clear way to provide an ordering of two ranges (of the same type). The ordering of their left sides, may not agree with the ordering of their right sides, or their midpoints.

But - OFTEN - they CAN be ordered! And that's often a useful concept. So capture that case at least. Just return nullopt if not comparable. Then the caller can decide how to break the 'tie' - with midpoint compare, or left or right edge compares...

Definition at line 453 of file Range.h.

◆ Intersects()

template<typename T , typename TRAITS >
template<typename T2 , typename TRAITS2 >
constexpr bool Stroika::Foundation::Traversal::Range< T, TRAITS >::Intersects ( const Range< T2, TRAITS2 > &  rhs) const
constexpr

Returns true iff there are any points shared in common between this range and the rhs range.

Example Usage
using RT = Range<int>;
constexpr auto eOpen = Openness::eOpen;
constexpr auto eClosed = Openness::eClosed;
Assert ((RT{1, 2}.Intersects (RT{1, 2})));
Assert ((not RT{1, 2, eOpen, eOpen}.Intersects (RT{2, 3, eOpen, eOpen})));
Assert ((not RT{1, 2, eOpen, eClosed}.Intersects (RT{2, 3, eOpen, eOpen})));
Assert ((RT{1, 2, eOpen, eClosed}.Intersects (RT{2, 3, eClosed, eOpen})));
See also
operator^

Definition at line 259 of file Range.inl.

◆ Intersection()

template<typename T , typename TRAITS >
constexpr Range< T, TRAITS > Stroika::Foundation::Traversal::Range< T, TRAITS >::Intersection ( const Range< T, TRAITS > &  rhs) const
constexpr

Compute the overlap/intersection between two ranges. The resulting range defines exactly the points in both places (so respects openness).

See also
operator^ - an operator alias for this function

Definition at line 329 of file Range.inl.

◆ Union()

template<typename T , typename TRAITS >
DisjointRange< T, Range< T, TRAITS > > Stroika::Foundation::Traversal::Range< T, TRAITS >::Union ( const Range< T, TRAITS > &  rhs) const

if two regions are disjoint, this can encompass a larger region than the actual union would

Definition at line 347 of file Range.inl.

◆ UnionBounds()

template<typename T , typename TRAITS >
constexpr Range< T, TRAITS > Stroika::Foundation::Traversal::Range< T, TRAITS >::UnionBounds ( const Range< T, TRAITS > &  rhs) const
constexpr

if two regions are disjoint, this can encompass a larger region than the actual union would

Note
See also Extend ();
See also Union ();

Definition at line 352 of file Range.inl.

◆ Extend()

template<typename T , typename TRAITS >
constexpr auto Stroika::Foundation::Traversal::Range< T, TRAITS >::Extend ( Common::ArgByValueType< T >  value) const
constexpr

Construct a new range from this range, but including the given point Note that can produce a range with different openness from the starting range (as the points added close the endpoints).

Note
See also UnionBounds ();

Definition at line 380 of file Range.inl.

◆ GetLowerBound()

template<typename T , typename TRAITS >
constexpr T Stroika::Foundation::Traversal::Range< T, TRAITS >::GetLowerBound ( ) const
constexpr
Precondition
not empty (); // special case - no upper/lower bound

Definition at line 394 of file Range.inl.

◆ GetUpperBound()

template<typename T , typename TRAITS >
constexpr T Stroika::Foundation::Traversal::Range< T, TRAITS >::GetUpperBound ( ) const
constexpr
Precondition
not empty (); // special case - no upper/lower bound

Definition at line 405 of file Range.inl.

◆ Offset()

template<typename T , typename TRAITS >
constexpr auto Stroika::Foundation::Traversal::Range< T, TRAITS >::Offset ( SignedDifferenceType  o) const
constexpr
Precondition
not empty
the Range produced by applying the given offset to *this remains valid with respect to the constraints on this Range.

Definition at line 416 of file Range.inl.

◆ Times()

template<typename T , typename TRAITS >
constexpr auto Stroika::Foundation::Traversal::Range< T, TRAITS >::Times ( o) const
constexpr
Precondition
not empty
the Range produced by applying the given factor to the upper and lower bounds.
T has operator* (T,T) -> T defined

Definition at line 422 of file Range.inl.

◆ ToString()

template<typename T , typename TRAITS >
Characters::String Stroika::Foundation::Traversal::Range< T, TRAITS >::ToString ( const function< Characters::String(const T &)> &  elt2String = [] (const T& x) -> Characters::String { return Characters::ToString (x); }) const

Print a displayable rendition of the given range, using the argument function to format the basic value_type.

Example Usage
Assert (Range<int>{3, 4}.ToString () == "[3 ... 4)");
Assert (Range<int>{3, 4}.ToString ([] (int n) { return "{}"_f (n); }) == "[3 ... 4)");
nonvirtual Characters::String ToString(const function< Characters::String(const T &)> &elt2String=[](const T &x) -> Characters::String { return Characters::ToString(x);}) const
Definition Range.inl:428

if the 'UpperBound' == kUpperBound, its not shown

Example Usage
Assert (Range<int>{3, nullopt}.ToString () == "[3 ... ]");

Similarly for (only) LowerBound == kLowerBound

Example Usage
Assert (Range<int>{nullopt, 4}.ToString () == "[ ... 4]");
See also
Characters::ToString ();

Definition at line 428 of file Range.inl.


The documentation for this class was generated from the following files: