From adafb1aa83b6c9d6e07d9baf0c82e31803e02ec6 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 17 Sep 2017 08:55:34 -0500 Subject: [PATCH 1/4] Bump Julia version and eliminate some version-dependent code --- .travis.yml | 2 +- REQUIRE | 2 +- appveyor.yml | 4 +- src/ColorVectorSpace.jl | 15 +----- src/dots.jl | 112 ---------------------------------------- test/runtests.jl | 47 +++++------------ 6 files changed, 18 insertions(+), 164 deletions(-) delete mode 100644 src/dots.jl diff --git a/.travis.yml b/.travis.yml index 27c03f3..d03cab7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ os: - linux - osx julia: - - 0.5 + - 0.6 - nightly notifications: email: false diff --git a/REQUIRE b/REQUIRE index 72e50ff..2034ee8 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,4 +1,4 @@ -julia 0.5 +julia 0.6 Colors 0.7.1 ColorTypes 0.4 FixedPointNumbers 0.3.0 diff --git a/appveyor.yml b/appveyor.yml index abd43b2..3c89917 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,7 +1,7 @@ environment: matrix: - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe" + - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" diff --git a/src/ColorVectorSpace.jl b/src/ColorVectorSpace.jl index 17f86bc..15cb151 100644 --- a/src/ColorVectorSpace.jl +++ b/src/ColorVectorSpace.jl @@ -280,19 +280,8 @@ dotc(x::AbstractGray, y::AbstractGray) = dotc(promote(x, y)...) float{T<:Gray}(::Type{T}) = typeof(float(zero(T))) # Mixed types -if VERSION < v"0.6.0-dev.2009" - (+)(a::MathTypes, b::MathTypes) = (+)(promote(a, b)...) - (-)(a::MathTypes, b::MathTypes) = (-)(promote(a, b)...) -else - (+)(a::MathTypes, b::MathTypes) = (+)(Base.promote_noncircular(a, b)...) - (-)(a::MathTypes, b::MathTypes) = (-)(Base.promote_noncircular(a, b)...) -end - -if VERSION < v"0.6.0-dev.1839" - include("dots.jl") -elseif VERSION < v"0.6.0-pre.beta.101" - Base.Broadcast.eltypestuple(c::Colorant) = Tuple{typeof(c)} -end +(+)(a::MathTypes, b::MathTypes) = (+)(Base.promote_noncircular(a, b)...) +(-)(a::MathTypes, b::MathTypes) = (-)(Base.promote_noncircular(a, b)...) Compat.@dep_vectorize_2arg Gray max Compat.@dep_vectorize_2arg Gray min diff --git a/src/dots.jl b/src/dots.jl deleted file mode 100644 index d11727d..0000000 --- a/src/dots.jl +++ /dev/null @@ -1,112 +0,0 @@ -# dot operations -import Base: .+, .-, .*, ./, .^ - (.*)(f::Real, c::AbstractRGB) = (*)(f, c) -(.*)(f::Real, c::TransparentRGB) = (*)(f, c) -(.*)(c::AbstractRGB, f::Real) = (*)(f, c) -(.*)(c::TransparentRGB, f::Real) = (*)(f, c) -(./)(c::AbstractRGB, f::Real) = (/)(c, f) -(./)(c::TransparentRGB, f::Real) = (/)(c, f) -(.+){C<:AbstractRGB}(A::AbstractArray{C}, b::AbstractRGB) = plus(A, b) -(.+){C<:AbstractRGB}(b::AbstractRGB, A::AbstractArray{C}) = plus(b, A) -(.-){C<:AbstractRGB}(A::AbstractArray{C}, b::AbstractRGB) = minus(A, b) -(.-){C<:AbstractRGB}(b::AbstractRGB, A::AbstractArray{C}) = minus(b, A) -(.*){T<:Number}(A::AbstractArray{T}, b::AbstractRGB) = mul(A, b) -(.*){T<:Number}(b::AbstractRGB, A::AbstractArray{T}) = mul(b, A) -(.+){C<:TransparentRGB}(A::AbstractArray{C}, b::TransparentRGB) = plus(A, b) -(.+){C<:TransparentRGB}(b::TransparentRGB, A::AbstractArray{C}) = plus(b, A) -(.-){C<:TransparentRGB}(A::AbstractArray{C}, b::TransparentRGB) = minus(A, b) -(.-){C<:TransparentRGB}(b::TransparentRGB, A::AbstractArray{C}) = minus(b, A) -(.*){T<:Number}(A::AbstractArray{T}, b::TransparentRGB) = mul(A, b) -(.*){T<:Number}(b::TransparentRGB, A::AbstractArray{T}) = mul(b, A) -(.*)(f::Real, c::AbstractGray) = (*)(f, c) -(.*)(c::AbstractGray, f::Real) = (*)(f, c) -(.*)(f::Real, c::TransparentGray) = (*)(f, c) -(.*)(c::TransparentGray, f::Real) = (*)(f, c) -(./)(c::AbstractGray, f::Real) = c/f -(./)(n::Number, c::AbstractGray) = n/gray(c) -(./)(c::TransparentGray, f::Real) = c/f -(.^){S}(a::AbstractGray{S}, b) = a^b -(.+)(a::AbstractGray, b::Number) = gray(a)+b -(.-)(a::AbstractGray, b::Number) = gray(a)-b -(.+)(a::Number, b::AbstractGray) = a+gray(b) -(.-)(a::Number, b::AbstractGray) = a-gray(b) - -(.+){C<:AbstractGray}(A::AbstractArray{C}, b::AbstractGray) = plus(A, b) -(.+){C<:AbstractGray}(b::AbstractGray, A::AbstractArray{C}) = plus(b, A) -(.-){C<:AbstractGray}(A::AbstractArray{C}, b::AbstractGray) = minus(A, b) -(.-){C<:AbstractGray}(b::AbstractGray, A::AbstractArray{C}) = minus(b, A) -(.*){T<:Number}(A::AbstractArray{T}, b::AbstractGray) = mul(A, b) -(.*){T<:Number}(b::AbstractGray, A::AbstractArray{T}) = mul(b, A) -(./){C<:AbstractGray}(A::AbstractArray{C}, b::AbstractGray) = divd(A, b) - -(.+){C<:TransparentGray}(A::AbstractArray{C}, b::TransparentGray) = plus(A, b) -(.+){C<:TransparentGray}(b::TransparentGray, A::AbstractArray{C}) = plus(b, A) -(.-){C<:TransparentGray}(A::AbstractArray{C}, b::TransparentGray) = minus(A, b) -(.-){C<:TransparentGray}(b::TransparentGray, A::AbstractArray{C}) = minus(b, A) -(.*){T<:Number}(A::AbstractArray{T}, b::TransparentGray) = mul(A, b) -(.*){T<:Number}(b::TransparentGray, A::AbstractArray{T}) = mul(b, A) - -# Called plus/minus instead of plus/sub because `sub` already has a meaning! -function plus(A::AbstractArray, b::Colorant) - bT = convert(eltype(A), b) - out = similar(A) - plus!(out, A, bT) -end -plus(b::Colorant, A::AbstractArray) = plus(A, b) -function minus(A::AbstractArray, b::Colorant) - bT = convert(eltype(A), b) - out = similar(A) - minus!(out, A, bT) -end -function minus(b::Colorant, A::AbstractArray) - bT = convert(eltype(A), b) - out = similar(A) - minus!(out, bT, A) -end -function mul{T<:Number}(A::AbstractArray{T}, b::Colorant) - bT = typeof(b*one(T)) - out = similar(A, bT) - mul!(out, A, b) -end -mul{T<:Number}(b::Colorant, A::AbstractArray{T}) = mul(A, b) -function divd{C<:AbstractGray}(A::AbstractArray{C}, b::AbstractGray) - bT = typeof(zero(C)/b) - out = similar(A, bT) - div!(out, A, b) -end - -for (func, op) in ((:plus!, :+), - (:minus!, :-), - (:mul!, :*), - (:div!, :/)) - @eval begin - function $func{T,N}(out, A::AbstractArray{T,N}, b) - Rout, RA = eachindex(out), eachindex(A) - if Rout == RA - for I in RA - @inbounds out[I] = $op(A[I], b) - end - else - for (Iout, IA) in zip(Rout, RA) - @inbounds out[Iout] = $op(A[IA], b) - end - end - out - end - end -end - -# This needs separate implementation because we can take -b of unsigned types -function minus!{T,N}(out, b::Colorant, A::AbstractArray{T,N}) - Rout, RA = eachindex(out), eachindex(A) - if Rout == RA - for I in RA - @inbounds out[I] = b - A[I] - end - else - for (Iout, IA) in zip(Rout, RA) - @inbounds out[Iout] = b - A[IA] - end - end - out -end diff --git a/test/runtests.jl b/test/runtests.jl index e26f0be..f54330e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -4,8 +4,6 @@ using ColorVectorSpace, Colors, FixedPointNumbers, Compat, StatsBase using Base.Test -const use_broadcast_rules = VERSION >= v"0.6.0-dev.1839" - macro test_colortype_approx_eq(a, b) :(test_colortype_approx_eq($(esc(a)), $(esc(b)), $(string(a)), $(string(b)))) end @@ -91,17 +89,10 @@ end @test typeof(acu-acf) == Vector{Gray{Float32}} @test typeof(acu.+acf) == Vector{Gray{Float32}} @test typeof(acu.-acf) == Vector{Gray{Float32}} - if use_broadcast_rules - @test typeof(acu+cf) == Vector{Gray{Float32}} - @test typeof(acu-cf) == Vector{Gray{Float32}} - @test typeof(acu.+cf) == Vector{Gray{Float32}} - @test typeof(acu.-cf) == Vector{Gray{Float32}} - else - @test typeof(acu+cf) == Vector{Gray{N0f8}} - @test typeof(acu-cf) == Vector{Gray{N0f8}} - @test typeof(acu.+cf) == Vector{Gray{N0f8}} - @test typeof(acu.-cf) == Vector{Gray{N0f8}} - end + @test typeof(acu+cf) == Vector{Gray{Float32}} + @test typeof(acu-cf) == Vector{Gray{Float32}} + @test typeof(acu.+cf) == Vector{Gray{Float32}} + @test typeof(acu.-cf) == Vector{Gray{Float32}} @test typeof(2*acf) == Vector{Gray{Float32}} @test typeof(2.*acf) == Vector{Gray{Float32}} @test typeof(0x02*acu) == Vector{Gray{Float32}} @@ -245,17 +236,10 @@ end @test typeof(acu-acf) == Vector{RGB{Float32}} @test typeof(acu.+acf) == Vector{RGB{Float32}} @test typeof(acu.-acf) == Vector{RGB{Float32}} - if use_broadcast_rules - @test typeof(acu+cf) == Vector{RGB{Float32}} - @test typeof(acu-cf) == Vector{RGB{Float32}} - @test typeof(acu.+cf) == Vector{RGB{Float32}} - @test typeof(acu.-cf) == Vector{RGB{Float32}} - else - @test typeof(acu+cf) == Vector{RGB{N0f8}} - @test typeof(acu-cf) == Vector{RGB{N0f8}} - @test typeof(acu.+cf) == Vector{RGB{N0f8}} - @test typeof(acu.-cf) == Vector{RGB{N0f8}} - end + @test typeof(acu+cf) == Vector{RGB{Float32}} + @test typeof(acu-cf) == Vector{RGB{Float32}} + @test typeof(acu.+cf) == Vector{RGB{Float32}} + @test typeof(acu.-cf) == Vector{RGB{Float32}} @test typeof(2*acf) == Vector{RGB{Float32}} @test typeof(convert(UInt8, 2)*acu) == Vector{RGB{Float32}} @test typeof(acu/2) == Vector{RGB{typeof(N0f8(0.5)/2)}} @@ -323,17 +307,10 @@ end @test typeof(acu-acf) == Vector{RGBA{Float32}} @test typeof(acu.+acf) == Vector{RGBA{Float32}} @test typeof(acu.-acf) == Vector{RGBA{Float32}} - if use_broadcast_rules - @test typeof(acu+cf) == Vector{RGBA{Float32}} - @test typeof(acu-cf) == Vector{RGBA{Float32}} - @test typeof(acu.+cf) == Vector{RGBA{Float32}} - @test typeof(acu.-cf) == Vector{RGBA{Float32}} - else - @test typeof(acu+cf) == Vector{RGBA{N0f8}} - @test typeof(acu-cf) == Vector{RGBA{N0f8}} - @test typeof(acu.+cf) == Vector{RGBA{N0f8}} - @test typeof(acu.-cf) == Vector{RGBA{N0f8}} - end + @test typeof(acu+cf) == Vector{RGBA{Float32}} + @test typeof(acu-cf) == Vector{RGBA{Float32}} + @test typeof(acu.+cf) == Vector{RGBA{Float32}} + @test typeof(acu.-cf) == Vector{RGBA{Float32}} @test typeof(2*acf) == Vector{RGBA{Float32}} @test typeof(convert(UInt8, 2)*acu) == Vector{RGBA{Float32}} @test typeof(acu/2) == Vector{RGBA{typeof(N0f8(0.5)/2)}} From 0d853b0dcafa153baa923655ac92cdca7a7cde7e Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 17 Sep 2017 08:57:06 -0500 Subject: [PATCH 2/4] Deprecate old implementation of `one` in favor of `oneunit` --- src/ColorVectorSpace.jl | 44 ++++++++++++++++++++++++----------------- test/runtests.jl | 8 ++++++++ 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/ColorVectorSpace.jl b/src/ColorVectorSpace.jl index 15cb151..2485cad 100644 --- a/src/ColorVectorSpace.jl +++ b/src/ColorVectorSpace.jl @@ -7,7 +7,7 @@ import StatsBase: histrange import Base: ==, +, -, *, /, ^, <, ~ import Base: abs, abs2, clamp, convert, copy, div, eps, isfinite, isinf, - isnan, isless, length, mapreduce, norm, one, promote_array_type, + isnan, isless, length, mapreduce, norm, oneunit, promote_array_type, promote_op, promote_rule, zero, trunc, floor, round, ceil, bswap, mod, rem, atan2, hypot, max, min, varm, real, typemin, typemax @@ -82,7 +82,7 @@ dotc(x::Real, y::Real) = dotc(promote(x, y)...) # Return types for arithmetic operations multype{A,B}(::Type{A}, ::Type{B}) = coltype(typeof(zero(A)*zero(B))) sumtype{A,B}(::Type{A}, ::Type{B}) = coltype(typeof(zero(A)+zero(B))) -divtype{A,B}(::Type{A}, ::Type{B}) = coltype(typeof(zero(A)/one(B))) +divtype{A,B}(::Type{A}, ::Type{B}) = coltype(typeof(zero(A)/oneunit(B))) powtype{A,B}(::Type{A}, ::Type{B}) = coltype(typeof(zero(A)^zero(B))) multype(a::Colorant, b::Colorant) = multype(eltype(a),eltype(b)) sumtype(a::Colorant, b::Colorant) = sumtype(eltype(a),eltype(b)) @@ -120,19 +120,19 @@ copy(c::AbstractRGB) = c (*)(f::Real, c::AbstractRGB) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*red(c), f*green(c), f*blue(c)) (*)(f::Real, c::TransparentRGB) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*red(c), f*green(c), f*blue(c), f*alpha(c)) function (*){T<:Normed}(f::Real, c::AbstractRGB{T}) - fs = f*(1/reinterpret(one(T))) + fs = f*(1/reinterpret(oneunit(T))) base_colorant_type(c){multype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end function (*){T<:Normed}(f::Normed, c::AbstractRGB{T}) - fs = reinterpret(f)*(1/widen(reinterpret(one(T)))^2) + fs = reinterpret(f)*(1/widen(reinterpret(oneunit(T)))^2) base_colorant_type(c){multype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end function (/){T<:Normed}(c::AbstractRGB{T}, f::Real) - fs = (one(f)/reinterpret(one(T)))/f + fs = (one(f)/reinterpret(oneunit(T)))/f base_colorant_type(c){divtype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end function (/){T<:Normed}(c::AbstractRGB{T}, f::Integer) - fs = (1/reinterpret(one(T)))/f + fs = (1/reinterpret(oneunit(T)))/f base_colorant_type(c){divtype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end (+){S,T}(a::AbstractRGB{S}, b::AbstractRGB{T}) = color_rettype(a, b){sumtype(S,T)}(red(a)+red(b), green(a)+green(b), blue(a)+blue(b)) @@ -164,13 +164,15 @@ abs2(c::TransparentRGB) = (ret = abs2(color(c)); ret + convert(typeof(ret), alph norm(c::AbstractRGB) = sqrt(abs2(c)) norm(c::TransparentRGB) = sqrt(abs2(c)) -one{C<:AbstractRGB}(::Type{C}) = C(1,1,1) -one{C<:TransparentRGB}(::Type{C}) = C(1,1,1,1) +oneunit{C<:AbstractRGB}(::Type{C}) = C(1,1,1) +oneunit{C<:TransparentRGB}(::Type{C}) = C(1,1,1,1) + zero{C<:AbstractRGB}(::Type{C}) = C(0,0,0) zero{C<:TransparentRGB}(::Type{C}) = C(0,0,0,0) zero{C<:YCbCr}(::Type{C}) = C(0,0,0) zero{C<:HSV}(::Type{C}) = C(0,0,0) -one(p::Colorant) = one(typeof(p)) +oneunit(p::Colorant) = oneunit(typeof(p)) +Base.one(c::Colorant) = Base.one(typeof(c)) zero(p::Colorant) = zero(typeof(p)) # These constants come from squaring the conversion to grayscale @@ -272,7 +274,7 @@ function Base.isapprox{Cx<:MathTypes,Cy<:MathTypes}(x::AbstractArray{Cx}, end zero{C<:TransparentGray}(::Type{C}) = C(0,0) -one{C<:TransparentGray}(::Type{C}) = C(1,1) +oneunit{C<:TransparentGray}(::Type{C}) = C(1,1) dotc{T<:AbstractGray}(x::T, y::T) = acc(gray(x))*acc(gray(y)) dotc(x::AbstractGray, y::AbstractGray) = dotc(promote(x, y)...) @@ -285,14 +287,6 @@ float{T<:Gray}(::Type{T}) = typeof(float(zero(T))) Compat.@dep_vectorize_2arg Gray max Compat.@dep_vectorize_2arg Gray min -for f in (:min, :max) - @eval begin - @deprecate($f{T<:Gray}(x::Number, y::AbstractArray{T}), - @compat $f.(x, y)) - @deprecate($f{T<:Gray}(x::AbstractArray{T}, y::Number), - @compat $f.(x, y)) - end -end # Arrays +{C<:MathTypes}(A::AbstractArray{C}) = A @@ -343,4 +337,18 @@ typemax{T<:ColorTypes.AbstractGray}(::Type{T}) = T(typemax(eltype(T))) typemin{T<:ColorTypes.AbstractGray}(::T) = T(typemin(eltype(T))) typemax{T<:ColorTypes.AbstractGray}(::T) = T(typemax(eltype(T))) +# deprecations +function Base.one(::Type{C}) where {C<:Union{TransparentGray,AbstractRGB,TransparentRGB}} + Base.depwarn("one($C) will soon switch to returning 1; you might need to switch to `oneunit`", :one) + C(_onetuple(C)...) +end +_onetuple(::Type{C}) where {C<:Colorant{T,N}} where {T,N} = ntuple(d->1, Val(N)) + +for f in (:min, :max) + @eval begin + @deprecate($f{T<:Gray}(x::Number, y::AbstractArray{T}), $f.(x, y)) + @deprecate($f{T<:Gray}(x::AbstractArray{T}, y::Number), $f.(x, y)) + end +end + end diff --git a/test/runtests.jl b/test/runtests.jl index f54330e..793b0f6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -146,6 +146,8 @@ end @testset "Unary operations with Gray" begin for g in (Gray(0.4), Gray{N0f8}(0.4)) + @test @inferred(zero(g)) === typeof(g)(0) + @test @inferred(oneunit(g)) === typeof(g)(1) for op in ColorVectorSpace.unaryOps try v = @eval $op(gray(g)) # if this fails, don't bother @@ -161,6 +163,8 @@ end @testset "Arithmetic with GrayA" begin p1 = GrayA{Float32}(Gray(0.8), 0.2) + @test @inferred(zero(p1)) === GrayA{Float32}(0,0) + @test @inferred(oneunit(p1)) === GrayA{Float32}(1,1) @test +p1 == p1 @test -p1 == GrayA(-0.8f0, -0.2f0) p2 = GrayA{Float32}(Gray(0.6), 0.3) @@ -193,6 +197,8 @@ end @testset "Arithemtic with RGB" begin cf = RGB{Float32}(0.1,0.2,0.3) + @test @inferred(zero(cf)) === RGB{Float32}(0,0,0) + @test @inferred(oneunit(cf)) === RGB{Float32}(1,1,1) @test +cf == cf @test -cf == RGB(-0.1f0, -0.2f0, -0.3f0) ccmp = RGB{Float32}(0.2,0.4,0.6) @@ -261,6 +267,8 @@ end @testset "Arithemtic with RGBA" begin cf = RGBA{Float32}(0.1,0.2,0.3,0.4) + @test @inferred(zero(cf)) === RGBA{Float32}(0,0,0,0) + @test @inferred(oneunit(cf)) === RGBA{Float32}(1,1,1,1) @test +cf == cf @test -cf == RGBA(-0.1f0, -0.2f0, -0.3f0, -0.4f0) ccmp = RGBA{Float32}(0.2,0.4,0.6,0.8) From 1a8a670bf2c44872df3c7278ae148e53c4c3f6b4 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 17 Sep 2017 08:57:40 -0500 Subject: [PATCH 3/4] Support `middle` on Gray Gray is the only one with an order, so no other colorants make sense --- src/ColorVectorSpace.jl | 5 ++++- test/runtests.jl | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ColorVectorSpace.jl b/src/ColorVectorSpace.jl index 2485cad..bd63aba 100644 --- a/src/ColorVectorSpace.jl +++ b/src/ColorVectorSpace.jl @@ -28,7 +28,7 @@ import Base: conj, sin, cos, tan, sinh, cosh, tanh, gamma, lfact, frexp, modf, airy, airyai, airyprime, airyaiprime, airybi, airybiprime, besselj0, besselj1, bessely0, bessely1, - eta, zeta, digamma, float + eta, zeta, digamma, float, middle export dotc @@ -202,6 +202,9 @@ for op in unaryOps @eval ($op)(c::AbstractGray) = $op(gray(c)) end +middle(c::AbstractGray) = base_colorant_type(c)(middle(gray(c))) +middle(x::C, y::C) where {C<:AbstractGray} = C(middle(gray(x), gray(y))) + (*)(f::Real, c::AbstractGray) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*gray(c)) (*)(f::Real, c::TransparentGray) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*gray(c), f*alpha(c)) (*)(c::AbstractGray, f::Real) = (*)(f, c) diff --git a/test/runtests.jl b/test/runtests.jl index 793b0f6..0174951 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -118,6 +118,8 @@ end @test typeof(float(Gray{N0f16}(0.5))) <: AbstractFloat @test quantile( Gray{N0f16}[0.0,0.5,1.0], 0.1) ≈ 0.10000152590218968 + @test middle(Gray(0.2)) === Gray(0.2) + @test middle(Gray(0.2), Gray(0.4)) === Gray((0.2+0.4)/2) end @testset "Comparisons with Gray" begin From c68b9257f817ec4c68a68858ba41d158e8b34b76 Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Sun, 17 Sep 2017 09:28:15 -0500 Subject: [PATCH 4/4] Avoid trying to call parametric constructors for non-parametric types Fixes #56 --- src/ColorVectorSpace.jl | 31 +++++++++++++++++++------------ test/runtests.jl | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/ColorVectorSpace.jl b/src/ColorVectorSpace.jl index bd63aba..467f46b 100644 --- a/src/ColorVectorSpace.jl +++ b/src/ColorVectorSpace.jl @@ -108,6 +108,13 @@ _color_rettype{C<:Colorant}(::Type{C}, ::Type{C}) = C color_rettype(c1::Colorant, c2::Colorant) = color_rettype(typeof(c1), typeof(c2)) +arith_colorant_type(::C) where {C<:Colorant} = arith_colorant_type(C) +arith_colorant_type(::Type{C}) where {C<:Colorant} = base_colorant_type(C) +arith_colorant_type(::Type{Gray24}) = Gray +arith_colorant_type(::Type{AGray32}) = AGray +arith_colorant_type(::Type{RGB24}) = RGB +arith_colorant_type(::Type{ARGB32}) = ARGB + ## Math on Colors. These implementations encourage inlining and, ## for the case of Normed types, nearly halve the number of multiplications (for RGB) @@ -117,23 +124,23 @@ copy(c::AbstractRGB) = c (+)(c::TransparentRGB) = mapc(+, c) (-)(c::AbstractRGB) = mapc(-, c) (-)(c::TransparentRGB) = mapc(-, c) -(*)(f::Real, c::AbstractRGB) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*red(c), f*green(c), f*blue(c)) -(*)(f::Real, c::TransparentRGB) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*red(c), f*green(c), f*blue(c), f*alpha(c)) +(*)(f::Real, c::AbstractRGB) = arith_colorant_type(c){multype(typeof(f),eltype(c))}(f*red(c), f*green(c), f*blue(c)) +(*)(f::Real, c::TransparentRGB) = arith_colorant_type(c){multype(typeof(f),eltype(c))}(f*red(c), f*green(c), f*blue(c), f*alpha(c)) function (*){T<:Normed}(f::Real, c::AbstractRGB{T}) fs = f*(1/reinterpret(oneunit(T))) - base_colorant_type(c){multype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) + arith_colorant_type(c){multype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end function (*){T<:Normed}(f::Normed, c::AbstractRGB{T}) fs = reinterpret(f)*(1/widen(reinterpret(oneunit(T)))^2) - base_colorant_type(c){multype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) + arith_colorant_type(c){multype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end function (/){T<:Normed}(c::AbstractRGB{T}, f::Real) fs = (one(f)/reinterpret(oneunit(T)))/f - base_colorant_type(c){divtype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) + arith_colorant_type(c){divtype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end function (/){T<:Normed}(c::AbstractRGB{T}, f::Integer) fs = (1/reinterpret(oneunit(T)))/f - base_colorant_type(c){divtype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) + arith_colorant_type(c){divtype(typeof(f),T)}(fs*reinterpret(red(c)), fs*reinterpret(green(c)), fs*reinterpret(blue(c))) end (+){S,T}(a::AbstractRGB{S}, b::AbstractRGB{T}) = color_rettype(a, b){sumtype(S,T)}(red(a)+red(b), green(a)+green(b), blue(a)+blue(b)) (-){S,T}(a::AbstractRGB{S}, b::AbstractRGB{T}) = color_rettype(a, b){sumtype(S,T)}(red(a)-red(b), green(a)-green(b), blue(a)-blue(b)) @@ -202,11 +209,11 @@ for op in unaryOps @eval ($op)(c::AbstractGray) = $op(gray(c)) end -middle(c::AbstractGray) = base_colorant_type(c)(middle(gray(c))) -middle(x::C, y::C) where {C<:AbstractGray} = C(middle(gray(x), gray(y))) +middle(c::AbstractGray) = arith_colorant_type(c)(middle(gray(c))) +middle(x::C, y::C) where {C<:AbstractGray} = arith_colorant_type(C)(middle(gray(x), gray(y))) -(*)(f::Real, c::AbstractGray) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*gray(c)) -(*)(f::Real, c::TransparentGray) = base_colorant_type(c){multype(typeof(f),eltype(c))}(f*gray(c), f*alpha(c)) +(*)(f::Real, c::AbstractGray) = arith_colorant_type(c){multype(typeof(f),eltype(c))}(f*gray(c)) +(*)(f::Real, c::TransparentGray) = arith_colorant_type(c){multype(typeof(f),eltype(c))}(f*gray(c), f*alpha(c)) (*)(c::AbstractGray, f::Real) = (*)(f, c) (*)(c::TransparentGray, f::Real) = (*)(f, c) (/)(c::AbstractGray, f::Real) = (one(f)/f)*c @@ -219,8 +226,8 @@ middle(x::C, y::C) where {C<:AbstractGray} = C(middle(gray(x), gray(y))) (-){S,T}(a::AbstractGray{S}, b::AbstractGray{T}) = color_rettype(a,b){sumtype(S,T)}(gray(a)-gray(b)) (-)(a::TransparentGray, b::TransparentGray) = color_rettype(a,b){sumtype(eltype(a),eltype(b))}(gray(a)-gray(b),alpha(a)-alpha(b)) (*){S,T}(a::AbstractGray{S}, b::AbstractGray{T}) = color_rettype(a,b){multype(S,T)}(gray(a)*gray(b)) -(^){S}(a::AbstractGray{S}, b::Integer) = base_colorant_type(a){powtype(S,Int)}(gray(a)^convert(Int,b)) -(^){S}(a::AbstractGray{S}, b::Real) = base_colorant_type(a){powtype(S,typeof(b))}(gray(a)^b) +(^){S}(a::AbstractGray{S}, b::Integer) = arith_colorant_type(a){powtype(S,Int)}(gray(a)^convert(Int,b)) +(^){S}(a::AbstractGray{S}, b::Real) = arith_colorant_type(a){powtype(S,typeof(b))}(gray(a)^b) (+)(c::AbstractGray) = c (+)(c::TransparentGray) = c (-)(c::AbstractGray) = typeof(c)(-gray(c)) diff --git a/test/runtests.jl b/test/runtests.jl index 0174951..ce339d6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -120,6 +120,12 @@ end @test quantile( Gray{N0f16}[0.0,0.5,1.0], 0.1) ≈ 0.10000152590218968 @test middle(Gray(0.2)) === Gray(0.2) @test middle(Gray(0.2), Gray(0.4)) === Gray((0.2+0.4)/2) + + # issue #56 + @test Gray24(0.8)*N0f8(0.5) === Gray{N0f8}(0.4) + @test Gray24(0.8)*0.5 === Gray(0.4) + @test Gray24(0.8)/2 === Gray(0.5f0*N0f8(0.8)) + @test Gray24(0.8)/2.0 === Gray(0.4) end @testset "Comparisons with Gray" begin @@ -195,6 +201,11 @@ end @test !isapprox(a, b, rtol = 0.01) @test isapprox(a, b, rtol = 0.1) + # issue #56 + @test AGray32(0.8,0.2)*N0f8(0.5) === AGray{N0f8}(0.4,0.1) + @test AGray32(0.8,0.2)*0.5 === AGray(0.4,0.1) + @test AGray32(0.8,0.2)/2 === AGray(0.5f0*N0f8(0.8),0.5f0*N0f8(0.2)) + @test AGray32(0.8,0.2)/2.0 === AGray(0.4,0.1) end @testset "Arithemtic with RGB" begin @@ -265,6 +276,11 @@ end a = RGB{Float64}(1.0, 1.0, 0.99) @test !(isapprox(a, b, rtol = 0.01)) @test isapprox(a, b, rtol = 0.1) + # issue #56 + @test RGB24(1,0,0)*N0f8(0.5) === RGB{N0f8}(0.5,0,0) + @test RGB24(1,0,0)*0.5 === RGB(0.5,0,0) + @test RGB24(1,0,0)/2 === RGB(0.5f0,0,0) + @test RGB24(1,0,0)/2.0 === RGB(0.5,0,0) end @testset "Arithemtic with RGBA" begin @@ -335,6 +351,11 @@ end a = ARGB{Float64}(1.0, 1.0, 1.0, 0.99) @test !(isapprox(a, b, rtol = 0.01)) @test isapprox(a, b, rtol = 0.1) + # issue #56 + @test ARGB32(1,0,0,0.8)*N0f8(0.5) === ARGB{N0f8}(0.5,0,0,0.4) + @test ARGB32(1,0,0,0.8)*0.5 === ARGB(0.5,0,0,0.4) + @test ARGB32(1,0,0,0.8)/2 === ARGB(0.5f0,0,0,0.5f0*N0f8(0.8)) + @test ARGB32(1,0,0,0.8)/2.0 === ARGB(0.5,0,0,0.4) end @testset "Mixed-type arithmetic" begin