From 7b0e72efc8f7fbf2c0bd5d30a8b6e2e22288547f Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Wed, 10 Jun 2020 23:15:39 -0700 Subject: [PATCH 01/12] Define `extrema` using `mapreduce`; support `init` --- base/compiler/compiler.jl | 18 ++++++++++ base/multidimensional.jl | 37 ++++++++++---------- base/operators.jl | 52 ---------------------------- base/reduce.jl | 71 ++++++++++++++++++++++++++++++++++++++- test/reduce.jl | 6 ++++ test/reducedim.jl | 4 +++ 6 files changed, 117 insertions(+), 71 deletions(-) diff --git a/base/compiler/compiler.jl b/base/compiler/compiler.jl index 4ac2e3ca9a4fd..0a2f2ba0e4895 100644 --- a/base/compiler/compiler.jl +++ b/base/compiler/compiler.jl @@ -48,6 +48,24 @@ include("operators.jl") include("pointer.jl") include("refvalue.jl") +# required for bootstrap +extrema(itr) = extrema(identity, itr) +function extrema(f, itr) + y = iterate(itr) + y === nothing && throw(ArgumentError("collection must be non-empty")) + (v, s) = y + vmin = vmax = f(v) + while true + y = iterate(itr, s) + y === nothing && break + (x, s) = y + fx = f(x) + vmax = max(fx, vmax) + vmin = min(fx, vmin) + end + return (vmin, vmax) +end + # checked arithmetic const checked_add = + const checked_sub = - diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 51de7184cb92f..ec68f55a3a864 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1566,9 +1566,13 @@ _unique_dims(A::AbstractArray, dims::Colon) = invoke(unique, Tuple{Any}, A) end """ - extrema(A::AbstractArray; dims) -> Array{Tuple} + extrema([f,] A::AbstractArray; dims, [init]) -> Array{Tuple} -Compute the minimum and maximum elements of an array over the given dimensions. +Compute the minimum and maximum of `f` applied to each element (if given) in the given +dimensions of `A`. + +!!! compat "Julia 1.2" + 2-argument `extrema` method requires Julia 1.2 or later. # Examples ```jldoctest @@ -1591,22 +1595,19 @@ julia> extrema(A, dims = (1,2)) (9, 15) ``` """ -extrema(A::AbstractArray; dims = :) = _extrema_dims(identity, A, dims) - -""" - extrema(f, A::AbstractArray; dims) -> Array{Tuple} - -Compute the minimum and maximum of `f` applied to each element in the given dimensions -of `A`. - -!!! compat "Julia 1.2" - This method requires Julia 1.2 or later. -""" -extrema(f, A::AbstractArray; dims=:) = _extrema_dims(f, A, dims) - -_extrema_dims(f, A::AbstractArray, ::Colon) = _extrema_itr(f, A) - -function _extrema_dims(f, A::AbstractArray, dims) +extrema(f::F, A::AbstractArray; dims=:, init=_InitialValue()) where {F} = + _extrema_dims(f, A, dims, init) + +_extrema_dims(f::F, A::AbstractArray, ::Colon, init) where {F} = + mapreduce(_DupY(f), _extrema_rf, A; init = init) +_extrema_dims(f::F, A::AbstractArray, ::Colon, ::_InitialValue) where {F} = + mapreduce(_DupY(f), _extrema_rf, A) +# Note: not passing `init = _InitialValue()` since user-defined +# `reduce`/`foldl` could cannot be aware of `Base._InitialValue`. + +_extrema_dims(f::F, A::AbstractArray, dims, init) where {F} = + mapreduce(_DupY(f), _extrema_rf, A; dims = dims, init = init) +function _extrema_dims(f::F, A::AbstractArray, dims, ::_InitialValue) where {F} sz = [size(A)...] for d in dims sz[d] = 1 diff --git a/base/operators.jl b/base/operators.jl index 605c0775ad00f..c59c3a18d6377 100644 --- a/base/operators.jl +++ b/base/operators.jl @@ -443,58 +443,6 @@ julia> minmax('c','b') """ minmax(x,y) = isless(y, x) ? (y, x) : (x, y) -""" - extrema(itr) -> Tuple - -Compute both the minimum and maximum element in a single pass, and return them as a 2-tuple. - -# Examples -```jldoctest -julia> extrema(2:10) -(2, 10) - -julia> extrema([9,pi,4.5]) -(3.141592653589793, 9.0) -``` -""" -extrema(itr) = _extrema_itr(identity, itr) - -""" - extrema(f, itr) -> Tuple - -Compute both the minimum and maximum of `f` applied to each element in `itr` and return -them as a 2-tuple. Only one pass is made over `itr`. - -!!! compat "Julia 1.2" - This method requires Julia 1.2 or later. - -# Examples -```jldoctest -julia> extrema(sin, 0:π) -(0.0, 0.9092974268256817) -``` -""" -extrema(f, itr) = _extrema_itr(f, itr) - -function _extrema_itr(f, itr) - y = iterate(itr) - y === nothing && throw(ArgumentError("collection must be non-empty")) - (v, s) = y - vmin = vmax = f(v) - while true - y = iterate(itr, s) - y === nothing && break - (x, s) = y - fx = f(x) - vmax = max(fx, vmax) - vmin = min(fx, vmin) - end - return (vmin, vmax) -end - -extrema(x::Real) = (x, x) -extrema(f, x::Real) = (y = f(x); (y, y)) - ## definitions providing basic traits of arithmetic operators ## """ diff --git a/base/reduce.jl b/base/reduce.jl index c73caaeac7a97..b850ab9c7577a 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -581,7 +581,7 @@ julia> prod(1:5; init = 1.0) """ prod(a; kw...) = mapreduce(identity, mul_prod, a; kw...) -## maximum & minimum +## maximum, minimum, & extrema _fast(::typeof(min),x,y) = min(x,y) _fast(::typeof(max),x,y) = max(x,y) function _fast(::typeof(max), x::AbstractFloat, y::AbstractFloat) @@ -762,6 +762,75 @@ Inf """ minimum(a; kw...) = mapreduce(identity, min, a; kw...) +""" + extrema(itr; [init]) -> Tuple + +Compute both the minimum and maximum element in a single pass, and return them as a 2-tuple. + +The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose +first/second element is a neutral element for `min`/`max` (i.e. which is greater/less than +or equal to any other element). This is required because it is unspecified whether `init` +is used for non-empty collections. Note: it implies that, for empty `itr`, the first +element is typically _greater_ than the last element. This is a "paradoxical" but yet +expected result. + +!!! compat "Julia 1.6" + Keyword argument `init` requires Julia 1.6 or later. + +# Examples +```jldoctest +julia> extrema(2:10) +(2, 10) + +julia> extrema([9,pi,4.5]) +(3.141592653589793, 9.0) + +julia> extrema([]; init = (Inf, -Inf)) +(Inf, -Inf) +``` +""" +extrema(itr; kw...) = extrema(identity, itr; kw...) + +""" + extrema(f, itr; [init]) -> Tuple + +Compute both the minimum and maximum of `f` applied to each element in `itr` and return +them as a 2-tuple. Only one pass is made over `itr`. + +The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose +first/second element is a neutral element for `min`/`max` (i.e. which is greater/less than +or equal to any other element). This is required because it is unspecified whether `init` +is used for non-empty collections. Note: it implies that, for empty `itr`, the first +element is typically _greater_ than the last element. This is a "paradoxical" but yet +expected result. + +!!! compat "Julia 1.2" + This method requires Julia 1.2 or later. + +!!! compat "Julia 1.6" + Keyword argument `init` requires Julia 1.6 or later. + +# Examples +```jldoctest +julia> extrema(sin, 0:π) +(0.0, 0.9092974268256817) + +julia> extrema(sin, Real[]; init = (1.0, -1.0)) # good, since -1 ≤ sin(::Real) ≤ 1 +(1.0, -1.0) +``` +""" +extrema(f, itr; kw...) = mapreduce(_DupY(f), _extrema_rf, itr; kw...) + +# Not using closure since `extrema(type, itr)` is a very likely use-case and it's better +# to avoid type-instability (#23618). +struct _DupY{F} <: Function + f::F +end +_DupY(f::Type{T}) where {T} = _DupY{Type{T}}(f) +@inline (f::_DupY)(x) = (y = f.f(x); (y, y)) + +@inline _extrema_rf((min1, max1), (min2, max2)) = (min(min1, min2), max(max1, max2)) + ## all & any """ diff --git a/test/reduce.jl b/test/reduce.jl index 4688709b099c9..6f39fd9f6d3c4 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -241,9 +241,15 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr) @test_throws ArgumentError maximum(Int[]) @test_throws ArgumentError minimum(Int[]) +@test_throws ArgumentError extrema(Int[]) @test maximum(Int[]; init=-1) == -1 @test minimum(Int[]; init=-1) == -1 +@test extrema(Int[]; init=(1, -1)) == (1, -1) + +@test maximum(sin, []; init=-1) == -1 +@test minimum(sin, []; init=1) == 1 +@test extrema(sin, []; init=(1, -1)) == (1, -1) @test maximum(5) == 5 @test minimum(5) == 5 diff --git a/test/reducedim.jl b/test/reducedim.jl index e51a075496f1c..b0668745d55a6 100644 --- a/test/reducedim.jl +++ b/test/reducedim.jl @@ -80,6 +80,10 @@ A = Array{Int}(undef, 0, 3) @test_throws ArgumentError maximum(A; dims=1) @test maximum(A; dims=1, init=-1) == reshape([-1,-1,-1], 1, 3) +@test maximum(zeros(0, 2); dims=1, init=-1) == fill(-1, 1, 2) +@test minimum(zeros(0, 2); dims=1, init=1) == ones(1, 2) +@test extrema(zeros(0, 2); dims=1, init=(1, -1)) == fill((1, -1), 1, 2) + # Test reduction along first dimension; this is special-cased for # size(A, 1) >= 16 Breduc = rand(64, 3) From c6ffc8739f572bf3fc57eb404474f727509c76e4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 12 Jun 2020 21:19:00 -0700 Subject: [PATCH 02/12] Add NEWS --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index b6ffe8c872af5..12d0609882366 100644 --- a/NEWS.md +++ b/NEWS.md @@ -47,7 +47,7 @@ Standard library changes * The function `isapprox(x,y)` now accepts the `norm` keyword argument also for numeric (i.e., non-array) arguments `x` and `y` ([#35883]). * `view`, `@view`, and `@views` now work on `AbstractString`s, returning a `SubString` when appropriate ([#35879]). * All `AbstractUnitRange{<:Integer}`s now work with `SubString`, `view`, `@view` and `@views` on strings ([#35879]). -* `sum`, `prod`, `maximum`, and `minimum` now support `init` keyword argument ([#36188], [#35839]). +* `sum`, `prod`, `maximum`, `minimum`, and `extrema` now support `init` keyword argument ([#36188], [#35839], [#36265]). #### LinearAlgebra * New method `LinearAlgebra.issuccess(::CholeskyPivoted)` for checking whether pivoted Cholesky factorization was successful ([#36002]). From 194c329435e7a312bfb22bcaa3d852c76f111c20 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 12 Jun 2020 21:48:53 -0700 Subject: [PATCH 03/12] Fix a typo --- base/multidimensional.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index ec68f55a3a864..97482fb5124e1 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1603,7 +1603,7 @@ _extrema_dims(f::F, A::AbstractArray, ::Colon, init) where {F} = _extrema_dims(f::F, A::AbstractArray, ::Colon, ::_InitialValue) where {F} = mapreduce(_DupY(f), _extrema_rf, A) # Note: not passing `init = _InitialValue()` since user-defined -# `reduce`/`foldl` could cannot be aware of `Base._InitialValue`. +# `reduce`/`foldl` cannot be aware of `Base._InitialValue`. _extrema_dims(f::F, A::AbstractArray, dims, init) where {F} = mapreduce(_DupY(f), _extrema_rf, A; dims = dims, init = init) From 793a02056357edb590e01589a6aaab8ca5cd82b4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 12 Jun 2020 22:42:15 -0700 Subject: [PATCH 04/12] Reword a comment slightly --- base/multidimensional.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 97482fb5124e1..119f6d7ca805f 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1603,7 +1603,8 @@ _extrema_dims(f::F, A::AbstractArray, ::Colon, init) where {F} = _extrema_dims(f::F, A::AbstractArray, ::Colon, ::_InitialValue) where {F} = mapreduce(_DupY(f), _extrema_rf, A) # Note: not passing `init = _InitialValue()` since user-defined -# `reduce`/`foldl` cannot be aware of `Base._InitialValue`. +# `reduce`/`foldl` cannot be aware of `Base._InitialValue` that is an +# internal implementation detail. _extrema_dims(f::F, A::AbstractArray, dims, init) where {F} = mapreduce(_DupY(f), _extrema_rf, A; dims = dims, init = init) From 5ebf8ad4ec97c2dea49401373751782438eeed45 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 19 Jun 2020 12:44:15 -0700 Subject: [PATCH 05/12] Apply suggestions from code review Co-authored-by: Milan Bouchet-Valat --- base/multidimensional.jl | 6 +++--- base/reduce.jl | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 119f6d7ca805f..aa4c0526e6581 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1568,11 +1568,11 @@ end """ extrema([f,] A::AbstractArray; dims, [init]) -> Array{Tuple} -Compute the minimum and maximum of `f` applied to each element (if given) in the given -dimensions of `A`. +Compute the minimum and maximum elements of `A` over dimensions `dims`. +If `f` is provided, return the minimum and maximum elements after applying `f` to them. !!! compat "Julia 1.2" - 2-argument `extrema` method requires Julia 1.2 or later. + The `extrema(f, A)` method requires Julia 1.2 or later. # Examples ```jldoctest diff --git a/base/reduce.jl b/base/reduce.jl index b850ab9c7577a..44032ce8523af 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -768,8 +768,8 @@ minimum(a; kw...) = mapreduce(identity, min, a; kw...) Compute both the minimum and maximum element in a single pass, and return them as a 2-tuple. The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose -first/second element is a neutral element for `min`/`max` (i.e. which is greater/less than -or equal to any other element). This is required because it is unspecified whether `init` +first and second elements are neutral elements for `min` and `max` respectively +(i.e. which are greater/less than or equal to any other element). is used for non-empty collections. Note: it implies that, for empty `itr`, the first element is typically _greater_ than the last element. This is a "paradoxical" but yet expected result. @@ -798,8 +798,8 @@ Compute both the minimum and maximum of `f` applied to each element in `itr` and them as a 2-tuple. Only one pass is made over `itr`. The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose -first/second element is a neutral element for `min`/`max` (i.e. which is greater/less than -or equal to any other element). This is required because it is unspecified whether `init` +first and second elements are neutral elements for `min` and `max` respectively +(i.e. which are greater/less than or equal to any other element). is used for non-empty collections. Note: it implies that, for empty `itr`, the first element is typically _greater_ than the last element. This is a "paradoxical" but yet expected result. From 2d70b7d5300e931a301ad0c828d01f7e781e768e Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 19 Jun 2020 12:46:48 -0700 Subject: [PATCH 06/12] Fixup docstrings --- base/reduce.jl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 44032ce8523af..15b0715d55aa2 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -769,10 +769,9 @@ Compute both the minimum and maximum element in a single pass, and return them a The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose first and second elements are neutral elements for `min` and `max` respectively -(i.e. which are greater/less than or equal to any other element). -is used for non-empty collections. Note: it implies that, for empty `itr`, the first -element is typically _greater_ than the last element. This is a "paradoxical" but yet -expected result. +(i.e. which are greater/less than or equal to any other element). It is used for non-empty +collections. Note: it implies that, for empty `itr`, the first element is typically +_greater_ than the last element. This is a "paradoxical" but yet expected result. !!! compat "Julia 1.6" Keyword argument `init` requires Julia 1.6 or later. @@ -799,10 +798,9 @@ them as a 2-tuple. Only one pass is made over `itr`. The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose first and second elements are neutral elements for `min` and `max` respectively -(i.e. which are greater/less than or equal to any other element). -is used for non-empty collections. Note: it implies that, for empty `itr`, the first -element is typically _greater_ than the last element. This is a "paradoxical" but yet -expected result. +(i.e. which are greater/less than or equal to any other element). It is used for non-empty +collections. Note: it implies that, for empty `itr`, the first element is typically +_greater_ than the last element. This is a "paradoxical" but yet expected result. !!! compat "Julia 1.2" This method requires Julia 1.2 or later. From 317548a457f5d91e9602dfdcb8f0b039e515d8d5 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 19 Jun 2020 13:30:44 -0700 Subject: [PATCH 07/12] Add simple tests for Core.Compiler.extrema --- test/reduce.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/reduce.jl b/test/reduce.jl index 6f39fd9f6d3c4..2ea40f5289c9a 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -255,15 +255,18 @@ prod2(itr) = invoke(prod, Tuple{Any}, itr) @test minimum(5) == 5 @test extrema(5) == (5, 5) @test extrema(abs2, 5) == (25, 25) +@test Core.Compiler.extrema(abs2, 5) == (25, 25) let x = [4,3,5,2] @test maximum(x) == 5 @test minimum(x) == 2 @test extrema(x) == (2, 5) + @test Core.Compiler.extrema(x) == (2, 5) @test maximum(abs2, x) == 25 @test minimum(abs2, x) == 4 @test extrema(abs2, x) == (4, 25) + @test Core.Compiler.extrema(abs2, x) == (4, 25) end @test maximum([-0.,0.]) === 0.0 From 360b3463cef1f03681ffdbffbb6cb005f9ac09f4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 20 Jun 2020 01:19:54 -0700 Subject: [PATCH 08/12] Name the output tuple elements (mn, mx) --- base/reduce.jl | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 15b0715d55aa2..335de05f94d6d 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -763,15 +763,17 @@ Inf minimum(a; kw...) = mapreduce(identity, min, a; kw...) """ - extrema(itr; [init]) -> Tuple + extrema(itr; [init]) -> (mn, mx) -Compute both the minimum and maximum element in a single pass, and return them as a 2-tuple. +Compute both the minimum `mn` and maximum `mx` element in a single pass, and return them +as a 2-tuple. The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose first and second elements are neutral elements for `min` and `max` respectively (i.e. which are greater/less than or equal to any other element). It is used for non-empty -collections. Note: it implies that, for empty `itr`, the first element is typically -_greater_ than the last element. This is a "paradoxical" but yet expected result. +collections. Note: it implies that, for empty `itr`, the returned value `(mn, mx)` satisfies +`mn ≥ mx` even though for non-empty `itr` it satisfies `mn ≤ mx`. This is a "paradoxical" +but yet expected result. !!! compat "Julia 1.6" Keyword argument `init` requires Julia 1.6 or later. @@ -791,16 +793,17 @@ julia> extrema([]; init = (Inf, -Inf)) extrema(itr; kw...) = extrema(identity, itr; kw...) """ - extrema(f, itr; [init]) -> Tuple + extrema(f, itr; [init]) -> (mn, mx) -Compute both the minimum and maximum of `f` applied to each element in `itr` and return -them as a 2-tuple. Only one pass is made over `itr`. +Compute both the minimum `mn` and maximum `mx` of `f` applied to each element in `itr` and +return them as a 2-tuple. Only one pass is made over `itr`. The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose first and second elements are neutral elements for `min` and `max` respectively (i.e. which are greater/less than or equal to any other element). It is used for non-empty -collections. Note: it implies that, for empty `itr`, the first element is typically -_greater_ than the last element. This is a "paradoxical" but yet expected result. +collections. Note: it implies that, for empty `itr`, the returned value `(mn, mx)` satisfies +`mn ≥ mx` even though for non-empty `itr` it satisfies `mn ≤ mx`. This is a "paradoxical" +but yet expected result. !!! compat "Julia 1.2" This method requires Julia 1.2 or later. From f27f874ed0babf750ff9dd0955f52c49a2ea8618 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 12 Nov 2021 15:44:19 -0800 Subject: [PATCH 09/12] Update base/multidimensional.jl --- base/multidimensional.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/multidimensional.jl b/base/multidimensional.jl index abdfd16c23bc4..c22d6cd922529 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -1752,7 +1752,7 @@ _extrema_dims(f::F, A::AbstractArray, ::Colon, ::_InitialValue) where {F} = _extrema_dims(f::F, A::AbstractArray, dims, init) where {F} = mapreduce(_DupY(f), _extrema_rf, A; dims = dims, init = init) function _extrema_dims(f::F, A::AbstractArray, dims, ::_InitialValue) where {F} - sz = [size(A)...] + sz = size(A) for d in dims sz = setindex(sz, 1, d) end From ce07cbf185295bd21dedac70ccabeeb3b4fcf22d Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 12 Nov 2021 18:54:56 -0500 Subject: [PATCH 10/12] Fix compat annotations --- base/reduce.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 1106d5409348e..832ae35bf04c9 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -798,8 +798,8 @@ collections. Note: it implies that, for empty `itr`, the returned value `(mn, mx `mn ≥ mx` even though for non-empty `itr` it satisfies `mn ≤ mx`. This is a "paradoxical" but yet expected result. -!!! compat "Julia 1.6" - Keyword argument `init` requires Julia 1.6 or later. +!!! compat "Julia 1.8" + Keyword argument `init` requires Julia 1.8 or later. # Examples ```jldoctest @@ -831,8 +831,8 @@ but yet expected result. !!! compat "Julia 1.2" This method requires Julia 1.2 or later. -!!! compat "Julia 1.6" - Keyword argument `init` requires Julia 1.6 or later. +!!! compat "Julia 1.8" + Keyword argument `init` requires Julia 1.8 or later. # Examples ```jldoctest From 3ceaaae94bb5a26c36a72c5e824f90c1821ca8a4 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 12 Nov 2021 18:59:07 -0500 Subject: [PATCH 11/12] Improve extrema docstring Co-authored-by: Tim Holy --- base/reduce.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 832ae35bf04c9..23a56c0c5f45f 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -793,10 +793,9 @@ as a 2-tuple. The value returned for empty `itr` can be specified by `init`. It must be a 2-tuple whose first and second elements are neutral elements for `min` and `max` respectively -(i.e. which are greater/less than or equal to any other element). It is used for non-empty -collections. Note: it implies that, for empty `itr`, the returned value `(mn, mx)` satisfies -`mn ≥ mx` even though for non-empty `itr` it satisfies `mn ≤ mx`. This is a "paradoxical" -but yet expected result. +(i.e. which are greater/less than or equal to any other element). As a consequence, when +`itr` is empty the returned `(mn, mx)` tuple will satisfy `mn ≥ mx`. When `init` is +specified it may be used even for non-empty `itr`. !!! compat "Julia 1.8" Keyword argument `init` requires Julia 1.8 or later. From 5669d6349569ff83394208609c1d5c4b2f86fa17 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Fri, 12 Nov 2021 23:34:05 -0500 Subject: [PATCH 12/12] Fix tests for SparseArrays --- stdlib/SparseArrays/test/higherorderfns.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/SparseArrays/test/higherorderfns.jl b/stdlib/SparseArrays/test/higherorderfns.jl index 8da605cf6c0c0..59079682938ee 100644 --- a/stdlib/SparseArrays/test/higherorderfns.jl +++ b/stdlib/SparseArrays/test/higherorderfns.jl @@ -709,8 +709,8 @@ end @test extrema(f, x) == extrema(f, y) @test extrema(spzeros(n, n)) == (0.0, 0.0) @test extrema(spzeros(n)) == (0.0, 0.0) - @test_throws ArgumentError extrema(spzeros(0, 0)) - @test_throws ArgumentError extrema(spzeros(0)) + @test_throws "reducing over an empty" extrema(spzeros(0, 0)) + @test_throws "reducing over an empty" extrema(spzeros(0)) @test extrema(sparse(ones(n, n))) == (1.0, 1.0) @test extrema(sparse(ones(n))) == (1.0, 1.0) @test extrema(A; dims=:) == extrema(B; dims=:)