From 80e8a28ed9c460473148a97bef0034521bee6111 Mon Sep 17 00:00:00 2001 From: Dahua Lin Date: Sat, 31 May 2014 07:06:33 -0500 Subject: [PATCH] reorganize tests for reduce --- base/reduce.jl | 21 +++---- test/reduce.jl | 150 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 110 insertions(+), 61 deletions(-) diff --git a/base/reduce.jl b/base/reduce.jl index 11d6b9c36625b..55f23b5d028b3 100644 --- a/base/reduce.jl +++ b/base/reduce.jl @@ -134,17 +134,19 @@ mapreduce(f, op, v0, itr) = mapfoldl(f, op, v0, itr) mapreduce_impl(f, op, A::AbstractArray, ifirst::Int, ilast::Int) = mapreduce_seq_impl(f, op, A, ifirst, ilast) -# for specific functions -reduce_empty(f, op, T) = error("Reducing over an empty array is not allow.") -reduce_empty(::IdFun, op::AddFun, T) = r_promote(op, zero(T)) -reduce_empty(::AbsFun, op::AddFun, T) = r_promote(op, abs(zero(T))) -reduce_empty(::Abs2Fun, op::AddFun, T) = r_promote(op, abs2(zero(T))) -reduce_empty(::IdFun, op::MulFun, T) = r_promote(op, one(T)) +# handling empty arrays +mr_empty(f, op, T) = error("Reducing over an empty array is not allow.") +mr_empty(::IdFun, op::AddFun, T) = r_promote(op, zero(T)) +mr_empty(::AbsFun, op::AddFun, T) = r_promote(op, abs(zero(T))) +mr_empty(::Abs2Fun, op::AddFun, T) = r_promote(op, abs2(zero(T))) +mr_empty(::IdFun, op::MulFun, T) = r_promote(op, one(T)) +mr_empty(::AbsFun, op::MaxFun, T) = abs(zero(T)) +mr_empty(::Abs2Fun, op::MaxFun, T) = abs2(zero(T)) function _mapreduce{T}(f, op, A::AbstractArray{T}) n = length(A) if n == 0 - return reduce_empty(f, op, T) + return mr_empty(f, op, T) elseif n == 1 return r_promote(op, evaluate(f, A[1])) elseif n < 16 @@ -310,12 +312,11 @@ minabs(a) = mapreduce(AbsFun(), MinFun(), a) ## extrema extrema(r::Range) = (minimum(r), maximum(r)) +extrema(x::Real) = (x, x) function extrema(itr) s = start(itr) - if done(itr, s) - error("argument is empty") - end + done(itr, s) && error("argument is empty") (v, s) = next(itr, s) vmin = v vmax = v diff --git a/test/reduce.jl b/test/reduce.jl index 20eb49c93d470..fc1e3db7aad2b 100644 --- a/test/reduce.jl +++ b/test/reduce.jl @@ -1,6 +1,5 @@ -## foldl & foldr -# folds +# fold(l|r) & mapfold(l|r) @test foldl(-, 1:5) == -13 @test foldl(-, 10, 1:5) == -5 @@ -13,23 +12,49 @@ @test Base.mapfoldr(abs2, -, 2:5) == -14 @test Base.mapfoldr(abs2, -, 10, 2:5) == -4 - -# reduce +# reduce & mapreduce @test reduce((x,y)->"($x+$y)", [9:11]) == "((9+10)+11)" @test reduce(max, [8 6 7 5 3 0 9]) == 9 @test reduce(+, 1000, [1:5]) == (1000 + 1 + 2 + 3 + 4 + 5) -# mapreduce @test mapreduce(-, +, [-10 -9 -3]) == ((10 + 9) + 3) @test mapreduce((x)->x[1:3], (x,y)->"($x+$y)", ["abcd", "efgh", "01234"]) == "((abc+efg)+012)" +# sum -z = zeros(2,2,2,2) -for i=1:16 - z[i] = i -end +@test sum(Int8[]) === 0 +@test sum(Int[]) === 0 +@test sum(Float64[]) === 0.0 + +@test sum(int8(3)) === int8(3) +@test sum(3) === 3 +@test sum(3.0) === 3.0 + +@test sum([int8(3)]) === 3 +@test sum([3]) === 3 +@test sum([3.0]) === 3.0 + +z = reshape(1:16, (2,2,2,2)) +fz = float(z) +@test sum(z) === 136 +@test sum(fz) === 136.0 + +@test_throws ErrorException sum(sin, Int[]) +@test sum(sin, 3) == sin(3.0) +@test sum(sin, [3]) == sin(3.0) +@test sum(sin, z) == sum(sin, fz) == sum(sin(fz)) + +z = [-4, -3, 2, 5] +fz = float(z) +@test Base.sumabs(Float64[]) === 0.0 +@test Base.sumabs([int8(-2)]) === 2 +@test Base.sumabs(z) === 14 +@test Base.sumabs(fz) === 14.0 -@test sum(z) == sum(z,(1,2,3,4))[1] == 136 +@test Base.sumabs2(Float64[]) === 0.0 +@test Base.sumabs2([int8(-2)]) === 4 +@test Base.sumabs2(z) === 54 +@test Base.sumabs2(fz) === 54.0 # check variants of summation for type-stability and other issues (#6069) sum2(itr) = invoke(sum, (Any,), itr) @@ -55,48 +80,36 @@ for f in (sum3, sum4, sum7, sum8) end @test typeof(sum(Int8[])) == typeof(sum(Int8[1])) == typeof(sum(Int8[1 7])) -prod2(itr) = invoke(prod, (Any,), itr) -@test prod(Int[]) == prod2(Int[]) == 1 -@test prod(Int[7]) == prod2(Int[7]) == 7 -@test typeof(prod(Int8[])) == typeof(prod(Int8[1])) == typeof(prod(Int8[1 7])) == typeof(prod2(Int8[])) == typeof(prod2(Int8[1])) == typeof(prod2(Int8[1 7])) +@test sum_kbn([1,1e100,1,-1e100]) == 2 -v = cell(2,2,1,1) -v[1,1,1,1] = 28.0 -v[1,2,1,1] = 36.0 -v[2,1,1,1] = 32.0 -v[2,2,1,1] = 40.0 +# prod -@test isequal(v,sum(z,(3,4))) +prod(Int[]) === 0 +prod(Int8[]) === 0 +prod(Float64[]) === 0.0 -@test sum_kbn([1,1e100,1,-1e100]) == 2 +prod([3]) === 0 +prod([int8(3)]) === 0 +prod([3.0]) === 0.0 -z = rand(10^6) -let es = sum_kbn(z), es2 = sum_kbn(z[1:10^5]) - @test (es - sum(z)) < es * 1e-13 - cs = cumsum(z) - @test (es - cs[end]) < es * 1e-13 - @test (es2 - cs[10^5]) < es2 * 1e-13 -end - -@test_throws ErrorException sum(sin, Int[]) -@test Base.sumabs(Float64[]) === 0.0 -@test Base.sumabs2(Float64[]) === 0.0 +prod(z) === 120 +prod(fz) === 120.0 -@test sum(sin, [1]) == sin(1) -@test Base.sumabs([int8(-2)]) === 2 -@test Base.sumabs2([int8(-2)]) === 4 +# check type-stability +prod2(itr) = invoke(prod, (Any,), itr) +@test prod(Int[]) === prod2(Int[]) === 1 +@test prod(Int[7]) === prod2(Int[7]) === 7 +@test typeof(prod(Int8[])) == typeof(prod(Int8[1])) == typeof(prod(Int8[1, 7])) == Int +@test typeof(prod2(Int8[])) == typeof(prod2(Int8[1])) == typeof(prod2(Int8[1 7])) == Int -x = -2:3 -@test sum(sin, x) == sum(sin(x)) -@test Base.sumabs(x) === 9 -@test Base.sumabs2(x) === 19 +# maximum & minimum & extrema -@test_approx_eq sum(sin, z) sum(sin(z)) -@test_approx_eq Base.sumabs(z) sum(abs(z)) -@test_approx_eq Base.sumabs2(z) sum(abs2(z)) +@test_throws ErrorException maximum(Int[]) +@test_throws ErrorException minimum(Int[]) @test maximum(5) == 5 @test minimum(5) == 5 +@test extrema(5) == (5, 5) @test maximum([4, 3, 5, 2]) == 5 @test minimum([4, 3, 5, 2]) == 2 @@ -110,25 +123,60 @@ x = -2:3 @test minimum([4., 3., NaN, 5., 2.]) == 2. @test extrema([4., 3., NaN, 5., 2.]) == (2., 5.) -@test extrema(1:5) == (1,5) +@test Base.maxabs(Int[]) == 0 +@test_throws ErrorException Base.minabs(Int[]) @test Base.maxabs(-2) == 2 @test Base.minabs(-2) == 2 @test Base.maxabs([1, -2, 3, -4]) == 4 @test Base.minabs([-1, 2, -3, 4]) == 1 -@test maximum(abs2, 3:7) == 49 -@test minimum(abs2, 3:7) == 9 - -@test any([true false; false false], 2) == [true false]' -@test any([true false; false false], 1) == [true false] - -@test all([true true; false true], 2) == [true false]' -@test all([true false; false true], 1) == [false false] +@test maximum(x->abs2(x), 3:7) == 49 +@test minimum(x->abs2(x), 3:7) == 9 + +# any & all + +@test any(Bool[]) == false +@test any([true]) == true +@test any([false, false]) == false +@test any([false, true]) == true +@test any([true, false]) == true +@test any([true, true]) == true +@test any([true, true, true]) == true +@test any([true, false, true]) == true +@test any([false, false, false]) == false + +@test all(Bool[]) == true +@test all([true]) == true +@test all([false, false]) == false +@test all([false, true]) == false +@test all([true, false]) == false +@test all([true, true]) == true +@test all([true, true, true]) == true +@test all([true, false, true]) == false +@test all([false, false, false]) == false + +@test any(x->x>0, Int[]) == false +@test any(x->x>0, [-3]) == false +@test any(x->x>0, [4]) == true +@test any(x->x>0, [-3, 4, 5]) == true + +@test all(x->x>0, Int[]) == true +@test all(x->x>0, [-3]) == false +@test all(x->x>0, [4]) == true +@test all(x->x>0, [-3, 4, 5]) == false ## cumsum, cummin, cummax +z = rand(10^6) +let es = sum_kbn(z), es2 = sum_kbn(z[1:10^5]) + @test (es - sum(z)) < es * 1e-13 + cs = cumsum(z) + @test (es - cs[end]) < es * 1e-13 + @test (es2 - cs[10^5]) < es2 * 1e-13 +end + @test isequal(cummin([1, 2, 5, -1, 3, -2]), [1, 1, 1, -1, -1, -2]) @test isequal(cummax([1, 2, 5, -1, 3, -2]), [1, 2, 5, 5, 5, 5])