From 65314eea3d2efd92139a2f12aa03a4f95dd4b8f1 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Tue, 30 May 2023 14:28:37 +0200 Subject: [PATCH 1/6] Update CI configuration --- .github/workflows/CI.yml | 60 +++++++++++++++------------------------- 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 97bfc55a..82a9a23f 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -6,9 +6,9 @@ on: push: branches: - master + tags: '*' pull_request: - concurrency: # Skip intermediate builds: always. # Cancel intermediate builds: only if it is a pull request build. @@ -19,59 +19,43 @@ jobs: test: name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }} runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.version == 'nightly' }} strategy: fail-fast: false matrix: version: - '1.6' - - '1.7' - - '1.8' + - '1' + - 'nightly' os: - ubuntu-latest arch: - x64 + include: + - version: 1 + os: ubuntu-latest + arch: x86 + - version: 1 + os: macOS-latest + arch: x64 + - version: 1 + os: windows-latest + arch: x64 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: julia-actions/setup-julia@v1 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - - uses: actions/cache@v1 - env: - cache-name: cache-artifacts - with: - path: ~/.julia/artifacts - key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} - restore-keys: | - ${{ runner.os }}-test-${{ env.cache-name }}- - ${{ runner.os }}-test- - ${{ runner.os }}- + - uses: julia-actions/cache@v1 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + with: + coverage: ${{ matrix.version == '1' && matrix.os == 'ubuntu-latest' && matrix.arch == 'x64' }} - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v1 + if: matrix.version == '1' && matrix.os == 'ubuntu-latest' && matrix.arch == 'x64' + - uses: codecov/codecov-action@v3 + if: matrix.version == '1' && matrix.os == 'ubuntu-latest' && matrix.arch == 'x64' with: file: lcov.info - # docs: - # name: Documentation - # runs-on: ubuntu-latest - # steps: - # - uses: actions/checkout@v2 - # - uses: julia-actions/setup-julia@v1 - # with: - # version: '1' - # - run: | - # julia --project=docs -e ' - # using Pkg - # Pkg.develop(PackageSpec(path=pwd())) - # Pkg.instantiate()' - # - run: | - # julia --project=docs -e ' - # using Documenter: DocMeta, doctest - # using MeasureBase - # DocMeta.setdocmeta!(MeasureBase, :DocTestSetup, :(using MeasureBase); recursive=true) - # doctest(MeasureBase)' - # - run: julia --project=docs docs/make.jl - # env: - # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - # DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} + From 5bf1b627b1054cde19c53b67d7170726d4797d68 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Tue, 30 May 2023 14:28:37 +0200 Subject: [PATCH 2/6] Update to Static.jl v0.8 --- Project.toml | 2 +- src/MeasureBase.jl | 3 +- src/combinators/power.jl | 49 ++++++++++++--------- src/combinators/smart-constructors.jl | 2 +- src/domains.jl | 2 +- src/standard/stdmeasure.jl | 6 +-- src/static.jl | 62 +++++++++++++++++++++++++++ test/transport.jl | 2 +- 8 files changed, 100 insertions(+), 28 deletions(-) create mode 100644 src/static.jl diff --git a/Project.toml b/Project.toml index a69b739d..25707bb7 100644 --- a/Project.toml +++ b/Project.toml @@ -48,6 +48,6 @@ NaNMath = "0.3, 1" PrettyPrinting = "0.3, 0.4" Reexport = "1" SpecialFunctions = "2" -Static = "0.5, 0.6" +Static = "0.8" Tricks = "0.1" julia = "1.3" diff --git a/src/MeasureBase.jl b/src/MeasureBase.jl index 72048c49..d8336689 100644 --- a/src/MeasureBase.jl +++ b/src/MeasureBase.jl @@ -32,7 +32,7 @@ using PrettyPrinting const Pretty = PrettyPrinting using ChainRulesCore -using FillArrays +import FillArrays using Static using FunctionChains @@ -106,6 +106,7 @@ using Compat using IrrationalConstants +include("static.jl") include("smf.jl") include("getdof.jl") include("transport.jl") diff --git a/src/combinators/power.jl b/src/combinators/power.jl index 1bc17866..01bae72f 100644 --- a/src/combinators/power.jl +++ b/src/combinators/power.jl @@ -1,22 +1,25 @@ import Base -using FillArrays: Fill -# """ -# A power measure is a product of a measure with itself. The number of elements in -# the product determines the dimensionality of the resulting support. -# Note that power measures are only well-defined for integer powers. +export PowerMeasure -# The nth power of a measure μ can be written μ^x. -# """ -# PowerMeasure{M,N,D} = ProductMeasure{Fill{M,N,D}} +""" + struct PowerMeasure{M,...} <: AbstractProductMeasure -export PowerMeasure +A power measure is a product of a measure with itself. The number of elements in +the product determines the dimensionality of the resulting support. +Note that power measures are only well-defined for integer powers. + +The nth power of a measure μ can be written μ^x. +""" struct PowerMeasure{M,A} <: AbstractProductMeasure parent::M axes::A end +dslength(μ::PowerMeasure) = prod(dssize(μ)) +dssize(μ::PowerMeasure) = map(dslength, μ.axes) + function Pretty.tile(μ::PowerMeasure) sz = length.(μ.axes) arg1 = Pretty.tile(μ.parent) @@ -24,35 +27,41 @@ function Pretty.tile(μ::PowerMeasure) return Pretty.pair_layout(arg1, arg2; sep = " ^ ") end +# ToDo: Make rand return static arrays for statically-sized power measures. + +_cartidxs(axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where {N} = CartesianIndices(map(_dynamic, axs)) + function Base.rand( rng::AbstractRNG, ::Type{T}, d::PowerMeasure{M}, ) where {T,M<:AbstractMeasure} - map(CartesianIndices(d.axes)) do _ + map(_cartidxs(d.axes)) do _ rand(rng, T, d.parent) end end function Base.rand(rng::AbstractRNG, ::Type{T}, d::PowerMeasure) where {T} - map(CartesianIndices(d.axes)) do _ + map(_cartidxs(d.axes)) do _ rand(rng, d.parent) end end +@inline _pm_axes(sz::Tuple{Vararg{<:IntegerLike,N}}) where N = map(one_to, sz) +@inline _pm_axes(axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where N = axs + @inline function powermeasure(x::T, sz::Tuple{Vararg{<:Any,N}}) where {T,N} - a = axes(Fill{T,N}(x, sz)) - A = typeof(a) - PowerMeasure{T,A}(x, a) + PowerMeasure(x, _pm_axes(sz)) end -marginals(d::PowerMeasure) = Fill(d.parent, d.axes) + +marginals(d::PowerMeasure) = fill_with(d.parent, d.axes) function Base.:^(μ::AbstractMeasure, dims::Tuple{Vararg{<:AbstractArray,N}}) where {N} powermeasure(μ, dims) end -Base.:^(μ::AbstractMeasure, dims::Tuple) = powermeasure(μ, Base.OneTo.(dims)) +Base.:^(μ::AbstractMeasure, dims::Tuple) = powermeasure(μ, one_to.(dims)) Base.:^(μ::AbstractMeasure, n) = powermeasure(μ, (n,)) # Base.show(io::IO, d::PowerMeasure) = print(io, d.parent, " ^ ", size(d.xs)) @@ -76,7 +85,7 @@ end end @inline function logdensity_def( - d::PowerMeasure{M,Tuple{Base.OneTo{StaticInt{N}}}}, + d::PowerMeasure{M,Tuple{Static.SOneTo{N}}}, x, ) where {M,N} parent = d.parent @@ -86,7 +95,7 @@ end end @inline function logdensity_def( - d::PowerMeasure{M,NTuple{N,Base.OneTo{StaticInt{0}}}}, + d::PowerMeasure{M,NTuple{N,Static.SOneTo{0}}}, x, ) where {M,N} static(0.0) @@ -110,7 +119,7 @@ end @inline getdof(μ::PowerMeasure) = getdof(μ.parent) * prod(map(length, μ.axes)) -@inline function getdof(::PowerMeasure{<:Any,NTuple{N,Base.OneTo{StaticInt{0}}}}) where {N} +@inline function getdof(::PowerMeasure{<:Any,NTuple{N,Static.SOneTo{0}}}) where {N} static(0) end @@ -135,7 +144,7 @@ logdensity_def(::PowerMeasure{P}, x) where {P<:PrimitiveMeasure} = static(0.0) # To avoid ambiguities function logdensity_def( - ::PowerMeasure{P,Tuple{Vararg{Base.OneTo{Static.StaticInt{0}},N}}}, + ::PowerMeasure{P,Tuple{Vararg{Static.SOneTo{0},N}}}, x, ) where {P<:PrimitiveMeasure,N} static(0.0) diff --git a/src/combinators/smart-constructors.jl b/src/combinators/smart-constructors.jl index 11d7bbbb..aa86ee40 100644 --- a/src/combinators/smart-constructors.jl +++ b/src/combinators/smart-constructors.jl @@ -37,7 +37,7 @@ end ############################################################################### # ProductMeasure -productmeasure(mar::Fill) = powermeasure(mar.value, mar.axes) +productmeasure(mar::FillArrays.Fill) = powermeasure(mar.value, mar.axes) function productmeasure(mar::ReadonlyMappedArray{T,N,A,Returns{M}}) where {T,N,A,M} return powermeasure(mar.f.value, axes(mar.data)) diff --git a/src/domains.jl b/src/domains.jl index e4c7f5e7..e03f753c 100644 --- a/src/domains.jl +++ b/src/domains.jl @@ -116,7 +116,7 @@ struct Simplex <: CodimOne end function zeroset(::Simplex) f(x::AbstractArray{T}) where {T} = sum(x) - one(T) - ∇f(x::AbstractArray{T}) where {T} = Fill(one(T), size(x)) + ∇f(x::AbstractArray{T}) where {T} = fill_with(one(T), size(x)) ZeroSet(f, ∇f) end diff --git a/src/standard/stdmeasure.jl b/src/standard/stdmeasure.jl index 2b50c1e5..1806575e 100644 --- a/src/standard/stdmeasure.jl +++ b/src/standard/stdmeasure.jl @@ -13,7 +13,7 @@ function transport_def(ν::StdMeasure, μ::PowerMeasure{<:StdMeasure}, x) end function transport_def(ν::PowerMeasure{<:StdMeasure}, μ::StdMeasure, x) - return Fill(transport_def(ν.parent, μ, only(x)), map(length, ν.axes)...) + return fill_with(transport_def(ν.parent, μ, only(x)), map(length, ν.axes)) end function transport_def( @@ -35,7 +35,7 @@ end # Implement transport_to(NU::Type{<:StdMeasure}, μ) and transport_to(ν, MU::Type{<:StdMeasure}): _std_measure(::Type{M}, ::StaticInt{1}) where {M<:StdMeasure} = M() -_std_measure(::Type{M}, dof::Integer) where {M<:StdMeasure} = M()^dof +_std_measure(::Type{M}, dof::IntegerLike) where {M<:StdMeasure} = M()^dof _std_measure_for(::Type{M}, μ::Any) where {M<:StdMeasure} = _std_measure(M, getdof(μ)) function transport_to(::Type{NU}, μ) where {NU<:StdMeasure} @@ -90,7 +90,7 @@ end @inline _offset_cumsum(s, x) = (s,) @inline _offset_cumsum(s) = () -function _stdvar_viewranges(μs::Tuple, startidx::Integer) +function _stdvar_viewranges(μs::Tuple, startidx::IntegerLike) N = map(getdof, μs) offs = _offset_cumsum(startidx, N...) map((o, n) -> o:o+n-1, offs, N) diff --git a/src/static.jl b/src/static.jl new file mode 100644 index 00000000..d73b7673 --- /dev/null +++ b/src/static.jl @@ -0,0 +1,62 @@ +""" + MeasureBase.IntegerLike + +Equivalent to `Union{Integer,Static.StaticInt}`. +""" +const IntegerLike = Union{Integer,Static.StaticInt} + + +""" + MeasureBase.one_to(n::IntegerLike) + +Creates a range from one to n. + +Returns an instance of `Base.OneTo` or `Static.SOneTo`, depending +on the type of `n`. +""" +@inline one_to(n::Integer) = Base.OneTo(n) +@inline one_to(::Static.StaticInt{N}) where N = Static.SOneTo{N}() + + +_dynamic(x::Number) = dynamic(x) +_dynamic(::Static.SOneTo{N}) where N = Base.OneTo(N) +_dynamic(r::AbstractUnitRange) = minimum(r):maximum(r) + + +""" + MeasureBase.fill_with(x, sz::NTuple{N,<:IntegerLike}) where N + +Creates an array of size `sz` filled with `x`. + +Returns an instance of `FillArrays.Fill`. +""" +function fill_with end + +@inline fill_with(x::T, sz::Tuple{Vararg{<:IntegerLike,N}}) where {T,N} = fill_with(x, map(one_to, sz)) + +@inline function fill_with(x::T, axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where {T,N} + # While `FillArrays.Fill` (mostly?) works with axes that are static unit + # ranges, some operations that automatic differentiation requires do fail + # on such instances of `Fill` (e.g. `reshape` from dynamic to static size). + # So need to use standard ranges for the axes for now: + dyn_axs = map(_dynamic, axs) + FillArrays.Fill(x, dyn_axs) +end + + +""" + MeasureBase.dslength(x)::IntegerLike + +Returns the length of `x` as a dynamic or static integer. +""" +dslength(x) = length(x) +dslength(x::AbstractUnitRange) = length(x) +dslength(::Static.OptionallyStaticUnitRange{StaticInt{A}, StaticInt{B}}) where {A,B} = StaticInt{B - A + 1}() + + +""" + MeasureBase.dssize(x)::Tuple{Vararg{IntegerLike}} + +Returns the size of `x` as a tuple of dynamic or static integers. +""" +dssize(x) = size(x) diff --git a/test/transport.jl b/test/transport.jl index 874cb88b..b71314de 100644 --- a/test/transport.jl +++ b/test/transport.jl @@ -8,7 +8,7 @@ using LogExpFunctions: logit using ChainRulesTestUtils @testset "transport_to" begin - test_rrule(MeasureBase._origin_depth, pushfwd(exp, StdUniform())) + test_rrule(MeasureBase._origin_depth, pushfwd(exp, StdUniform()), output_tangent = static(0)) for (f, μ) in [ (logit, StdUniform()) From 6cf96e52ba5cfc03546b196d2c304790e1a35e32 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Tue, 30 May 2023 14:29:37 +0200 Subject: [PATCH 3/6] Increase package version to v0.14.6 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 25707bb7..d7a2d510 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "MeasureBase" uuid = "fa1605e6-acd5-459c-a1e6-7e635759db14" authors = ["Chad Scherrer and contributors"] -version = "0.14.5" +version = "0.14.6" [deps] ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" From 165708f6ce0b7dd1d46bcb17a7871ef334bc7fa8 Mon Sep 17 00:00:00 2001 From: Chad Scherrer Date: Tue, 30 May 2023 06:56:21 -0700 Subject: [PATCH 4/6] format --- src/combinators/power.jl | 14 ++++++-------- src/static.jl | 17 ++++++++--------- test/transport.jl | 6 +++++- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/combinators/power.jl b/src/combinators/power.jl index 01bae72f..a66355bc 100644 --- a/src/combinators/power.jl +++ b/src/combinators/power.jl @@ -29,7 +29,9 @@ end # ToDo: Make rand return static arrays for statically-sized power measures. -_cartidxs(axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where {N} = CartesianIndices(map(_dynamic, axs)) +function _cartidxs(axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where {N} + CartesianIndices(map(_dynamic, axs)) +end function Base.rand( rng::AbstractRNG, @@ -47,14 +49,13 @@ function Base.rand(rng::AbstractRNG, ::Type{T}, d::PowerMeasure) where {T} end end -@inline _pm_axes(sz::Tuple{Vararg{<:IntegerLike,N}}) where N = map(one_to, sz) -@inline _pm_axes(axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where N = axs +@inline _pm_axes(sz::Tuple{Vararg{<:IntegerLike,N}}) where {N} = map(one_to, sz) +@inline _pm_axes(axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where {N} = axs @inline function powermeasure(x::T, sz::Tuple{Vararg{<:Any,N}}) where {T,N} PowerMeasure(x, _pm_axes(sz)) end - marginals(d::PowerMeasure) = fill_with(d.parent, d.axes) function Base.:^(μ::AbstractMeasure, dims::Tuple{Vararg{<:AbstractArray,N}}) where {N} @@ -84,10 +85,7 @@ end end end -@inline function logdensity_def( - d::PowerMeasure{M,Tuple{Static.SOneTo{N}}}, - x, -) where {M,N} +@inline function logdensity_def(d::PowerMeasure{M,Tuple{Static.SOneTo{N}}}, x) where {M,N} parent = d.parent sum(1:N) do j @inbounds logdensity_def(parent, x[j]) diff --git a/src/static.jl b/src/static.jl index d73b7673..25eafb3f 100644 --- a/src/static.jl +++ b/src/static.jl @@ -5,7 +5,6 @@ Equivalent to `Union{Integer,Static.StaticInt}`. """ const IntegerLike = Union{Integer,Static.StaticInt} - """ MeasureBase.one_to(n::IntegerLike) @@ -15,14 +14,12 @@ Returns an instance of `Base.OneTo` or `Static.SOneTo`, depending on the type of `n`. """ @inline one_to(n::Integer) = Base.OneTo(n) -@inline one_to(::Static.StaticInt{N}) where N = Static.SOneTo{N}() - +@inline one_to(::Static.StaticInt{N}) where {N} = Static.SOneTo{N}() _dynamic(x::Number) = dynamic(x) -_dynamic(::Static.SOneTo{N}) where N = Base.OneTo(N) +_dynamic(::Static.SOneTo{N}) where {N} = Base.OneTo(N) _dynamic(r::AbstractUnitRange) = minimum(r):maximum(r) - """ MeasureBase.fill_with(x, sz::NTuple{N,<:IntegerLike}) where N @@ -32,7 +29,9 @@ Returns an instance of `FillArrays.Fill`. """ function fill_with end -@inline fill_with(x::T, sz::Tuple{Vararg{<:IntegerLike,N}}) where {T,N} = fill_with(x, map(one_to, sz)) +@inline function fill_with(x::T, sz::Tuple{Vararg{<:IntegerLike,N}}) where {T,N} + fill_with(x, map(one_to, sz)) +end @inline function fill_with(x::T, axs::Tuple{Vararg{<:AbstractUnitRange,N}}) where {T,N} # While `FillArrays.Fill` (mostly?) works with axes that are static unit @@ -43,7 +42,6 @@ function fill_with end FillArrays.Fill(x, dyn_axs) end - """ MeasureBase.dslength(x)::IntegerLike @@ -51,8 +49,9 @@ Returns the length of `x` as a dynamic or static integer. """ dslength(x) = length(x) dslength(x::AbstractUnitRange) = length(x) -dslength(::Static.OptionallyStaticUnitRange{StaticInt{A}, StaticInt{B}}) where {A,B} = StaticInt{B - A + 1}() - +function dslength(::Static.OptionallyStaticUnitRange{StaticInt{A},StaticInt{B}}) where {A,B} + StaticInt{B - A + 1}() +end """ MeasureBase.dssize(x)::Tuple{Vararg{IntegerLike}} diff --git a/test/transport.jl b/test/transport.jl index b71314de..34359784 100644 --- a/test/transport.jl +++ b/test/transport.jl @@ -8,7 +8,11 @@ using LogExpFunctions: logit using ChainRulesTestUtils @testset "transport_to" begin - test_rrule(MeasureBase._origin_depth, pushfwd(exp, StdUniform()), output_tangent = static(0)) + test_rrule( + MeasureBase._origin_depth, + pushfwd(exp, StdUniform()), + output_tangent = static(0), + ) for (f, μ) in [ (logit, StdUniform()) From 5fac9a8e669975c311063189380cf8d25b84a345 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Tue, 30 May 2023 15:58:29 +0200 Subject: [PATCH 5/6] Fix docstring for PowerMeasure Co-authored-by: Chad Scherrer --- src/combinators/power.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/combinators/power.jl b/src/combinators/power.jl index a66355bc..a66c769c 100644 --- a/src/combinators/power.jl +++ b/src/combinators/power.jl @@ -10,7 +10,7 @@ the product determines the dimensionality of the resulting support. Note that power measures are only well-defined for integer powers. -The nth power of a measure μ can be written μ^x. +The nth power of a measure μ can be written μ^n. """ struct PowerMeasure{M,A} <: AbstractProductMeasure parent::M From 6b8d8bbf1547f876ceff68330b506c3c2fc3271e Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Tue, 30 May 2023 16:18:08 +0200 Subject: [PATCH 6/6] Rename dslength and dssize --- src/combinators/power.jl | 4 ++-- src/static.jl | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/combinators/power.jl b/src/combinators/power.jl index a66c769c..76cd4859 100644 --- a/src/combinators/power.jl +++ b/src/combinators/power.jl @@ -17,8 +17,8 @@ struct PowerMeasure{M,A} <: AbstractProductMeasure axes::A end -dslength(μ::PowerMeasure) = prod(dssize(μ)) -dssize(μ::PowerMeasure) = map(dslength, μ.axes) +maybestatic_length(μ::PowerMeasure) = prod(maybestatic_size(μ)) +maybestatic_size(μ::PowerMeasure) = map(maybestatic_length, μ.axes) function Pretty.tile(μ::PowerMeasure) sz = length.(μ.axes) diff --git a/src/static.jl b/src/static.jl index 25eafb3f..b3a09dc5 100644 --- a/src/static.jl +++ b/src/static.jl @@ -43,19 +43,19 @@ end end """ - MeasureBase.dslength(x)::IntegerLike + MeasureBase.maybestatic_length(x)::IntegerLike Returns the length of `x` as a dynamic or static integer. """ -dslength(x) = length(x) -dslength(x::AbstractUnitRange) = length(x) -function dslength(::Static.OptionallyStaticUnitRange{StaticInt{A},StaticInt{B}}) where {A,B} +maybestatic_length(x) = length(x) +maybestatic_length(x::AbstractUnitRange) = length(x) +function maybestatic_length(::Static.OptionallyStaticUnitRange{StaticInt{A},StaticInt{B}}) where {A,B} StaticInt{B - A + 1}() end """ - MeasureBase.dssize(x)::Tuple{Vararg{IntegerLike}} + MeasureBase.maybestatic_size(x)::Tuple{Vararg{IntegerLike}} Returns the size of `x` as a tuple of dynamic or static integers. """ -dssize(x) = size(x) +maybestatic_size(x) = size(x)