Skip to content

Commit 8f9dd5d

Browse files
ssikdar1andreasnoack
authored andcommitted
#34234 normalize(a) for multidimensional arrays (#34239)
* Add support normalize multi dim arrays * remove trailing whitespace from test * var name v => a for inner function * Update normalize tests Case for OffsetArray where A[1] would fail but first(A) would not. Also some more test cases to compare with the vector case * add NEWS item * make docstring example w/ array more julia-thonic * reduce redundant test cases * add test for normalize on Int64 array * add 0 1 and high dim test cases
1 parent 8e6a2ae commit 8f9dd5d

File tree

3 files changed

+59
-21
lines changed

3 files changed

+59
-21
lines changed

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ Standard library changes
3030

3131

3232
#### LinearAlgebra
33-
3433
* The BLAS submodule now supports the level-2 BLAS subroutine `hpmv!` ([#34211]).
34+
* `normalize` now supports multidimensional arrays ([#34239])
3535

3636
#### Markdown
3737

stdlib/LinearAlgebra/src/generic.jl

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,39 +1582,39 @@ function isapprox(x::AbstractArray, y::AbstractArray;
15821582
end
15831583

15841584
"""
1585-
normalize!(v::AbstractVector, p::Real=2)
1585+
normalize!(a::AbstractArray, p::Real=2)
15861586
1587-
Normalize the vector `v` in-place so that its `p`-norm equals unity,
1588-
i.e. `norm(v, p) == 1`.
1587+
Normalize the array `a` in-place so that its `p`-norm equals unity,
1588+
i.e. `norm(a, p) == 1`.
15891589
See also [`normalize`](@ref) and [`norm`](@ref).
15901590
"""
1591-
function normalize!(v::AbstractVector, p::Real=2)
1592-
nrm = norm(v, p)
1593-
__normalize!(v, nrm)
1591+
function normalize!(a::AbstractArray, p::Real=2)
1592+
nrm = norm(a, p)
1593+
__normalize!(a, nrm)
15941594
end
15951595

1596-
@inline function __normalize!(v::AbstractVector, nrm::AbstractFloat)
1596+
@inline function __normalize!(a::AbstractArray, nrm::AbstractFloat)
15971597
# The largest positive floating point number whose inverse is less than infinity
15981598
δ = inv(prevfloat(typemax(nrm)))
15991599

16001600
if nrm δ # Safe to multiply with inverse
16011601
invnrm = inv(nrm)
1602-
rmul!(v, invnrm)
1602+
rmul!(a, invnrm)
16031603

16041604
else # scale elements to avoid overflow
16051605
εδ = eps(one(nrm))/δ
1606-
rmul!(v, εδ)
1607-
rmul!(v, inv(nrm*εδ))
1606+
rmul!(a, εδ)
1607+
rmul!(a, inv(nrm*εδ))
16081608
end
16091609

1610-
v
1610+
a
16111611
end
16121612

16131613
"""
1614-
normalize(v::AbstractVector, p::Real=2)
1614+
normalize(a::AbstractArray, p::Real=2)
16151615
1616-
Normalize the vector `v` so that its `p`-norm equals unity,
1617-
i.e. `norm(v, p) == 1`.
1616+
Normalize the array `a` so that its `p`-norm equals unity,
1617+
i.e. `norm(a, p) == 1`.
16181618
See also [`normalize!`](@ref) and [`norm`](@ref).
16191619
16201620
# Examples
@@ -1638,15 +1638,29 @@ julia> c = normalize(a, 1)
16381638
16391639
julia> norm(c, 1)
16401640
1.0
1641+
1642+
julia> a = [1 2 4 ; 1 2 4]
1643+
2×3 Array{Int64,2}:
1644+
1 2 4
1645+
1 2 4
1646+
1647+
julia> norm(a)
1648+
6.48074069840786
1649+
1650+
julia> normalize(a)
1651+
2×3 Array{Float64,2}:
1652+
0.154303 0.308607 0.617213
1653+
0.154303 0.308607 0.617213
1654+
16411655
```
16421656
"""
1643-
function normalize(v::AbstractVector, p::Real = 2)
1644-
nrm = norm(v, p)
1645-
if !isempty(v)
1646-
vv = copy_oftype(v, typeof(v[1]/nrm))
1647-
return __normalize!(vv, nrm)
1657+
function normalize(a::AbstractArray, p::Real = 2)
1658+
nrm = norm(a, p)
1659+
if !isempty(a)
1660+
aa = copy_oftype(a, typeof(first(a)/nrm))
1661+
return __normalize!(aa, nrm)
16481662
else
1649-
T = typeof(zero(eltype(v))/nrm)
1663+
T = typeof(zero(eltype(a))/nrm)
16501664
return T[]
16511665
end
16521666
end

stdlib/LinearAlgebra/test/generic.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,14 @@ module TestGeneric
55
using Test, LinearAlgebra, Random
66

77
const BASE_TEST_PATH = joinpath(Sys.BINDIR, "..", "share", "julia", "test")
8+
89
isdefined(Main, :Quaternions) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "Quaternions.jl"))
910
using .Main.Quaternions
1011

12+
isdefined(Main, :OffsetArrays) || @eval Main include(joinpath($(BASE_TEST_PATH), "testhelpers", "OffsetArrays.jl"))
13+
using .Main.OffsetArrays
14+
15+
1116
Random.seed!(123)
1217

1318
n = 5 # should be odd
@@ -248,6 +253,25 @@ end
248253
end
249254
end
250255

256+
@testset "normalize for multidimensional arrays" begin
257+
258+
for arr in (
259+
fill(10.0, ()), # 0 dim
260+
[1.0], # 1 dim
261+
[1.0 2.0 3.0; 4.0 5.0 6.0], # 2-dim
262+
rand(1,2,3), # higher dims
263+
rand(1,2,3,4),
264+
OffsetArray([-1,0], (-2,)) # no index 1
265+
)
266+
@test normalize(arr) == normalize!(copy(arr))
267+
@test size(normalize(arr)) == size(arr)
268+
@test axes(normalize(arr)) == axes(arr)
269+
@test vec(normalize(arr)) == normalize(vec(arr))
270+
end
271+
272+
@test typeof(normalize([1 2 3; 4 5 6])) == Array{Float64,2}
273+
end
274+
251275
@testset "Issue #30466" begin
252276
@test norm([typemin(Int), typemin(Int)], Inf) == -float(typemin(Int))
253277
@test norm([typemin(Int), typemin(Int)], 1) == -2float(typemin(Int))

0 commit comments

Comments
 (0)