Skip to content

Commit dae5922

Browse files
Replace _get_idx w/ CartesianIndices/LinearIndices
1 parent 5e9d10d commit dae5922

File tree

9 files changed

+85
-93
lines changed

9 files changed

+85
-93
lines changed

ext/ClimaCoreCUDAExt.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ using CUDA: threadIdx, blockIdx, blockDim
1111
import StaticArrays: SVector, SMatrix, SArray
1212
import ClimaCore.DataLayouts: slab, column
1313
import ClimaCore.Utilities: half
14+
import ClimaCore.Utilities: cart_ind, linear_ind
1415
import ClimaCore.RecursiveApply:
1516
, , , radd, rmul, rsub, rdiv, rmap, rzero, rmin, rmax
1617

ext/cuda/operators_finite_difference.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function copyto_stencil_kernel!(
6363
gid = threadIdx().x + (blockIdx().x - 1) * blockDim().x
6464
if gid Nv * Nq * Nq * Nh
6565
(li, lw, rw, ri) = bds
66-
(v, i, j, h) = Topologies._get_idx((Nv, Nq, Nq, Nh), gid)
66+
(v, i, j, h) = cart_ind((Nv, Nq, Nq, Nh), gid).I
6767
hidx = (i, j, h)
6868
idx = v - 1 + li
6969
window =

ext/cuda/operators_integral.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function column_integral_definite_kernel!(
3737
idx = threadIdx().x + (blockIdx().x - 1) * blockDim().x
3838
Ni, Nj, _, _, Nh = size(Fields.field_values(ᶜfield))
3939
if idx <= Ni * Nj * Nh
40-
i, j, h = Topologies._get_idx((Ni, Nj, Nh), idx)
40+
i, j, h = cart_ind((Ni, Nj, Nh), idx).I
4141
∫field_column = Spaces.column(∫field, i, j, h)
4242
ᶜfield_column = Spaces.column(ᶜfield, i, j, h)
4343
_column_integral_definite!(∫field_column, ᶜfield_column)
@@ -52,7 +52,7 @@ function column_integral_indefinite_kernel!(
5252
idx = threadIdx().x + (blockIdx().x - 1) * blockDim().x
5353
Ni, Nj, _, _, Nh = size(Fields.field_values(ᶜfield))
5454
if idx <= Ni * Nj * Nh
55-
i, j, h = Topologies._get_idx((Ni, Nj, Nh), idx)
55+
i, j, h = cart_ind((Ni, Nj, Nh), idx).I
5656
ᶠ∫field_column = Spaces.column(ᶠ∫field, i, j, h)
5757
ᶜfield_column = Spaces.column(ᶜfield, i, j, h)
5858
_column_integral_indefinite!(ᶠ∫field_column, ᶜfield_column)
@@ -117,7 +117,7 @@ function column_mapreduce_kernel_extruded!(
117117
idx = threadIdx().x + (blockIdx().x - 1) * blockDim().x
118118
Ni, Nj, _, _, Nh = size(Fields.field_values(reduced_field))
119119
if idx <= Ni * Nj * Nh
120-
i, j, h = Topologies._get_idx((Ni, Nj, Nh), idx)
120+
i, j, h = cart_ind((Ni, Nj, Nh), idx).I
121121
reduced_field_column = Spaces.column(reduced_field, i, j, h)
122122
field_columns = map(field -> Spaces.column(field, i, j, h), fields)
123123
_column_mapreduce!(fn, op, reduced_field_column, field_columns...)

ext/cuda/operators_thomas_algorithm.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function thomas_algorithm_kernel!(
2424
idx = threadIdx().x + (blockIdx().x - 1) * blockDim().x
2525
Ni, Nj, _, _, Nh = size(Fields.field_values(A))
2626
if idx <= Ni * Nj * Nh
27-
i, j, h = Topologies._get_idx((Ni, Nj, Nh), idx)
27+
i, j, h = cart_ind((Ni, Nj, Nh), idx).I
2828
thomas_algorithm!(Spaces.column(A, i, j, h), Spaces.column(b, i, j, h))
2929
end
3030
return nothing

ext/cuda/topologies_dss.jl

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,9 @@ function dss_load_perimeter_data_kernel!(
4646
sized = (nlevels, Nq, Nq, nfidx, nelems) # size of data
4747

4848
if gidx prod(sizep)
49-
(level, p, fidx, elem) = Topologies._get_idx(sizep, gidx)
49+
(level, p, fidx, elem) = cart_ind(sizep, gidx).I
5050
(ip, jp) = perimeter[p]
51-
data_idx = Topologies._get_idx(sized, (level, ip, jp, fidx, elem))
51+
data_idx = linear_ind(sized, (level, ip, jp, fidx, elem))
5252
pperimeter_data[level, p, fidx, elem] = pdata[data_idx]
5353
end
5454
return nothing
@@ -86,9 +86,9 @@ function dss_unload_perimeter_data_kernel!(
8686
sized = (nlevels, Nq, Nq, nfidx, nelems) # size of data
8787

8888
if gidx prod(sizep)
89-
(level, p, fidx, elem) = Topologies._get_idx(sizep, gidx)
89+
(level, p, fidx, elem) = cart_ind(sizep, gidx).I
9090
(ip, jp) = perimeter[p]
91-
data_idx = Topologies._get_idx(sized, (level, ip, jp, fidx, elem))
91+
data_idx = linear_ind(sized, (level, ip, jp, fidx, elem))
9292
pdata[data_idx] = pperimeter_data[level, p, fidx, elem]
9393
end
9494
return nothing
@@ -139,7 +139,7 @@ function dss_local_kernel!(
139139
(nlevels, nperimeter, nfidx, _) = size(pperimeter_data)
140140
if gidx nlevels * nfidx * nlocalvertices # local vertices
141141
sizev = (nlevels, nfidx, nlocalvertices)
142-
(level, fidx, vertexid) = Topologies._get_idx(sizev, gidx)
142+
(level, fidx, vertexid) = cart_ind(sizev, gidx).I
143143
sum_data = FT(0)
144144
st, en =
145145
local_vertex_offset[vertexid], local_vertex_offset[vertexid + 1]
@@ -157,7 +157,7 @@ function dss_local_kernel!(
157157
nfacedof = div(nperimeter - 4, 4)
158158
sizef = (nlevels, nfidx, nlocalfaces)
159159
(level, fidx, faceid) =
160-
Topologies._get_idx(sizef, gidx - nlevels * nfidx * nlocalvertices)
160+
cart_ind(sizef, gidx - nlevels * nfidx * nlocalvertices).I
161161
(lidx1, face1, lidx2, face2, reversed) = interior_faces[faceid]
162162
(first1, inc1, last1) =
163163
Topologies.perimeter_face_indices_cuda(face1, nfacedof, false)
@@ -247,21 +247,18 @@ function dss_transform_kernel!(
247247
sizet_wt = (Nq, Nq, 1, nelems)
248248
sizet_metric = (nlevels, Nq, Nq, nmetric, nelems)
249249

250-
(level, p, localelemno) = Topologies._get_idx(sizet, gidx)
250+
(level, p, localelemno) = cart_ind(sizet, gidx).I
251251
elem = localelems[localelemno]
252252
(ip, jp) = perimeter[p]
253253

254-
weight = pweight[Topologies._get_idx(sizet_wt, (ip, jp, 1, elem))]
254+
weight = pweight[linear_ind(sizet_wt, (ip, jp, 1, elem))]
255255
for fidx in scalarfidx
256-
data_idx =
257-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx, elem))
256+
data_idx = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
258257
pperimeter_data[level, p, fidx, elem] = pdata[data_idx] * weight
259258
end
260259
for fidx in covariant12fidx
261-
data_idx1 =
262-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx, elem))
263-
data_idx2 =
264-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
260+
data_idx1 = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
261+
data_idx2 = linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
265262
(idx11, idx12, idx21, idx22) =
266263
Topologies._get_idx_metric(sizet_metric, (level, ip, jp, elem))
267264
pperimeter_data[level, p, fidx, elem] =
@@ -276,10 +273,8 @@ function dss_transform_kernel!(
276273
) * weight
277274
end
278275
for fidx in contravariant12fidx
279-
data_idx1 =
280-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx, elem))
281-
data_idx2 =
282-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
276+
data_idx1 = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
277+
data_idx2 = linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
283278
(idx11, idx12, idx21, idx22) =
284279
Topologies._get_idx_metric(sizet_metric, (level, ip, jp, elem))
285280
pperimeter_data[level, p, fidx, elem] =
@@ -363,19 +358,16 @@ function dss_untransform_kernel!(
363358
sizet_wt = (Nq, Nq, 1, nelems)
364359
sizet_metric = (nlevels, Nq, Nq, nmetric, nelems)
365360

366-
(level, p, localelemno) = Topologies._get_idx(sizet, gidx)
361+
(level, p, localelemno) = cart_ind(sizet, gidx).I
367362
elem = localelems[localelemno]
368363
ip, jp = perimeter[p]
369364
for fidx in scalarfidx
370-
data_idx =
371-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx, elem))
365+
data_idx = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
372366
pdata[data_idx] = pperimeter_data[level, p, fidx, elem]
373367
end
374368
for fidx in covariant12fidx
375-
data_idx1 =
376-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx, elem))
377-
data_idx2 =
378-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
369+
data_idx1 = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
370+
data_idx2 = linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
379371
(idx11, idx12, idx21, idx22) =
380372
Topologies._get_idx_metric(sizet_metric, (level, ip, jp, elem))
381373
pdata[data_idx1] =
@@ -386,10 +378,8 @@ function dss_untransform_kernel!(
386378
p∂x∂ξ[idx22] * pperimeter_data[level, p, fidx + 1, elem]
387379
end
388380
for fidx in contravariant12fidx
389-
data_idx1 =
390-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx, elem))
391-
data_idx2 =
392-
Topologies._get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
381+
data_idx1 = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
382+
data_idx2 = linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
393383
(idx11, idx12, idx21, idx22) =
394384
Topologies._get_idx_metric(sizet_metric, (level, ip, jp, elem))
395385
pdata[data_idx1] =
@@ -445,7 +435,7 @@ function dss_local_ghost_kernel!(
445435
nghostvertices = length(ghost_vertex_offset) - 1
446436
if gidx nlevels * nfidx * nghostvertices
447437
sizev = (nlevels, nfidx, nghostvertices)
448-
(level, fidx, vertexid) = Topologies._get_idx(sizev, gidx)
438+
(level, fidx, vertexid) = cart_ind(sizev, gidx).I
449439
sum_data = FT(0)
450440
st, en =
451441
ghost_vertex_offset[vertexid], ghost_vertex_offset[vertexid + 1]
@@ -506,8 +496,8 @@ function fill_send_buffer_kernel!(
506496
sizet = (nlevels, nfid, nsend)
507497
#if gidx ≤ nsend * nlevels * nfid
508498
if gidx nlevels * nfid * nsend
509-
#(isend, level, fidx) = Topologies._get_idx(sizet, gidx)
510-
(level, fidx, isend) = Topologies._get_idx(sizet, gidx)
499+
#(isend, level, fidx) = cart_ind(sizet, gidx).I
500+
(level, fidx, isend) = cart_ind(sizet, gidx).I
511501
lidx = send_buf_idx[isend, 1]
512502
ip = send_buf_idx[isend, 2]
513503
idx = level + ((fidx - 1) + (isend - 1) * nfid) * nlevels
@@ -551,8 +541,8 @@ function load_from_recv_buffer_kernel!(
551541
sizet = (nlevels, nfid, nrecv)
552542
#if gidx ≤ nrecv * nlevels * nfid
553543
if gidx nlevels * nfid * nrecv
554-
#(irecv, level, fidx) = Topologies._get_idx(sizet, gidx)
555-
(level, fidx, irecv) = Topologies._get_idx(sizet, gidx)
544+
#(irecv, level, fidx) = cart_ind(sizet, gidx).I
545+
(level, fidx, irecv) = cart_ind(sizet, gidx).I
556546
lidx = recv_buf_idx[irecv, 1]
557547
ip = recv_buf_idx[irecv, 2]
558548
idx = level + ((fidx - 1) + (irecv - 1) * nfid) * nlevels
@@ -605,7 +595,7 @@ function dss_ghost_kernel!(
605595

606596
if gidx nlevels * nfidx * nghostvertices
607597
(level, fidx, ghostvertexidx) =
608-
Topologies._get_idx((nlevels, nfidx, nghostvertices), gidx)
598+
cart_ind((nlevels, nfidx, nghostvertices), gidx).I
609599
idxresult, lvertresult = repr_ghost_vertex[ghostvertexidx]
610600
ipresult = perimeter_vertex_node_index(lvertresult)
611601
result = pperimeter_data[level, ipresult, fidx, idxresult]

src/Topologies/Topologies.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ using DocStringExtensions
55
import ClimaComms, Adapt
66

77
import ..ClimaCore
8-
import ..Utilities: Cache
8+
import ..Utilities: Cache, cart_ind, linear_ind
99
import ..Geometry
1010
import ..Domains: Domains, coordinate_type
1111
import ..Meshes: Meshes, domain, coordinates

src/Topologies/dss.jl

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -367,17 +367,17 @@ function dss_transform!(
367367

368368
@inbounds for elem in localelems
369369
for (p, (ip, jp)) in enumerate(perimeter)
370-
pw = pweight[_get_idx(sizet_wt, (ip, jp, 1, elem))]
370+
pw = pweight[linear_ind(sizet_wt, (ip, jp, 1, elem))]
371371

372372
for fidx in scalarfidx, level in 1:nlevels
373-
data_idx = _get_idx(sizet_data, (level, ip, jp, fidx, elem))
373+
data_idx = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
374374
pperimeter_data[level, p, fidx, elem] = pdata[data_idx] * pw
375375
end
376376

377377
for fidx in covariant12fidx, level in 1:nlevels
378-
data_idx1 = _get_idx(sizet_data, (level, ip, jp, fidx, elem))
378+
data_idx1 = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
379379
data_idx2 =
380-
_get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
380+
linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
381381
(idx11, idx12, idx21, idx22) =
382382
_get_idx_metric(sizet_metric, (level, ip, jp, elem))
383383
pperimeter_data[level, p, fidx, elem] =
@@ -393,9 +393,9 @@ function dss_transform!(
393393
end
394394

395395
for fidx in contravariant12fidx, level in 1:nlevels
396-
data_idx1 = _get_idx(sizet_data, (level, ip, jp, fidx, elem))
396+
data_idx1 = linear_ind(sizet_data, (level, ip, jp, fidx, elem))
397397
data_idx2 =
398-
_get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
398+
linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
399399
(idx11, idx12, idx21, idx22) =
400400
_get_idx_metric(sizet_metric, (level, ip, jp, elem))
401401
pperimeter_data[level, p, fidx, elem] =
@@ -467,16 +467,17 @@ function dss_untransform!(
467467
for (p, (ip, jp)) in enumerate(perimeter)
468468
for fidx in scalarfidx
469469
for level in 1:nlevels
470-
data_idx = _get_idx(sizet_data, (level, ip, jp, fidx, elem))
470+
data_idx =
471+
linear_ind(sizet_data, (level, ip, jp, fidx, elem))
471472
pdata[data_idx] = pperimeter_data[level, p, fidx, elem]
472473
end
473474
end
474475
for fidx in covariant12fidx
475476
for level in 1:nlevels
476477
data_idx1 =
477-
_get_idx(sizet_data, (level, ip, jp, fidx, elem))
478+
linear_ind(sizet_data, (level, ip, jp, fidx, elem))
478479
data_idx2 =
479-
_get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
480+
linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
480481
(idx11, idx12, idx21, idx22) =
481482
_get_idx_metric(sizet_metric, (level, ip, jp, elem))
482483
pdata[data_idx1] =
@@ -490,9 +491,9 @@ function dss_untransform!(
490491
for fidx in contravariant12fidx
491492
for level in 1:nlevels
492493
data_idx1 =
493-
_get_idx(sizet_data, (level, ip, jp, fidx, elem))
494+
linear_ind(sizet_data, (level, ip, jp, fidx, elem))
494495
data_idx2 =
495-
_get_idx(sizet_data, (level, ip, jp, fidx + 1, elem))
496+
linear_ind(sizet_data, (level, ip, jp, fidx + 1, elem))
496497
(idx11, idx12, idx21, idx22) =
497498
_get_idx_metric(sizet_metric, (level, ip, jp, elem))
498499
pdata[data_idx1] =
@@ -520,7 +521,7 @@ function dss_load_perimeter_data!(
520521
sizet = (nlevels, Nq, Nq, nfid, nelems)
521522
for elem in 1:nelems, (p, (ip, jp)) in enumerate(perimeter)
522523
for fidx in 1:nfid, level in 1:nlevels
523-
idx = _get_idx(sizet, (level, ip, jp, fidx, elem))
524+
idx = linear_ind(sizet, (level, ip, jp, fidx, elem))
524525
pperimeter_data[level, p, fidx, elem] = pdata[idx]
525526
end
526527
end
@@ -539,7 +540,7 @@ function dss_unload_perimeter_data!(
539540
sizet = (nlevels, Nq, Nq, nfid, nelems)
540541
for elem in 1:nelems, (p, (ip, jp)) in enumerate(perimeter)
541542
for fidx in 1:nfid, level in 1:nlevels
542-
idx = _get_idx(sizet, (level, ip, jp, fidx, elem))
543+
idx = linear_ind(sizet, (level, ip, jp, fidx, elem))
543544
pdata[idx] = pperimeter_data[level, p, fidx, elem]
544545
end
545546
end

src/Topologies/dss_transform.jl

Lines changed: 12 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -231,47 +231,20 @@ end
231231
end
232232

233233
# helper functions for DSS2
234-
function _get_idx(sizet::NTuple{5, Int}, loc::NTuple{5, Int})
235-
(n1, n2, n3, n4, n5) = sizet
236-
(i1, i2, i3, i4, i5) = loc
237-
return i1 +
238-
((i2 - 1) + ((i3 - 1) + ((i4 - 1) + (i5 - 1) * n4) * n3) * n2) * n1
239-
end
240-
241-
function _get_idx(sizet::NTuple{4, Int}, loc::NTuple{4, Int})
242-
(n1, n2, n3, n4) = sizet
243-
(i1, i2, i3, i4) = loc
244-
return i1 + ((i2 - 1) + ((i3 - 1) + (i4 - 1) * n3) * n2) * n1
245-
end
246-
247-
function _get_idx(sizet::NTuple{3, Int}, idx::Int)
248-
(n1, n2, n3) = sizet
249-
i3 = cld(idx, n1 * n2)
250-
i2 = cld(idx - (i3 - 1) * n1 * n2, n1)
251-
i1 = idx - (i3 - 1) * n1 * n2 - (i2 - 1) * n1
252-
return (i1, i2, i3)
253-
end
254-
255-
function _get_idx(sizet::NTuple{4, Int}, idx::Int)
256-
(n1, n2, n3, n4) = sizet
257-
i4 = cld(idx, n1 * n2 * n3)
258-
i3 = cld(idx - (i4 - 1) * n1 * n2 * n3, n1 * n2)
259-
i2 = cld(idx - (i4 - 1) * n1 * n2 * n3 - (i3 - 1) * n1 * n2, n1)
260-
i1 = idx - (i4 - 1) * n1 * n2 * n3 - (i3 - 1) * n1 * n2 - (i2 - 1) * n1
261-
return (i1, i2, i3, i4)
262-
end
263234

264235
function _get_idx_metric(sizet::NTuple{5, Int}, loc::NTuple{4, Int})
265-
nmetric = sizet[4]
266-
(i11, i12, i21, i22) = nmetric == 4 ? (1, 2, 3, 4) : (1, 2, 4, 5)
267-
(level, i, j, elem) = loc
268-
return (
269-
_get_idx(sizet, (level, i, j, i11, elem)),
270-
_get_idx(sizet, (level, i, j, i12, elem)),
271-
_get_idx(sizet, (level, i, j, i21, elem)),
272-
_get_idx(sizet, (level, i, j, i22, elem)),
273-
)
274-
return nothing
236+
@inbounds begin
237+
nmetric = sizet[4]
238+
(i11, i12, i21, i22) = nmetric == 4 ? (1, 2, 3, 4) : (1, 2, 4, 5)
239+
(level, i, j, elem) = loc
240+
inds = (
241+
linear_ind(sizet, (level, i, j, i11, elem)),
242+
linear_ind(sizet, (level, i, j, i12, elem)),
243+
linear_ind(sizet, (level, i, j, i21, elem)),
244+
linear_ind(sizet, (level, i, j, i22, elem)),
245+
)
246+
return inds
247+
end
275248
end
276249

277250
function _representative_slab(

src/Utilities/Utilities.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,31 @@ include("plushalf.jl")
44
include("unrolled_functions.jl")
55
include("cache.jl")
66

7+
"""
8+
cart_ind(n::NTuple, i::Integer)
9+
10+
Returns a `CartesianIndex` from the list
11+
`CartesianIndices(map(x->Base.OneTo(x), n))[i]`
12+
given size `n` and location `i`.
13+
"""
14+
Base.@propagate_inbounds cart_ind(n::NTuple, i::Integer) =
15+
@inbounds CartesianIndices(map(x -> Base.OneTo(x), n))[i]
16+
17+
"""
18+
linear_ind(n::NTuple, ci::CartesianIndex)
19+
linear_ind(n::NTuple, t::NTuple)
20+
21+
Returns a linear index from the list
22+
`LinearIndices(map(x->Base.OneTo(x), n))[ci]`
23+
given size `n` and cartesian index `ci`.
24+
25+
The `linear_ind(n::NTuple, t::NTuple)` wraps `t`
26+
in a `Cartesian` index and calls
27+
`linear_ind(n::NTuple, ci::CartesianIndex)`.
28+
"""
29+
Base.@propagate_inbounds linear_ind(n::NTuple, ci::CartesianIndex) =
30+
@inbounds LinearIndices(map(x -> Base.OneTo(x), n))[ci]
31+
Base.@propagate_inbounds linear_ind(n::NTuple, loc::NTuple) =
32+
linear_ind(n, CartesianIndex(loc))
33+
734
end # module

0 commit comments

Comments
 (0)