# Domain and Array Operations¶

## Distribution, Domain and Array Equality operators¶

Equality operators are defined to test if two distributions are equivalent or not:

```dist1 == dist2
dist1 != dist2
```

Or to test if two domains are equivalent or not:

```dom1 == dom2
dom1 != dom2
```

Arrays are promoted, so the result of the equality operators is an array of booleans. To get a single result use the `equals` method instead.

```arr1 == arr2 // compare each element resulting in an array of booleans
arr1 != arr2 // compare each element resulting in an array of booleans
arr1.equals(arr2) // compare entire arrays resulting in a single boolean
```

## Miscellaneous Domain and Array Operators¶

### The domain count operator `#`¶

The `#` operator can be applied to dense rectangular domains with a tuple argument whose size matches the rank of the domain (or optionally an integer in the case of a 1D domain). The operator is equivalent to applying the `#` operator to the component ranges of the domain and then using them to slice the domain.

### The array count operator `#`¶

The `#` operator can be applied to dense rectangular arrays with a tuple argument whose size matches the rank of the array (or optionally an integer in the case of a 1D array). The operator is equivalent to applying the `#` operator to the array's domain and using the result to slice the array.

### The array swap operator `<=>`¶

The `<=>` operator can be used to swap the contents of two arrays with the same shape.

### The array alias operator `=>`¶

The `=>` operator can be used in a variable declaration to create a new alias of an array. The new variable will refer to the same array elements as the aliased array. In the following example, the variable `Inner` refers to the inner 9 elements of `A`.

```var A: [0..10] int;
var Inner => A[1..9];
```

## Set Operations on Associative Domains and Arrays¶

Associative domains and arrays support a number of operators for set manipulations. The supported set operators are:

 + | Union & Intersection - Difference ^ Symmetric Difference

Consider the following code where `A` and `B` are associative arrays:

```var C = A op B;
```

The result `C` is a new associative array backed by a new associative domain. The domains of `A` and `B` are not modified by `op`.

There are also op= variants that store the result into the first operand.

Consider the following code where `A` and `B` are associative arrays:

```A op= B;
```

`A` must not share its domain with another array, otherwise the program will halt with an error message.

For the `+=` and `|=` operators, the value from `B` will overwrite the existing value in `A` when indices overlap.

## Functions and Methods on Arrays and Domains¶

proc `isRectangularDom`(d: domain) param

Return true if the argument `d` is a rectangular domain. Otherwise return false.

proc `isRectangularArr`(a: []) param

Return true if the argument `a` is an array with a rectangular domain. Otherwise return false.

proc `isIrregularDom`(d: domain) param

Return true if `d` is an irregular domain; e.g. is not rectangular. Otherwise return false.

proc `isIrregularArr`(a: []) param

Return true if `a` is an array with an irregular domain; e.g. not rectangular. Otherwise return false.

proc `isAssociativeDom`(d: domain) param

Return true if `d` is an associative domain. Otherwise return false.

proc `isAssociativeArr`(a: []) param

Return true if `a` is an array with an associative domain. Otherwise return false.

proc `isEnumDom`(d: domain) param

Return true if `d` is an associative domain defined over an enumerated type. Otherwise return false.

proc `isEnumArr`(a: []) param

Return true if `a` is an array with an enumerated domain. Otherwise return false.

proc `isOpaqueDom`(d: domain) param

Return true if `d` is an opaque domain. Otherwise return false.

proc `isSparseDom`(d: domain) param

Return true if `d` is a sparse domain. Otherwise return false.

proc `isSparseArr`(a: []) param

Return true if `a` is an array with a sparse domain. Otherwise return false.

type `domain`
`proc domain.~domain()`
proc `dist`

Return the domain map that implements this domain

proc `rank` param

Return the number of dimensions in this domain

proc `idxType` type

Return the type of the indices of this domain

proc `stridable` param

Return true if this is a stridable domain

proc `domain`(i: integral ...rank)
proc `dims`()

Returns a tuple of ranges describing the bounds of a rectangular domain. For a sparse domain, returns the bounds of the parent domain.

proc `dim`(d: int)

Returns a range representing the boundary of this domain in a particular dimension.

proc `shape`

Returns a tuple of `idxType` describing the size of each dimension. For a sparse domain, returns the shape of the parent domain.

proc `clear`()

Remove all indices from this domain, leaving it empty

proc `add`(i)

Add index `i` to this domain. This method is also available as the `+=` operator.

proc `bulkAdd`(inds: [] _value.rank*(_value.idxType), dataSorted = false, isUnique = false, preserveInds = true)

Adds indices in `inds` to this domain in bulk.

For sparse domains, an operation equivalent to this method is available with the `+=` operator, where the right-hand-side is an array. However, in that case, default values will be used for the flags `dataSorted`, `isUnique`, and `preserveInds`. This method is available because in some cases, expensive operations can be avoided by setting those flags. To do so, `bulkAdd` must be called explicitly (instead of `+=`).

Note

Right now, this method and the corresponding `+=` operator are only available for sparse domains. In the future, we expect that these methods will be available for all irregular domains.

Arguments: inds -- Indices to be added. `inds` can be an array of `rank*idxType` or an array of `idxType` for 1-D domains. dataSorted : bool -- `true` if data in `inds` is sorted. isUnique : bool -- `true` if data in `inds` has no duplicates. preserveInds : bool -- `true` if data in `inds` needs to be preserved. Number of indices added to the domain int
proc `remove`(i)

Remove index `i` from this domain

proc `requestCapacity`(i)

Request space for a particular number of values in an domain.

Currently only applies to associative domains.

proc `size`

Return the number of indices in this domain

proc `numIndices`

Return the number of indices in this domain

proc `low`

Return the lowest index in this domain

proc `high`

Return the highest index in this domain

proc `stride`

Return the stride of the indices in this domain

proc `alignment`

Return the alignment of the indices in this domain

proc `first`

Return the first index in this domain

proc `last`

Return the last index in this domain

proc `alignedLow`

Return the low index in this domain factoring in alignment

proc `alignedHigh`

Return the high index in this domain factoring in alignment

proc `member`(i: _value.idxType ...rank)

Return true if `i` is a member of this domain. Otherwise return false.

proc `isSubset`(super: domain)

Returns true if this domain is a subset of `super`. Otherwise returns false.

proc `isSuper`(sub: domain)

Returns true if this domain is a superset of `sub`. Otherwise returns false.

proc `expand`(off: rank*(_value.idxType))

Returns a new domain that is the current domain expanded by `off(d)` in dimension `d` if `off(d)` is positive or contracted by `off(d)` in dimension `d` if `off(d)` is negative.

proc `expand`(off: _value.idxType)

Returns a new domain that is the current domain expanded by `off` in all dimensions if `off` is positive or contracted by `off` in all dimensions if `off` is negative.

proc `exterior`(off: rank*(_value.idxType))

Returns a new domain that is the exterior portion of the current domain with `off(d)` indices for each dimension `d`. If `off(d)` is negative, compute the exterior from the low bound of the dimension; if positive, compute the exterior from the high bound.

proc `exterior`(off: _value.idxType)

Returns a new domain that is the exterior portion of the current domain with `off` indices for each dimension. If `off` is negative, compute the exterior from the low bound of the dimension; if positive, compute the exterior from the high bound.

proc `interior`(off: rank*(_value.idxType))

Returns a new domain that is the interior portion of the current domain with `off(d)` indices for each dimension `d`. If `off(d)` is negative, compute the interior from the low bound of the dimension; if positive, compute the interior from the high bound.

proc `interior`(off: _value.idxType)

Returns a new domain that is the interior portion of the current domain with `off` indices for each dimension. If `off` is negative, compute the interior from the low bound of the dimension; if positive, compute the interior from the high bound.

proc `translate`(off)

Returns a new domain that is the current domain translated by `off(d)` in each dimension `d`.

proc `translate`(off)

Returns a new domain that is the current domain translated by `off` in each dimension.

iter `sorted`(comparator: ?t = chpl_defaultComparator())

Yield the domain indices in sorted order

proc `safeCast`(type t)

Cast a rectangular domain to another rectangular domain type. If the old type is stridable and the new type is not stridable, ensure that the stride was 1.

proc `targetLocales`()

Returns an array of locales over which this domain has been distributed.

proc `hasSingleLocalSubdomain`() param

Return true if the local subdomain can be represented as a single domain. Otherwise return false.

proc `localSubdomain`()

Return the subdomain that is local to the current locale

iter `localSubdomains`()

Yield the subdomains that are local to the current locale

type `array`
proc `eltType` type

The type of elements contained in the array

proc `idxType` type

The type of indices used in the array's domain

proc `rank` param

The number of dimensions in the array

proc `numElements`

Return the number of elements in the array

proc `size`

Return the number of elements in the array

proc `IRV`
proc `IRV` ref

Return the Implicitly Represented Value for sparse arrays

iter `sorted`(comparator: ?t = chpl_defaultComparator())

Yield the array elements in sorted order.

proc `targetLocales`()

Returns an array of locales over which this array has been distributed.

proc `hasSingleLocalSubdomain`() param

Return true if the local subdomain can be represented as a single domain. Otherwise return false.

proc `localSubdomain`()

Return the subdomain that is local to the current locale

iter `localSubdomains`()

Yield the subdomains that are local to the current locale

proc `isEmpty`(): bool

Return true if the array has no elements

proc `push_back`(val: this.eltType)

Add element `val` to the back of the array, extending the array's domain by one. If the domain was `{1..5}` it will become `{1..6}`.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `pop_back`()

Remove the last element from the array, reducing the size of the domain by one. If the domain was `{1..5}` it will become `{1..4}`

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `push_front`(val: this.eltType)

Add element `val` to the front of the array, extending the array's domain by one. If the domain was `{1..5}` it will become `{0..5}`.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `pop_front`()

Remove the first element of the array reducing the size of the domain by one. If the domain was `{1..5}` it will become `{2..5}`.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `insert`(pos: this.idxType, val: this.eltType)

Insert element `val` into the array at index `pos`. Shift the array elements above `pos` up one index. If the domain was `{1..5}` it will become `{1..6}`.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `remove`(pos: this.idxType)

Remove the element at index `pos` from the array and shift the array elements above `pos` down one index. If the domain was `{1..5}` it will become `{1..4}`.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `remove`(pos: this.idxType, count: this.idxType)

Remove `count` elements from the array starting at index `pos` and shift elements above `pos+count` down by `count` indices.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `remove`(pos: range(this.idxType, stridable = false))

Remove the elements at the indices in the `pos` range and shift the array elements down by `pos.size` elements. If the domain was `{1..5}` and this is called with `2..3` as an argument, the new domain would be `{1..3}` and the array would contain the elements formerly at positions 1, 4, and 5.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `reverse`()

Reverse the order of the values in the array.

proc `clear`()

Remove all elements from the array leaving the domain empty. If the domain was `{5..10}` it will become `{5..4}`.

The array must be a rectangular 1-D array; its domain must be non-stridable and not shared with other arrays.

proc `find`(val: this.eltType): (bool, index(this.domain))

Return a tuple containing `true` and the index of the first instance of `val` in the array, or if `val` is not found, a tuple containing `false` and an unspecified value is returned.

proc `count`(val: this.eltType): int

Return the number of times `val` occurs in the array.

proc `shape`

Returns a tuple of integers describing the size of each dimension. For a sparse array, returns the shape of the parent domain.

proc `array.``equals`(that: [])

Return true if all this array is the same size and shape as argument `that` and all elements of this array are equal to the corresponding element in `that`. Otherwise return false.

proc `isDmapType`(type t) param

Return true if `t` is a domain map type. Otherwise return false.

proc `isDmapValue`(e) param

Return true if `e` is a domain map. Otherwise return false.

proc `isDomainType`(type t) param

Return true if `t` is a domain type. Otherwise return false.

proc `isDomainValue`(e) param

Return true if `e` is a domain. Otherwise return false.

proc `isArrayType`(type t) param

Return true if `t` is an array type. Otherwise return false.

proc `isArrayValue`(e) param

Return true if `e` is an array. Otherwise return false.

proc `reshape`(A: [], D: domain)

Returns a copy of the array `A` containing the same values but in the shape of the domain `D`. The number of indices in the domain must equal the number of elements in the array. The elements of `A` are copied into the new array using the default iteration orders over `D` and `A`.