Domain and Array Operations¶
Operations on Domains and Arrays.
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.
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.
Parallel Safety with respect to Arrays and Domains¶
Users must take care when applying operations to arrays and domains concurrently from distinct tasks. For instance, if one task is modifying the index set of a domain while another task is operating on either the domain itself or an array declared over that domain, this represents a race and could have arbitrary consequences including incorrect results and program crashes. While making domains and arrays safe with respect to such concurrent operations would be appealing, Chapel’s current position is that such safety guarantees would be prohibitively expensive.
Chapel arrays do support concurrent reads, writes, iterations, and operations as long as their domains are not being modified simultaneously. Such operations are subject to Chapel’s memory consistency model like any other memory accesses. Similarly, tasks may make concurrent queries and iterations on a domain as long as another task is not simultaneously modifying the domain’s index set.
By default, associative domains permit multiple tasks
to modify their index sets concurrently. This adds some amount of
overhead to these operations. If the user knows that all such
modifications will be done serially or in a parallel-safe context,
the overheads can be avoided by setting parSafe
to false
in
the domain’s type declaration. For example, the following
declaration creates an associative domain of strings where the
implementation will do nothing to ensure that simultaneous
modifications to the domain are parallel-safe:
var D: domain(string, parSafe=false);
As with any other domain type, it is not safe to access an
associative array while its domain is changing, regardless of
whether parSafe
is set to true
or false
.
Functions and Methods on Arrays and Domains¶
- proc isRectangularDom(d: domain) param¶
Warning
isRectangularDom is deprecated - please use isRectangular method on domain
- proc isRectangularArr(a: []) param¶
Warning
isRectangularArr is deprecated - please use isRectangular method on array
- proc isIrregularDom(d: domain) param¶
Warning
isIrregularDom is deprecated - please use isIrregular method on domain
- proc isIrregularArr(a: []) param¶
Warning
isIrregularArr is deprecated - please use isIrregular method on array
- proc isAssociativeDom(d: domain) param¶
Warning
isAssociativeDom is deprecated - please use isAssociative method on domain
- proc isAssociativeArr(a: []) param¶
Warning
isAssociativeArr is deprecated - please use isAssociative method on array
- proc isSparseDom(d: domain) param¶
Warning
isSparseDom is deprecated - please use isSparse method on domain
- proc isSparseArr(a: []) param¶
Warning
isSparseArr is deprecated - please use isSparse method on array
- type domain¶
The domain type
- proc init(_pid: int, _instance, _unowned: bool)¶
- proc init(value)
- proc init(d: _distribution, param rank: int, type idxType = int, param stridable: bool = false, definedConst: bool = false)
- proc init(d: _distribution, param rank: int, type idxType = int, param stridable: bool = false, ranges: rank*(range(idxType, BoundedRangeType.bounded, stridable)), definedConst: bool = false)
- proc init(d: _distribution, type idxType, param parSafe: bool = true, definedConst: bool = false)
- proc init(d: _distribution, dom: domain, definedConst: bool = false)
- proc init=(const ref other: domain)¶
- proc init=(const ref other: 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 intIdxType type¶
The
idxType
as represented by an integer type. WhenidxType
is an enum type, this evaluates toint
. Otherwise, it evaluates toidxType
.
- proc stridable param¶
Return true if this is a stridable domain
- iter these()¶
Yield the domain indices
- proc this(i: integral ...rank)¶
- proc dims()¶
Return a tuple of ranges describing the bounds of a rectangular domain. For a sparse domain, return the bounds of the parent domain.
- proc dim(d: int)¶
Return a range representing the boundary of this domain in a particular dimension.
- proc shape¶
Return a tuple of
intIdxType
describing the size of each dimension. Note that this routine is in the process of changing to return a tuple ofint
, similar to the.size
query on ranges, domains, and arrays. SeeChapelRange.range.size
for details.For a sparse domain, this returns the shape of the parent domain.
- proc ref clear()
Remove all indices from this domain, leaving it empty
- proc ref add(in i)
Add index
i
to this domain. This method is also available as the+=
operator.The domain must be irregular.
- proc makeIndexBuffer(size: int)¶
Creates an index buffer which can be used for faster index addition.
For example, instead of:
var spsDom: sparse subdomain(parentDom); for i in someIndexIterator() do spsDom += i;
You can use SparseIndexBuffer for better performance:
var spsDom: sparse subdomain(parentDom); var idxBuf = spsDom.makeIndexBuffer(size=N); for i in someIndexIterator() do idxBuf.add(i); idxBuf.commit();
The above snippet will create a buffer of size N indices, and will automatically commit indices to the sparse domain as the buffer fills up. Indices are also committed when the buffer goes out of scope.
Note
The interface and implementation is not stable and may change in the future.
- Arguments
size : int – Size of the buffer in number of indices.
- proc ref bulkAdd(inds: [] _value.rank*(_value.idxType), dataSorted = false, isUnique = false, preserveInds = true, addOn = nilLocale)
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 flagsdataSorted
,isUnique
, andpreserveInds
. 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.Note
nilLocale
is a sentinel value to denote that the locale where this addition should occur is unknown. We expect this to change in the future.- Arguments
inds – Indices to be added.
inds
can be an array ofrank*idxType
or an array ofidxType
for 1-D domains.dataSorted : bool –
true
if data ininds
is sorted.isUnique : bool –
true
if data ininds
has no duplicates.preserveInds : bool –
true
if data ininds
needs to be preserved.addOn : locale – The locale where the indices should be added. Default value is
nil
which indicates that locale is unknown or there are more than one.
- Returns
Number of indices added to the domain
- Return type
int
- proc ref remove(i)
Remove index
i
from this domain
- proc ref 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. For domains whose
intIdxType != int
, please refer to the note inChapelRange.range.size
about changes to this routine’s return type.
- proc sizeAs(type t: integral): t¶
Return the number of indices in this domain as the specified type
- 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 contains(i: _value.idxType ...rank)¶
Return true if this domain contains
i
. Otherwise return false. For sparse domains, only indices with a value are considered to be contained in the domain.
- proc isSubset(super: domain)¶
Return true if this domain is a subset of
super
. Otherwise returns false.
- proc isSuper(sub: domain)¶
Return true if this domain is a superset of
sub
. Otherwise returns false.
- proc orderToIndex(order: int)¶
Returns the ith index in the domain counting from 0. For example,
{2..10 by 2}.orderToIndex(2)
would return6
.The order of a multidimensional domain follows its serial iterator. For example,
{1..3, 1..2}.orderToIndex(3)
would return(2, 2)
.Note
Right now, this method supports only dense rectangular domains with numeric indices
- Arguments
order – Order for which the corresponding index in the domain has to be found.
- Returns
Domain index for a given order in the domain.
- proc expand(off: rank*(intIdxType))¶
Return a new domain that is the current domain expanded by
off(d)
in dimensiond
ifoff(d)
is positive or contracted byoff(d)
in dimensiond
ifoff(d)
is negative.
- proc expand(off: intIdxType)
Return a new domain that is the current domain expanded by
off
in all dimensions ifoff
is positive or contracted byoff
in all dimensions ifoff
is negative.
- proc exterior(off: rank*(intIdxType))¶
Return a new domain that is the exterior portion of the current domain with
off(d)
indices for each dimensiond
. Ifoff(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: intIdxType)
Return a new domain that is the exterior portion of the current domain with
off
indices for each dimension. Ifoff
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*(intIdxType))¶
Return a new domain that is the interior portion of the current domain with
off(d)
indices for each dimensiond
. Ifoff(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: intIdxType)
Return a new domain that is the interior portion of the current domain with
off
indices for each dimension. Ifoff
is negative, compute the interior from the low bound of the dimension; if positive, compute the interior from the high bound.
- proc translate(off)¶
Return a new domain that is the current domain translated by
off(d)
in each dimensiond
.
- proc translate(off)
Return a new domain that is the current domain translated by
off
in each dimension.
- proc isEmpty(): bool¶
Return true if the domain has no indices
- proc localSlice(r ...rank)¶
Return a local view of the sub-array (slice) defined by the provided range(s), halting if the slice contains elements that are not local.
Indexing into this local view is cheaper, because the indices are known to be local.
- proc localSlice(d: domain)
Return a local view of the sub-array (slice) defined by the provided domain, halting if the slice contains elements that are not local.
Indexing into this local view is cheaper, because the indices are known to be local.
- iter sorted(comparator: ?t = chpl_defaultComparator())¶
Yield the domain indices in sorted order
- proc safeCast(type t: domain)¶
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() const ref¶
Return 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(loc: locale = here)¶
Return the subdomain that is local to loc.
- Arguments
loc : locale – indicates the locale for which the query should take place (defaults to here)
- iter localSubdomains(loc: locale = here)¶
Yield the subdomains that are local to loc.
- Arguments
loc : locale – indicates the locale for which the query should take place (defaults to here)
- proc isRectangular() param¶
Return true if this domain is a rectangular. Otherwise return false.
- proc isIrregular() param¶
Return true if
d
is an irregular domain; e.g. is not rectangular. Otherwise return false.
- proc isAssociative() param¶
Return true if
d
is an associative domain. Otherwise return false.
- proc isSparse() param¶
Return true if
d
is a sparse domain. Otherwise return false.
- type array¶
The array type
- 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 intIdxType type
- proc rank param
The number of dimensions in the array
- proc indices¶
Return the array’s indices as a copy of its domain.
Note
In a forthcoming release, we expect
.indices
to change in behavior to return/yield indices using a local representation rather than as a clone of the array’s domain. In order to preserve the legacy behavior in your program, please use.domain
instead (or a copy thereof).If you’d like to opt into a prototype of the new behavior, recompile with
-sarrayIndicesAlwaysLocal=true
. For dense, rectangular arrays, this will have the effect of returning a local domain representing the array’s indices; for a sparse or associative array, it will invoke a serial iterator that yields the array’s indices.See https://github.com/chapel-lang/chapel/issues/17883 for further details.
Warning
the current behavior of ‘.indices’ on arrays is deprecated; see https://chapel-lang.org/docs/1.25/builtins/ChapelArray.html#ChapelArray.indices for details
- proc dims()
Return a tuple of ranges describing the bounds of a rectangular domain. For a sparse domain, return the bounds of the parent domain.
- proc dim(d: int)
Return a range representing the boundary of this domain in a particular dimension.
- iter these() ref
Yield the array elements
- proc size
Return the number of elements in the array
- proc sizeAs(type t: integral)
Return the number of elements in the array as the specified type.
- proc reindex(newDomain: domain)¶
Return an array view over a new domain. The new domain must be of the same rank and size as the original array’s domain.
For example:
var A: [1..10] int; const D = {6..15}; ref reA = A.reindex(D); reA[6] = 1; // updates A[1]
- proc reindex(newDims ...)
Return an array view over a new domain defined implicitly by one or more newDims, which must be ranges. The new domain must be of the same rank and size as the original array’s domain.
For example:
var A: [3..4, 5..6] int; ref reA = A.reindex(13..14, 15..16); reA[13,15] = 1; // updates A[3,5]
- proc IRV¶
Return the Implicitly Represented Value for sparse arrays
- iter sorted(comparator: ?t = chpl_defaultComparator())
Yield the array elements in sorted order.
- proc targetLocales() const ref
Return 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(loc: locale = here)
Return the subdomain that is local to loc.
- Arguments
loc : locale – indicates the locale for which the query should take place (defaults to here)
- iter localSubdomains(loc: locale = here)
Yield the subdomains that are local to loc.
- Arguments
loc : locale – indicates the locale for which the query should take place (defaults to here)
- proc isEmpty(): bool
Return true if the array has no elements
- proc last
Return the last element in the array. The array must be a rectangular 1-D array.
- proc first
Return the first element in the array. The array must be a rectangular 1-D array.
- proc reverse()¶
Reverse the order of the values in the array.
- proc find(val: this.eltType): (bool, index(this.domain))¶
Return a tuple containing
true
and the index of the first instance ofval
in the array, or ifval
is not found, a tuple containingfalse
and an unspecified value is returned.
- proc count(val: this.eltType): int¶
Return the number of times
val
occurs in the array.
- proc shape
Return a tuple of integers describing the size of each dimension. For a sparse array, returns the shape of the parent domain.
- proc isRectangular() param
Return true if the argument
a
is an array with a rectangular domain. Otherwise return false.
- proc isIrregular() param
Return true if
a
is an array with an irregular domain; e.g. not rectangular. Otherwise return false.
- proc isAssociative() param
Return true if
a
is an array with an associative domain. Otherwise return false.
- proc isSparse() param
Return true if
a
is an array with a sparse domain. Otherwise return false.
- proc array.equals(that: []): bool¶
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 inthat
. 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)¶
Return a copy of the array
A
containing the same values but in the shape of the domainD
. The number of indices in the domain must equal the number of elements in the array. The elements ofA
are copied into the new array using the default iteration orders overD
andA
.