morph::range

#include <morph/range.h>

Header file: morph/range.h.

Table of Contents

Summary

morph::range is a class for specifying a mathematical closed interval [min, max]. Its data consists of just two numbers indicating the minimum and maximum of the interval.

It is used as a return object for the vec::range and vvec::range methods and gives semantic meaning to the two values min and max, which are public and accessible directly by client code (if a 2 element array were used for a range, the client coder would have to remember if element 0 was min or max).

The range object can participate in the process of determining the range of values in a data container and it can test for a value being within the interval.

Design

morph::range takes one template argument, specifying the type of the values.

namespace morph {
    template <typename T>
    struct range
    {

morph::range is constexpr capable.

Construct

morph::range<T> r;                                 // Default range has min == max == T{0}
morph::range<T> r(T{0}, T{10});                    // Construct with a defined interval [0, 10]
morph::range<T> r (morph::range_init::for_search); // Construct ready for search

Set

Set the range manually in a single function call

morph::range<int> r; // range initially [0, 0]
r.set (-100, 100);   // range now [-100, 100]

or use initializer braces

r = { -100, 100 };

Update the range to include a value

morph::range<int> r; // range initially 0 to 0
bool changed1 = r.update (100);      // range now 0 to 100
bool changed2 = r.update (-100);     // range now -100 to 100
bool changed3 = r.update (50);       // range unchanged; still -100 to 100

update returns a bool which will be true if the range was changed and false if the range is not changed. In the example above, changed1 and changed2 will both be true, but changed3 will contain false.

Query

To query the max or min of the range, just access the max or min members:

std::cout << "range maximum is " << r.max << " and its minimum is " << r.min << std::endl;

You can stream the range to get both at once:

std::cout << r << std::endl;

This would output [-100,100] in our previous example.

There’s a helper function to get range.max - range.min:

std::cout << "The range 'spans': " << r.span() << std::endl;

Includes value?

Test a value to see if the range includes this value:

r.includes (45);     // would return bool true, following on from previous example
r.includes (-450);   // would return bool false

Contains a range?

You can determine if one range fits inside another with range::contains():

morph::range<int> r1 = { 1, 100 };
morph::range<int> r2 = { 10, 90 };
morph::range<int> r3 = { -1, 2 };
std::cout << "range " << r1 << (r1.contains(r2) ? " contains " : " doesn't contain ") << r2 << std::endl;
std::cout << "range " << r1 << (r1.contains(r3) ? " contains " : " doesn't contain ") << r3 << std::endl;

Comparison

You can compare ranges to be equal or not equal to each other

morph::range<int> r1 = { 1, 100 };
morph::range<int> r2 = { 10, 90 };
bool equality_test = (r1 == r2);
bool nonequality_test = (r1 != r2);

Determine the range from data

Determine a range from data. Here, we initialize a range with min taking the maximum possible value for the type and max taking the minimum possible value. This is done with a call to range::search_init. We then run through the data container, calling update for each element. For example:

morph::vvec<double> data (10, 0.0);
data.randomize();
range<double> r; // Default constructed range is [ 0, 0 ]
r.search_init(); // prepare range for search
for (auto d : data) { r.update (d); } // update on each element of data
std::cout << "The range of values in data was: " << r << std::endl;

To save a line of code, use the constructor for setting up a range ready-configured for search:

morph::vvec<double> data;
data.randomize();
range<double> r (morph::range_init::for_search); // avoids need for r.search_init()
for (auto d : data) { r.update (d); }
std::cout << "The range of values in data was: " << r << std::endl;