Home
ObjexxFCL 3.0
 

Index Ranges

As in Fortran, each dimension of an FArray can be given an arbitrary index range. An index range is specified by its lower and upper indices. The ObjexxFCL IndexRange class hierarchy provides this index range capability. IndexRange is an abstract base class of StaticIndexRange and DynamicIndexRange.

IndexRange is the abstract base class and functions that can work with StaticIndexRange and DynamicIndexRange objects uniformly can be written to handle them as abstract IndexRange objects.

StaticIndexRange ranges are used in argument FArrays and they are not automatically updated by changes to Dimension objects in their assigned values. The SRange shorthand (typedef) name for StaticIndexRange is used below.

DynamicIndexRange ranges are used in real and proxy FArrays and they are automatically updated by changes to Dimension objects in their assigned values. The DRange shorthand (typedef) name for DynamicIndexRange is used below.

Construction

Default constructors create zero-sized ranges [1,0].

Copy constructors are available for all IndexRange types.

Upper index constructors taking a single argument create ranges with a lower index of 1. The upper index argument can be any value convertible to int, a Dimension or Dimension expression, or ObjexxFCL::star to indicate an unbounded upper index (for the last dimension of assumed-size argument/proxy arrays).

Index range constructors taking lower and upper index arguments create ranges with the specified range. The lower and upper index arguments can be any value convertible to int or a Dimension or Dimension expression. The upper index argument can also be ObjexxFCL::star to indicate an unbounded upper index (for the last dimension of assumed-size argument/proxy arrays).

Here are some sample IndexRange constructors:

SRange I; // Default construction
SRange I( 10 ); // [1,10]
SRange I( star ); // [1,unbounded]
Dimension m( 20 );
SRange I( 2, m ); // [2,20] (even if m changes)
DRange J( 2, m ); // [2,m] (tracks m's changes)

Assignment

IndexRanges assignment operators and functions parallel the constructors. Assignments with the = operator match the single argument constructors and the assign member functions parallel the upper index and index range constructors. Single argument l and u member functions can be used to assign just the lower or upper index, respectively.

Functions

The lower and upper indices of an IndexRange can be accessed with the l and u member functions and the size with the size member function:

SRange I( -5, 5 ); // [-5,5]
std::cout << I.l() << std::endl; // Prints -5
std::cout << I.u() << std::endl; // Prints 5
std::cout << I.size() << std::endl; // Prints 11

A number of predicate (boolean) functions are available for IndexRanges, including initialized, bounded, unbounded, and legal. You can also ask an IndexRange whether it contains an index or another range or whether it intersects another range.

The contain and intersect modifying member functions will modify an IndexRange to contain a specified index or range or to intersect a specified range, respectively. The clear member function will clear an IndexRange back to a default-constructed state.

You can compare two index ranges with the operators { ==, !=, >, >=, <, <= }.

Notes on IndexRanges

  • An index range is indicated by [l,u] in the following notes.
  • A zero-sized IndexRange is indicated by a range of the form [l,l-1].
  • An unbounded IndexRange has an unknown upper extent and is indicated by a range of the form [l,l-2] and is generally specified by passing ObjexxFCL::star as the upper index. Such an IndexRange includes all indices >= l. The size of an unbounded IndexRange is set to the constant npos defined in IndexRange. The IndexRange member functions bounded and unbounded can be used to test for this condition.
  • Using ObjexxFCL::Star() instead of ObjexxFCL::star as the single constructor argument in an IndexRange declaration will cause it to be treated as a function, not object, declaration: this can be worked around by wrapping the argument in parentheses like this ( ObjexxFCL::Star() ) but it is better to avoid the chance of confusion and just use the predefined object ObjexxFCL::star.
  • Applying the contain or intersect functions to a DynamicIndexRange can cause the lower, upper, or both indices to become constant values that are decoupled from any Dimensions since these functions use current range values.
  • IndexRanges don't have reference semantics like Dimensions: copy construction and assignment between IndexRanges doesn't create a reference relationship between them, it only copies their values. Those values, however, may contain Dimension expressions and those do create a reference relationship from the IndexRanges to the Dimensions of such expressions.
  • IndexRanges are indexed by the int type.
  • On platforms with a 32-bit int:
    • l is limited to the range: [-2147483646,2147483647]
    • u is limited to the range: [-2147483648,2147483647]
    Violations of these ranges are detected in assertion-enabled debug builds.
  • l - 2 <= u is required.
  • u can be l - 1 for zero-sized range and l - 2 for unbounded-upper range.
  • A DynamicIndexRange is uninitialized if its l or u indices depend on one or more uninitialized Dimensions.
  • The size of an uninitialized IndexRange is defined to be zero even for unbounded ranges.