diff --git a/Project.toml b/Project.toml index d854b70..9d84f49 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "FunctionImplementations" uuid = "7c7cc465-9c6a-495f-bdd1-f42428e86d0c" -version = "0.4.1" +version = "0.4.2" authors = ["ITensor developers and contributors"] [workspace] diff --git a/docs/make.jl b/docs/make.jl index 8ffffb2..e9509b5 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,8 +1,9 @@ -using FunctionImplementations: FunctionImplementations using Documenter: Documenter, DocMeta, deploydocs, makedocs +using FunctionImplementations: FunctionImplementations DocMeta.setdocmeta!( - FunctionImplementations, :DocTestSetup, :(using FunctionImplementations); recursive = true + FunctionImplementations, :DocTestSetup, :(using FunctionImplementations); + recursive = true ) include("make_index.jl") @@ -14,11 +15,12 @@ makedocs(; format = Documenter.HTML(; canonical = "https://itensor.github.io/FunctionImplementations.jl", edit_link = "main", - assets = ["assets/favicon.ico", "assets/extras.css"], + assets = ["assets/favicon.ico", "assets/extras.css"] ), - pages = ["Home" => "index.md", "Reference" => "reference.md"], + pages = ["Home" => "index.md", "Reference" => "reference.md"] ) deploydocs(; - repo = "github.com/ITensor/FunctionImplementations.jl", devbranch = "main", push_preview = true + repo = "github.com/ITensor/FunctionImplementations.jl", devbranch = "main", + push_preview = true ) diff --git a/docs/make_index.jl b/docs/make_index.jl index 1094a7d..f9478fc 100644 --- a/docs/make_index.jl +++ b/docs/make_index.jl @@ -1,5 +1,5 @@ -using Literate: Literate using FunctionImplementations: FunctionImplementations +using Literate: Literate function ccq_logo(content) include_ccq_logo = """ @@ -17,5 +17,5 @@ Literate.markdown( joinpath(pkgdir(FunctionImplementations), "docs", "src"); flavor = Literate.DocumenterFlavor(), name = "index", - postprocess = ccq_logo, + postprocess = ccq_logo ) diff --git a/docs/make_readme.jl b/docs/make_readme.jl index 7cb3c2a..53d7968 100644 --- a/docs/make_readme.jl +++ b/docs/make_readme.jl @@ -1,5 +1,5 @@ -using Literate: Literate using FunctionImplementations: FunctionImplementations +using Literate: Literate function ccq_logo(content) include_ccq_logo = """ @@ -17,5 +17,5 @@ Literate.markdown( joinpath(pkgdir(FunctionImplementations)); flavor = Literate.CommonMarkFlavor(), name = "README", - postprocess = ccq_logo, + postprocess = ccq_logo ) diff --git a/ext/FunctionImplementationsFillArraysExt/FunctionImplementationsFillArraysExt.jl b/ext/FunctionImplementationsFillArraysExt/FunctionImplementationsFillArraysExt.jl index 7ea8b8a..b1ae6cf 100644 --- a/ext/FunctionImplementationsFillArraysExt/FunctionImplementationsFillArraysExt.jl +++ b/ext/FunctionImplementationsFillArraysExt/FunctionImplementationsFillArraysExt.jl @@ -1,7 +1,7 @@ module FunctionImplementationsFillArraysExt -using FillArrays: FillArrays as FA, AbstractFill, RectDiagonal import FunctionImplementations as FI +using FillArrays: FillArrays as FA, AbstractFill, RectDiagonal function check_perm(a::AbstractArray, perm) (ndims(a) == length(perm) && isperm(perm)) || diff --git a/src/concatenate.jl b/src/concatenate.jl index 0b1e644..97870f0 100644 --- a/src/concatenate.jl +++ b/src/concatenate.jl @@ -11,13 +11,13 @@ reminiscent of how Broadcast works. The various entry points for specializing behavior are: -* Destination selection can be achieved through: + - Destination selection can be achieved through: ```julia Base.similar(concat::Concatenated{Style}, ::Type{T}, axes) where {Style} ``` -* Custom implementations: + - Custom implementations: ```julia Base.copy(concat::Concatenated{Style}) # custom implementation of cat @@ -28,11 +28,12 @@ Base.copyto!(dest, concat::Concatenated{Nothing}) # custom implementation of cat module Concatenate export concatenate -VERSION >= v"1.11.0-DEV.469" && eval(Meta.parse("public Concatenated, cat, cat!, concatenated")) +VERSION >= v"1.11.0-DEV.469" && + eval(Meta.parse("public Concatenated, cat, cat!, concatenated")) -using Base: promote_eltypeof import Base.Broadcast as BC using ..FunctionImplementations: zero! +using Base: promote_eltypeof unval(::Val{x}) where {x} = x @@ -116,7 +117,11 @@ end function cat_axes(dims, a::AbstractArray, as::AbstractArray...) return ntuple(cat_ndims(dims, a, as...)) do dim - return dim in dims ? cat_axis(map(Base.Fix2(axes, dim), (a, as...))...) : axes(a, dim) + return if dim in dims + cat_axis(map(Base.Fix2(axes, dim), (a, as...))...) + else + axes(a, dim) + end end end function cat_axes(dims::Val, as::AbstractArray...) @@ -191,11 +196,19 @@ end __cat_offset!(A, shape, catdims, offsets) = A function __cat_offset1!(A, shape, catdims, offsets, x) inds = ntuple(length(offsets)) do i - (i <= length(catdims) && catdims[i]) ? offsets[i] .+ cat_indices(x, i) : 1:shape[i] + return if (i <= length(catdims) && catdims[i]) + offsets[i] .+ cat_indices(x, i) + else + 1:shape[i] + end end _copy_or_fill!(A, inds, x) newoffsets = ntuple(length(offsets)) do i - (i <= length(catdims) && catdims[i]) ? offsets[i] + cat_size(x, i) : offsets[i] + return if (i <= length(catdims) && catdims[i]) + offsets[i] + cat_size(x, i) + else + offsets[i] + end end return newoffsets end diff --git a/src/style.jl b/src/style.jl index 5f66f1b..97ef067 100644 --- a/src/style.jl +++ b/src/style.jl @@ -10,7 +10,6 @@ by defining a type/method pair struct MyContainerImplementationStyle <: ImplementationStyle end FunctionImplementations.ImplementationStyle(::Type{<:MyContainer}) = MyContainerImplementationStyle() - """ abstract type ImplementationStyle end ImplementationStyle(::Type{T}) where {T} = throw(MethodError(ImplementationStyle, (T,))) @@ -69,20 +68,37 @@ The result does not have to be one of the input arguments, it could be a third t """ ImplementationStyle(::S, ::S) where {S <: ImplementationStyle} = S() # homogeneous types preserved # Fall back to UnknownImplementationStyle. This is necessary to implement argument-swapping -ImplementationStyle(::ImplementationStyle, ::ImplementationStyle) = UnknownImplementationStyle() +function ImplementationStyle(::ImplementationStyle, ::ImplementationStyle) + return UnknownImplementationStyle() +end # UnknownImplementationStyle loses to everything -ImplementationStyle(::UnknownImplementationStyle, ::UnknownImplementationStyle) = UnknownImplementationStyle() -ImplementationStyle(::S, ::UnknownImplementationStyle) where {S <: ImplementationStyle} = S() +function ImplementationStyle(::UnknownImplementationStyle, ::UnknownImplementationStyle) + return UnknownImplementationStyle() +end +function ImplementationStyle( + ::S, + ::UnknownImplementationStyle + ) where {S <: ImplementationStyle} + return S() +end # Precedence rules ImplementationStyle(::A, ::A) where {A <: AbstractArrayImplementationStyle} = A() -function ImplementationStyle(a::A, b::B) where {A <: AbstractArrayImplementationStyle, B <: AbstractArrayImplementationStyle} +function ImplementationStyle( + a::A, + b::B + ) where {A <: AbstractArrayImplementationStyle, B <: AbstractArrayImplementationStyle} if Base.typename(A) ≡ Base.typename(B) return A() end return UnknownImplementationStyle() end # Any specific array type beats DefaultArrayImplementationStyle -ImplementationStyle(a::AbstractArrayImplementationStyle, ::DefaultArrayImplementationStyle) = a +function ImplementationStyle( + a::AbstractArrayImplementationStyle, + ::DefaultArrayImplementationStyle + ) + return a +end ## logic for deciding the ImplementationStyle @@ -94,6 +110,7 @@ Uses [`ImplementationStyle`](@ref) to get the style for each argument, and uses [`result_style`](@ref) to combine styles. # Examples + ```jldoctest julia> FunctionImplementations.style([1], [1 2; 3 4]) FunctionImplementations.DefaultArrayImplementationStyle() @@ -115,10 +132,16 @@ determine a common `ImplementationStyle`. # Examples ```jldoctest -julia> FunctionImplementations.result_style(FunctionImplementations.DefaultArrayImplementationStyle(), FunctionImplementations.DefaultArrayImplementationStyle()) +julia> FunctionImplementations.result_style( + FunctionImplementations.DefaultArrayImplementationStyle(), + FunctionImplementations.DefaultArrayImplementationStyle() + ) FunctionImplementations.DefaultArrayImplementationStyle() -julia> FunctionImplementations.result_style(FunctionImplementations.UnknownImplementationStyle(), FunctionImplementations.DefaultArrayImplementationStyle()) +julia> FunctionImplementations.result_style( + FunctionImplementations.UnknownImplementationStyle(), + FunctionImplementations.DefaultArrayImplementationStyle() + ) FunctionImplementations.DefaultArrayImplementationStyle() ``` """ @@ -129,24 +152,41 @@ function result_style(s1::S, s2::S) where {S <: ImplementationStyle} return s1 ≡ s2 ? s1 : error("inconsistent styles, custom rule needed") end # Test both orders so users typically only have to declare one order -result_style(s1, s2) = result_join(s1, s2, ImplementationStyle(s1, s2), ImplementationStyle(s2, s1)) +function result_style(s1, s2) + return result_join(s1, s2, ImplementationStyle(s1, s2), ImplementationStyle(s2, s1)) +end # result_join is the final arbiter. Because `ImplementationStyle` for undeclared pairs results in UnknownImplementationStyle, # we defer to any case where the result of `ImplementationStyle` is known. -result_join(::Any, ::Any, ::UnknownImplementationStyle, ::UnknownImplementationStyle) = UnknownImplementationStyle() +function result_join( + ::Any, + ::Any, + ::UnknownImplementationStyle, + ::UnknownImplementationStyle + ) + return UnknownImplementationStyle() +end result_join(::Any, ::Any, ::UnknownImplementationStyle, s::ImplementationStyle) = s result_join(::Any, ::Any, s::ImplementationStyle, ::UnknownImplementationStyle) = s # For AbstractArray types with undefined precedence rules, # we have to signal conflict. Because ArrayImplementationConflict is a subtype of AbstractArray, # this will "poison" any future operations (if we instead returned `DefaultArrayImplementationStyle`, then for # 3-array functions returned type would depend on argument order). -result_join(::AbstractArrayImplementationStyle, ::AbstractArrayImplementationStyle, ::UnknownImplementationStyle, ::UnknownImplementationStyle) = - ArrayImplementationConflict() +function result_join( + ::AbstractArrayImplementationStyle, + ::AbstractArrayImplementationStyle, + ::UnknownImplementationStyle, + ::UnknownImplementationStyle + ) + return ArrayImplementationConflict() +end # Fallbacks in case users define `rule` for both argument-orders (not recommended) -result_join(::Any, ::Any, s1::S, s2::S) where {S <: ImplementationStyle} = result_style(s1, s2) +function result_join(::Any, ::Any, s1::S, s2::S) where {S <: ImplementationStyle} + return result_style(s1, s2) +end @noinline function result_join(::S, ::T, ::U, ::V) where {S, T, U, V} - error( + return error( """ conflicting rules defined FunctionImplementations.ImplementationStyle(::$S, ::$T) = $U() diff --git a/test/runtests.jl b/test/runtests.jl index 2124a45..e5afded 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -13,15 +13,20 @@ const GROUP = uppercase( arg == "" ? "ALL" : arg else only(match(pat, ARGS[arg_id]).captures) - end, + end ) -"match files of the form `test_*.jl`, but exclude `*setup*.jl`" +""" +match files of the form `test_*.jl`, but exclude `*setup*.jl` +""" function istestfile(path) fn = basename(path) - return endswith(fn, ".jl") && startswith(basename(fn), "test_") && !contains(fn, "setup") + return endswith(fn, ".jl") && startswith(basename(fn), "test_") && + !contains(fn, "setup") end -"match files of the form `*.jl`, but exclude `*_notest.jl` and `*setup*.jl`" +""" +match files of the form `*.jl`, but exclude `*_notest.jl` and `*setup*.jl` +""" function isexamplefile(path) fn = basename(path) return endswith(fn, ".jl") && !endswith(fn, "_notest.jl") && !contains(fn, "setup") @@ -60,7 +65,7 @@ end :macrocall, GlobalRef(Suppressor, Symbol("@suppress")), LineNumberNode(@__LINE__, @__FILE__), - :(include($filename)), + :(include($filename)) ) ) end diff --git a/test/test_aqua.jl b/test/test_aqua.jl index 5ab80ef..3b26b9c 100644 --- a/test/test_aqua.jl +++ b/test/test_aqua.jl @@ -1,5 +1,5 @@ -using FunctionImplementations: FunctionImplementations using Aqua: Aqua +using FunctionImplementations: FunctionImplementations using Test: @testset @testset "Code quality (Aqua.jl)" begin diff --git a/test/test_basics.jl b/test/test_basics.jl index b872604..51988ea 100644 --- a/test/test_basics.jl +++ b/test/test_basics.jl @@ -20,10 +20,13 @@ using Test: @test, @testset end @testset "ImplementationStyle" begin # Test basic ImplementationStyle trait for different array types - @test FI.ImplementationStyle(typeof([1, 2, 3])) ≡ FI.DefaultArrayImplementationStyle() + @test FI.ImplementationStyle(typeof([1, 2, 3])) ≡ + FI.DefaultArrayImplementationStyle() @test FI.style([1, 2, 3]) ≡ FI.DefaultArrayImplementationStyle() - @test FI.ImplementationStyle(typeof([1 2; 3 4])) ≡ FI.DefaultArrayImplementationStyle() - @test FI.ImplementationStyle(typeof(rand(2, 3, 4))) ≡ FI.DefaultArrayImplementationStyle() + @test FI.ImplementationStyle(typeof([1 2; 3 4])) ≡ + FI.DefaultArrayImplementationStyle() + @test FI.ImplementationStyle(typeof(rand(2, 3, 4))) ≡ + FI.DefaultArrayImplementationStyle() # Test custom ImplementationStyle definition struct CustomImplementationStyle <: FI.ImplementationStyle end @@ -75,7 +78,8 @@ using Test: @test, @testset @test result ≡ FI.DefaultArrayImplementationStyle() # Test result_style with single argument - @test FI.result_style(FI.DefaultArrayImplementationStyle()) isa FI.DefaultArrayImplementationStyle + @test FI.result_style(FI.DefaultArrayImplementationStyle()) isa + FI.DefaultArrayImplementationStyle # Test result_style with two identical styles s = FI.DefaultArrayImplementationStyle()