Skip to content

Commit 29a44ad

Browse files
committed
Use positional arguments for repeat() and loosen signature
Put 'outer' first as it is more natural to omit 'inner'. Deprecate the old version with keyword arguments. Also change the signature to accept any AbstractArray as first argument, and any type for 'outer' and 'inner', to allow in particular passing tuples or arrays. Allow passing an empty collection to imply a no-op.
1 parent 3da9aee commit 29a44ad

File tree

5 files changed

+142
-58
lines changed

5 files changed

+142
-58
lines changed

base/abstractarraymath.jl

Lines changed: 53 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -200,39 +200,74 @@ function repmat(a::AbstractVector, m::Int)
200200
end
201201

202202
# Generalized repmat
203-
function repeat{T}(A::Array{T};
204-
inner::Array{Int} = ones(Int, ndims(A)),
205-
outer::Array{Int} = ones(Int, ndims(A)))
203+
"""
204+
repeat(A::AbstractArray, outer[, inner])
205+
206+
Construct an array by repeating the entries of `a`. The i-th element of `outer`
207+
specifies the number of times that a slice along the i-th dimension of `a`
208+
should be repeated. The i-th element of `inner` specifies the number of times
209+
that the individual entries of the i-th dimension of `a` should be repeated.
210+
Pass an empty tuple as `outer` (or any other empty collection, which is equivalent
211+
to a tuple of ones of length `ndims(a)`) to use only inner repetitions.
212+
213+
```jldoctest
214+
julia> repeat(1:2, 2)
215+
4-element Array{Int64,1}:
216+
1
217+
2
218+
1
219+
2
220+
221+
julia> repeat(1:2, (), 2)
222+
4-element Array{Int64,1}:
223+
1
224+
1
225+
2
226+
2
227+
228+
julia> repeat([1 2; 3 4], (1, 2), (2, 1))
229+
4x4 Array{Int64,2}:
230+
1 2 1 2
231+
1 2 1 2
232+
3 4 3 4
233+
3 4 3 4
234+
```
235+
"""
236+
function repeat(A::AbstractArray, outer, inner = ())
206237
ndims_in = ndims(A)
207-
length_inner = length(inner)
208-
length_outer = length(outer)
209-
ndims_out = max(ndims_in, length_inner, length_outer)
238+
length_inner = isempty(inner) ? ndims(A) : length(inner)
239+
length_outer = isempty(outer) ? ndims(A) : length(outer)
210240

211-
if length_inner < ndims_in || length_outer < ndims_in
212-
throw(ArgumentError("inner/outer repetitions must be set for all input dimensions"))
213-
end
241+
length_inner >= ndims_in || throw(ArgumentError("only $(length(inner)) repetitions specified, for input array with $(ndims(A)) dimensions"))
242+
length_outer >= ndims_in || throw(ArgumentError("only $(length(outer)) repetitions specified for input array with $(ndims(A)) dimensions"))
243+
244+
ndims_out = max(ndims_in, length_inner, length_outer)
214245

215-
inner = vcat(inner, ones(Int,ndims_out-length_inner))
216-
outer = vcat(outer, ones(Int,ndims_out-length_outer))
246+
inner_a = isempty(inner) ?
247+
ones(Int,ndims_in) :
248+
vcat(collect(inner), ones(Int,ndims_out-length_inner))
249+
outer_a = isempty(outer) ?
250+
ones(Int,ndims_in) :
251+
vcat(collect(outer), ones(Int,ndims_out-length_outer))
217252

218253
size_in = size(A)
219-
size_out = ntuple(i->inner[i]*size(A,i)*outer[i],ndims_out)::Dims
220-
inner_size_out = ntuple(i->inner[i]*size(A,i),ndims_out)::Dims
254+
size_out = ntuple(i->inner_a[i]*size(A,i)*outer_a[i],ndims_out)::Dims
255+
inner_size_out = ntuple(i->inner_a[i]*size(A,i),ndims_out)::Dims
221256

222-
indices_in = Array(Int, ndims_in)
223-
indices_out = Array(Int, ndims_out)
257+
indices_in = Vector{Int}(ndims_in)
258+
indices_out = Vector{Int}(ndims_out)
224259

225260
length_out = prod(size_out)
226-
R = Array(T, size_out)
261+
R = similar(A, size_out)
227262

228263
for index_out in 1:length_out
229264
ind2sub!(indices_out, size_out, index_out)
230265
for t in 1:ndims_in
231266
# "Project" outer repetitions into inner repetitions
232267
indices_in[t] = mod1(indices_out[t], inner_size_out[t])
233268
# Find inner repetitions using flooring division
234-
if inner[t] != 1
235-
indices_in[t] = fld1(indices_in[t], inner[t])
269+
if inner_a[t] != 1
270+
indices_in[t] = fld1(indices_in[t], inner_a[t])
236271
end
237272
end
238273
index_in = sub2ind(size_in, indices_in...)

base/deprecated.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -893,3 +893,6 @@ function isexecutable(st::Filesystem.StatStruct)
893893
return (st.mode & 0o111) > 0
894894
end
895895
export isreadable, iswritable, isexecutable
896+
897+
# 12953
898+
@deprecate repeat(A::AbstractArray; outer = ones(Int, ndims(A)), inner = ones(Int, ndims(A))) repeat(A, outer, inner)

base/docs/helpdb.jl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4935,13 +4935,6 @@ Return an iterator over all keys in a collection. `collect(keys(d))` returns an
49354935
"""
49364936
keys
49374937

4938-
doc"""
4939-
repeat(A, inner = Int[], outer = Int[])
4940-
4941-
Construct an array by repeating the entries of `A`. The i-th element of `inner` specifies the number of times that the individual entries of the i-th dimension of `A` should be repeated. The i-th element of `outer` specifies the number of times that a slice along the i-th dimension of `A` should be repeated.
4942-
"""
4943-
repeat
4944-
49454938
doc"""
49464939
scale(A, b)
49474940
scale(b, A)

doc/stdlib/linalg.rst

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -842,11 +842,34 @@ Linear algebra functions in Julia are largely implemented by calling functions f
842842
843843
Construct a matrix by repeating the given matrix ``n`` times in dimension 1 and ``m`` times in dimension 2.
844844

845-
.. function:: repeat(A, inner = Int[], outer = Int[])
845+
.. function:: repeat(A::AbstractArray, outer[, inner])
846846

847847
.. Docstring generated from Julia source
848848
849-
Construct an array by repeating the entries of ``A``\ . The i-th element of ``inner`` specifies the number of times that the individual entries of the i-th dimension of ``A`` should be repeated. The i-th element of ``outer`` specifies the number of times that a slice along the i-th dimension of ``A`` should be repeated.
849+
Construct an array by repeating the entries of ``a``\ . The i-th element of ``outer`` specifies the number of times that a slice along the i-th dimension of ``a`` should be repeated. The i-th element of ``inner`` specifies the number of times that the individual entries of the i-th dimension of ``a`` should be repeated. Pass an empty tuple as ``outer`` (or any other empty collection, which is equivalent to a tuple of ones of length ``ndims(a)``\ ) to use only inner repetitions.
850+
851+
.. doctest::
852+
853+
julia> repeat(1:2, 2)
854+
4-element Array{Int64,1}:
855+
1
856+
2
857+
1
858+
2
859+
860+
julia> repeat(1:2, (), 2)
861+
4-element Array{Int64,1}:
862+
1
863+
1
864+
2
865+
2
866+
867+
julia> repeat([1 2; 3 4], (1, 2), (2, 1))
868+
4x4 Array{Int64,2}:
869+
1 2 1 2
870+
1 2 1 2
871+
3 4 3 4
872+
3 4 3 4
850873

851874
.. function:: kron(A, B)
852875

test/arrayops.jl

Lines changed: 61 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -402,53 +402,57 @@ let
402402
@test isequal(cumsum(A,2),A2)
403403
@test isequal(cumsum(A,3),A3)
404404

405-
R = repeat([1, 2], inner = [1], outer = [1])
406-
@test R == [1, 2]
407-
R = repeat([1, 2], inner = [2], outer = [1])
408-
@test R == [1, 1, 2, 2]
409-
R = repeat([1, 2], inner = [1], outer = [2])
410-
@test R == [1, 2, 1, 2]
411-
R = repeat([1, 2], inner = [2], outer = [2])
412-
@test R == [1, 1, 2, 2, 1, 1, 2, 2]
413-
R = repeat([1, 2], inner = [1, 1], outer = [1, 1])
405+
R1 = repeat([1, 2], 1)
406+
R2 = repeat([1, 2], (1,), (1,))
407+
@test R1 == R2 == [1, 2]
408+
R1 = repeat([1, 2], (), (2,))
409+
R2 = repeat([1, 2], (1,), (2,))
410+
@test R1 == R2 == [1, 1, 2, 2]
411+
R1 = repeat([1, 2], 2)
412+
R2 = repeat([1, 2], (2,), (1,))
413+
@test R1 == R2 == [1, 2, 1, 2]
414+
R1 = repeat([1, 2], 2, 2)
415+
R2 = repeat([1, 2], (2,), (2,))
416+
@test R1 == R2 == [1, 1, 2, 2, 1, 1, 2, 2]
417+
R = repeat([1, 2], (1, 1), (1, 1))
414418
@test R == [1, 2]''
415-
R = repeat([1, 2], inner = [2, 1], outer = [1, 1])
419+
R = repeat([1, 2], (1, 1), (2, 1))
416420
@test R == [1, 1, 2, 2]''
417-
R = repeat([1, 2], inner = [1, 2], outer = [1, 1])
421+
R = repeat([1, 2], (1, 1), (1, 2))
418422
@test R == [1 1; 2 2]
419-
R = repeat([1, 2], inner = [1, 1], outer = [2, 1])
423+
R = repeat([1, 2], (2, 1), (1, 1))
420424
@test R == [1, 2, 1, 2]''
421-
R = repeat([1, 2], inner = [1, 1], outer = [1, 2])
425+
R = repeat([1, 2], (1, 2), (1, 1))
422426
@test R == [1 1; 2 2]
423427

424428
R = repeat([1 2;
425-
3 4], inner = [1, 1], outer = [1, 1])
429+
3 4], (1, 1), (1, 1))
426430
@test R == [1 2;
427431
3 4]
428432
R = repeat([1 2;
429-
3 4], inner = [1, 1], outer = [2, 1])
433+
3 4], (2, 1), (1, 1))
430434
@test R == [1 2;
431435
3 4;
432436
1 2;
433437
3 4]
434438
R = repeat([1 2;
435-
3 4], inner = [1, 1], outer = [1, 2])
439+
3 4], (1, 2), (1, 1))
436440
@test R == [1 2 1 2;
437441
3 4 3 4]
438442
R = repeat([1 2;
439-
3 4], inner = [1, 1], outer = [2, 2])
443+
3 4], (2, 2), (1, 1))
440444
@test R == [1 2 1 2;
441445
3 4 3 4;
442446
1 2 1 2;
443447
3 4 3 4]
444448
R = repeat([1 2;
445-
3 4], inner = [2, 1], outer = [1, 1])
449+
3 4], (1, 1), (2, 1))
446450
@test R == [1 2;
447451
1 2;
448452
3 4;
449453
3 4]
450454
R = repeat([1 2;
451-
3 4], inner = [2, 1], outer = [2, 1])
455+
3 4], (2, 1), (2, 1))
452456
@test R == [1 2;
453457
1 2;
454458
3 4;
@@ -458,13 +462,13 @@ let
458462
3 4;
459463
3 4]
460464
R = repeat([1 2;
461-
3 4], inner = [2, 1], outer = [1, 2])
465+
3 4], (1, 2), (2, 1))
462466
@test R == [1 2 1 2;
463467
1 2 1 2;
464468
3 4 3 4;
465469
3 4 3 4;]
466470
R = repeat([1 2;
467-
3 4], inner = [2, 1], outer = [2, 2])
471+
3 4], (2, 2), (2, 1))
468472
@test R == [1 2 1 2;
469473
1 2 1 2;
470474
3 4 3 4;
@@ -474,33 +478,33 @@ let
474478
3 4 3 4;
475479
3 4 3 4]
476480
R = repeat([1 2;
477-
3 4], inner = [1, 2], outer = [1, 1])
481+
3 4], (1, 1), (1, 2))
478482
@test R == [1 1 2 2;
479483
3 3 4 4]
480484
R = repeat([1 2;
481-
3 4], inner = [1, 2], outer = [2, 1])
485+
3 4], (2, 1), (1, 2))
482486
@test R == [1 1 2 2;
483487
3 3 4 4;
484488
1 1 2 2;
485489
3 3 4 4]
486490
R = repeat([1 2;
487-
3 4], inner = [1, 2], outer = [1, 2])
491+
3 4], (1, 2), (1, 2))
488492
@test R == [1 1 2 2 1 1 2 2;
489493
3 3 4 4 3 3 4 4]
490494
R = repeat([1 2;
491-
3 4], inner = [1, 2], outer = [2, 2])
495+
3 4], (2, 2), (1, 2))
492496
@test R == [1 1 2 2 1 1 2 2;
493497
3 3 4 4 3 3 4 4;
494498
1 1 2 2 1 1 2 2;
495499
3 3 4 4 3 3 4 4]
496500
R = repeat([1 2;
497-
3 4], inner = [2, 2], outer = [1, 1])
501+
3 4], (1, 1), (2, 2))
498502
@test R == [1 1 2 2;
499503
1 1 2 2;
500504
3 3 4 4;
501505
3 3 4 4]
502506
R = repeat([1 2;
503-
3 4], inner = [2, 2], outer = [2, 1])
507+
3 4], (2, 1), (2, 2))
504508
@test R == [1 1 2 2;
505509
1 1 2 2;
506510
3 3 4 4;
@@ -510,13 +514,13 @@ let
510514
3 3 4 4;
511515
3 3 4 4]
512516
R = repeat([1 2;
513-
3 4], inner = [2, 2], outer = [1, 2])
517+
3 4], (1, 2), (2, 2))
514518
@test R == [1 1 2 2 1 1 2 2;
515519
1 1 2 2 1 1 2 2;
516520
3 3 4 4 3 3 4 4;
517521
3 3 4 4 3 3 4 4]
518522
R = repeat([1 2;
519-
3 4], inner = [2, 2], outer = [2, 2])
523+
3 4], (2, 2), (2, 2))
520524
@test R == [1 1 2 2 1 1 2 2;
521525
1 1 2 2 1 1 2 2;
522526
3 3 4 4 3 3 4 4;
@@ -525,17 +529,21 @@ let
525529
1 1 2 2 1 1 2 2;
526530
3 3 4 4 3 3 4 4;
527531
3 3 4 4 3 3 4 4]
532+
@test_throws ArgumentError repeat([1 2;
533+
3 4], 2, (2, 2))
534+
@test_throws ArgumentError repeat([1 2;
535+
3 4], (2, 2), 2)
528536

529537
A = reshape(1:8, 2, 2, 2)
530-
R = repeat(A, inner = [1, 1, 2], outer = [1, 1, 1])
538+
R = repeat(A, (1, 1, 1), (1, 1, 2))
531539
T = reshape([1:4; 1:4; 5:8; 5:8], 2, 2, 4)
532540
@test R == T
533541
A = Array(Int, 2, 2, 2)
534542
A[:, :, 1] = [1 2;
535543
3 4]
536544
A[:, :, 2] = [5 6;
537545
7 8]
538-
R = repeat(A, inner = [2, 2, 2], outer = [2, 2, 2])
546+
R = repeat(A, (2, 2, 2), (2, 2, 2))
539547
@test R[1, 1, 1] == 1
540548
@test R[2, 2, 2] == 1
541549
@test R[3, 3, 3] == 8
@@ -545,6 +553,28 @@ let
545553
@test R[7, 7, 7] == 8
546554
@test R[8, 8, 8] == 8
547555

556+
# Test with ranges and array repetitions
557+
R1 = repeat(1:2, [1], [])
558+
R2 = repeat(1:2, [1], [1])
559+
@test R1 == R2 == [1, 2]
560+
R1 = repeat(1:2, [], [2])
561+
R2 = repeat(1:2, [1], [2])
562+
@test R1 == R2 == [1, 1, 2, 2]
563+
R1 = repeat(1:2, [2], [])
564+
R2 = repeat(1:2, [2], [1])
565+
@test R1 == R2 == [1, 2, 1, 2]
566+
R = repeat(1:2, [2], [2])
567+
@test R == [1, 1, 2, 2, 1, 1, 2, 2]
568+
R1 = repeat([1 2;
569+
3 4], [], [2, 1])
570+
R2 = repeat([1 2;
571+
3 4], [1, 1], [2, 1])
572+
@test R1 == R2 == [1 2;
573+
1 2;
574+
3 4;
575+
3 4]
576+
577+
548578
A = rand(4,4)
549579
for s in Any[A[1:2:4, 1:2:4], sub(A, 1:2:4, 1:2:4)]
550580
c = cumsum(s, 1)

0 commit comments

Comments
 (0)