text:
const MYID = myid()
const OTHERIDS = filter(id-> id != MYID, procs())[rand(1:(nprocs()-1))]

function check_leaks()
    if length(DistributedArrays.refs) > 0
        sleep(0.1)  # allow time for any cleanup to complete and test again
        length(DistributedArrays.refs) > 0 && warn("Probable leak of ", length(DistributedArrays.refs), " darrays")
    end
end

facts("test distribute") do
    A = randn(100,100)

    context("test default distribute") do
        DA = distribute(A)
        @fact length(procs(DA)) --> nworkers()
        close(DA)
    end

    context("test distribute with procs arguments") do
        DA = distribute(A, procs = [1, 2])
        @fact length(procs(DA)) --> 2
        close(DA)
    end

    context("test distribute with procs and dist arguments") do
        DA = distribute(A, procs = [1, 2], dist = [1,2])
        @fact size(procs(DA)) --> (1,2)
        close(DA)
    end
end

check_leaks()

facts("test DArray equality") do
    D = drand((200,200), [MYID, OTHERIDS])
    DC = copy(D)

    context("test isequal(::Array, ::DArray)") do
        @fact D == DC --> true
    end

    context("test copy(::DArray) does a copy of each localpart") do
        @spawnat OTHERIDS localpart(DC)[1] = 0
        @fact fetch(@spawnat OTHERIDS localpart(D)[1] != 0) --> true
    end

    close(D)
    close(DC)
end

check_leaks()

facts("test @DArray comprehension constructor") do

    context("test valid use of @DArray") do
        D = @DArray [i+j for i=1:10, j=1:10]
        @fact D --> [i+j for i=1:10, j=1:10]
        close(D)
    end

    context("test invalid use of @DArray") do
        @fact_throws ArgumentError eval(:((@DArray [1,2,3,4])))
    end
end

check_leaks()

facts("test DArray / Array conversion") do
    D = drand((200,200), [MYID, OTHERIDS])

    context("test convert(::Array, ::(Sub)DArray)") do
        S = convert(Matrix{Float64}, D[1:150, 1:150])
        A = convert(Matrix{Float64}, D)

        @fact A[1:150,1:150] --> S
        D2 = convert(DArray{Float64,2,Matrix{Float64}}, A)
        @fact D2 --> D
        @fact fetch(@spawnat MYID localpart(D)[1,1]) --> D[1,1]
        @fact fetch(@spawnat OTHERIDS localpart(D)[1,1]) --> D[1,101]
        close(D2)
    end
    close(D)
end

check_leaks()

facts("test DArray reduce") do
    D = DArray(id->fill(myid(), map(length,id)), (10,10), [MYID, OTHERIDS])

    context("test reduce") do
        @fact reduce(+, D) --> ((50*MYID) + (50*OTHERIDS))
    end

    context("test map / reduce") do
        D2 = map(x->1, D)
        @fact reduce(+, D2) --> 100
        close(D2)
    end

    context("test map! / reduce") do
        map!(x->1, D)
        @fact reduce(+, D) --> 100
    end
    close(D)
end

check_leaks()

facts("test scale") do
    A = randn(100,100)
    DA = distribute(A)
    @fact scale!(DA, 2) --> scale!(A, 2)
    close(DA)
end

check_leaks()

facts("test mapreduce on DArrays") do
    # temporaroly reduce to three iterations because of https://github.com/JuliaLang/julia/issues/15766
    # for _ = 1:25, f = [x -> Int128(2x), x -> Int128(x^2), x -> Int128(x^2 + 2x - 1)], opt = [+, *]
    for _ = 1:3, f = [x -> Int128(2x), x -> Int128(x^2), x -> Int128(x^2 + 2x - 1)], opt = [+, *]
        A = rand(1:5, rand(2:30))
        DA = distribute(A)
        @fact mapreduce(f, opt, DA) - mapreduce(f, opt, A) == 0 --> true
        close(DA)
    end
end

check_leaks()

facts("test mapreducedim on DArrays") do
    D = DArray(I->fill(myid(), map(length,I)), (73,73), [MYID, OTHERIDS])
    D2 = map(x->1, D)
    @fact mapreducedim(t -> t*t, +, D2, 1) --> mapreducedim(t -> t*t, +, convert(Array, D2), 1)
    @fact mapreducedim(t -> t*t, +, D2, 2) --> mapreducedim(t -> t*t, +, convert(Array, D2), 2)
    @fact mapreducedim(t -> t*t, +, D2, (1,2)) --> mapreducedim(t -> t*t, +, convert(Array, D2), (1,2))

    close(D)
    close(D2)
    darray_closeall()   # temp created by the mapreduce above
end

check_leaks()

facts("test mapreducdim, reducedim on DArrays") do
    dims = (20,20,20)
    DA = drandn(dims)
    A = convert(Array, DA)

    for dms in (1, 2, 3, (1,2), (1,3), (2,3), (1,2,3))
        @fact mapreducedim(t -> t*t, +, DA, dms) --> roughly(mapreducedim(t -> t*t, +, A, dms))
        @fact mapreducedim(t -> t*t, +, DA, dms, 1.0) --> roughly(mapreducedim(t -> t*t, +, A, dms, 1.0))
        @fact reducedim(*, DA, dms) --> roughly(reducedim(*, A, dms))
        @fact reducedim(*, DA, dms, 2.0) --> roughly(reducedim(*, A, dms, 2.0))
    end
    close(DA)
    darray_closeall()   # temp created by the mapreduce above
end

check_leaks()

facts("test statistical functions on DArrays") do
    dims = (20,20,20)
    DA = drandn(dims)
    A = convert(Array, DA)

    context("test mean") do
        for dms in (1, 2, 3, (1,2), (1,3), (2,3), (1,2,3))
            @fact mean(DA,dms) --> roughly(mean(A,dms), atol=1e-12)
        end
    end

    context("test std") do
        for dms in (1, 2, 3, (1,2), (1,3), (2,3), (1,2,3))
            @pending std(DA,dms) --> roughly(std(A,dms), atol=1e-12)
        end
    end
    close(DA)
    darray_closeall()   # temporaries created above
end

check_leaks()

facts("test sum on DArrays") do
    A = randn(100,100)
    DA = distribute(A)

    @fact_throws ArgumentError sum(DA,-1)
    @fact_throws ArgumentError sum(DA, 0)

    @fact sum(DA) --> roughly(sum(A), atol=1e-12)
    @fact sum(DA,1) --> roughly(sum(A,1), atol=1e-12)
    @fact sum(DA,2) --> roughly(sum(A,2), atol=1e-12)
    @fact sum(DA,3) --> roughly(sum(A,3), atol=1e-12)
    close(DA)
    darray_closeall()   # temporaries created above
end

check_leaks()

facts("test size on DArrays") do
    A = randn(100,100)
    DA = distribute(A)

    @fact_throws size(DA, 0) # BoundsError
    @fact size(DA,1) --> size(A,1)
    @fact size(DA,2) --> size(A,2)
    @fact size(DA,3) --> size(A,3)
    close(DA)
end

check_leaks()

# test length / endof
facts("test collections API") do
    A = randn(23,23)
    DA = distribute(A)

    context("test length") do
        @fact length(DA) --> length(A)
    end

    context("test endof") do
        @fact endof(DA) --> endof(A)
    end
    close(DA)
end

check_leaks()

facts("test max / min / sum") do
    a = map(x->Int(round(rand() * 100)) - 50, Array(Int, 100,1000))
    d = distribute(a)

    @fact sum(d) --> sum(a)
    @fact maximum(d) --> maximum(a)
    @fact minimum(d) --> minimum(a)
    @fact maxabs(d) --> maxabs(a)
    @fact minabs(d) --> minabs(a)
    @fact sumabs(d) --> sumabs(a)
    @fact sumabs2(d) --> sumabs2(a)
    close(d)
end

check_leaks()

facts("test all / any") do
    a = map(x->Int(round(rand() * 100)) - 50, Array(Int, 100,1000))
    a = [true for i in 1:100]
    d = distribute(a)

    @fact all(d) --> true
    @fact any(d) --> true

    close(d)

    a[50] = false
    d = distribute(a)
    @fact all(d) --> false
    @fact any(d) --> true

    close(d)

    a = [false for i in 1:100]
    d = distribute(a)
    @fact all(d) --> false
    @fact any(d) --> false

    close(d)

    d = dones(10,10)
    @fact all(x-> x>1.0, d) --> false
    @fact all(x-> x>0.0, d) --> true

    close(d)

    a = ones(10,10)
    a[10] = 2.0
    d = distribute(a)
    @fact any(x-> x == 1.0, d) --> true
    @fact any(x-> x == 2.0, d) --> true
    @fact any(x-> x == 3.0, d) --> false

    close(d)
end

check_leaks()

facts("test count" ) do
    a = ones(10,10)
    a[10] = 2.0
    d = distribute(a)

    @fact count(x-> x == 2.0, d) --> 1
    @fact count(x-> x == 1.0, d) --> 99
    @fact count(x-> x == 0.0, d) --> 0

    close(d)
end

check_leaks()

facts("test prod") do
    a = fill(2, 10);
    d = distribute(a);
    @fact prod(d) --> 2^10

    close(d)
end

check_leaks()

facts("test zeros") do
    context("1D dzeros default element type") do
        A = dzeros(10)
        @fact A --> zeros(10)
        @fact eltype(A) --> Float64
        @fact size(A) --> (10,)
        close(A)
    end

    context("1D dzeros with specified element type") do
        A = dzeros(Int, 10)
        @fact A --> zeros(10)
        @fact eltype(A) --> Int
        @fact size(A) --> (10,)
        close(A)
    end

    context("2D dzeros default element type, Dims constuctor") do
        A = dzeros((10,10))
        @fact A --> zeros((10,10))
        @fact eltype(A) --> Float64
        @fact size(A) --> (10,10)
        close(A)
    end

    context("2D dzeros specified element type, Dims constructor") do
        A = dzeros(Int, (10,10))
        @fact A --> zeros(Int, (10,10))
        @fact eltype(A) --> Int
        @fact size(A) --> (10,10)
        close(A)
    end

    context("2D dzeros, default element type") do
        A = dzeros(10,10)
        @fact A --> zeros(10,10)
        @fact eltype(A) --> Float64
        @fact size(A) --> (10,10)
        close(A)
    end

    context("2D dzeros, specified element type") do
        A = dzeros(Int, 10, 10)
        @fact A --> zeros(Int, 10, 10)
        @fact eltype(A) --> Int
        @fact size(A) --> (10,10)
        close(A)
    end
end

check_leaks()

facts("test dones") do
    context("1D dones default element type") do
        A = dones(10)
        @fact A --> ones(10)
        @fact eltype(A) --> Float64
        @fact size(A) --> (10,)
        close(A)
    end

    context("1D dones with specified element type") do
        A = dones(Int, 10)
        @fact eltype(A) --> Int
        @fact size(A) --> (10,)
        close(A)
    end

    context("2D dones default element type, Dims constuctor") do
        A = dones((10,10))
        @fact A --> ones((10,10))
        @fact eltype(A) --> Float64
        @fact size(A) --> (10,10)
        close(A)
    end

    context("2D dones specified element type, Dims constructor") do
        A = dones(Int, (10,10))
        @fact A --> ones(Int, (10,10))
        @fact eltype(A) --> Int
        @fact size(A) --> (10,10)
        close(A)
    end

    context("2D dones, default element type") do
        A = dones(10,10)
        @fact A --> ones(10,10)
        @fact eltype(A) --> Float64
        @fact size(A) --> (10,10)
        close(A)
    end

    context("2D dones, specified element type") do
        A = dones(Int, 10, 10)
        @fact A --> ones(Int, 10, 10)
        @fact eltype(A) --> Int
        @fact size(A) --> (10,10)
        close(A)
    end
end

check_leaks()

facts("test drand") do
    context("1D drand") do
        A = drand(100)
        @fact eltype(A) --> Float64
        @fact size(A) --> (100,)
        @fact all(x-> x >= 0.0 && x <= 1.0, A) --> true
        close(A)
    end

    context("1D drand, specified element type") do
        A = drand(Int, 100)
        @fact eltype(A) --> Int
        @fact size(A) --> (100,)
        close(A)
    end

    context("2D drand, Dims constructor") do
        A = drand((50,50))
        @fact eltype(A) --> Float64
        @fact size(A) --> (50,50)
        @fact all(x-> x >= 0.0 && x <= 1.0, A) --> true
        close(A)
    end

    context("2D drand") do
        A = drand(100,100)
        @fact eltype(A) --> Float64
        @fact size(A) --> (100,100)
        @fact all(x-> x >= 0.0 && x <= 1.0, A) --> true
        close(A)
    end

    context("2D drand, Dims constructor, specified element type") do
        A = drand(Int, (100,100))
        @fact eltype(A) --> Int
        @fact size(A) --> (100,100)
        close(A)
    end

    context("2D drand, specified element type") do
        A = drand(Int, 100, 100)
        @fact eltype(A) --> Int
        @fact size(A) --> (100,100)
        close(A)
    end
end

check_leaks()

facts("test randn") do
    context("1D drandn") do
        A = drandn(100)
        @fact eltype(A) --> Float64
        @fact size(A) --> (100,)
        close(A)
    end

    context("2D drandn, Dims constructor") do
        A = drandn((50,50))
        @fact eltype(A) --> Float64
        @fact size(A) --> (50,50)
        close(A)
    end

    context("2D drandn") do
        A = drandn(100,100)
        @fact eltype(A) --> Float64
        @fact size(A) --> (100,100)
        close(A)
    end
end

check_leaks()

facts("test c/transpose") do
    context("test ctranspose real") do
        A = drand(Float64, 100, 200)
        @fact A' --> Array(A)'
        close(A)
    end
    context("test ctranspose complex") do
        A = drand(Complex128, 200, 100)
        @fact A' --> Array(A)'
        close(A)
    end
    context("test transpose real") do
        A = drand(Float64, 200, 100)
        @fact A.' --> Array(A).'
        close(A)
    end
    context("test ctranspose complex") do
        A = drand(Complex128, 100, 200)
        @fact A.' --> Array(A).'
        close(A)
    end

    darray_closeall()  # close the temporaries created above
end

check_leaks()

facts("test convert from subdarray") do
    a = drand(20, 20);

    s = sub(a, 1:5, 5:8)
    @fact isa(s, SubDArray) --> true
    @fact s --> convert(DArray, s)

    s = sub(a, 6:5, 5:8)
    @fact isa(s, SubDArray) --> true
    @fact s --> convert(DArray, s)
    close(a)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

facts("test scalar math") do
    a = drand(20, 20);
    b = convert(Array, a)
    for f in (:abs, :abs2, :acos, :acosd, :acot,
              :acotd, :acsch, :angle, :asech, :asin,
              :asind, :asinh, :atan, :atand, :atanh,
              :big, :cbrt, :ceil, :cis, :complex, :conj,
              :cos, :cosc, :cosd, :cosh, :cospi, :cot,
              :cotd, :coth, :csc, :cscd, :csch, :dawson,
              :deg2rad, :digamma, :erf, :erfc, :erfcinv,
              :erfcx, :erfi, :erfinv, :exp, :exp10, :exp2,
              :expm1, :exponent, :float, :floor, :gamma, :imag,
              :invdigamma, :isfinite, :isinf, :isnan, :lfact,
              :lgamma, :log, :log10, :log1p, :log2, :rad2deg, :real,
              :sec, :secd, :sech, :sign, :sin, :sinc, :sind,
              :sinh, :sinpi, :sqrt, :tan, :tand, :tanh, :trigamma)
        context("$f") do
            @fact (eval(f))(a) --> (eval(f))(b)
        end
    end
    a = a + 1
    b = b + 1
    for f in (:asec, :asecd, :acosh, :acsc, :acscd, :acoth)
        context("$f") do
            @fact (eval(f))(a) --> (eval(f))(b)
        end
    end
    close(a)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

# The mapslices tests have been taken from Base.
# Commented out tests that need to be enabled in due course when DArray support is more complete
facts("test mapslices") do
    a = drand((5,5), workers(), [1, min(nworkers(), 5)])
    if VERSION < v"0.5.0-dev+4361"
        h = mapslices(v -> hist(v,0:0.1:1)[2], a, 1)
    else
        h = mapslices(v -> fit(Histogram,v,0:0.1:1).weights, a, 1)
    end
#    H = mapslices(v -> hist(v,0:0.1:1)[2], a, 2)
#    s = mapslices(sort, a, [1])
#    S = mapslices(sort, a, [2])
    for i = 1:5
        if VERSION < v"0.5.0-dev+4361"
            @fact h[:,i] --> hist(a[:,i],0:0.1:1)[2]
        else
            @fact h[:,i] --> fit(Histogram, a[:,i],0:0.1:1).weights
        end
#        @fact vec(H[i,:]) => hist(vec(a[i,:]),0:0.1:1)[2]
#        @fact s[:,i] => sort(a[:,i])
#        @fact vec(S[i,:]) => sort(vec(a[i,:]))
    end

    # issue #3613
    b = mapslices(sum, dones(Float64, (2,3,4), workers(), [1,1,min(nworkers(),4)]), [1,2])
    @fact size(b) --> exactly((1,1,4))
    @fact all(b.==6) --> true

    # issue #5141
    ## Update Removed the version that removes the dimensions when dims==1:ndims(A)
    c1 = mapslices(x-> maximum(-x), a, [])
#    @fact c1 => -a

    # issue #5177
    c = dones(Float64, (2,3,4,5), workers(), [1,1,1,min(nworkers(),5)])
    m1 = mapslices(x-> ones(2,3), c, [1,2])
    m2 = mapslices(x-> ones(2,4), c, [1,3])
    m3 = mapslices(x-> ones(3,4), c, [2,3])
    @fact size(m1) == size(m2) == size(m3) == size(c) --> true

    n1 = mapslices(x-> ones(6), c, [1,2])
    n2 = mapslices(x-> ones(6), c, [1,3])
    n3 = mapslices(x-> ones(6), c, [2,3])
    n1a = mapslices(x-> ones(1,6), c, [1,2])
    n2a = mapslices(x-> ones(1,6), c, [1,3])
    n3a = mapslices(x-> ones(1,6), c, [2,3])
    @fact (size(n1a) == (1,6,4,5) && size(n2a) == (1,3,6,5) && size(n3a) == (2,1,6,5)) --> true
    @fact (size(n1) == (6,1,4,5) && size(n2) == (6,3,1,5) && size(n3) == (2,6,1,5)) --> true
    close(a)
    close(c)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

facts("test scalar ops") do
    a = drand(20,20)
    b = convert(Array, a)
    c = drand(20,20)
    d = convert(Array, c)

    for f in (:+, :-, :.+, :.-, :.*, :./, :.%, :div, :mod)
        context("$f") do
            x = rand()
            @fact (eval(f))(a, x) --> (eval(f))(b, x)
            @fact (eval(f))(x, a) --> (eval(f))(x, b)
            @fact (eval(f))(a, c) --> (eval(f))(b, d)
        end
    end

    close(a)
    close(c)

    a = dones(Int, 20, 20)
    b = convert(Array, a)
    for f in (:.<<, :.>>)
        context("$f") do
            @fact (eval(f))(a, 2) --> (eval(f))(b, 2)
            @fact (eval(f))(2, a) --> (eval(f))(2, b)
            @fact (eval(f))(a, a) --> (eval(f))(b, b)
        end
    end

    for f in (:rem,)
        context("$f") do
            x = rand()
            @fact (eval(f))(a, x) --> (eval(f))(b, x)
        end
    end
    close(a)
    close(c)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

facts("test broadcast ops") do
    wrkrs = workers()
    nwrkrs = length(wrkrs)
    nrows = 20 * nwrkrs
    ncols = 10 * nwrkrs
    a = drand((nrows,ncols), wrkrs, (1, nwrkrs))
    m = mean(a, 1)
    c = a .- m
    d = convert(Array, a) .- convert(Array, m)
    @fact c --> d
    darray_closeall()
end

check_leaks()

facts("test matrix multiplication") do
    A = drandn(20,20)
    b = drandn(20)
    B = drandn(20,20)

    @fact norm(convert(Array, A*b) - convert(Array, A)*convert(Array, b), Inf) --> less_than(sqrt(eps()))
    @fact norm(convert(Array, A*B) - convert(Array, A)*convert(Array, B), Inf) -->  less_than(sqrt(eps()))
    @fact norm(convert(Array, A'*b) - convert(Array, A)'*convert(Array, b), Inf) --> less_than(sqrt(eps()))
    @fact norm(convert(Array, A'*B) - convert(Array, A)'*convert(Array, B), Inf) --> less_than(sqrt(eps()))
    close(A)
    close(b)
    close(B)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

facts("test norm") do
    x = drandn(20)

    @fact abs(norm(x) - norm(convert(Array, x))) --> less_than(sqrt(eps()))
    @fact abs(norm(x, 1) - norm(convert(Array, x), 1)) --> less_than(sqrt(eps()))
    @fact abs(norm(x, 2) - norm(convert(Array, x), 2)) --> less_than(sqrt(eps()))
    @fact abs(norm(x, Inf) - norm(convert(Array, x), Inf)) --> less_than(sqrt(eps()))
    close(x)
end

check_leaks()

facts("test axpy!") do
    x = drandn(20)
    y = drandn(20)

    @fact norm(convert(Array, LinAlg.axpy!(2.0, x, copy(y))) - LinAlg.axpy!(2.0, convert(Array, x), convert(Array, y))) --> less_than(sqrt(eps()))
    @fact_throws LinAlg.axpy!(2.0, x, zeros(length(x) + 1)) DimensionMismatch
    close(x)
    close(y)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

facts("test ppeval") do
    A = drandn((10, 10, nworkers()), workers(), [1, 1, nworkers()])
    B = drandn((10, nworkers()), workers(), [1, nworkers()])

    R = zeros(10, nworkers())
    for i = 1:nworkers()
        R[:, i] = convert(Array, A)[:, :, i]*convert(Array, B)[:, i]
    end
    @fact convert(Array, ppeval(*, A, B)) --> roughly(R)
    @fact sum(ppeval(eigvals, A)) --> roughly(sum(ppeval(eigvals, A, eye(10, 10))))
    close(A)
    close(B)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

facts("test nnz") do
    A = sprandn(10, 10, 0.5)
    @fact nnz(distribute(A)) --> nnz(A)
end

facts("test matmatmul") do
    A = drandn(30, 30)
    B = drandn(30, 20)
    a = convert(Array, A)
    b = convert(Array, B)

    AB = A * B
    AtB = A.' * B
    AcB = A' * B

    ab = a * b
    atb = a.' * b
    acb = a' * b

    @fact AB --> roughly(ab)
    @fact AtB --> roughly(atb)
    @fact AcB --> roughly(acb)
    darray_closeall()  # close the temporaries created above
end

check_leaks()

darray_closeall()

facts("test for any leaks") do
    sleep(1.0)     # allow time for any cleanup to complete
    allrefszero = Bool[remotecall_fetch(()->length(DistributedArrays.refs) == 0, p) for p in procs()]
    @fact all(allrefszero) --> true

    allregistrieszero = Bool[remotecall_fetch(()->length(DistributedArrays.registry) == 0, p) for p in procs()]
    @fact all(allregistrieszero) --> true
end


text:
using Test, LightGraphs, LightGraphsIO

@test_broken 1 == 2

ext: jl


text:
"""
    @audit expr -> Tuple{Any,Expr}

Evaluate the expression and return both the result and the original expression. Useful for
ensuring that the provided expression is syntactically valid. If provided expression cannot
be evaluated the exception will be returned instead of the result.
"""
macro audit(expr::Expr)
    result = quote
        tuple(
            try
                @eval let
                    $expr
                end
            catch e
                e
            end,
            $(QuoteNode(expr)),
        )
    end
    return esc(result)
end

macro expr(expr::Expr)
    esc(QuoteNode(expr))
end

function strip_lineno!(expr::Expr)
    filter!(expr.args) do ex
        isa(ex, LineNumberNode) && return false
        if isa(ex, Expr)
            ex.head === :line && return false
            strip_lineno!(ex::Expr)
        end
        return true
    end
    return expr
end

macro test_splitdef_invalid(expr)
    result = quote
        @test_throws ArgumentError splitdef($expr)
        @test splitdef($expr, throw=false) === nothing
    end
    return esc(result)
end

function_form(short::Bool) = string(short ? "short" : "long", "-form")

@testset "splitdef / combinedef" begin
    @testset "empty function" begin
        f, expr = @audit function f end
        @test length(methods(f)) == 0

        d = splitdef(expr)
        @test keys(d) == Set([:head, :name])
        @test d[:head] == :function
        @test d[:name] == :f

        c_expr = combinedef(d)
        @test c_expr == expr
    end

    @testset "long-form function" begin
        f, expr = @audit function f() end
        @test length(methods(f)) == 1
        @test f() === nothing

        d = splitdef(expr)
        @test keys(d) == Set([:head, :name, :body])
        @test d[:head] == :function
        @test d[:name] == :f
        @test strip_lineno!(d[:body]) == Expr(:block)

        c_expr = combinedef(d)
        @test c_expr == expr
    end

    @testset "short-form function" begin
        f, expr = @audit f() = nothing
        @test length(methods(f)) == 1
        @test f() === nothing

        d = splitdef(expr)
        @test keys(d) == Set([:head, :name, :body])
        @test d[:head] == :(=)
        @test d[:name] == :f
        @test strip_lineno!(d[:body]) == Expr(:block, :nothing)

        c_expr = combinedef(d)
        @test c_expr == expr
    end

    @testset "long-form anonymous function" begin
        f, expr = @audit function () end
        @test length(methods(f)) == 1
        @test f() === nothing

        d = splitdef(expr)
        @test keys(d) == Set([:head, :body])
        @test d[:head] == :function
        @test strip_lineno!(d[:body]) == Expr(:block)

        c_expr = combinedef(d)
        @test c_expr == expr
    end

    @testset "short-form anonymous function" begin
        f, expr = @audit () -> nothing
        @test length(methods(f)) == 1
        @test f() === nothing

        d = splitdef(expr)
        @test keys(d) == Set([:head, :body])
        @test d[:head] == :(->)
        @test strip_lineno!(d[:body]) == Expr(:block, :nothing)

        c_expr = combinedef(d)
        @test c_expr == expr
    end

    @testset "args ($(function_form(short)) function)" for short in (true, false)
        @testset "f(x)" begin
            f, expr = if short
                @audit f(x) = x
            else
                @audit function f(x) x end
            end
            @test length(methods(f)) == 1
            @test f(0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :body])
            @test d[:args] == [:x]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "f(x::Integer)" begin
            f, expr = if short
                @audit f(x::Integer) = x
            else
                @audit function f(x::Integer) x end
            end
            @test length(methods(f)) == 1
            @test f(0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :body])
            @test d[:args] == [:(x::Integer)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "f(x=1)" begin
            f, expr = if short
                @audit f(x=1) = x
            else
                @audit function f(x=1) x end
            end
            @test length(methods(f)) == 2
            @test f(0) == 0
            @test f() == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :body])
            @test d[:args] == [Expr(:kw, :x, 1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "f(x::Integer=1)" begin
            f, expr = if short
                @audit f(x::Integer=1) = x
            else
                @audit function f(x::Integer=1) x end
            end
            @test length(methods(f)) == 2
            @test f(0) == 0
            @test f() == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :body])
            @test d[:args] == [Expr(:kw, :(x::Integer), 1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end
    end

    @testset "args ($(function_form(short)) anonymous function)" for short in (true, false)
        @testset "x" begin
            f, expr = if short
                @audit x -> x
            else
                @audit function (x) x end
            end
            @test length(methods(f)) == 1
            @test f(0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:x]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "x::Integer" begin
            f, expr = if short
                @audit x::Integer -> x
            else
                @audit function (x::Integer) x end
            end
            @test length(methods(f)) == 1
            @test f(0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:(x::Integer)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(x=1)" begin
            f, expr = if short
                @audit (x=1) -> x
            else
                @audit function (x=1) x end
            end
            @test length(methods(f)) == 2
            @test f(0) == 0
            @test f() == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:(x=1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(x::Integer=1)" begin
            f, expr = if short
                @audit (x::Integer=1) -> x
            else
                @audit function (x::Integer=1) x end
            end
            @test length(methods(f)) == 2
            @test f(0) == 0
            @test f() == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:(x::Integer=1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(x,)" begin
            f, expr = if short
                @audit (x,) -> x
            else
                @audit function (x,) x end
            end
            @test length(methods(f)) == 1
            @test f(0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:x]

            c_expr = combinedef(d)
            expr = short ? (@expr x -> x) : (@expr function (x) x end)
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end

        @testset "(x::Integer,)" begin
            f, expr = if short
                @audit (x::Integer,) -> x
            else
                @audit function (x::Integer,) x end
            end
            @test length(methods(f)) == 1
            @test f(0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:(x::Integer)]

            c_expr = combinedef(d)
            expr = short ? (@expr x::Integer -> x) : (@expr function (x::Integer) x end)
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end

        @testset "(x=1,)" begin
            f, expr = if short
                @audit (x=1,) -> x
            else
                @audit function (x=1,) x end
            end
            @test length(methods(f)) == 2
            @test f(0) === 0
            @test f() === 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:(x=1)]

            c_expr = combinedef(d)
            expr = short ? (@expr (x=1) -> x) : (@expr function (x=1) x end)
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end

        @testset "(x::Integer=1,)" begin
            f, expr = if short
                @audit (x::Integer=1,) -> x
            else
                @audit function (x::Integer=1,) x end
            end
            @test length(methods(f)) == 2
            @test f(0) == 0
            @test f() == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:(x::Integer=1)]

            c_expr = combinedef(d)
            expr = short ? (@expr (x::Integer=1) -> x) : (@expr function (x::Integer=1) x end)
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end
    end

    @testset "kwargs ($(function_form(short)) function)" for short in (true, false)
        @testset "f(; x)" begin
            f, expr = if short
                @audit f(; x) = x
            else
                @audit function f(; x) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :kwargs, :body])
            @test d[:kwargs] == [:x]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "f(; x::Integer)" begin
            f, expr = if short
                @audit f(; x::Integer) = x
            else
                @audit function f(; x::Integer) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :kwargs, :body])
            @test d[:kwargs] == [:(x::Integer)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "f(; x=1)" begin
            f, expr = if short
                @audit f(; x=1) = x
            else
                @audit function f(; x=1) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :kwargs, :body])
            @test d[:kwargs] == [Expr(:kw, :x, 1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "f(; x::Integer=1)" begin
            f, expr = if short
                @audit f(; x::Integer=1) = x
            else
                @audit function f(; x::Integer=1) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :kwargs, :body])
            @test d[:kwargs] == [Expr(:kw, :(x::Integer), 1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end
    end

    @testset "kwargs ($(function_form(short)) function)" for short in (true, false)
        @testset "(; x)" begin
            f, expr = if short
                @audit (; x) -> x
            else
                @audit function (; x) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :kwargs, :body])
            @test d[:kwargs] == [:x]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(; x::Integer)" begin
            f, expr = if short
                @audit (; x::Integer) -> x
            else
                @audit function (; x::Integer) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :kwargs, :body])
            @test d[:kwargs] == [:(x::Integer)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(; x=1)" begin
            f, expr = if short
                @audit (; x=1) -> x
            else
                @audit function (; x=1) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :kwargs, :body])
            @test d[:kwargs] == [Expr(:kw, :x, 1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(; x::Integer=1)" begin
            f, expr = if short
                @audit (; x::Integer=1) -> x
            else
                @audit function (; x::Integer=1) x end
            end
            @test length(methods(f)) == 1
            @test f(x=0) == 0

            d = splitdef(expr)
            @test keys(d) == Set([:head, :kwargs, :body])
            @test d[:kwargs] == [Expr(:kw, :(x::Integer), 1)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end
    end

    # When using :-> there are a few definitions that use a block expression instead of the
    # typical tuple.
    @testset "block expression ($(function_form(short)) anonymous function)" for short in (true, false)
        @testset "(;)" begin
            f, expr = if short
                @audit (;) -> nothing
            else
                @audit function (;) nothing end
            end
            @test length(methods(f)) == 1
            @test f() === nothing

            # Note: the semi-colon is missing from the expression
            d = splitdef(expr)
            @test keys(d) == Set([:head, :kwargs, :body])
            @test d[:kwargs] == []

            c_expr = combinedef(d)
            expr = Expr(:->, Expr(:tuple, Expr(:parameters)), Expr(:block, :nothing))
            expr.head = short ? :-> : :function
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end

        @testset "(x;)" begin
            f, expr = if short
                @audit (x;) -> x
            else
                @audit function (x;) x end
            end
            @test length(methods(f)) == 1
            @test f(0) == 0

            # Note: the semi-colon is missing from the expression
            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :kwargs, :body])
            @test d[:args] == [:x]
            @test d[:kwargs] == []

            c_expr = combinedef(d)
            expr = Expr(:->, Expr(:tuple, Expr(:parameters), :x), Expr(:block, :x))
            expr.head = short ? :-> : :function
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end

        @testset "(x; y)" begin
            f, expr = if short
                @audit (x; y) -> (x, y)
            else
                @audit function (x; y); (x, y) end
            end
            @test length(methods(f)) == 1
            @test f(0, y=1) == (0, 1)

            # Note: the semi-colon is missing from the expression
            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :kwargs, :body])
            @test d[:args] == [:x]
            @test d[:kwargs] == [:y]

            c_expr = combinedef(d)
            expr = Expr(:->, Expr(:tuple, Expr(:parameters, :y), :x), Expr(:block, :((x, y))))
            expr.head = short ? :-> : :function
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end

        @testset "Expr(:block, :x, :y)" begin
            expr = Expr(:->, Expr(:block, :x, :y), Expr(:block, :((x, y))))
            expr.head = short ? :-> : :function
            f = @eval $expr
            @test length(methods(f)) == 1
            @test f(0, y=1) == (0, 1)

            # Note: the semi-colon is missing from the expression
            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :kwargs, :body])
            @test d[:args] == [:x]
            @test d[:kwargs] == [:y]

            c_expr = combinedef(d)
            expr = Expr(:->, Expr(:tuple, Expr(:parameters, :y), :x), Expr(:block, :((x, y))))
            expr.head = short ? :-> : :function
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end
    end

    @testset "where ($(function_form(short)) function)" for short in (true, false)
        @testset "single where" begin
            f, expr = if short
                @audit f(::A) where A = nothing
            else
                @audit function f(::A) where A; nothing end
            end
            @test length(methods(f)) == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :whereparams, :body])
            @test d[:whereparams] == [:A]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "curly where" begin
            f, expr = if short
                @audit f(::A, ::B) where {A, B <: A} = nothing
            else
                @audit function f(::A, ::B) where {A, B <: A}; nothing end
            end
            @test length(methods(f)) == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :whereparams, :body])
            @test d[:whereparams] == [:A, :(B <: A)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "multiple where" begin
            f, expr = if short
                @audit f(::A, ::B) where B <: A where A = nothing
            else
                @audit function f(::A, ::B) where B <: A where A; nothing end
            end
            @test length(methods(f)) == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :whereparams, :body])
            @test d[:whereparams] == [:A, :(B <: A)]

            c_expr = combinedef(d)
            expr = @expr f(::A, ::B) where {A, B <: A} = nothing
            expr.head = short ? :(=) : :function
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end
    end

    @testset "where ($(function_form(short)) anonymous function)" for short in (true, false)
        @testset "where" begin
            f, expr = if short
                @audit ((::A) where A) -> nothing
            else
                @audit function (::A) where A; nothing end
            end
            @test length(methods(f)) == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :whereparams, :body])
            @test d[:whereparams] == [:A]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "curly where" begin
            f, expr = if short
                @audit ((::A, ::B) where {A, B <: A}) -> nothing
            else
                @audit function (::A, ::B) where {A, B <: A}; nothing end
            end
            @test length(methods(f)) == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :whereparams, :body])
            @test d[:whereparams] == [:A, :(B <: A)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "multiple where" begin
            f, expr = if short
                @audit ((::A, ::B) where B <: A where A) -> nothing
            else
                @audit function (::A, ::B) where B <: A where A; nothing end
            end
            @test length(methods(f)) == 1

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :whereparams, :body])
            @test d[:whereparams] == [:A, :(B <: A)]

            c_expr = combinedef(d)
            expr = @expr ((::A, ::B) where {A, B <: A}) -> nothing
            expr.head = short ? :-> : :function
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end
    end

    @testset "return-type ($(function_form(short)) function)" for short in (true, false)
        @testset "f(x)::Integer" begin
            f, expr = if short
                @audit f(x)::Integer = x
            else
                @audit function f(x)::Integer; x end
            end
            @test length(methods(f)) == 1
            @test f(0.0) isa Integer

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :rtype, :body])
            @test d[:rtype] == :Integer

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(f(x::T)::Integer) where T" begin
            f, expr = if short
                @audit (f(x::T)::Integer) where T = x
            else
                @audit function (f(x::T)::Integer) where T; x end
            end
            @test length(methods(f)) == 1
            @test f(0.0) isa Integer

            d = splitdef(expr)
            @test keys(d) == Set([:head, :name, :args, :rtype, :whereparams, :body])
            @test d[:rtype] == :Integer

            c_expr = combinedef(d)
            @test c_expr == expr
        end
    end

    @testset "return-type (short-form anonymous function)" begin
        @testset "(x,)::Integer" begin
            f, expr = @audit (x,)::Integer -> x  # Interpreted as `(x::Integer,) -> x`
            @test length(methods(f)) == 1
            @test f(0) == 0
            @test_throws MethodError f(0.0)

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:((x,)::Integer)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(((x::T,)::Integer) where T)" begin
            f, expr = @audit (((x::T,)::Integer) where T) -> x
            @test f isa ErrorException

            @test_broken splitdef(expr, throw=false) === nothing

            d = Dict(
                :head => :(->),
                :args => [:(x::T)],
                :rtype => :Integer,
                :whereparams => [:T],
                :body => quote
                    x
                end
            )
            c_expr = combinedef(d)
            expr = @expr (((x::T)::Integer) where T) -> x
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end
    end

    @testset "return-type (long-form anonymous function)" begin
        @testset "(x)::Integer" begin
            # Interpreted as `function (x::Integer); x end`
            f, expr = @audit function (x)::Integer; x end
            @test length(methods(f)) == 1
            @test f(0) == 0
            @test_throws MethodError f(0.0)

            d = splitdef(expr)
            @test keys(d) == Set([:head, :args, :body])
            @test d[:args] == [:(x::Integer)]

            c_expr = combinedef(d)
            @test c_expr == expr
        end

        @testset "(((x::T)::Integer) where T)" begin
            expr = Expr(:function,
                Expr(:where, Expr(:(::), Expr(:tuple, :(x::T)), :Integer), :T),
                Expr(:block, :x),
            )
            @test_throws ErrorException eval(expr)

            @test_broken splitdef(expr, throw=false) === nothing

            d = Dict(
                :head => :function,
                :args => [:(x::T)],
                :rtype => :Integer,
                :whereparams => [:T],
                :body => quote
                    x
                end
            )
            c_expr = combinedef(d)
            @test strip_lineno!(c_expr) == strip_lineno!(expr)
        end
    end

    @testset "invalid definitions" begin
        # Invalid function type
        @test_splitdef_invalid Expr(:block)

        # Too few expression arguments
        @test_splitdef_invalid Expr(:function)
        @test_splitdef_invalid Expr(:(=), :f)

        # Too many expression arguments
        @test_splitdef_invalid Expr(:function, :f, :x, :y)
        @test_splitdef_invalid Expr(:(=), :f, :x, :y)

        # Invalid or missing arguments
        @test_splitdef_invalid :(f{S} = 0)
        @test_broken splitdef(:(a::Number::Int -> a); throws=false) === nothing

        # Invalid argument block expression
        ex = :((x; y; z) -> 0)  # Note: inlining this strips LineNumberNodes from the block
        @test any(arg -> arg isa LineNumberNode, ex.args[1].args)
        @test_splitdef_invalid ex
        @test_splitdef_invalid Expr(:->, Expr(:block, :x, :y, :z), Expr(:block, 0))

        # Empty function contains extras
        @test_throws ArgumentError combinedef(Dict(:head => :function, :name => :f, :args => []))
    end
end


text:
module ScalingNoInterpTests

using Interpolations, Base.Test

xs = -pi:2pi/10:pi
f1(x) = sin(x)
f2(x) = cos(x)
f3(x) = sin(x) .* cos(x)
f(x,y) = y == 1 ? f1(x) : (y == 2 ? f2(x) : (y == 3 ? f3(x) : error("invalid value for y (must be 1, 2 or 3, you used $y)")))
ys = 1:3

A = hcat(f1(xs), f2(xs), f3(xs))

itp = interpolate(A, (BSpline(Quadratic(Periodic())), NoInterp()), OnGrid())
sitp = scale(itp, xs, ys)

for (ix,x0) in enumerate(xs[1:end-1]), y0 in ys
    x,y = x0, y0
    @test_approx_eq_eps sitp[x,y] f(x,y) .05
end

@test length(gradient(sitp, pi/3, 2)) == 1

if VERSION < v"0.5.0-dev" # Test.with_handler was removed in 0.5

    # Test error messages for incorrect initialization
    function message_is(message)
        r -> r.err.msg == message || error("Incorrect error message: expected '$message' but was '$(r.err.msg)'")
    end
    Test.with_handler(message_is("Must scale 2-dimensional interpolation object with exactly 2 ranges (you used 1)")) do
        @test scale(itp, xs)
    end
    Test.with_handler(message_is("NoInterp dimension 2 must be scaled with unit range 1:3")) do
        @test scale(itp, xs, -1:1)
    end
    Test.with_handler(message_is("The length of the range in dimension 1 (8) did not equal the size of the interpolation object in that direction (11)")) do
        @test scale(itp, -pi:2pi/7:pi, 1:3)
    end
    Test.with_handler(message_is("Must index into 2-dimensional scaled interpolation object with exactly 2 indices (you used 1)")) do
        @test sitp[2.3]
    end
    Test.with_handler(message_is("Must index into 2-dimensional scaled interpolation object with exactly 2 indices (you used 1)")) do
        @test gradient(sitp, 2.3)
    end
    Test.with_handler(message_is("The length of the provided gradient vector (2) did not match the number of interpolating dimensions (1)")) do
        @test gradient!(Array(Float64, 2), sitp, 2.3, 2)
    end

end

end


text:
export LinearRelative, PackedLinearRelative

"""
$(TYPEDEF)

Default linear offset between two scalar variables.

```math
X_2 = X_1 + η_Z
```
"""
struct LinearRelative{N, T <: SamplableBelief} <: AbstractRelativeRoots
  Z::T
end

# need several helper constructors since the dimension over which LinearRelative will be used is unknown at this point
function LinearRelative{N}( z0::T=MvNormal(zeros(N), diagm(ones(N))) ) where {N, T <: SamplableBelief}
  #
  LinearRelative{N, T}(z0)
end

LinearRelative(::UniformScaling=LinearAlgebra.I) = LinearRelative{1}(MvNormal(zeros(1), diagm(ones(1))))
LinearRelative(nm::Distributions.ContinuousUnivariateDistribution) = LinearRelative{1, typeof(nm)}(nm)
LinearRelative(nm::MvNormal) = LinearRelative{length(nm.μ), typeof(nm)}(nm)
LinearRelative(nm::Union{<:BallTreeDensity,<:ManifoldKernelDensity}) = LinearRelative{Ndim(nm), typeof(nm)}(nm)

getManifold(::InstanceType{LinearRelative{N}}) where N = getManifold(ContinuousEuclid{N})

# TODO standardize
getDimension(::InstanceType{LinearRelative{N}}) where {N} = N

# new and simplified interface for both nonparametric and parametric
function (s::CalcFactor{<:LinearRelative})(z, x1, x2)
  # TODO convert to distance(distance(x2,x1),z) # or use dispatch on `-` -- what to do about `.-`
  # v0.21+, should return residual
  !(z isa Vector{Float64}) && (@warn "H" z x1 x2)
  return z .- (x2 .- x1)
end

Base.convert(::Type{<:MB.AbstractManifold}, ::InstanceType{LinearRelative{N}}) where N = Manifolds.TranslationGroup(N)

"""
$(TYPEDEF)
Serialization type for `LinearRelative` binary factor.
"""
Base.@kwdef mutable struct PackedLinearRelative <: AbstractPackedFactor
  Z::PackedSamplableBelief
end
function convert(::Type{PackedLinearRelative}, d::LinearRelative)
  PackedLinearRelative(convert(PackedSamplableBelief, d.Z))
end
function convert(::Type{LinearRelative}, d::PackedLinearRelative)
  LinearRelative(convert(SamplableBelief, d.Z))
end

#


text:
#= Synchronous Modelica primitives

Clock()
Clock(intervalCounter::Int, resolution::Int=1)  # Add version with rational number
Clock(interval::Float64)
Clock(condition::Bool, startInterval::Float64=0.0)
Clock(c::Clock, solverMethod)

previous(x)

sample(u, c::Clock)
sample(u)

hold(u) = u

subSample(u, factor::Int)
superSample(u, factor::Int)
shiftSample(u, shiftCounter::Int, resolution::Int=1)  # Add version with rational number
backSample(u, backCounter::Int, resolution::Int=1)  # Add version with rational number

noClock()

interval(u)

=#

export Clock, sample, hold, previous

Clock(interval, m::SimulationModel, nr::Int) = Clock(m.options.startTime, interval, m, nr)

function Clock(startTime, interval, m::SimulationModel{FloatType,TimeType}, nr::Int)::Bool where {FloatType,TimeType}
# Clock ticks at startTime, startTime + interval, startTime + 2*interval, ...
# This is independent of the starTime of the simulation. Example:
#   if startTime = -3, interval = 1.5, m.options.startTime = 1.0 then
#   the clock ticks at 1.5, 3.0, 4.5, ...
    eh = m.eventHandler
    if isEvent(m)
        if isInitial(m)
            startTime2 = convert(TimeType, startTime)
            interval2  = convert(TimeType, interval)

            tFirst = startTime2 >= eh.time ? startTime2 : startTime2 + div(eh.time - startTime2, interval2, RoundUp)*interval2
            if abs(eh.time - tFirst) < 1e-10
                eh.clock[nr] = eh.time
                setNextEvent!(eh, eh.clock[nr], triggerEventDirectlyAfterInitial=true)
            else
                eh.clock[nr] = tFirst
                setNextEvent!(eh, eh.clock[nr])
            end

        elseif isFirstEventIterationDirectlyAfterInitial(m)
            eh.clock[nr] = eh.time + convert(TimeType,interval)
            setNextEvent!(eh, eh.clock[nr])
            return true

        elseif isFirstEventIteration(m) && isAfterSimulationStart(m)
            tick = abs(eh.time - eh.clock[nr]) < 1E-10
            if tick
                eh.clock[nr] = eh.time + convert(TimeType,interval)
                setNextEvent!(eh, eh.clock[nr])
                return true
            end
            setNextEvent!(eh, eh.clock[nr])
        end
    end

    return false
end

@inline function sample(v, clock::Bool, m::SimulationModel{FloatType,TimeType}, nr::Int) where {FloatType,TimeType}
    eh = m.eventHandler
    if isInitial(m) || clock
        eh.sample[nr] = v
    end
    return eh.sample[nr]
end

@inline function previous(clock::Bool, m::SimulationModel, nr::Int)
    # m.previous[nr] is initialized with the start/init value of v before the first model evaluation
    if clock
        m.previous[nr] = m.nextPrevious[nr]
    end
    return m.previous[nr]
end

hold(v) = v

@inline function hold(v, clock::Bool, m::SimulationModel, nr::Int)
    # m.hold[nr] is initialized with the start/init value of v before the first model evaluation
    if clock
        m.hold[nr] = v
    end
    return m.hold[nr]
end


text:
using Documenter, Snowball

makedocs(;
    modules=[Snowball],
    format=Documenter.HTML(),
    pages=[
        "Home" => "index.md",
    ],
    repo="https://github.com/juliatext/Snowball.jl/blob/{commit}{path}#L{line}",
    sitename="Snowball.jl",
    authors="Avik Sengupta, Julia Computing",
    assets=String[],
)

deploydocs(;
    repo="github.com/JuliaText/Snowball.jl",
)

max_stars_repo_name: JuliaText/Snowball


text:
using Polynomials: Poly, roots

"""
The Universal gas constant.
"""
const R = 8.3144598

"""
The phase which determines a computational algorithm.
"""
@enum Phase LIQUID VAPOR

"""
    EquilibriumData(T::Float64, P::Float64, x::Float64, y::Float64, Vv::Float64,
                    Vl::Float64, ϕl::Array{Float64, 1}, ϕv::Array{Float64, 1})

Contains the data about an equilibrium point.
"""
struct EquilibriumData
    T::Float64
    P::Float64
    x::Array{Float64, 1}
    y::Array{Float64, 1}
    ϕv::Array{Float64, 1}
    Vv::Float64
    ϕl::Array{Float64, 1}
    Vl::Float64
end

"""
    Mixture(name::AbstractString, x::Array{Float64, 1},
            y::Array{Float64, 1}, Tb::Array{Float64, 1},
            Tcr::Array{Float64, 1}, Pcr::Array{Float64, 1},
            ω::Array{Float64, 1}, k::Array{Float64, 1} = [])

Construct an instance of a mixture from the data about its individual
components (Where `ω` is a Pitzer acentric factors and `k` is a Binary interaction
parameters).

Mole fractions `x` and `y` must not include the last components (For example,
if a number of components is 4 then a length of `x` and `y` must be equals 3).
Sum of `x` and sum of `y` must be less or equal to 1.
"""
type Mixture
    name::AbstractString
    x::Array{Float64, 1}
    y::Array{Float64, 1}
    Tb::Array{Float64, 1}
    Tcr::Array{Float64, 1}
    Pcr::Array{Float64, 1}
    ω::Array{Float64, 1}
    k::Array{Float64, 2}
    RTcr::Array{Float64, 1}
    RTcr²::Array{Float64, 1}
    RTcr²⁵::Array{Float64, 1}
    function Mixture(name::AbstractString, x::Array{Float64, 1},
                     y::Array{Float64, 1}, Tb::Array{Float64, 1},
                     Tcr::Array{Float64, 1}, Pcr::Array{Float64, 1},
                     ω::Array{Float64, 1}, k = nothing)
        append!(x, 1 - sum(x))
        append!(y, 1 - sum(y))
        if !(length(x) == length(y) == length(Tb) ==
             length(Tcr) == length(Pcr) == length(ω))
            error("Length of all vectors must be the same.")
        end
        RTcr = R * Tcr
        RTcr² = RTcr.^2
        RTcr²⁵ = R^2 * Tcr.^2.5
        if k == nothing
            l = length(x)
            k = zeros((l, l))
        end
        return new(name, x, y, Tb, Tcr, Pcr, ω, k, RTcr, RTcr², RTcr²⁵)
    end
end

################################################################################
## Equations of state
################################################################################

abstract type Equation end

"""
    SRK(mix::Mixture)

Contains the data that necessary for solving
Soave-Redlich-Kwong equation of state.
"""
type SRK <: Equation
    mix::Mixture
    Ωa::Float64
    Ωb::Float64
    m̄::Array{Float64, 1}
    function SRK(mix::Mixture)
        m̄ = 0.48508 + 1.55171 * mix.ω - 0.15613 * mix.ω.^2
        return new(mix, 0.42747, 0.08664, m̄)
    end
end

"""
    PR(mix::Mixture)

Contains the data that necessary for solving
Peng-Robinson equation of state.
"""
type PR <: Equation
    mix::Mixture
    Ωa::Float64
    Ωb::Float64
    m̄::Array{Float64, 1}
    function PR(mix::Mixture)
        m̄ = 0.37464 + 1.54226 * mix.ω - 0.26992 * mix.ω.^2
        return new(mix, 0.457235, 0.077796, m̄)
    end
end

"""
    RK(mix::Mixture)

Contains the data that necessary for solving
Redlich-Kwong equation of state.
"""
type RK <: Equation
    mix::Mixture
    Ωa::Float64
    Ωb::Float64
    function RK(mix::Mixture)
        return new(mix, 0.42747, 0.08664)
    end
end

"""
    VdW(mix::Mixture)

Contains the data that necessary for solving
Van-der-Waals equation of state.
"""
type VdW <: Equation
    mix::Mixture
    Ωa::Float64
    Ωb::Float64
    function VdW(mix::Mixture)
        return new(mix, 0.421875, 0.125000)
    end
end

################################################################################
## Generic Functions
################################################################################

"""
    calc_compres_factor(coefs::Array{Float64, 1})

Solves the equation of state in a form of a cubic polynomial and return an
array of 3 roots if all of them is real or an array of 1 real root otherwise.
"""
function calc_compres_factor(coefs::Array{Float64, 1})

    z = roots(Poly(coefs))
    if any(!isreal, z)
        return nothing
    end
    return z
end

################################################################################
## Specific Functions
################################################################################

"""
    calc_params(eq::Equation, T::Float64, P::Float64, phase::Phase)

Computes the parameters for futher calculations of the fugacity coefficient.
"""
function calc_params end

function calc_params(eq::Union{SRK,PR}, T::Float64, P::Float64,
                     phase::Phase)

    frac = phase == LIQUID ? eq.mix.x : eq.mix.y

    ᾱ = (1 + eq.m̄ .* (1 - sqrt.(T ./ eq.mix.Tcr))).^2
    ā = (eq.Ωa * eq.mix.RTcr² ./ eq.mix.Pcr) .* ᾱ
    b̄ = eq.Ωb * eq.mix.RTcr ./ eq.mix.Pcr

    aa = (1 - eq.mix.k) .* sqrt.(ā*ā')
    top = 2 * aa * frac
    a = sum(aa .* (frac * frac'))
    b = sum(frac .* b̄)

    RT = R * T
    Ā = top ./ a
    B̄ = b̄ * P / RT

    A = a * P / RT^2
    B = b * P / RT

    return (A, B, Ā, B̄)
end

function calc_params(eq::RK, T::Float64, P::Float64, phase::Phase)

    frac = phase == LIQUID ? eq.mix.x : eq.mix.y

    ā = eq.Ωa * eq.mix.RTcr²⁵ ./ eq.mix.Pcr
    b̄ = eq.Ωb * eq.mix.RTcr ./ eq.mix.Pcr

    Ā = ā * P / (R^2 * T^2.5)
    B̄ = b̄ * P / (R * T)

    A = sum(frac .* sqrt.(Ā))^2
    B = sum(frac .* B̄)

    return (A, B, Ā, B̄)
end

function calc_params(eq::VdW, T::Float64, P::Float64, phase::Phase)

    frac = phase == LIQUID ? eq.mix.x : eq.mix.y

    Ā = eq.Ωa * eq.mix.RTcr² ./ eq.mix.Pcr
    B̄ = eq.Ωb * eq.mix.RTcr ./ eq.mix.Pcr

    A = sum(frac .* sqrt.(Ā))^2
    B = sum(frac .* B̄)

    return (A, B, Ā, B̄)
end

"""
    calc_fugacity_coef(eq::Equation, T::Float64, P::Float64, phase::Phase)

Computes the fugacity coefficients for a components in a given mixture by
a given equation in a given phase.

Returns tuple of the fugacity coefficients and molar volume of the phase.
"""
function calc_fugacity_coef(eq::Equation, T::Float64, P::Float64, phase::Phase)

    A, B, Ā, B̄ = calc_params(eq, T, P, phase)
    RT::Float64 = R*T
    eq_type = typeof(eq)

    coefs::Array{Float64, 1} = []
    if eq_type == SRK || eq_type == RK
        coefs = [-A * B, A - B - B^2, -1.0, 1.0]
    elseif eq_type == PR
        coefs = [-A * B + B^2 + B^3, A - 2 * B - 3 * B^2, -1.0 + B, 1.0]
    elseif eq_type == VdW
        coefs = [-A * B * P^2 / RT^3, A * P / RT^2, -(B * P / RT + 1), 1.0]
    end

    zs = calc_compres_factor(coefs)
    if zs == nothing
        return nothing
    end
    Z::Float64 = phase == LIQUID ? min(zs...) : max(zs...)
    V::Float64 = Z * RT / P

    if eq_type == SRK
        h1 = (Z - 1) * B̄ / B
        h2 = Z - B
        h3 = (A / B) * (B̄ / B - Ā)
        h4 = 1 + B / Z
    elseif eq_type == PR
        h1 = B̄ * (Z - 1) / B
        h2 = Z - B
        h3 = (A / (2.8284 * B)) * (B̄ / B - Ā)
        h4 = (Z + 2.4142 * B) / (Z - 0.4142 * B)
    elseif eq_type == RK
        h1 = (Z - 1) * B̄ / B
        h2 = Z - B
        h3 = (A / B) * (B̄ / B - 2 * sqrt.(Ā / A))
        h4 = 1 + B / Z
    elseif eq_type == VdW
        h1 = B̄ / (V - B)
        h2 = Z * (1 - B / V)
        h3 = -2 * sqrt.(Ā * A) / (RT * V)
        h4 = e
    end
    #@show [h1, h2, h3, h4]
	#@show P
	#@show T
    ϕ::Array{Float64, 1} = exp.(h1 - log(h2) + h3 * log(h4))

    return (ϕ, V)
end

"""
    solve(eq::Equation, T::Float64, P::Float64)

Solves the equation of state and returns thermodynamic data for given point.
"""
function solve(eq::Equation, T::Float64, P::Float64)

    v = calc_fugacity_coef(eq, T, P, VAPOR)
    l = calc_fugacity_coef(eq, T, P, LIQUID)

    if v == nothing || l == nothing
        return nothing
    end
    return EquilibriumData(T, P, copy(eq.mix.x), copy(eq.mix.y), v..., l...)
end


text:
module PSDUtils

import MJDSigGen: get_signal!

using MJDSigGen: SigGenSetup, outside_detector
using LegendTextIO: DarioHitsEventTuple
using DSP: gaussian, conv
using Random: AbstractRNG, default_rng
using Distributions: Normal
using StaticArrays

export todetcoords, todetcoords!, charge_cloud_size, getA, get_rise_time,
	apply_coll_effects, moving_average!, moving_average, get_noisy_energy, addnoise!

"""Convert to detector coordinates [mm]"""
function todetcoords(x::Real, y::Real, z::Real, zlen::Real)
	return 10(z + 200), 10x, -10y + zlen / 2
end

todetcoords((x, y, z)::NTuple{3, Real}, zlen::Real) = todetcoords(x, y, z, zlen)
todetcoords(v::SVector{3, T}, zlen::Real) where {T<:Real} =
    SVector{3, T}(todetcoords(v[1], v[2], v[3], zlen))

function todetcoords!(event::DarioHitsEventTuple, zlen::Real)
	event.pos .= todetcoords.(event.pos, zlen)
	return event
end

function get_signal!(
    final_pulse::DenseVector{Float32},
    working_pulse::DenseVector{Float32},
    setup::SigGenSetup,
	pos,
	E
)
	length(pos) == length(E) || throw(ArgumentError(
		"number of pos ($(length(pos)) != number of E ($(length(E))))"))

    for i in 1:length(pos)
        pos_prime = todetcoords(Tuple(pos[i]), setup.xtal_length)
        if !outside_detector(setup, pos_prime)
            get_signal!(working_pulse, setup, pos_prime)
            final_pulse .+= E[i] .* working_pulse
        end
	end

    return final_pulse
end

function get_signal!(setup::SigGenSetup, pos, E)
    return get_signal!(
        zeros(Float32, setup.ntsteps_out),
        Vector{Float32}(undef, setup.ntsteps_out),
        setup, pos, E
    )
end

get_signal!(setup::SigGenSetup, event::DarioHitsEventTuple) = get_signal!(setup, event.pos, event.E)

"""
	charge_cloud_size(energy)

returns charge cloud size as maximum of A + B × energy and 0.01.

Parameters A and B were obtained from MC of BSI inv-coax (evolution of R90, rescaled for FWHM)
"""
charge_cloud_size(energy) = max(-0.03499440089585633 + 0.0003359462486002238 * energy, 0.01)

## Signal Processing ##

getA(signal) = maximum(diff(signal))

function get_rise_time(signal, lowthr, highthr, tstep=1)
	highthr >= lowthr || throw(ArgumentError(
		"highthr ($highthr) must be >= lowthr ($lowthr)"))

	minindex = nothing;
	maxindex = nothing;

	for k=1:length(signal)
		if signal[k]>=highthr
			maxindex = k;
			break;
		end
	end

	if maxindex===nothing
		return -1
	end

	for k=maxindex:-1:1
		if signal[k]<=lowthr
			minindex = k+1;
			break;
		end
	end

	if(maxindex==nothing || minindex==nothing)
		risetime = 0;
	else
		risetime = (maxindex-minindex) * tstep;
	end

	return risetime
end

function gausswindow(σ::Real, nσ::Real, tstep::Real)
    # number of time steps to 1σ
    stepσ = σ / tstep

    # Number of samples so that nσ of stepσ reaches edge of window
    n = round(Int, 2 * nσ * stepσ)

    return gaussian(n, 0.5 / nσ)
end

function pad_signal!(padvec, signal, wl)
    sl = length(signal)

    # Padding only needed at end, since the beginning of the signal is ≈ 0
    padvec[1:sl] .= signal
    padvec[sl+1:wl+sl-1] .= signal[end]

    return padvec[1:sl+wl-1]
end

function apply_coll_effects(
    signal, δτ::Real, tstep::Real, padding::Bool = true;
    padvec = (padding ? similar(signal) : similar(signal, 0)), nσ = 4
)
    # because δτ is FWHM
    σ = δτ / (2 * √(2 * log(2)))

    # gaussian window with nσ to each edge
    w = gausswindow(σ, nσ, tstep)

    if padding
        sl = length(signal)
        wl = length(w)

		length(padvec) < sl + wl - 1 && resize!(padvec, sl + wl - 1)

        return conv(pad_signal!(padvec, signal, wl), w)[1:sl + wl - 1]
    else
        return conv(signal, w)
    end
end

function moving_average!(out, signal, width::Integer)
	length(out) == length(signal) || throw(ArgumentError(
		"ouptut vector must have same length as input vector"))

	# offsets from middle of window to beginning and end of window
	bo = ceil(Int, width / 2)
	eo = width - bo - 1

	# Set beginning of output to the first moving mean
	out[1:bo] .= sum(signal[1:width])

	for i in bo+1:length(signal)-eo-1
		out[i] = out[i-1] - signal[i-bo] + signal[i+eo+1]
	end

	out[end-eo:end] .= out[end-eo-1]
	out ./= width
	return out
end

function moving_average!(out, signal, width::Integer, n::Integer)
	for _ in 1:floor(Int, n / 2)
		moving_average!(out, signal, width)
		moving_average!(signal, out, width)
	end

	if isodd(n)
		moving_average!(out, signal, width)
		return out
	else
		return signal
	end
end

function moving_average(signal, width::Integer)
	moving_average!(similar(signal), signal, width)
end

function moving_average(signal, width::Integer, n::Integer)
	moving_average!(similar(signal), copy(signal), width, n)
end

function apply_electronics(pulse; GBP = 150e+06, Cd = 3.5e-12, Ts = 1e-9, tau = 65e-6, Kv = 0.5e6, Cf = 0.65e-12, Rf = 2e7)
    wop = GBP / (2 * pi * Kv)
    Cmod = Cf + Cd
    wmod = 1.0 / (Rf * Cmod)
    alfa = Cmod / (Cf * GBP)

    b0 = 1.0 / alfa
    a2 = 1.0
    a1 = 1.0 / alfa + wop + wmod
    a0 = 1.0 / (tau * alfa) + wmod*wop

    # then the transfer function in the *Laplace* s-domain looks like this:
    #                       b0
    #   T(s) = ----------------------------
    #             a2 * s^2 + a1 * s + a0

    # PolynomialRatio needs z-transform paramters: s- and z-domains can be connected by
    # the bilinear transform:
    #        z - 1
    # s = K -------- , K = Ts/2  , Ts - sampling period
    #        z + 1
    #
    # we can then convert T(s) to T(z):
    #              bz2 * z^2 + bz1 * z + bz0
    #   T(z) = -------------------------------
    #              az2 * z^2 + az1 * z + az0
    #

    K = 2/Ts

    az2 = 1.0   # normalized
    az1 = (2*a0 - 2*K^2)/(K^2 + a1*K + a0)
    az0 = (K^2 - a1*K + a0)/(K^2 + a1*K + a0)

    bz2 = b0/(K^2 + a1*K + a0)
    bz1 = 2*b0/(K^2 + a1*K + a0)
    bz0 = b0/(K^2 + a1*K + a0)

    myfilter = PolynomialRatio([bz2, bz1, bz0], [az2, az1, az0])

    filtered = filt(myfilter, vcat([0], diff(pulse)))
end

## Noise ##

get_noisy_energy(rng::AbstractRNG, E, σE) = rand(rng, Normal(E, σE))

get_noisy_energy(E, σE) = rand(default_rng(), Normal(E, σE))

function addnoise!(signal, noise, noise_index)
	@boundscheck checkbounds(noise, noise_index)

    i = 1
    j = noise_index

    nl = length(noise)
    sl = length(signal)

    while sl - i > nl - j
        signal[i:i + nl - j] .+= noise[j:end]

        i += nl - j + 1
        j = 1
    end

    signal[i:end] .+= noise[j:j + sl - i]

    return signal
end

addnoise!(signal, noise) = addnoise!(signal, noise, rand(default_rng(), eachindex(noise)))
addnoise!(rng::AbstractRNG, signal, noise) =
	addnoise!(signal, noise, rand(rng, eachindex(noise)))

end # PSDUtils


text:
# taken from JuliaRobotics/BotCoreLCMTypes/test/runtests.jl

using CaesarLCMTypes
using LCMCore
using LCMCore: fingerprint
using Base.Test

#=
first run $ ~/.julia/v0.6/LCMCore/deps/builds/lcm/lcmgen/lcm-gen -p --ppath . *.lcm

The following Python code was used to retrieve all of the
fingerprints for the various caesar lcmtypes automatically:
import sys
import inspect
import struct
import caesar
for name, obj in inspect.getmembers(caesar):
    if inspect.isclass(obj):
        print("{:s} => {:d},".format(name, struct.unpack('q', obj._get_packed_fingerprint())[0]))
=#

"""
Equality test for most types, but we compare LCMType instances
by looking at their fields, since otherwise == just falls back
to === which compares object identity and is thus not very
informative.
"""
closeenough(x, y) = x == y
function closeenough(x::LCMType, y::LCMType)
    (typeof(x) == typeof(y)) || return false
    for name in fieldnames(x)
        closeenough(getfield(x, name), getfield(y, name)) || return false
    end
    true
end

@testset "CaesarLCMTypes" begin
    expected_fingerprints_network_order = Dict(
        apriltag_detections_t => -8756471515517054953,
        apriltag_t => 8846306677841471956,
        brookstone_supertype_t => 6173426112200236032,
        example_t => 1609464439235171639,
        generic_factor_t => -9150067746642263183,
        generic_variable_t => -6355586019449534452,
        image_metadata_t => -8143784636512515174,
        image_t => -1083725853459778796,
        point_cloud_t => 2003008221351621598,
        pose_node_t => 249794548766818026,
        pose_pose_nh_t => 4072811593573625988,
        pose_pose_xyh_nh_t => -6037466938990705104,
        pose_pose_xyh_t => 9116064949984549703,
        prior_zpr_t => -3254265534732152215,
    )

    for (lcmtype, fingerprint_network_order) in expected_fingerprints_network_order
        @testset "$lcmtype" begin
            @testset "constructor" begin
                msg = lcmtype()
                for name in fieldnames(typeof(msg))
                    @test closeenough(getfield(msg, name), LCMCore.defaultval(typeof(getfield(msg, name))))
                end
            end
            @testset "fingerprint" begin
                @test hton(fingerprint(lcmtype)) == fingerprint_network_order
            end
        end
    end
end


text:
using CoupledConditionalSMC
import SequentialMonteCarlo.SMCModel

@inline function makeCharacter(v1::Vector{Particle}, v2::Vector{Particle},
  start::Int64, finish::Int64) where Particle
  for j in start:finish
    if v1[j] != v2[j]
      return "x"
    end
  end
  return "-"
end

function makeString(v1::Vector{Particle}, v2::Vector{Particle},
  quantum::Int64) where Particle
  s::String = ""
  n::Int64 = length(v1)
  for i = 1:n
    if mod(i, quantum) == 1 || quantum == 1
      start = i
      finish = min(i+quantum-1, n)
      s *= makeCharacter(v1, v2, start, finish)
    end
  end
  s *= "\n"
  return s
end

# run the CCxPF and visualize until the meeting time
function visualizeCCSMC(model::SMCModel, lM::F, N::Int64,
  algorithm::Symbol = :BS, independentInitialization::Bool = false,
  rngCouple::Bool = false, maxit::Int64 = typemax(Int64)) where F<:Function

  if algorithm == :BS
    println("\nBackward sampling, N = ", N, ":\n")
  elseif algorithm == :AS
    println("\nAncestor sampling, N = ", N, ":\n")
  else
    println("\nAncestral tracing, N = ", N, ":\n")
  end
  ccsmcio = CCSMCIO{model.particle, model.pScratch}(N, model.maxn)

  initializeCCSMC(model, lM, ccsmcio, algorithm, independentInitialization)

  quantum = max(1, ceil(Int64, ccsmcio.n / displaysize(stdout)[2]))

  ref1 = ccsmcio.ref1
  ref2 = ccsmcio.ref2

  printstyled(makeString(ref1, ref2, quantum), color=:green)

  for i in 1:maxit
    if algorithm == :BS || algorithm == :AS
      ccXpf!(model, lM, ccsmcio, algorithm, rngCouple)
    else
      ccXpf!(model, ccsmcio, rngCouple)
    end
    printstyled(makeString(ref1, ref2, quantum), color=:green)
    if CoupledConditionalSMC.checkEqual(ref1, ref2)
      println("coupled at iteration $i")
      return i
    end
  end
  println("never coupled in $maxit iterations")
  return maxit
end

# run the CCPF and visualize until the meeting time
function visualizeCCSMC(model::SMCModel, N::Int64,
  independentInitialization::Bool = false, rngCouple::Bool = false,
  maxit::Int64 = typemax(Int64))
  return visualizeCCSMC(model, error, N, :AT, independentInitialization,
    rngCouple, maxit)
end

function computeBoundary(v1::Vector{Particle}, v2::Vector{Particle}) where Particle
  for i = 1:length(v1)
    if v1[i] != v2[i] return i-1 end
  end
  return length(v1)
end

# run the CCBPF and record the boundaries
function CCSMCBoundaries(model::SMCModel, lM::F, N::Int64,
  algorithm::Symbol, maxit::Int64) where F<:Function

  ccsmcio = CCSMCIO{model.particle, model.pScratch}(N, model.maxn)
  initializeCCSMC(model, lM, ccsmcio, algorithm, true)

  boundaries = Vector{Int64}(undef, maxit)
  ref1 = ccsmcio.ref1
  ref2 = ccsmcio.ref2
  n = length(ref1)

  maxb::Int64 = 1
  for i in 1:maxit
    ccXpf!(model, lM, ccsmcio, algorithm)
    boundary = computeBoundary(ref1, ref2)
    boundaries[i] = boundary
    if boundary == n
      return boundaries[1:i]
    end
  end
  return boundaries
end

function CCSMCBoundaries(model::SMCModel, N::Int64,
  maxit::Int64 = typemax(Int64))
  return CCSMCBoundaries(model, error, N, maxit, :AT)
end


text:
"""
`carica`
since jld2 files are saved as dictionaries
it is painful to indicates always the variable name you want.
In this way it automatically calls the first key of the dictionary
and retunrs the variable stored
"""
function carica(filename)
    file = FileIO.load(filename)
    if isa(file, Dict)
        data = file[collect(keys(file))[1]]
    else
        data = FileIO.load(filename) |> DataFrame
    end
    return data
end


text:
import DataStructures
import StaticArrays
using BenchmarkTools

include("../src/soalight.jl")
include("../src/allocator.jl")
include("../src/stack.jl")

function testbase(n, p)
    s = DataStructures.Stack{Tuple{Int, typeof(p)}}()
    for j in 1:n[]
        push!(s, (j, p))
    end
    for j in n[]:-1:1
        @assert j == pop!(s)[1]
    end
end

function testalloc(n, p, s)
    for j in 1:n[]
        push!(s, (j, p))
    end
    for j in n[]:-1:1
        @assert j == pop!(s)[1]
    end
    @assert isempty(s)
    emptyend!(s.alloc)
end

ans = nothing
for n in [100000, 10]
    println(n, " elements")
    for p in [1, 10, 100]
        println(" payload of ", p, " float(s)")

        Payload = StaticArrays.SVector{p ,Float64}

        GC.gc()

        print("  DataStructures.Stack           ")
        @btime ($ans = testbase(Ref($n), zeros($Payload)))

        GC.gc()

        print("  Stack with fixed allocator     ")
        alloc = Allocator{Tuple{Int, Payload}, Int}(n)
        s = Stack{Tuple{Int, Payload}, Int, Allocator{Tuple{Int, Payload}, Int}}(alloc)
        @btime ($ans = testalloc(Ref($n), zeros($Payload), $s))

        GC.gc()

        print("  Stack with resizable allocator ")
        alloc = Allocator{Tuple{Int, Payload}, Int}(nothing)
        s = Stack{Tuple{Int, Payload}, Int, Allocator{Tuple{Int, Payload}, Int}}(alloc)
        @btime ($ans = testalloc(Ref($n), zeros($Payload), $s))
    end
end


text:
using DONEs
using Random
using LinearAlgebra

Random.seed!(1)

n = 3
rfe = RFE(20,n,0.1)

lb = -ones(n)
ub = ones(n)
σs = 0.1 # surrogate exploration
σf = 0.1 # function exploration
done = DONE(rfe, lb, ub, σs, σf)

f(x) = dot(x.-0.1,x.-0.1) + 0.05*randn() # simple quadratic function
N = 40
for i in 1:N
    xi = new_input(done)
    yi = f(xi)
    add_measurement!(done, xi, yi)
    update_optimal_input!(done)
end

println("Estimated minimum:")
evaluateRFE(rfe, done.current_optimal_x) |> display
println("Estimated minimizer")
done.current_optimal_x |> display


text:
function authorization_code_to_access_token(authz_code_info::_AuthorizationCodeInformation)
    authorization_code = authz_code_info.authorization_code
    client_id          = authz_code_info.client_id
    redirect_uri       = authz_code_info.redirect_uri
    token_endpoint     = authz_code_info.token_endpoint

    _response = HTTP.request(
        "POST",
        token_endpoint;
        headers = Dict("Content-Type" => "application/x-www-form-urlencoded"),
        body = URIs.escapeuri(Dict(
            "client_id" => client_id,
            "code" => authorization_code,
            "grant_type" => "authorization_code",
            "redirect_uri" => redirect_uri,
        )),
    )
    access_token_response = JSON3.read(String(_response.body))
    access_token = access_token_response.access_token

    authorization_code_is_jwt, authorization_code_jwt_decoded = try_decode_jwt(authorization_code)
    access_token_is_jwt, access_token_jwt_decoded = try_decode_jwt(access_token)

    access_token_info = _AccessTokenInformation(;
        authorization_code             = authorization_code,
        authorization_code_is_jwt      = authorization_code_is_jwt,
        authorization_code_jwt_decoded = authorization_code_jwt_decoded,
        access_token                   = access_token,
        access_token_is_jwt            = access_token_is_jwt,
        access_token_jwt_decoded       = access_token_jwt_decoded,
        access_token_response          = access_token_response,
    )

    return access_token_info
end


text:
mutable struct XPCallbacks
    start_cdata::Function
    end_cdata::Function
    comment::Function
    character_data::Function
    default::Function
    default_expand::Function
    start_element::Function
    end_element::Function
    start_namespace::Function
    end_namespace::Function
end

mutable struct XPStreamHandler{D}
    cbs::XPCallbacks
    parser::XML_Parser
    data::D
end

# Create an XPCallbacks instance filled with nop callbacks
XPCallbacks() = XPCallbacks(
    (handler::XPStreamHandler) -> nothing,
    (handler::XPStreamHandler) -> nothing,
    (handler::XPStreamHandler, txt::AbstractString) -> nothing,
    (handler::XPStreamHandler, txt::AbstractString) -> nothing,
    (handler::XPStreamHandler, txt::AbstractString) -> nothing,
    (handler::XPStreamHandler, txt::AbstractString) -> nothing,
    (handler::XPStreamHandler, name::AbstractString, attrs_in::Dict{AbstractString,AbstractString}) -> nothing,
    (handler::XPStreamHandler, name::AbstractString) -> nothing,
    (handler::XPStreamHandler, prefix::AbstractString, uri::AbstractString) -> nothing,
    (handler::XPStreamHandler, prefix::AbstractString) -> nothing
)

function streaming_start_cdata(p_cbs::Ptr{Nothing})
    h = unsafe_pointer_to_objref(p_cbs)::XPStreamHandler

    h.cbs.start_cdata(h)
    return
end

function streaming_end_cdata(p_cbs::Ptr{Nothing})
    h = unsafe_pointer_to_objref(p_cbs)::XPStreamHandler

    h.cbs.end_cdata(h)
    return
end

function streaming_cdata(p_cbs::Ptr{Nothing}, s::Ptr{UInt8}, len::Cint)
    h = unsafe_pointer_to_objref(p_cbs)::XPStreamHandler

    txt = unsafe_string(s, Int(len))

    h.cbs.character_data(h, txt)

    return
end

function streaming_start_element(p_cbs::Ptr{Nothing}, name::Ptr{UInt8}, attrs_in::Ptr{Ptr{UInt8}})
    h = unsafe_pointer_to_objref(p_cbs)::XPStreamHandler
    txt::AbstractString = unsafe_string(name)
    attrs::Dict{AbstractString,AbstractString} = attrs_in_to_dict(attrs_in)

    h.cbs.start_element(h, txt, attrs)

    return
end

function streaming_end_element(p_h::Ptr{Nothing}, name::Ptr{UInt8})
    h = unsafe_pointer_to_objref(p_h)::XPStreamHandler
    txt::AbstractString = unsafe_string(name)

    h.cbs.end_element(h, txt)

    return
end

function streaming_comment(p_h::Ptr{Nothing}, data::Ptr{UInt8})
    h = unsafe_pointer_to_objref(p_h)::XPStreamHandler
    txt = unsafe_string(data)

    h.cbs.comment(h, txt)

    return
end

function streaming_default(p_h::Ptr{Nothing}, data::Ptr{UInt8}, len::Cint)
    xph = unsafe_pointer_to_objref(p_h)::XPStreamHandler
    txt = unsafe_string(data)

    h.cbs.default(h, txt)

    return
end

function streaming_default_expand(p_h::Ptr{Nothing}, data::Ptr{UInt8}, len::Cint)
    h = unsafe_pointer_to_objref(p_h)::XPStreamHandler
    txt = unsafe_string(data)

    h.cbs.default_expand(h, txt)

    return
end

function streaming_start_namespace(p_h::Ptr{Nothing}, prefix::Ptr{UInt8}, uri::Ptr{UInt8})
    h = unsafe_pointer_to_objref(p_h)::XPStreamHandler
    prefix = unsafe_string(prefix)
    uri = unsafe_string(uri)

    h.cbs.start_namespace(h, prefix, uri)

    return
end

function streaming_end_namespace(p_h::Ptr{Nothing}, prefix::Ptr{UInt8})
    h = unsafe_pointer_to_objref(p_h)::XPStreamHandler
    prefix = unsafe_string(prefix)

    h.cbs.end_namespace(h, prefix)

    return
end

# Unsupported callbacks: External Entity, NotationDecl, Not Stand Alone, Processing, UnparsedEntityDecl, StartDocType
# SetBase and GetBase

function make_parser(cbs::XPCallbacks,data=nothing,sep='\0')
    cb_streaming_start_cdata = @cfunction(streaming_start_cdata, Nothing, (Ptr{Nothing},))
    cb_streaming_end_cdata = @cfunction(streaming_end_cdata, Nothing, (Ptr{Nothing},))
    cb_streaming_cdata = @cfunction(streaming_cdata, Nothing, (Ptr{Nothing}, Ptr{UInt8}, Cint))
    cb_streaming_comment = @cfunction(streaming_comment, Nothing, (Ptr{Nothing}, Ptr{UInt8}))
    cb_streaming_default = @cfunction(streaming_default, Nothing, (Ptr{Nothing}, Ptr{UInt8}, Cint))
    cb_streaming_default_expand = @cfunction(streaming_default_expand, Nothing, (Ptr{Nothing}, Ptr{UInt8}, Cint))
    cb_streaming_start_element = @cfunction(streaming_start_element, Nothing, (Ptr{Nothing}, Ptr{UInt8}, Ptr{Ptr{UInt8}}))
    cb_streaming_end_element = @cfunction(streaming_end_element, Nothing, (Ptr{Nothing}, Ptr{UInt8}))
    cb_streaming_start_namespace = @cfunction(streaming_start_namespace, Nothing, (Ptr{Nothing}, Ptr{UInt8}, Ptr{UInt8}))
    cb_streaming_end_namespace = @cfunction(streaming_end_namespace, Nothing, (Ptr{Nothing}, Ptr{UInt8}))

    p::XML_Parser = (sep == '\0') ? XML_ParserCreate(C_NULL) : XML_ParserCreateNS(C_NULL, sep);
    if (p == C_NULL) error("XML_ParserCreate failed") end

    h = XPStreamHandler(cbs, p, data)
    p_h = pointer_from_objref(h)
    XML_SetUserData(p, p_h);

    XML_SetCdataSectionHandler(p, cb_streaming_start_cdata, cb_streaming_end_cdata)
    XML_SetCharacterDataHandler(p, cb_streaming_cdata)
    XML_SetCommentHandler(p, cb_streaming_comment)
    XML_SetDefaultHandler(p, cb_streaming_default)
    XML_SetDefaultHandlerExpand(p, cb_streaming_default_expand)
    XML_SetElementHandler(p, cb_streaming_start_element, cb_streaming_end_element)
#    XML_SetExternalEntityRefHandler(p, f_ExternaEntity)
    XML_SetNamespaceDeclHandler(p, cb_streaming_start_namespace, cb_streaming_end_namespace)
#    XML_SetNotationDeclHandler(p, f_NotationDecl)
#    XML_SetNotStandaloneHandler(p, f_NotStandalone)
#    XML_SetProcessingInstructionHandler(p, f_ProcessingInstruction)
#    XML_SetUnparsedEntityDeclHandler(p, f_UnparsedEntityDecl)
#    XML_SetStartDoctypeDeclHandler(p, f_StartDoctypeDecl)

    return h
end

function stop(h::XPStreamHandler)
    XML_StopParser(h.parser, XML_FALSE)
#    XML_ParserFree(h.parser)
end

function pause(h::XPStreamHandler)
    XML_StopParser(h.parser, XML_TRUE)
end

function resume(h::XPStreamHandler)
    XML_ResumeParser(h.parser)
end

function free(h::XPStreamHandler)
    XML_ParserFree(h.parser)
end

function parsefile(filename::AbstractString,callbacks::XPCallbacks; bufferlines=1024, data=nothing)
    h = make_parser(callbacks, data)
    # TODO: Support suspending for files too
    suspended = false
    file = open(filename, "r")
    try
        io = IOBuffer()
        while !eof(file)
            i::Int = 0
            truncate(io, 0)
            while i < bufferlines && !eof(file)
                write(io, readline(file))
                i += 1
            end
            txt = String(take!(copy(io)))
            rc = XML_Parse(h.parser, txt, sizeof(txt), 0)
            if (rc != XML_STATUS_OK) && (XML_GetErrorCode(h.parser) != XML_ERROR_ABORTED)
                # Do not fail if the user aborted the parsing
                error("Error parsing document : $rc")
            end
            if XML_GetErrorCode(h.parser) == XML_ERROR_ABORTED
                break
            end
        end
        rc = XML_Parse(h.parser, "", length(""), 1)
        #if (rc == XML_STATUS_SUSPENDED)
        #    suspended = true
        #    return XPStreamHandler(callbacks,  parser)
        #end
        if (rc != XML_STATUS_OK) && (XML_GetErrorCode(h.parser) != XML_ERROR_ABORTED)
            # Do not fail if the user aborted the parsing
            error("Error parsing document : $rc")
        end
    catch e
        stre = string(e)
        (err, line, column, pos) = xp_geterror(h.parser)
        rethrow("$e, $err, $line, $column, $pos")
    finally
        if !suspended
            XML_ParserFree(h.parser)
        end
        close(file)
    end
end

function parse(txt::AbstractString,callbacks::XPCallbacks; data=nothing)
    h = make_parser(callbacks, data)
    suspended = false

    try
        rc = XML_Parse(h.parser, txt, sizeof(txt), 1)
        if (rc == XML_STATUS_SUSPENDED)
            suspended = true
            return h
        end
        if (rc != XML_STATUS_OK) && (XML_GetErrorCode(h.parser) != XML_ERROR_ABORTED)
            # Do not fail if the user aborted the parsing
            error("Error parsing document : $rc")
        end
    catch e
        stre = string(e)
        (err, line, column, pos) = xp_geterror(h.parser)
        rethrow("$e, $err, $line, $column, $pos")

    finally
        if !suspended
            XML_ParserFree(h.parser)
        end
    end
end


text:
@testset "357.count-numbers-with-unique-digits.jl" begin
    for (i, j) in zip(2:8, [91, 739, 5275, 32491, 168571, 712891, 2345851])
        @test count_numbers_with_unique_digits(i) == j
    end
end


text:
# This file calculates the field strength at the center of a Faraday cage. Warning, the run-time is long.
# See /Laplace.jl for a more interactive version.
using ApproxFun, SingularIntegralEquations

z_0 = 2.0
ui(x,y) = logabs(complex(x,y)-z_0)
g1(x,y) = 1/2

function electricfield(N,r)
    # Set the domains.
    cr = exp(im*2π*[0:N-1]/N)
    crl = (1-2r)cr
    crr = (1+2r)cr
    dom = ∪(Segment.(crl,crr))
    #dom = ∪(Circle.(cr,ones(length(cr))r))
    #dom = ∪(Segment.(crl[1:2:end],crr[1:2:end]) ∪ ∪(Circle.(cr[2:2:end],ones(length(cr[2:2:end]))r))

    sp = Space(dom)
    cwsp = CauchyWeight(sp⊗sp,0)
    uiΓ,⨍ = Fun(t->ui(real(t),imag(t))+0im,sp),DefiniteLineIntegral(dom)

    G = GreensFun(g1,cwsp;method=:Cholesky)

    ∂u∂n = ⨍[G]\uiΓ

    us(x,y) = -logkernel(∂u∂n,complex(x,y))/2
    ut(x,y) = ui(x,y) + us(x,y)
    h = 1e-5
    abs((ut(h,0.)-ut(-h,0.))/2h)
end

NNr1,NTr1 = [4:15],[4:15,17:2:20,30:10:80]
ENr1 = Float64[@time electricfield(N,1e-1im) for N in NNr1]
println("Done ENr1")
ETr1 = Float64[@time electricfield(N,1e-1) for N in NTr1]
println("Done ETr1")

NNr2,NTr2 = [[5:10],[15:5:20],[30:10:80]],[[5:10],[15:5:20],[30:10:100]]
ENr2 = Float64[@time electricfield(N,1e-2im) for N in NNr2]
println("Done ENr2")
ETr2 = Float64[@time electricfield(N,1e-2) for N in NTr2]
println("Done ETr2")

#Nr3 = [[5:10],[15:5:20],[30:10:90],[100:50:200]]
#@time Er3 = Float64[electricfield(N,1e-3) for N in Nr3]
#@time Er4 = Float64[electricfield(N,1e-4) for N in Nr3]


text:
using CairoMakie, Distributions, Random
Random.seed!(124)
n = 4
colors = to_colormap(:seaborn_colorblind, 8)
sides = [:left, :right, :right]

set_theme!(theme_dark())
fig = Figure(resolution = (600,400))
ax = Axis(fig[1,1]; palette = (; patchcolor = colors))
for i in [-5,5], j in 1:n
    violin!(fill(j, 1000), rand(Normal(i,rand()+0.5), 1000);
    side = i >-3 ? sides[rand(1:3)] : :both)
end
violin!(fill(2.5, 1000), rand(Normal(0,2.5), 1000); color = :transparent,
    strokewidth = 0.85, strokecolor = :grey90, show_median = true,
    mediancolor = :white)
violin!(fill(4.5, 1000), rand(Normal(2,2), 1000); color = (:dodgerblue,0.1),
    strokewidth = 0.85, strokecolor = :dodgerblue, show_median = true,
    medianlinewidth = 3)
ax.xticks = (1:n, string.('A':'D'))
hideydecorations!(ax; grid = false)
save("violin.png", fig, px_per_unit = 2)
display(fig)


text:
"""
Build a problem to be ingested by a solver.
"""
function build_problem(model::Spacecraft, N, tf, dt, xf_pos, u0; waypoints=[])
    n, m = size(model)
    x0_pos = SA[0, 0, 0.]
    x0 = RobotDynamics.build_state(model, x0_pos, UnitQuaternion(I), zeros(3), zeros(3))
    xf = RobotDynamics.build_state(model, xf_pos, UnitQuaternion(I), zeros(3), zeros(3))

    push!(waypoints, Waypoint(xf_pos, N))

    @show x0
    @show xf

    Q = Diagonal(RobotDynamics.fill_state(model, 0., 0., 0., 0.))
    R = Diagonal(@SVector [1 / mass(model), 1, 1, 1])
    Qw = Diagonal(RobotDynamics.fill_state(model, 1000., 0., 0., 0.))
    obj = Objective(TrajectoryCost(N, combine(LQR(Q, R, model), WaypointsLQR(waypoints, Qw, R, model))))

    conSet = ConstraintList(n,m,N)
    x_min = repeat([-Inf], n)
    x_max = -x_min
    u_min = vcat(0., repeat([-model.max_amplitude_angular_control], 3))
    u_max = vcat(model.max_thrust, repeat([model.max_amplitude_angular_control], 3))

    add_constraint!(conSet, BoundConstraint(n,m; u_min, u_max, x_min, x_max), 1:N-1)
    # add_constraint!(conSet, GoalConstraint(xf), N)
    # wp = getproperty.(waypoints, :location)
    # add_constraint!(conSet, SphereConstraint(n, getindex.(wp, 1), [getindex.(wp, i) for i ∈ 1:length(wp)]..., repeat([10.], length(waypoints))), 1:N-1)

    prob = Problem(model, obj, xf, tf, x0=x0, constraints=conSet, dt=dt)
    initial_controls!(prob, u0)
    rollout!(prob)
    prob
end


text:
struct CIFAR100 <: ColorImage{MLImage} end
getModule(::CIFAR100) = MLDatasets.CIFAR100
size(::CIFAR100) = (50000, 0, 10000)
problem(::CIFAR100) = Classification

max_stars_repo_name: GruAna/PreprocessData

max_issues_repo_name: GruAna/PreprocessData

max_forks_repo_name: GruAna/PreprocessData


text:
module FractalDimension

using DrWatson
using Reexport
@reexport using DynamicalSystems, PyPlot, Statistics

include("fractal_dim_fit.jl")

include("data_generation.jl")
export Data
include("make_C_H.jl")

function mse(x, y)
    m = length(x)
    @assert m == length(y)
    @inbounds mse = sum(abs2(x[i] - y[i]) for i in 1:m) / m
    return mse
end
using Statistics: mean
rmse(x, y) = sqrt(mse(x, y))
export rmse

include("style.jl") # this doesn't work with `@quickactivate` for some reason
include("mainplot.jl")

end

max_stars_repo_name: Datseris/FractalDimension

max_issues_repo_name: Datseris/FractalDimension

max_forks_repo_name: Datseris/FractalDimension


text:
using HorizonSideRobots
include("roblib.jl")

function main(r::Robot)
    local_ans = 0
    field_size = 1
    side = East

    local_ans += temperature(r)
    println("temperature here is " * string(temperature(r)))

    while !isborder(r,North)
        while !isborder(r,side)
            local_ans += special_move(r, side)
            field_size += 1
        end
        local_ans += special_move(r, North)

        field_size += 1
        side=inverse_side(side)
    end
    while !isborder(r,side)
        local_ans += special_move(r, side)
        field_size += 1
    end

    return (local_ans/(field_size))
end

function special_move(r::Robot, side::HorizonSide)
    move!(r,side)
    println("temperature here is " * string(temperature(r)))
    return temperature(r)
end

max_stars_repo_name: Savko-fokin/mirea-progs

max_issues_repo_name: Savko-fokin/mirea-progs

max_forks_repo_name: Savko-fokin/mirea-progs


text:
using Camoforge
using Test

@testset "Camoforge.jl" begin
    # Write your tests here.
end