text:
using ExactWrightFisher

@testset "test exact L2 Gamma distance functions" begin
    # @test_warn AssertionError DualOptimalFiltering.log_int_prod_2_Gammas(0.5, 0.5, 0.5, 1)
    @test DualOptimalFiltering.log_int_prod_2_Gammas(1, 1, 1, 1) == -log(2)
    @test DualOptimalFiltering.log_int_prod_2_Gammas(2, 0.5, 1, 0.5) == log(0.5^2*0.5 )
    # @test DualOptimalFiltering.log_int_prod_2_Gammas(0.1, 1.2, 1.1, 0.3) ≈ Float64(log(DualOptimalFiltering.prod_2_gammas_arb(0.1, 1.2, 1.1, 0.3) ))

    @test DualOptimalFiltering.int_prod_2_Gammas(1, 1, 1, 1) == 0.5
    @test DualOptimalFiltering.int_prod_2_Gammas(2, 0.5, 1, 0.5) ≈ 0.5^2*0.5

    @test_nowarn DualOptimalFiltering.log_L2_dist_Gamma_mixtures(log.([0.2,0.3,0.5]), [1,2,3], [1,2,4], log.([0.6,0.4]), [1,2], [4,2])
    @test !isfinite(DualOptimalFiltering.log_L2_dist_Gamma_mixtures(log.([0.2,0.3,0.5]), [1,2,3], [1,2,4], log.([0.2,0.3,0.5]), [1,2,3], [1,2,4]))

    # @test DualOptimalFiltering.log_L2_dist_Gamma_mixtures(log.([0.2,0.3,0.5]), [1,2,3], [1,2,4], log.([0.6,0.4]), [1,2], [4,2]) ≈ Float64(log(DualOptimalFiltering.L2_dist_Gamma_mixtures_arb([0.2,0.3,0.5], [1,2,3], [1,2,4], [0.6,0.4], [1,2], [4,2])))

    Random.seed!(0)
    δ = 3.
    γ = 3.
    σ = 0.5
    λ = 1.
    θ = γ/σ^2
    X = DualOptimalFiltering.generate_CIR_trajectory(range(0, stop = 2, length = 20), δ, γ, σ, λ);
    Y = map(λ -> rand(Poisson(λ),10), X);
    data = Dict(zip(range(0, stop = 2, length = 20), Y))
    Λ_of_t, wms_of_t, θ_of_t = DualOptimalFiltering.filter_CIR(δ, γ, σ, λ, data);
    Λ_of_t1, wms_of_t1, θ_of_t1 = DualOptimalFiltering.filter_CIR_keep_fixed_number(δ, γ, σ, λ, data, 1);

    time_grid = data |> keys |> collect |> sort
    logw1 = log.(wms_of_t[time_grid[20]])
    αlist_1, βlist_1 = DualOptimalFiltering.create_gamma_mixture_parameters(δ, θ_of_t[time_grid[20]], Λ_of_t[time_grid[20]][isfinite.(logw1)])

    logw2 = log.(wms_of_t1[time_grid[20]])
    αlist_2, βlist_2 = DualOptimalFiltering.create_gamma_mixture_parameters(δ, θ_of_t1[time_grid[20]], Λ_of_t1[time_grid[20]])

    @test_nowarn DualOptimalFiltering.log_L2_dist_Gamma_mixtures(logw1[isfinite.(logw1)], αlist_1, βlist_1, logw2, αlist_2, βlist_2)

    cc = DualOptimalFiltering.create_gamma_mixture_pdf(δ, θ_of_t[time_grid[20]], Λ_of_t[time_grid[20]][isfinite.(logw1)], wms_of_t[time_grid[20]][isfinite.(logw1)])

    cc1 = DualOptimalFiltering.create_gamma_mixture_pdf(δ, θ_of_t1[time_grid[20]], Λ_of_t1[time_grid[20]], wms_of_t1[time_grid[20]])

    # res = DualOptimalFiltering.L2_dist_1D(cc, cc1)
    # @test exp(DualOptimalFiltering.log_L2_dist_Gamma_mixtures(logw1[isfinite.(logw1)], αlist_1, βlist_1, logw2, αlist_2, βlist_2)) ≈ res[1] atol=res[2]
end;

@testset "test exact L2 distance functions for Dirichlet mixtures" begin

    @test DualOptimalFiltering.lmvbeta([1,1]) == 0.0
    @test DualOptimalFiltering.log_int_prod_2_Dir([1,1], [1,1]) == 0.0
    @test DualOptimalFiltering.log_int_prod_2_Dir([1,1,1], [1,1,1]) ≈ 0.6931471805599453

    @test_nowarn DualOptimalFiltering.log_L2_dist_Dirichlet_mixtures(log.([0.2,0.3,0.5]), [[1,2,3],[1,2,4],[5,3,2]], log.([0.6,0.4]), [[1,2,1],[4,2,3]])
    @test_nowarn DualOptimalFiltering.log_L2_dist_Dirichlet_mixtures(log.([0.2,0.3,0.5]), [[1,2,3],[1,2,4],[5,3,2]], log.([0.2,0.3,0.5]), [[1,2,3],[1,2,4],[5,3,2]])

    Random.seed!(0);
    α_vec = [1.2, 1.4, 1.3]
    # α = α_vec
    K = length(α_vec)
    Pop_size_WF3 = 10
    Nparts = 100
    time_grid_WF3 = range(0, stop = 1, length = 5)
    wfchain = Wright_Fisher_K_dim_exact_trajectory([0.2, 0.4, 0.4], time_grid_WF3, α_vec)
    wfobs_WF3 = [rand(Multinomial(Pop_size_WF3, wfchain[:,k])) for k in 1:size(wfchain,2)] |> l -> hcat(l...)
    data_WF3 = Dict(zip(time_grid_WF3 , [wfobs_WF3[:,t]' |> collect for t in 1:size(wfobs_WF3,2)]))

    # log_ν_dict_arb, log_Cmmi_dict_arb, log_binomial_coeff_dict_arb = DualOptimalFiltering.precompute_log_terms_arb(data_WF3, sum(α_vec); digits_after_comma_for_time_precision = 4)
    #
    #
    # Λ_of_t_arb, wms_of_t_arb = DualOptimalFiltering.filter_WF_precomputed(α_vec, data_WF3, log_ν_dict_arb, log_Cmmi_dict_arb, log_binomial_coeff_dict_arb)

    Λ_of_t, wms_of_t = DualOptimalFiltering.filter_WF_adaptive_precomputation_keep_fixed_number(α_vec, data_WF3, 30)

    times = keys(Λ_of_t) |> collect |> sort

    # res = DualOptimalFiltering.compute_L2_distance_between_two_Dirichlet_mixtures(α_vec, Λ_of_t_arb[times[5]], wms_of_t_arb[times[5]], Λ_of_t[times[5]], wms_of_t[times[5]])
    @test_nowarn DualOptimalFiltering.log_L2_dist_Dirichlet_mixtures(log.(wms_of_t[times[5]]), DualOptimalFiltering.create_dirichlet_mixture(α_vec, Λ_of_t[times[5]]), log.(wms_of_t[times[4]]),  DualOptimalFiltering.create_dirichlet_mixture(α_vec, Λ_of_t[times[4]]))

    # @test_nowarn DualOptimalFiltering.log_L2_dist_Dirichlet_mixtures(α_vec, Λ_of_t[times[2]], wms_of_t[times[2]], Λ_of_t[times[3]], wms_of_t[times[3]])

    # @test exp(DualOptimalFiltering.log_L2_dist_Dirichlet_mixtures(log.(wms_of_t_arb[times[3]]), DualOptimalFiltering.create_dirichlet_mixture(α_vec, Λ_of_t_arb[times[3]]), log.(wms_of_t[times[3]]),  DualOptimalFiltering.create_dirichlet_mixture(α_vec, Λ_of_t[times[3]]))) ≈ res[1] atol=res[2]

end;

max_stars_repo_name: konkam/DualOptimalFiltering

max_issues_repo_name: konkam/DualOptimalFiltering

max_forks_repo_name: konkam/DualOptimalFiltering


text:
# This file is a part of JuliaFEM.
# License is MIT: see https://github.com/JuliaFEM/FEMPlates.jl/blob/master/LICENSE

using Test, FEMBase, FEMPlates

# Create 1x1 element, assemble stiffness matrix.

X = Dict(1 => [0.0, 0.0],
         2 => [1.0, 0.0],
         3 => [0.0, 1.0])
element = Element(Tri3, [1, 2, 3])
update!(element, "geometry", X)
update!(element, "youngs modulus", 4.0*4880.0)
update!(element, "thickness", 1.0)
update!(element, "poissons ratio", 1/3)
update!(element, "distributed load", 6.0)
problem = Problem(DKT, "test plate", 3)
add_elements!(problem, [element])
time = 0.0
assemble!(problem, time)
K = Matrix(problem.assembly.K)
f = Matrix(problem.assembly.f)

K_expected = [
 4880     0     0  -2440   1220  -1220  -2440  1220     0
    0   915  -305    610    305    610   -610  -610   305
    0  -305   915    610    305   -610   -610   610   305
-2440   610   610   2440      0    610      0  -610   610
 1220   305   305      0    610   -305  -1220   305   305
-1220   610  -610    610   -305    915    610  -915     0
-2440  -610  -610      0  -1220    610   2440  -610  -610
 1220  -610   610   -610    305   -915   -610   915     0
    0   305   305    610    305      0   -610     0   305]
@test isapprox(K, K_expected)

f_expected = zeros(9)
f_expected[1:3:end] .= 1.0
@test isapprox(f, f_expected)

ext: jl


text:
X = "little"
"Mary had a $X lamb"

max_stars_repo_name: ethansaxenian/RosettaDecode

max_issues_repo_name: ethansaxenian/RosettaDecode

max_forks_repo_name: ethansaxenian/RosettaDecode


text:
using Test

import MathOptInterface
const MOI = MathOptInterface
const MOIT = MathOptInterface.Test
const MOIU = MathOptInterface.Utilities
const MOIB = MathOptInterface.Bridges

include(joinpath(dirname(@__DIR__), "utilities.jl"))

mock = MOIU.MockOptimizer(MOIU.UniversalFallback(MOIU.Model{Float64}()))
config = MOIT.TestConfig()

@testset "Vectorize" begin
    bridged_mock = MOI.Bridges.Constraint.Vectorize{Float64}(mock)

    MOIT.scalar_function_constant_not_zero(bridged_mock)

    MOIT.basic_constraint_tests(
        bridged_mock,
        config,
        include = Iterators.product(
            [
                MOI.SingleVariable,
                MOI.ScalarAffineFunction{Float64},
                # TODO: add when operate(vcat, ...) is implemented for quadratic
                # MOI.ScalarQuadraticFunction{Float64},
            ],
            [
                MOI.EqualTo{Float64},
                MOI.GreaterThan{Float64},
                MOI.LessThan{Float64},
            ],
        ),
    )

    MOIU.set_mock_optimize!(
        mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
            mock,
            [1, 0],
            (MOI.VectorAffineFunction{Float64}, MOI.Nonpositives) => [[-1]],
            (MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives) =>
                [[0], [1]],
        ),
    )
    MOIT.linear2test(bridged_mock, config)

    MOIU.set_mock_optimize!(
        mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]),
    )
    MOIT.linear4test(bridged_mock, config)

    MOIU.set_mock_optimize!(
        mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [4 / 3, 4 / 3]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [4, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2]),
    )
    MOIT.linear5test(mock, config)

    MOIU.set_mock_optimize!(
        mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, 0]),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [100, -100]),
    )
    MOIT.linear6test(mock, config)

    MOIU.set_mock_optimize!(
        mock,
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
            mock,
            [0, 1 / 2, 1],
            (MOI.VectorAffineFunction{Float64}, MOI.Nonpositives) =>
                [[-1], [-2]],
            (MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives) =>
                [[2], [0], [0]],
        ),
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
            mock,
            [1],
            (MOI.VectorAffineFunction{Float64}, MOI.Nonpositives) => [[-1]],
            (MOI.VectorAffineFunction{Float64}, MOI.Nonnegatives) => [[0]],
        ),
    )
    # linear14 has double variable bounds for the z variable
    mock.eval_variable_constraint_dual = false
    MOIT.linear14test(bridged_mock, config)
    mock.eval_variable_constraint_dual = true

    mock.optimize! =
        (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
            mock,
            ones(3),
            (MOI.VectorAffineFunction{Float64}, MOI.Zeros) => [[2]],
        )
    MOIT.psdt0vtest(bridged_mock, config)

    ci = first(
        MOI.get(
            bridged_mock,
            MOI.ListOfConstraintIndices{
                MOI.ScalarAffineFunction{Float64},
                MOI.EqualTo{Float64},
            }(),
        ),
    )

    @testset "$attr" for attr in [
        MOI.ConstraintPrimalStart(),
        MOI.ConstraintDualStart(),
    ]
        @test MOI.supports(bridged_mock, attr, typeof(ci))
        MOI.set(bridged_mock, attr, ci, 2.0)
        @test MOI.get(bridged_mock, attr, ci) == 2.0
    end

    test_delete_bridge(
        bridged_mock,
        ci,
        3,
        ((MOI.VectorAffineFunction{Float64}, MOI.Zeros, 0),),
    )
end


text:
using FinalProjectRepo
using Test, ReferenceTests, BSON

# make sure to turn off GPU usage, at least for Github Actions

include("part1.jl")
include("multigrid.jl")
include("krylov.jl")
include("part2.jl")


text:
__precompile__()

module TropicalSemiring

export Trop, Min, Max, inf

import Base: +, *, ==, ^, -

"""
    Min

Indicating that we are in the tropical semiring ``(ℝ ∪ {∞}, ⊕, ⊙)`` with the
min convention.
"""
struct Min end

"""
    Max

Indicating that we are in the tropical semiring ``(ℝ ∪ {-∞}, ⊕, ⊙)`` with the
max convention.
"""
struct Max end

const MinMax = Union{Min, Max}

"""
    Trop{MM<:MinMax, T<:Real}

A `Trop` number is an element of a the tropical semi-ring. These come in two
flavours `Max` and `Min`. In the `Max` case this is the semi-ring ``(ℝ ∪ {-∞}, ⊕, ⊙)`` where
``⊕`` is the usual multiplication and ``⊙`` is the usual maximum.
In the `Min` case this is the semi-ring ``(ℝ ∪ {∞}, ⊕, ⊙)`` where
``⊕`` is the usual multiplication and ``⊙`` is the usual minimum.
"""
struct Trop{MM<:MinMax, T<:Real} <: Number
    val::T
    isinf::Bool
end
Trop{MM, T}(x::Real) where {T<:Real, MM<:MinMax} = Trop{MM, T}(convert(T, x), false)
Trop{MM}(x::T, isinf=false) where {T<:Real, MM<:MinMax} = Trop{MM, T}(x, isinf)
Trop(x::Real, isinf=false) = Trop{Max}(x, isinf)

Base.isinf(x::Trop) = x.isinf

function (+)(a::Trop{Max, T}, b::Trop{Max, T}) where {T<:Real}
    Trop{Max}(max(a.val, b.val), isinf(a) || isinf(b))
end
function (+)(a::Trop{Min, T}, b::Trop{Min, T}) where {T<:Real}
    Trop{Min}(min(a.val, b.val), isinf(a) || isinf(b))
end

# this doesn't make sense, but we define it nonetheless to make
# MultivariatePolynomials happy
(-)(a::Trop) = a

function (*)(a::Trop{MM, T}, b::Trop{MM, T}) where {MM<:MinMax, T<:Real}
    Trop{MM}(a.val + b.val, isinf(a) || isinf(b))
end

function (^)(a::Trop{MM, T}, p::Integer) where {MM<:MinMax, T<:Real}
    Trop(convert(T, p) * a.val, isinf(a))
end

function Base.isequal(a::Trop{M, T}, b::Trop{M, S}) where {M, S, T}
    isinf(a) || isinf(b) ? isinf(a) == isinf(b) : a.val == b.val
end
Base.isequal(a::Trop{Min, T}, b::Trop{Max, S}) where {S, T} = false
Base.isequal(a::Trop{Max, T}, b::Trop{Min, S}) where {S, T} = false

(==)(a::Trop, b::Trop) = isequal(a,b)

Base.one(::Trop{MM, T}) where {MM, T} = Trop{MM}(zero(T))
Base.one(::Type{Trop{MM, T}}) where {MM, T} = Trop{MM}(zero(T))

Base.zero(::Trop{MM, T}) where {MM, T} = Trop{MM}(zero(T), true)
Base.zero(::Type{Trop{MM, T}}) where {MM, T} = Trop{MM}(zero(T), true)

function Base.show(io::IO, a::Trop{MM, T}) where {MM, T}
    if isinf(a)
        if MM === Max
            print(io, "∞")
        else
            print(io, "-∞")
        end
    else
        print(io, a.val)
    end
end

function Base.promote_rule(::Type{Trop{MM, T}}, ::Type{Trop{MM, S}}) where {MM, S,T}
    Trop{MM, promote_type(S,T)}
end

function Base.convert(::Type{Trop{MM, T}}, t::Trop{MM, S}) where {MM, T<:Real, S<:Real}
    Trop{MM}(convert(T, t.val), t.isinf)
end

"""
    inf(M::Type{<:Union{Min, Max}} = Max)

Constructs ``-∞`` in the case of `Max` and ``∞`` in the case of `Min`.
"""
inf(minmax::Type{M}=Max) where {M<:MinMax} = Trop{M}(true, true)

end # module


text:
__precompile__()

module SCS

import Compat: unsafe_string

if isfile(joinpath(dirname(@__FILE__), "..", "deps", "deps.jl"))
    include("../deps/deps.jl")
else
    error("SCS not properly installed. Please run Pkg.build(\"SCS\") and restart julia")
end

import Base.Libdl: RTLD_LAZY, RTLD_DEEPBIND, RTLD_GLOBAL, dlopen

function __init__()
    vnum = VersionNumber(SCS_version())
    # default binaries need access to Julia's lapack symbols
    @unix_only dlopen(Base.liblapack_name, RTLD_LAZY|RTLD_DEEPBIND|RTLD_GLOBAL)
    if !(vnum.major == 1 && vnum.minor == 1)
        depsdir = realpath(joinpath(dirname(@__FILE__),"..","deps"))
        error("Current SCS version installed is $(SCS_version()), but we require version 1.1.*. On Linux and Windows, delete the contents of the `$depsdir` directory except for the files `build.jl` and `.gitignore`, then rerun Pkg.build(\"SCS\"). On OS X, run `using Homebrew; Homebrew.update()` in Julia.")
    end
end

include("types.jl")
include("low_level_wrapper.jl")
include("high_level_wrapper.jl")
include("SCSSolverInterface.jl")  # MathProgBase interface

end # module


text:
@testset "TSP  $G" begin
    @testset "random instances" begin
        n = 10
        g = CompleteGraph(n, G)
        for seed=7:20
            # println("##### Seed $seed #############")
            Random.seed!(seed)
            w = EdgeMap(g, e->rand())
            status, W, tour = solve_tsp(g, w, verb=false)
            @test Int(status) == 1
            @test 0 < W < n
            @test length(tour) == n
            @test tour[1] == 1
            @test unique(tour) == tour

            status, W2, tour2 = solve_tsp(g, w, cutoff = 0.9, verb=false)
            @test Int(status) == 1
            @test 0 < W2 < n
            @test length(tour2) == n
            @test tour2[1] == 1
            @test unique(tour2) == tour2
            # @test tour2 ==  tour
        end
    end
end# testset


text:
@testset "Set parameters" begin
    lpm = MathProgBase.LinearQuadraticModel(GLPKSolverLP(it_lim=9513, tol_bnd=4.149))
    @test lpm.param.it_lim == 9513
    @test lpm.param.tol_bnd == 4.149
    mipm = MathProgBase.LinearQuadraticModel(GLPKSolverMIP(it_lim=5910, tol_obj=1.52e-3))
    @test mipm.smplxparam.it_lim == 5910
    @test mipm.param.tol_obj == 1.52e-3
end

@testset "Set MPB parameters" begin
    # setparameters! on model
    lpm = MathProgBase.LinearQuadraticModel(GLPKSolverLP())
    MathProgBase.setparameters!(lpm, TimeLimit=23.0)
    @test lpm.param.tm_lim == 23000.0

    # setparameters! on solver
    lps = GLPKSolverLP()
    MathProgBase.setparameters!(lps, TimeLimit=23.0)
    lpm2 = MathProgBase.LinearQuadraticModel(lps)
    @test lpm2.param.tm_lim == 23000.0
end


text:
using Twitter, Test

twitterauth(ENV["CONSUMER_KEY"], ENV["CONSUMER_SECRET"], ENV["ACCESS_TOKEN"], ENV["ACCESS_TOKEN_SECRET"])

#get_mentions_timeline
mentions_timeline_default = get_mentions_timeline()
tw = mentions_timeline_default[1]
tw_df = DataFrame(mentions_timeline_default)
@test 0 <= length(mentions_timeline_default) <= 20
@test typeof(mentions_timeline_default) == Vector{Tweets}
@test typeof(tw) == Tweets
@test size(tw_df)[2] == 30

#get_user_timeline
user_timeline_default = get_user_timeline(screen_name = "randyzwitch")
@test typeof(user_timeline_default) == Vector{Tweets}

#get_home_timeline
home_timeline_default = get_home_timeline()
@test typeof(home_timeline_default) == Vector{Tweets}

#get_single_tweet_id
get_tweet_by_id = get_single_tweet_id(id = "434685122671939584")
@test typeof(get_tweet_by_id) == Tweets

#get_search_tweets
duke_tweets = get_search_tweets(q = "#Duke")
@test typeof(duke_tweets) <: Dict

#test sending/deleting direct messages
#commenting out because Twitter API changed. Come back to fix
# send_dm = post_direct_messages_send(text = "Testing from Julia, this might disappear later $(time())", screen_name = "randyzwitch")
# get_single_dm = get_direct_messages_show(id = send_dm.id)
# destroy = post_direct_messages_destroy(id = send_dm.id)
# @test typeof(send_dm) == Tweets
# @test typeof(get_single_dm) == Tweets
# @test typeof(destroy) == Tweets

#creating/destroying friendships
add_friend = post_friendships_create(screen_name = "kyrieirving")
unfollow = post_friendships_destroy(screen_name = "kyrieirving")
unfollow_df = DataFrame(unfollow)
@test typeof(add_friend) == Users
@test typeof(unfollow) == Users
@test size(unfollow_df)[2] == 40


text:
"""
    ispangram(input)

Return `true` if `input` contains every alphabetic character (case insensitive).

"""
function ispangram(input)
    alphabet="abcdefghijklmnopqrstuvwxyz"

    for c in lowercase(input)
        if c in alphabet
            alphabet=replace(alphabet,c=>"")
        end
    end

    # return alphabet
    return (alphabet == "")
end

max_stars_repo_name: stepinski/julia-in

max_issues_repo_name: stepinski/julia-init

max_forks_repo_name: stepinski/julia-init


text:
# SPDX-License-Identifier: MIT

function rightlabel(label)
    typeof(label) <: Tuple ?  rightlabel(label[end]) : label
end

"""
    struct HierarchicalFSM{T} <: AbstractFSM{T}
        fsm::AbstractFSM{T}
        state_mapping::Dict{Any,<:AbstractFSM{T}}
    end

FSM where each state is an FSM. This FSM is used to "compose" different
FSMs, e.g. a lexicon and a language model.
"""
struct HierarchicalFSM{T} <: AbstractFSM{T}
    fsm::AbstractFSM{T}
    state_mapping::Dict
end

function makestate(s1, s2)
    label = if typeof(s1.label) <: Tuple && typeof(s2.label) <: Tuple
        (s1.label..., s2.label...)
    elseif typeof(s1.label) <: Tuple
        (s1.label..., s2.label)
    elseif typeof(s2.label) <: Tuple
        (s1.label, s2.label...)
    else
        (s1.label, s2.label)
    end
    State((s1..., s2...), label,
          s1.initweight * s2.initweight, s1.finalweight * s2.finalweight)
end

function states(hfsm::HierarchicalFSM{T}) where T
    retval = []
    for s1 in states(hfsm.fsm)
        for s2 in states(hfsm.state_mapping[rightlabel(s1.label)])
            push!(retval, makestate(s1, s2))
        end
    end
    retval
end

function arcs(hfsm::HierarchicalFSM{T}, state::State{T}) where T
    s1, s2 = state.id

    retval = []
    for arc in arcs(hfsm.state_mapping[rightlabel(s1.label)], s2)
        push!(retval, Arc(makestate(s1, arc.dest), arc.weight))
    end

    if isfinal(s2)
        for arc in arcs(hfsm.fsm, s1)
            mlabel = rightlabel(arc.dest.label)
            for s in filter(isinit, states(hfsm.state_mapping[mlabel]))
                weight = s2.finalweight * arc.weight * s.initweight
                push!(retval, Arc(makestate(arc.dest, s), weight))
            end
        end
    end
    retval
end

max_forks_repo_name: BUTSpeechFIT/ProbabilisticFSMs


text:
# This file is auto-generated by AWSMetadata.jl
using AWS
using AWS.AWSServices: appflow
using AWS.Compat
using AWS.UUIDs

"""
    create_connector_profile(connection_mode, connector_profile_config, connector_profile_name, connector_type)
    create_connector_profile(connection_mode, connector_profile_config, connector_profile_name, connector_type, params::Dict{String,<:Any})

 Creates a new connector profile associated with your AWS account. There is a soft quota of
100 connector profiles per AWS account. If you need more connector profiles than this quota
allows, you can submit a request to the Amazon AppFlow team through the Amazon AppFlow
support channel.

# Arguments
- `connection_mode`:  Indicates the connection mode and specifies whether it is public or
  private. Private flows use AWS PrivateLink to route data over AWS infrastructure without
  exposing it to the public internet.
- `connector_profile_config`:  Defines the connector-specific configuration and
  credentials.
- `connector_profile_name`:  The name of the connector profile. The name is unique for each
  ConnectorProfile in your AWS account.
- `connector_type`:  The type of connector, such as Salesforce, Amplitude, and so on.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"kmsArn"`:  The ARN (Amazon Resource Name) of the Key Management Service (KMS) key you
  provide for encryption. This is required if you do not want to use the Amazon
  AppFlow-managed KMS key. If you don't provide anything here, Amazon AppFlow uses the Amazon
  AppFlow-managed KMS key.
"""
create_connector_profile(connectionMode, connectorProfileConfig, connectorProfileName, connectorType; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/create-connector-profile", Dict{String, Any}("connectionMode"=>connectionMode, "connectorProfileConfig"=>connectorProfileConfig, "connectorProfileName"=>connectorProfileName, "connectorType"=>connectorType); aws_config=aws_config)
create_connector_profile(connectionMode, connectorProfileConfig, connectorProfileName, connectorType, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/create-connector-profile", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("connectionMode"=>connectionMode, "connectorProfileConfig"=>connectorProfileConfig, "connectorProfileName"=>connectorProfileName, "connectorType"=>connectorType), params)); aws_config=aws_config)

"""
    create_flow(destination_flow_config_list, flow_name, source_flow_config, tasks, trigger_config)
    create_flow(destination_flow_config_list, flow_name, source_flow_config, tasks, trigger_config, params::Dict{String,<:Any})

 Enables your application to create a new flow using Amazon AppFlow. You must create a
connector profile before calling this API. Please note that the Request Syntax below shows
syntax for multiple destinations, however, you can only transfer data to one item in this
list at a time. Amazon AppFlow does not currently support flows to multiple destinations at
once.

# Arguments
- `destination_flow_config_list`:  The configuration that controls how Amazon AppFlow
  places data in the destination connector.
- `flow_name`:  The specified name of the flow. Spaces are not allowed. Use underscores (_)
  or hyphens (-) only.
- `source_flow_config`:  The configuration that controls how Amazon AppFlow retrieves data
  from the source connector.
- `tasks`:  A list of tasks that Amazon AppFlow performs while transferring the data in the
  flow run.
- `trigger_config`:  The trigger settings that determine how and when the flow runs.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`:  A description of the flow you want to create.
- `"kmsArn"`:  The ARN (Amazon Resource Name) of the Key Management Service (KMS) key you
  provide for encryption. This is required if you do not want to use the Amazon
  AppFlow-managed KMS key. If you don't provide anything here, Amazon AppFlow uses the Amazon
  AppFlow-managed KMS key.
- `"tags"`:  The tags used to organize, track, or control access for your flow.
"""
create_flow(destinationFlowConfigList, flowName, sourceFlowConfig, tasks, triggerConfig; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/create-flow", Dict{String, Any}("destinationFlowConfigList"=>destinationFlowConfigList, "flowName"=>flowName, "sourceFlowConfig"=>sourceFlowConfig, "tasks"=>tasks, "triggerConfig"=>triggerConfig); aws_config=aws_config)
create_flow(destinationFlowConfigList, flowName, sourceFlowConfig, tasks, triggerConfig, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/create-flow", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("destinationFlowConfigList"=>destinationFlowConfigList, "flowName"=>flowName, "sourceFlowConfig"=>sourceFlowConfig, "tasks"=>tasks, "triggerConfig"=>triggerConfig), params)); aws_config=aws_config)

"""
    delete_connector_profile(connector_profile_name)
    delete_connector_profile(connector_profile_name, params::Dict{String,<:Any})

 Enables you to delete an existing connector profile.

# Arguments
- `connector_profile_name`:  The name of the connector profile. The name is unique for each
  ConnectorProfile in your account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"forceDelete"`:  Indicates whether Amazon AppFlow should delete the profile, even if it
  is currently in use in one or more flows.
"""
delete_connector_profile(connectorProfileName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/delete-connector-profile", Dict{String, Any}("connectorProfileName"=>connectorProfileName); aws_config=aws_config)
delete_connector_profile(connectorProfileName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/delete-connector-profile", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("connectorProfileName"=>connectorProfileName), params)); aws_config=aws_config)

"""
    delete_flow(flow_name)
    delete_flow(flow_name, params::Dict{String,<:Any})

 Enables your application to delete an existing flow. Before deleting the flow, Amazon
AppFlow validates the request by checking the flow configuration and status. You can delete
flows one at a time.

# Arguments
- `flow_name`:  The specified name of the flow. Spaces are not allowed. Use underscores (_)
  or hyphens (-) only.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"forceDelete"`:  Indicates whether Amazon AppFlow should delete the flow, even if it is
  currently in use.
"""
delete_flow(flowName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/delete-flow", Dict{String, Any}("flowName"=>flowName); aws_config=aws_config)
delete_flow(flowName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/delete-flow", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("flowName"=>flowName), params)); aws_config=aws_config)

"""
    describe_connector_entity(connector_entity_name)
    describe_connector_entity(connector_entity_name, params::Dict{String,<:Any})

 Provides details regarding the entity used with the connector, with a description of the
data model for each entity.

# Arguments
- `connector_entity_name`:  The entity name for that connector.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"connectorProfileName"`:  The name of the connector profile. The name is unique for each
  ConnectorProfile in the AWS account.
- `"connectorType"`:  The type of connector application, such as Salesforce, Amplitude, and
  so on.
"""
describe_connector_entity(connectorEntityName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-connector-entity", Dict{String, Any}("connectorEntityName"=>connectorEntityName); aws_config=aws_config)
describe_connector_entity(connectorEntityName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-connector-entity", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("connectorEntityName"=>connectorEntityName), params)); aws_config=aws_config)

"""
    describe_connector_profiles()
    describe_connector_profiles(params::Dict{String,<:Any})

 Returns a list of connector-profile details matching the provided connector-profile names
and connector-types. Both input lists are optional, and you can use them to filter the
result.  If no names or connector-types are provided, returns all connector profiles in a
paginated form. If there is no match, this operation returns an empty list.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"connectorProfileNames"`:  The name of the connector profile. The name is unique for
  each ConnectorProfile in the AWS account.
- `"connectorType"`:  The type of connector, such as Salesforce, Amplitude, and so on.
- `"maxResults"`:  Specifies the maximum number of items that should be returned in the
  result set. The default for maxResults is 20 (for all paginated API operations).
- `"nextToken"`:  The pagination token for the next page of data.
"""
describe_connector_profiles(; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-connector-profiles"; aws_config=aws_config)
describe_connector_profiles(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-connector-profiles", params; aws_config=aws_config)

"""
    describe_connectors()
    describe_connectors(params::Dict{String,<:Any})

 Describes the connectors vended by Amazon AppFlow for specified connector types. If you
don't specify a connector type, this operation describes all connectors vended by Amazon
AppFlow. If there are more connectors than can be returned in one page, the response
contains a nextToken object, which can be be passed in to the next call to the
DescribeConnectors API operation to retrieve the next page.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"connectorTypes"`:  The type of connector, such as Salesforce, Amplitude, and so on.
- `"nextToken"`:  The pagination token for the next page of data.
"""
describe_connectors(; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-connectors"; aws_config=aws_config)
describe_connectors(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-connectors", params; aws_config=aws_config)

"""
    describe_flow(flow_name)
    describe_flow(flow_name, params::Dict{String,<:Any})

 Provides a description of the specified flow.

# Arguments
- `flow_name`:  The specified name of the flow. Spaces are not allowed. Use underscores (_)
  or hyphens (-) only.

"""
describe_flow(flowName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-flow", Dict{String, Any}("flowName"=>flowName); aws_config=aws_config)
describe_flow(flowName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-flow", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("flowName"=>flowName), params)); aws_config=aws_config)

"""
    describe_flow_execution_records(flow_name)
    describe_flow_execution_records(flow_name, params::Dict{String,<:Any})

 Fetches the execution history of the flow.

# Arguments
- `flow_name`:  The specified name of the flow. Spaces are not allowed. Use underscores (_)
  or hyphens (-) only.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`:  Specifies the maximum number of items that should be returned in the
  result set. The default for maxResults is 20 (for all paginated API operations).
- `"nextToken"`:  The pagination token for the next page of data.
"""
describe_flow_execution_records(flowName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-flow-execution-records", Dict{String, Any}("flowName"=>flowName); aws_config=aws_config)
describe_flow_execution_records(flowName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/describe-flow-execution-records", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("flowName"=>flowName), params)); aws_config=aws_config)

"""
    list_connector_entities()
    list_connector_entities(params::Dict{String,<:Any})

 Returns the list of available connector entities supported by Amazon AppFlow. For example,
you can query Salesforce for Account and Opportunity entities, or query ServiceNow for the
Incident entity.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"connectorProfileName"`:  The name of the connector profile. The name is unique for each
  ConnectorProfile in the AWS account, and is used to query the downstream connector.
- `"connectorType"`:  The type of connector, such as Salesforce, Amplitude, and so on.
- `"entitiesPath"`:  This optional parameter is specific to connector implementation. Some
  connectors support multiple levels or categories of entities. You can find out the list of
  roots for such providers by sending a request without the entitiesPath parameter. If the
  connector supports entities at different roots, this initial request returns the list of
  roots. Otherwise, this request returns all entities supported by the provider.
"""
list_connector_entities(; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/list-connector-entities"; aws_config=aws_config)
list_connector_entities(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/list-connector-entities", params; aws_config=aws_config)

"""
    list_flows()
    list_flows(params::Dict{String,<:Any})

 Lists all of the flows associated with your account.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"maxResults"`:  Specifies the maximum number of items that should be returned in the
  result set.
- `"nextToken"`:  The pagination token for next page of data.
"""
list_flows(; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/list-flows"; aws_config=aws_config)
list_flows(params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/list-flows", params; aws_config=aws_config)

"""
    list_tags_for_resource(resource_arn)
    list_tags_for_resource(resource_arn, params::Dict{String,<:Any})

 Retrieves the tags that are associated with a specified flow.

# Arguments
- `resource_arn`:  The Amazon Resource Name (ARN) of the specified flow.

"""
list_tags_for_resource(resourceArn; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("GET", "/tags/$(resourceArn)"; aws_config=aws_config)
list_tags_for_resource(resourceArn, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("GET", "/tags/$(resourceArn)", params; aws_config=aws_config)

"""
    start_flow(flow_name)
    start_flow(flow_name, params::Dict{String,<:Any})

 Activates an existing flow. For on-demand flows, this operation runs the flow immediately.
For schedule and event-triggered flows, this operation activates the flow.

# Arguments
- `flow_name`:  The specified name of the flow. Spaces are not allowed. Use underscores (_)
  or hyphens (-) only.

"""
start_flow(flowName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/start-flow", Dict{String, Any}("flowName"=>flowName); aws_config=aws_config)
start_flow(flowName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/start-flow", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("flowName"=>flowName), params)); aws_config=aws_config)

"""
    stop_flow(flow_name)
    stop_flow(flow_name, params::Dict{String,<:Any})

 Deactivates the existing flow. For on-demand flows, this operation returns an
unsupportedOperationException error message. For schedule and event-triggered flows, this
operation deactivates the flow.

# Arguments
- `flow_name`:  The specified name of the flow. Spaces are not allowed. Use underscores (_)
  or hyphens (-) only.

"""
stop_flow(flowName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/stop-flow", Dict{String, Any}("flowName"=>flowName); aws_config=aws_config)
stop_flow(flowName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/stop-flow", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("flowName"=>flowName), params)); aws_config=aws_config)

"""
    tag_resource(resource_arn, tags)
    tag_resource(resource_arn, tags, params::Dict{String,<:Any})

 Applies a tag to the specified flow.

# Arguments
- `resource_arn`:  The Amazon Resource Name (ARN) of the flow that you want to tag.
- `tags`:  The tags used to organize, track, or control access for your flow.

"""
tag_resource(resourceArn, tags; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/tags/$(resourceArn)", Dict{String, Any}("tags"=>tags); aws_config=aws_config)
tag_resource(resourceArn, tags, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/tags/$(resourceArn)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("tags"=>tags), params)); aws_config=aws_config)

"""
    untag_resource(resource_arn, tag_keys)
    untag_resource(resource_arn, tag_keys, params::Dict{String,<:Any})

 Removes a tag from the specified flow.

# Arguments
- `resource_arn`:  The Amazon Resource Name (ARN) of the flow that you want to untag.
- `tag_keys`:  The tag keys associated with the tag that you want to remove from your flow.

"""
untag_resource(resourceArn, tagKeys; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("DELETE", "/tags/$(resourceArn)", Dict{String, Any}("tagKeys"=>tagKeys); aws_config=aws_config)
untag_resource(resourceArn, tagKeys, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("DELETE", "/tags/$(resourceArn)", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("tagKeys"=>tagKeys), params)); aws_config=aws_config)

"""
    update_connector_profile(connection_mode, connector_profile_config, connector_profile_name)
    update_connector_profile(connection_mode, connector_profile_config, connector_profile_name, params::Dict{String,<:Any})

 Updates a given connector profile associated with your account.

# Arguments
- `connection_mode`:  Indicates the connection mode and if it is public or private.
- `connector_profile_config`:  Defines the connector-specific profile configuration and
  credentials.
- `connector_profile_name`:  The name of the connector profile and is unique for each
  ConnectorProfile in the AWS Account.

"""
update_connector_profile(connectionMode, connectorProfileConfig, connectorProfileName; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/update-connector-profile", Dict{String, Any}("connectionMode"=>connectionMode, "connectorProfileConfig"=>connectorProfileConfig, "connectorProfileName"=>connectorProfileName); aws_config=aws_config)
update_connector_profile(connectionMode, connectorProfileConfig, connectorProfileName, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/update-connector-profile", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("connectionMode"=>connectionMode, "connectorProfileConfig"=>connectorProfileConfig, "connectorProfileName"=>connectorProfileName), params)); aws_config=aws_config)

"""
    update_flow(destination_flow_config_list, flow_name, tasks, trigger_config)
    update_flow(destination_flow_config_list, flow_name, tasks, trigger_config, params::Dict{String,<:Any})

 Updates an existing flow.

# Arguments
- `destination_flow_config_list`:  The configuration that controls how Amazon AppFlow
  transfers data to the destination connector.
- `flow_name`:  The specified name of the flow. Spaces are not allowed. Use underscores (_)
  or hyphens (-) only.
- `tasks`:  A list of tasks that Amazon AppFlow performs while transferring the data in the
  flow run.
- `trigger_config`:  The trigger settings that determine how and when the flow runs.

# Optional Parameters
Optional parameters can be passed as a `params::Dict{String,<:Any}`. Valid keys are:
- `"description"`:  A description of the flow.
- `"sourceFlowConfig"`:
"""
update_flow(destinationFlowConfigList, flowName, tasks, triggerConfig; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/update-flow", Dict{String, Any}("destinationFlowConfigList"=>destinationFlowConfigList, "flowName"=>flowName, "tasks"=>tasks, "triggerConfig"=>triggerConfig); aws_config=aws_config)
update_flow(destinationFlowConfigList, flowName, tasks, triggerConfig, params::AbstractDict{String}; aws_config::AbstractAWSConfig=global_aws_config()) = appflow("POST", "/update-flow", Dict{String, Any}(mergewith(_merge, Dict{String, Any}("destinationFlowConfigList"=>destinationFlowConfigList, "flowName"=>flowName, "tasks"=>tasks, "triggerConfig"=>triggerConfig), params)); aws_config=aws_config)


text:
using CUDA

# Test GPU movement inside the call to `gradient`
@testset "GPU movement" begin
  r = rand(Float32, 3,3)
  @test gradient(x -> sum(cu(x)), r)[1] isa Array{Float32, 2}
end

@testset "basic bcasting" begin
  a = Float32.(1:9)
  a_gpu = a |> cu

  v(x, n) = sum(x .^ n)
  g = gradient(x -> v(x, 7), a)[1]
  g_gpu = gradient(x -> v(x, 7), a_gpu)[1]
  @test g_gpu isa CuArray
  @test g_gpu |> collect ≈ g

  w(x) = sum(broadcast(log, x))
  g = gradient(x -> w(x), a)[1]
  g_gpu = gradient(x -> w(x), a_gpu)[1]
  @test g_gpu isa CuArray
  @test g_gpu |> collect ≈ g

end

@testset "jacobian" begin
  v1 = cu(collect(1:3f0))

  res1 = jacobian(x -> x .* x', collect(1:3f0))[1]
  j1 = jacobian(x -> x .* x', v1)[1]
  @test j1 isa CuArray
  @test j1 ≈ cu(res1)

  res2 = jacobian(x -> x ./ sum(x), collect(1:3f0))[1]
  j2 = jacobian(() -> v1 ./ sum(v1), Params([v1]))
  @test j2[v1] isa CuArray
  @test j2[v1] ≈ cu(res2)
end


text:
abstract type AbstractPhspIterator end
abstract type AbstractParticle end
abstract type AbstractIAEAParticle <: AbstractParticle end

abstract type Format end
struct FormatEGS <: Format end
struct FormatIAEA <: Format end

Format(p::AbstractIAEAParticle) = FormatIAEA()
Base.length(iter::AbstractPhspIterator) = iter.length

function Base.iterate(iter::AbstractPhspIterator)
    seekstart(iter.io)
    _iterate(iter)
end
function Base.iterate(iter::AbstractPhspIterator, state)
    _iterate(iter)
end

@inline function _iterate(iter::AbstractPhspIterator)
    io = iter.io
    h = iter.header
    P = ptype(h)
    if eof(iter.io)
        nothing
    else
        p = read_particle(io, h)
        dummy_state = nothing
        p, dummy_state
    end
end

function Base.IteratorSize(iter::AbstractPhspIterator)
    Base.HasLength()
end
function Base.IteratorSize(iter::Base.Iterators.Take{<:AbstractPhspIterator})
    Base.IteratorSize(iter.xs)
end
function Base.close(iter::AbstractPhspIterator)
    close(iter.io)
end

"""
    ptype(h)

Return type of particles from header.
"""
function ptype end
ptype(T::Type) = error("$T has no ptype")
ptype(h) = ptype(typeof(h))


text:
addprocs(4)
include("test_distributed_dists.jl")

max_stars_repo_name: tanmaykm/DistributedDistances

max_issues_repo_name: tanmaykm/DistributedDistances

max_forks_repo_name: tanmaykm/DistributedDistances


text:
@testset "line tools" begin

    line = Line(pi/2, 1)
    @test point_in_line(line, 0.)==1.
end

max_stars_repo_name: SimonCoste/LineIntersections

max_issues_repo_name: SimonCoste/LineIntersections

max_forks_repo_name: SimonCoste/LineIntersections


text:
using XMLconvert
using Base.Test

file1 = "ex1.xml"
file2 = "ex2.xml"
xdoc = parse_file(file1)
xroot = root(xdoc)

xdoc2 = parse_file(file2)
xroot2 = root(xdoc2)

function xml2dict_check(root_node)
    mdict = xml2dict(root_node)
    return isa(mdict, DataStructures.MultiDict)
end

function json_conversion_check(root_node)
    json_str = xml2json(root_node)
    return isa(json_str, String)
end

function attributes_to_elements_check(root_node)
    attributes_to_elements!(root_node)
    mdict = xml2dict(root_node)
    return mdict
end

@test xml2dict_check(xroot)
@test json_conversion_check(xroot)

muldict = attributes_to_elements_check(xroot2)

@test isa(muldict, DataStructures.MultiDict)

@test muldict["owner"][1]["age"][1] == 99
@test muldict["owner"][1]["name"][1] == "Henry Chinaski"
@test muldict["book"][1]["title"][1]["title"][1] == "Everyday Italian"

fdict = flatten(muldict)

@test haskey(fdict, "book-author")
@test haskey(fdict, "book-title-lang")
@test length(fdict["book-author"]) == 3

@test isa(show_key_structure(muldict), Void)


text:
push!(LOAD_PATH,"../src/")
using Documenter, Quiqbox

makedocs(
    sitename="Quiqbox.jl",
    modules = [Quiqbox],
    authors="Weishi Wang",
    pages=[
        "Home"=>"index.md"
        "Manual"=>[
            "basis.md"
            "SCF.md"
            "optimization.md"
        ]
        "Base"=>[
            "coreFunction.md"
            "coreType.md"
            "toolFunction.md"
        ]
        "Submodule"=>[
            "molden.md"
        ]
        "Index"=>"list.md"
    ]
)

deploydocs(repo="github.com/frankwswang/Quiqbox.jl.git",
           devbranch = "main",
           target = "build",
           push_preview = true)


text:
### A Pluto.jl notebook ###
# v0.12.16

using Markdown
using InteractiveUtils

# ╔═╡ 4b51367c-09ec-11eb-16d9-3dcd2910078e
begin
	using PyPlot
	#using PyCall #I'll gonna use SpecialFunctions.jl and HypergeometricFunctions.jl
	using LaTeXStrings
	using SpecialFunctions
	using HypergeometricFunctions
end

# ╔═╡ eb325bf2-09e3-11eb-3b88-9b0d15626515
md"## Fractional Fourier-Kravchuk evolution on waveguides"

# ╔═╡ 74a12d8e-0f69-11eb-0650-e79c06fd1080
md"Kravchuk matrix is defined as

$K(i,j)=\sqrt{\frac{\omega(j)}{h(i)}}k(i,j),$
with the functions $\omega$ and $h$ given by

$\omega(j)=\binom{N}{j}p^{j}(1-p)^{N-j},\quad h(i)=\frac{\frac{1-p}{p^{i}}}{\binom{N}{i}},$
and the Kravchuk polynomials obtained by the Hypergeometrical function

$k(i,j)=~_{2}F_{1}(-j,-i,-N,1/p).$

Note: When $p=1/2$, the symmetric Kravchuk polynomials are obtained, henceforth, the symmetric Kravchuk functions follows.
"

# ╔═╡ 7f8aad74-09ec-11eb-3c25-a538f18da2f9
begin
	rc("text", usetex=true)
	ion()
end

# ╔═╡ c28078de-09ec-11eb-0c25-a1bd3c7cdd8b
md" Define the parameters"

# ╔═╡ cb9e6110-09ec-11eb-29bb-b33f49eb026a
begin
	N = 32
	dim = N+1
	const p = 1/2.0
end;

# ╔═╡ bb1e9a12-0fe6-11eb-0551-137403aecef6
function bspecial(n,k)
	return 1/((n+1)*beta(k+1,n-k+1))
end;

# ╔═╡ ee7b88a2-0fe6-11eb-3465-8b70e58f07c1
function kravs(i,j)
	return HypergeometricFunctions._₂F₁maclaurin(-j,-i,-N,1/p)
end;

# ╔═╡ 4f876a76-0fe7-11eb-3f46-0f18d733b446
function omegas(j)
	return bspecial(N,j)*(p^j)*(1-p)^(N-j)
end;

# ╔═╡ 590a100a-0fe7-11eb-017c-4d4ff299ed8a
function hs(i)
	return (((1-p)/p)^i)/(bspecial(N,i))
end;

# ╔═╡ a5f2bf3c-0fe7-11eb-3377-8d5228bb6476
function Ks(i,j)
	return sqrt(omegas(j)/hs(i))*kravs(i,j)
end;

# ╔═╡ d01de678-0fe8-11eb-2831-89f652e45a9a
@timed begin
	KTs = zeros(Float64,(dim,dim))
	for l in 0:N
    	for m in 0:N
        	KTs[l+1,m+1] = Ks(l,m)
    	end
	end
end

# ╔═╡ 4692817e-0fe9-11eb-22e0-dfdab6509141
begin
	fig1 = figure(figsize=(5,5))
	ax1 = gca()
	ax1.imshow(KTs, cmap="gray")
	ax1.set_title(L"\textbf{Kravchuk Matrix}\; K(i,j)\;\textbf{(The trilobite)}")
	ax1.set_xlabel(L"\textbf{Pseudo Energy Level:}\; 0\leq i\leq N")
	ax1.set_ylabel(L"\textbf{Position Index:}\; 0\leq j\leq N")
	ax1.tick_params(direction="out",length=5,width=2,labelsize=10)
	ax1.set_xticks(0:8:N, minor = false)
	ax1.set_yticks(0:8:N, minor = false)

	axins1a = ax1.inset_axes([0, 0.8, 0.2, 0.2])
	axins1a.plot(KTs[1,:],"k:",linewidth=1)
	axins1a.set_xticklabels("")
	axins1a.set_yticklabels("")
	axins1a.text(7.5,0.01,L"K(0,j)",fontsize=9)

	axins2a = ax1.inset_axes([0.8, 0, 0.2, 0.2])
	axins2a.plot(KTs[N+1,:],"k:",linewidth=1)
	axins2a.set_xticklabels("")
	axins2a.set_yticklabels("")
	axins2a.text(15,-0.35,L"K(N,j)",fontsize=9)

	tight_layout()
	#savefig("trilo.png",dpi=300,transparent=true)
end

# ╔═╡ 33089668-09ed-11eb-30db-8f33d969a115
md"
October 16

Status: Kravchuk matrix completed. Changed definitions of functions using native Julia libraries

Next: Write the fractional evolution, and plotting the results
"

# ╔═╡ Cell order:
# ╟─eb325bf2-09e3-11eb-3b88-9b0d15626515
# ╟─74a12d8e-0f69-11eb-0650-e79c06fd1080
# ╠═4b51367c-09ec-11eb-16d9-3dcd2910078e
# ╠═7f8aad74-09ec-11eb-3c25-a538f18da2f9
# ╟─c28078de-09ec-11eb-0c25-a1bd3c7cdd8b
# ╠═cb9e6110-09ec-11eb-29bb-b33f49eb026a
# ╠═bb1e9a12-0fe6-11eb-0551-137403aecef6
# ╠═ee7b88a2-0fe6-11eb-3465-8b70e58f07c1
# ╠═4f876a76-0fe7-11eb-3f46-0f18d733b446
# ╠═590a100a-0fe7-11eb-017c-4d4ff299ed8a
# ╠═a5f2bf3c-0fe7-11eb-3377-8d5228bb6476
# ╠═d01de678-0fe8-11eb-2831-89f652e45a9a
# ╠═4692817e-0fe9-11eb-22e0-dfdab6509141
# ╟─33089668-09ed-11eb-30db-8f33d969a115


text:
using Test
using Distributions: Normal, params
using DataStructures: Queue, enqueue!, dequeue!

include("../edges/edge_gaussian.jl")
include("../nodes/node_gaussian.jl")

@testset "constructor" begin

    m0 = 0.0
    W0 = 1.0
    state_type = "current"
    nodes = Dict{String, Symbol}()
    id = "x"

    x = EdgeGaussian(m0, W0, state_type, nodes, id)

    @test isa(x.params, Dict{String, Float64})
    @test x.params["mean"] == m0
    @test x.params["precision"] == W0
    @test x.state_type == "current"
    @test x.id == "x"

    # TODO test invalid inputs
end

@testset "update" begin

    m0 = 0.0
    W0 = 1.0
    state_type = "current"
    nodes = Dict{String, Symbol}()
    id = "x"

    message_left = Normal(0.0, 1.0)
    message_right = Normal(1.0, 4.0)

    x = EdgeGaussian(m0, W0, state_type, nodes, id)
    update(x, message_left, message_right)

    @test x.params["precision"] == 5.0
    @test x.params["mean"] == 0.8

    new_mean, new_prec = params(message(x))
    @test new_prec == 5.0
    @test new_mean == 0.8
end

@testset "queue_message" begin

    f = NodeGaussian(:x, :y, 1.0, 1.0, "f")
    g = NodeGaussian(:z, :x, 1.0, 1.0, "g")

    m0 = 0.0
    W0 = 1.0
    state_type = "current"
    nodes = Dict{String, Symbol}("left" => :f, "bottom" => :g)
    id = "x"

    message_left = Normal(0.0, 1.0)
    message_right = Normal(1.0, 4.0)

    x = EdgeGaussian(m0, W0, state_type, nodes, id)
    update(x, message_left, message_right)
    act(x, message(x), 1.0)
    act(x, message(x), 1.0)

    @test dequeue!(f.incoming_messages) == (Normal(0.8, 5.0), 1.0, "data")
    @test dequeue!(g.incoming_messages) == (Normal(0.8, 5.0), 1.0, "mean")
end

max_stars_repo_name: wmkouw/schedulefreeMP

max_issues_repo_name: wmkouw/schedulefreeMP

max_forks_repo_name: wmkouw/schedulefreeMP


text:
using Dates, BusinessDays, Roots, AOPE
# MIT License
# Copyright (c) 2019: Antonio Saragga Seabra

# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""
    yca(cleanprice,annualcoupons,redemptionvalue,startdate,enddate)

**Yield Corrente Ajustada** ou yield simples.

The simple yield is computed as:
```math
\\frac{\\text{annual total value of coupons}+(\\text{redemption value}-\\text{clean price})/L}{\\text{clean price}}
\\text{where}
L = \\frac{\\text{# days in the period excluding 29 Feb.}}{365}
```
"""
function yca(cleanprice, annualcoupons, redemptionvalue, startdate::Date, enddate::Date)
    L = (Dates.value(enddate - startdate) - ndays29feb(startdate,enddate))/365
    return (annualcoupons + (redemptionvalue - cleanprice)/L)/cleanprice
end

"""
    ytm(price,cf,m,dc)
        price: scalar
        cf: K vector of cash flows
        m:  K vector of times for the cash flows
        dc: type of composition: Discrete/Continuous

Computes the **Yield-to-Maturity** of a bond. The redemption date may be: maturity, call date, put date

The ytr is computed as:
```math
ytr = y: \\text{price} = \\sum_{i=1}^k \\frac{cf_i}{(1+y)^{m_i}}
ytr = y: \\text{price} = \\sum_{i=1}^k cf_i*\\exp{-y*m_i}}
```
"""
function ytm(price,cf,m, dc)
    return Roots.find_zero(y->spreço(cf, m, y, dc)-price,0.01)
end

function ytmisda(P, g, k, h, n, f1, f2, C, v)
    return Roots.fzero(y->spreço(g, k, h, n, f1, f2, C, v, y)-P,0.01)
end

"""
zspread(price, cf, m, r, dc)

Computes the z-spread of a bond given benchmark interest rates and the dirty price (P) of the bond
    P:  liquidation price
    r:  scalar or K vector of benchmark interest rates
    cf: scalar or K vector of cash flows
    m:  K vector of times for the cash flows
    dc: Discrete/Continuous composition
returns
    scalar, the z-spread
"""
function zspread(P, cf, m, r, dc)
    return Roots.find_zero(z->spreço(cf, m, r, z, dc)-P,0.01)
end


text:
# Adapted from:
# SOSDEMO9 --- Matrix SOS decomposition
# Section 3.9 of SOSTOOLS User's Manual

function sosdemo9_test(optimizer, config::MOIT.Config)
    @polyvar x1 x2 x3

    P = [x1^4+x1^2*x2^2+x1^2*x3^2 x1*x2*x3^2-x1^3*x2-x1*x2*(x2^2+2*x3^2);
         x1*x2*x3^2-x1^3*x2-x1*x2*(x2^2+2*x3^2) x1^2*x2^2+x2^2*x3^2+(x2^2+2*x3^2)^2]

    # Test if P(x1,x2,x3) is an SOS matrix
    model = _model(optimizer)
    PolyJuMP.setpolymodule!(model, SumOfSquares)
    # TODO return H so that P = H.'*H
    @constraint(model, P in PSDCone())

    JuMP.optimize!(model)
    @test JuMP.termination_status(model) == MOI.OPTIMAL
    @test JuMP.primal_status(model) == MOI.FEASIBLE_POINT
end
sd_tests["sosdemo9"] = sosdemo9_test

max_stars_repo_name: blegat/SumOfSquares

max_issues_repo_name: blegat/SumOfSquares

max_forks_repo_name: blegat/SumOfSquares


text:
module Worker
using Manager: StartWork, Ping
using Cairn.Client

immutable t
    port::Int64
end

function Handle(job::MapJob, conn::TCPSocket)
    mktempdir() do d
        master = Cairn.Client.find_connection(job.dfs)
        exe_f, _ = mktemp(d)
        close(_)
        Cairn.Client.download(master, [job.executable], d, [exe_f])
        UDF = evalfile(map_f) #TODO Note, horrbily insecure! Also TODO: Implement non-jl files

        f_ch = Channel{ASCIIString}(3)
        location = mktempdir(d)
        @async Cairn.Client.download(master, job.files, location, Nullable(f_ch))

        mktempdir() do  results
            count = length(job.files)
            # Run UDF in sync
            while count != 0
                count -= 1
                orig, f = take!(f_ch)
                UDF(orig, f, results)
            end

            # Do Shuffle
            @sync for name = readdir(results)
                @async begin
                    object = "$(job.results_dir).$name"
                    of = joinpath(results, name)
                    r = Cairn.command_result(master, Cairn.RPC.CreateRequest(object, job.replication))::Cairn.RPC.CreateResponse
                    m = Mmap.mmap(of, Vector{UInt8})
                    hash = SHA.sha256(m)
                    file = SimpleFileServer.File(hash, hash, length(m))
                    for client =map( x ->  SimpleFileServer.Client.make(x...),  r.replicas)
                        SimpleFileServer.upload(client, file, m)
                    end
                    r = Cairn.command_result(master, Cairn.RPC.AppendChunksRequest(object, [hash]))::Cairn.RPC.AppendChunksRequest
                end
            end
        end
        # r = Cairn.command_result(master, Cairn.RPC.AppendChunksRequest(object, [hash]))::Cairn.RPC.AppendChunksRequest ? What to append to this one..
    end
    # Notify done?
end

function Handle(job::ReduceJob, conn::TCPSocket)
    mktempdir() do d
        master = Cairn.Client.find_connection(job.dfs)
        exe_f, _ = mktemp(d)
        close(_)
        Cairn.Client.download(master, [job.executable], d, [exe_f])
        UDF = evalfile(map_f) #TODO Note, horrbily insecure! Also TODO: Implement non-jl files

        f_ch = Channel{ASCIIString}(3)
        location = mktempdir(d)
        @async Cairn.Client.download(master, job.files, location, Nullable(f_ch))

        mktempdir() do  results
            count = length(job.files)
            # Run UDF in parallel (hopefull better disk utlization?)
            @sync while count != 0
                count -= 1
                orig, f = take!(f_ch)
                @async begin
                    UDF(orig, f, results)
                    # upload immediately
                    object = "$(job.results_dir).$orig"
                    of = joinpath(results, name)
                    r = Cairn.command_result(master, Cairn.RPC.CreateRequest(object, job.replication))::Cairn.RPC.CreateResponse
                    m = Mmap.mmap(of, Vector{UInt8})
                    hash = SHA.sha256(m)
                    file = SimpleFileServer.File(hash, hash, length(m))
                    for client =map( x ->  SimpleFileServer.Client.make(x...),  r.replicas)
                        SimpleFileServer.upload(client, file, m)
                    end
                    r = Cairn.command_result(master, Cairn.RPC.AppendChunksRequest(object, [hash]))::Cairn.RPC.AppendChunksRequest
                end
            end

            # Do Shuffle
            @sync for name = readdir(results)
            end
        end
    end
    # No need to notify done! will be implicit
end

function RPCServer(node::t)
    server = listen(node.port)
    @info "RPC Server Starting on port $(node.port))"
    while true
        conn = accept(server)
        @async begin
            while true
                try
                    args = deserialize(conn)::BaseMessage
                    @info "RPCServer $(node)) Args: $args"
                    try
                        r = Handle(args, conn)
                        @info "RPCServer $(node) Response: $r"
                        serialize(conn,r)
                        flush(conn)
                    catch err
                        @debug "RPCServer $(node) Error Handling:\n    $args\n     $err"
                        close(conn)
                        break
                    end
                catch err
                    @debug "RPCServer $(node) Connection Failed With $err"
                    close(conn)
                    break
                    # finally
                    #     close(conn)
                end
            end
        end
    end
end

function run_job()
    # TODO: Download Code, Download files from DFS and begin streaming them into the Map phase
    # TODO: Create a module for maintaining a directory with keys
    # TODO: Use the DFS to perform a shuffle
    # TODO: Get a portion of the keys to reduce
    # TODO: Run reduce on said key
end

function start(p::Int64)
    RPCServer(t(p))
end

end


text:
using Weber
using Base.Test
include("find_timing.jl")

seq_events,_,_ = find_timing() do
  addtrial(moment(10ms,() -> record(:a)),
           moment(10ms,() -> record(:b)),
           moment(10ms,() -> record(:c)))
end

@testset "Moment Sequencing" begin
  @test seq_events == [:a,:b,:c]
end


text:
module WinEncoding
    const cp950=include("cp950.jl")
    const cp1252b=include("cp1252b.jl")
    const cp936=include("cp936.jl")
    const cp932=include("cp932.jl")
    const cp932b=include("cp932b.jl")
    const _x80=[0xc2,0x80]             # '\u80'
    const _x80_936=[0xe2,0x82,0xac]     # '\u20ac' '€'
    const _xff=[0xef, 0xa3, 0xb8]      # '\uf8f8'
    const _xff_936=[0xef, 0xa3, 0xb5]      # '\uf8f5'
    const _invalid=[0xef, 0xbf, 0xbd]  # '�'
    export decode1252

    """
        decode950(a::Vector{UInt8})
    Convert an array of bytes a representing text in encoding cp950 to a string.
    fallback to big5-hkscs or '\ufffd';no invalid sequence error;non-blocking
    """
    function decode950(ss::Vector{UInt8})
        blength=length(ss)
        o=zeros(UInt8,blength*2+1)
        b=1
        skip1=false
        @inbounds for (i,c) in enumerate(ss)
            skip1==true && (skip1=false;continue)
            c<0x80 && (o[b]=c; b+=1;continue)
            c==0x80 && (copyto!(o,b,_x80,1,2); b+=2;continue)
            c==0xff && (copyto!(o,b,_xff,1,3); b+=3;continue)
            i % 1_000_000 == 1 && yield()
            skip1=true
            hh=c-0x80
            ll= ((i1=i+1) <= blength ) ? ss[i1] : 0x00
            cc= (ll < 0x40 || ll==0xff || 0x7e<ll<0xa1) ? _invalid  : (ll-=0x3f;ll > 0x3f && (ll-=0x22);cp950[hh][ll])
            ccl=length(cc)
            unsafe_copyto!(o,b,cc,1,ccl)
            b+=ccl
        end
        @view(o[1:b-1]) |> String
    end
    """
        decode936(a::Vector{UInt8})
    Convert an array of bytes a representing text in encoding cp936/gbk to a string.
    fallback to '\ufffd';no invalid sequence error;non-blocking
    """
    function decode936(ss::Vector{UInt8})
        blength=length(ss)
        o=zeros(UInt8,blength*2+1)
        b=1
        skip1=false
        @inbounds for (i,c) in enumerate(ss)
            skip1==true && (skip1=false;continue)
            c<0x80 && (o[b]=c; b+=1;continue)
            c==0x80 && (copyto!(o,b,_x80_936,1,3); b+=3;continue)
            c==0xff && (copyto!(o,b,_xff_936,1,3); b+=3;continue)
            i % 1_000_000 == 1 && yield()
            skip1=true
            hh=c-0x80
            ll= ((i1=i+1) <= blength ) ? ss[i1] : 0x00
            cc= (ll < 0x40 || ll==0xff ) ? _invalid  : cp936[hh][ll-0x3f]
            ccl=length(cc)
            unsafe_copyto!(o,b,cc,1,ccl)
            b+=ccl
        end
        @view(o[1:b-1]) |> String
    end
    """
        decode932(a::Vector{UInt8})
    Convert an array of bytes a representing text in encoding cp932/sjis to a string.
    fallback to '・';no invalid sequence error;non-blocking
    """
    function decode932(ss::Vector{UInt8})
        blength=length(ss)
        o=zeros(UInt8,blength*2+1)
        b=1
        skip1=false
        @inbounds for (i,c) in enumerate(ss)
            skip1==true && (skip1=false;continue)
            c<0x80 && (o[b]=c; b+=1;continue)
            if (c == 0x80 || 0xa0 <= c <0xe0 || c > 0xef)
                let cc=cp932b[c-0x7f]; ccl=length(cc)
                    copyto!(o,b,cc,1,ccl); b+=ccl;continue
                end
            end
            i % 1_000_000 == 1 && yield()
            skip1=true
            hh=c-0x80
            hh > 0x1f && (hh-=0x40)
            ll= ((i1=i+1) <= blength ) ? ss[i1] : 0x00
            cc= (ll < 0x40 || ll > 0xfc ) ? _invalid  : cp932[hh][ll-0x3f]
            ccl=length(cc)
            unsafe_copyto!(o,b,cc,1,ccl)
            b+=ccl
        end
        @view(o[1:b-1]) |> String
    end
    #internal use
    function _7bit(ss)
        for c in ss
            c < 0x80 || return false
        end
        true
    end
    #internal use
    function _7bit2(ss)
        for (i,c) in enumerate(ss)
            c < 0x80 || return (false,i-one(i))
        end
        true,length(ss)
    end
    """
        decode1252(a::Vector{UInt8})
    Convert an array of bytes a representing text in encoding cp1252 to a string.
    [0x8d] => '\\u8d' as windows api does;no invalid sequence error;non-blocking
    """
    function decode1252(ss::Vector{UInt8})
        o=zeros(UInt8,length(ss)*3)
        is7bit,len = _7bit2(ss)
#         o[1:len]=ss[1:len]
#         unsafe_copyto!(o,1,ss,1,len)
        copyto!(o,1,ss,1,len)
        b=len+1
        @inbounds for c in @view(ss[b:end])
            if c<0x80
                o[b]=c
                b+=1
            else
                b % 1_000_000 == 1 && yield()
                cc=cp1252b[c+1]
                ccl=length(cc)
                unsafe_copyto!(o,b,cc,1,ccl)
                b+=ccl
            end
        end
        view(o,1:b-1) |> String
    end
end # module


text:
# utility functions needed for sandshark

using DelimitedFiles
using Interpolations
using ProgressMeter

include(joinpath(@__DIR__, "CommonUtils.jl"))

datadir = joinpath(ENV["HOME"],"data","sandshark","full_wombat_2018_07_09","extracted")
matcheddir = joinpath(datadir, "matchedfilter", "particles")
beamdir = joinpath(datadir, "beamformer", "particles")

function loaddircsvs(datadir)
  # https://docs.julialang.org/en/v0.6.1/stdlib/file/#Base.Filesystem.walkdir
  datadict = Dict{Int, Array{Float64}}()
  for (root, dirs, files) in walkdir(datadir)
    # println("Files in $root")
    for file in files
      # println(joinpath(root, file)) # path to files
      data = readdlm(joinpath(root, file),',')
      datadict[parse(Int,split(file,'.')[1])/1] = data
    end
  end
  return datadict
end

rangedata = loaddircsvs(matcheddir)
azidata = loaddircsvs(beamdir)
timestamps = intersect(sort(collect(keys(rangedata))), sort(collect(keys(azidata))))

# NAV data
navdata = Dict{Int, Vector{Float64}}()
navfile = readdlm(joinpath(datadir, "nav_data.csv"))
for row in navfile
    s = split(row, ",")
    id = round(Int, 1e9*parse(Float64, s[1]))
    # round(Int, 1000 * parse(s[1])) = 1531153292381
    navdata[id] = parse.(Float64,s)
end
navkeys = sort(collect(keys(navdata)))
# NAV colums are X,Y = 7,8
# lat,long = 9,10
# time,pitch,roll,heading,speed,[Something], internal_x,internal_y,internal_lat,internal_long, yaw_rad

# LBL data - note the timestamps need to be exported as float in future.
lbldata = Dict{Int,  Vector{Float64}}()
lblfile = readdlm(joinpath(datadir, "lbl.csv"))
for row in lblfile
    s = split(row, ",")
    id = round(Int, 1e9*parse(Float64, s[1]))
    if s[2] != "NaN"
        lbldata[id] = parse.(Float64, s)
    end
end
lblkeys = sort(collect(keys(lbldata)))

# function heading2yaw(heading)
# heading = map( x->deg2rad(navdata[x][4]), navkeys )
# wrapheading = TU.wrapRad.(heading)
# end

# GET Y = north,  X = East,  Heading along +Y clockwise [0,360)]
# east = Float64[]
# north = Float64[]
# heading = Float64[]

# WANT X = North,  Y = West,  Yaw is right and rule from +X (0) towards +Y pi/2, [-pi,pi)
# so the drawPoses picture will look flipped from Nicks picture
# remember theta = atan2(y,x)    # this is right hand rule
X = Float64[]
Y = Float64[]
yaw = Float64[]
for id in navkeys
  # push!(east, getindex(navdata[id],7)) # x-column csv
  # push!(north, getindex(navdata[id],8)) # y-column csv
  # push!(heading, getindex(navdata[id],4))
  # push!(yaw, TU.wrapRad(-deg2rad(getindex(navdata[id],4))))

  push!(X, 0.7*getindex(navdata[id],7) ) # 8
  push!(Y, 0.7*getindex(navdata[id],8) ) # 7
  push!(yaw, TU.wrapRad(pi/2-deg2rad(getindex(navdata[id],4))) )  # rotation about +Z
end

lblX = Float64[]
lblY = Float64[]
for id in lblkeys
    push!(lblX, getindex(lbldata[id],2) )
    push!(lblY, getindex(lbldata[id],3) )
end

# Build interpolators for x, y, yaw
interp_x = LinearInterpolation(navkeys, X)
interp_y = LinearInterpolation(navkeys, Y)
interp_yaw = LinearInterpolation(navkeys, yaw)

function poorMansDeconv_BF(XX = collect(range(-pi,pi,length=1000)),
                           YY = ppbrDict[epochs[1]].bearing(XX)      )
  #
  YY1 = YY.^4
  YY1 ./= maximum(YY1)
  YY2 = YY1.^4
  YY2 ./= maximum(YY2)
  # Gadfly.plot(x=XX, y=YY2, Geom.line)
  bss = AliasingScalarSampler(XX, YY2)
  pts = reshape(rand(bss, 200), 1, :)
  pc = manikde!(pts, Sphere1)
  # plotKDECircular(pc)

  return pc
end

# Step: Selecting a subset for processing and build up a cache of the factors.

function doEpochs(timestamps, rangedata, azidata, interp_x, interp_y, interp_yaw, odonoise; TSTART=356, TEND=1200, SNRfloor::Float64=0.6, STRIDE::Int=4)
  #
  ## Caching factors
  ppbrDict = Dict{Int, Pose2Point2BearingRange}()
  ppbDict = Dict{Int, Pose2Point2Bearing}()
  pprDict = Dict{Int, Pose2Point2Range}()
  odoDict = Dict{Int, Pose2Pose2}()
  NAV = Dict{Int, Vector{Float64}}()

  XX = collect(range(-pi,pi,length=1000))

  epochs = timestamps[TSTART:STRIDE:TEND]
  lastepoch = 0
  @showprogress "preparing data" for ep in epochs
    # @show ep
    if lastepoch != 0
      # @show interp_yaw(ep)
      deltaAng = interp_yaw(ep) - interp_yaw(lastepoch)

      wXi = TU.SE2([interp_x(lastepoch);interp_y(lastepoch);interp_yaw(lastepoch)])
      wXj = TU.SE2([interp_x(ep);interp_y(ep);interp_yaw(ep)])
      iDXj = se2vee(wXi\wXj)
      NAV[ep] = iDXj
      # NAV[ep][1:2] .*= 0.7
      # println("$(iDXj[1]), $(iDXj[2]), $(iDXj[3])")

      odoDict[ep] = Pose2Pose2(MvNormal(NAV[ep], odonoise) )
    end
    rangepts = rangedata[ep][:]
    rangeprob = kde!(rangepts)

    # azipts = azidata[ep][:,1]
    azipts = collect(azidata[ep][:,1:1]')
    aziptsw = TU.wrapRad.(azipts)

    # direct
    aziprobl = kde!(azipts)
    # npts = rand(aziprobl, 200)
    # aziprob = manikde!(npts, Sphere1)

    # with deconv
    aziprob = poorMansDeconv_BF(XX, aziprobl(XX))

    # alternative range probability
    rawmf = readdlm("/home/dehann/data/sandshark/full_wombat_2018_07_09/extracted/matchedfilter/raw/$(ep).csv",',')
    dvmf = exp.(rawmf[:,2])
    dvmf .= dvmf.^4
    dvmf ./= cumsum(dvmf)[end]
    dvmf .= dvmf.^2
    dvmf ./= cumsum(dvmf)[end]
    range_bss = AliasingScalarSampler(rawmf[:,1], dvmf, SNRfloor=SNRfloor) # exp.(rawmf[:,2])

    # prep the factor functions
    ppbrDict[ep] = Pose2Point2BearingRange(aziprob, range_bss) # rangeprob
    ppbDict[ep] = Pose2Point2Bearing(aziprob) # rangeprob
    pprDict[ep] = Pose2Point2Range(range_bss) # rangeprob
    lastepoch = ep
  end
  return epochs, odoDict, ppbrDict, ppbDict, pprDict, NAV
end

function initializeAUV_noprior(dfg::AbstractDFG,
                               dashboard::Dict;
                               stride_range::Int=4,
                               magStdDeg::Float64=5.0,
                               stride_solve::Int=30 )
  #
  addVariable!(dfg, :x0, Pose2)

  # Pinger location is [17; 1.8]
  addVariable!(dfg, :l1, Point2, solvable=0)
  beaconprior = PriorPoint2( MvNormal([17; 1.8], Matrix(Diagonal([0.1; 0.1].^2)) ) )
  addFactor!(dfg, [:l1], beaconprior, autoinit=true, solvable=0)

  addVariable!(dfg, :drt_0, Pose2, solvable=0)
  drec = MutablePose2Pose2Gaussian(MvNormal(zeros(3), Matrix{Float64}(LinearAlgebra.I, 3,3)))
  addFactor!(dfg, [:x0; :drt_0], drec, solvable=0, autoinit=false)
  # NOTE have not added to dashboard[:drtMpp] yet

  # reference odo solution
  addVariable!(dfg, :drt_ref, Pose2, solvable=0)
  drec = MutablePose2Pose2Gaussian(MvNormal(zeros(3), Matrix{Float64}(LinearAlgebra.I, 3,3)))
  addFactor!(dfg, [:x0; :drt_ref], drec, solvable=0, autoinit=false)
  dashboard[:drtOdoRef] = (:x0, :drt_ref, drec)

  # store current real time tether factor
  dashboard[:drtMpp] = Dict{Symbol,MutablePose2Pose2Gaussian}(:x0 => drec)
  # dashboard[:drtCurrent] = (:x0, :drt_0)
  # standard odo process noise levels
  # TODO, debug and refine cont2disc
  dashboard[:Qc_odo] = Diagonal([0.01;0.01;0.001].^2) |> Matrix

  dashboard[:odoTime] = unix2datetime(0)
  dashboard[:poseRate] = Second(1)
  dashboard[:lastPose] = :x0

  # dashboard[:solvables] = Channel{Vector{Symbol}}(100)

  # dashboard[:loopSolver] = true

  # dashboard[:SOLVESTRIDE] = stride_solve
  # add a range measurement every xth pose
  dashboard[:poseStride] = 0
  # dashboard[:canTakePoses] = HSMReady
  # dashboard[:solveInProgress] = SSMReady

  # dashboard[:poseSolveToken] = Channel{Symbol}(3)

  dashboard[:RANGESTRIDE] = stride_range # add a range measurement every xth pose
  dashboard[:rangesBuffer] = CircularBuffer{Tuple{DateTime, Array{Float64,2}, Vector{Bool}}}(dashboard[:RANGESTRIDE]+4)
  dashboard[:rangeCount] = 0

  dashboard[:SNRfloor] = 0.6

  dashboard[:realTimeSlack] = Millisecond(0)

  dashboard[:magBuffer] = CircularBuffer{Tuple{DateTime, Float64, Vector{Bool}}}(20)
  dashboard[:magNoise] = deg2rad(magStdDeg)

  dashboard[:lblBuffer] = CircularBuffer{Tuple{DateTime, Array{Float64,1}, Vector{Bool}}}(dashboard[:RANGESTRIDE]+4)

  dashboard[:odoCov] = Matrix{Float64}(Diagonal([0.5;0.3;0.2].^2))

  dashboard[:savePlotting] = false

  dashboard[:solveSettings] = ManageSolveSettings(
    stride_solve,
    true,
    Channel{Vector{Symbol}}(100),
    SSMReady,
    Channel{Symbol}(3),
    HSMReady,
    (:x0, :drt_0)
  )

  nothing
end

## NOTE, moved to RoME/src/Slam.jl
# # Requires
# #  dashboard: SOLVESTRIDE, loopSolver, solvables, loopSolver, solveInProgress, poseSolveToken, canTakePoses, drtCurrent
# #
# function manageSolveTree!(dfg::AbstractDFG,
#                           dashboard::Dict;
#                           dbg::Bool=false,
#                           timinglog=Base.stdout,
#                           limitfixeddown::Bool=true  )
#
#   @info "logpath=$(getLogPath(dfg))"
#   getSolverParams(dfg).drawtree = true
#   getSolverParams(dfg).qfl = dashboard[:SOLVESTRIDE]
#   getSolverParams(dfg).isfixedlag = true
#   getSolverParams(dfg).limitfixeddown = limitfixeddown
#   getSolverParams(dfg).maxincidence = 1000
#
#   # allow async process
#   # getSolverParams(dfg).async = true
#
#   # prep with empty tree
#   tree = emptyBayesTree()
#
#   # needs to run asynchronously
#   ST = @async begin
#     while @show length(ls(dfg, :x0, solvable=1)) == 0
#       "waiting for prior on x0" |> println
#       sleep(1)
#     end
#     solvecycle = 0
#     # keep solving
#     while dashboard[:loopSolver]
#       t0 = time_ns()
#       solvecycle += 1
#       # add any newly solvables (atomic)
#       while !isready(dashboard[:solvables]) && dashboard[:loopSolver]
#         sleep(0.2)
#       end
#       dt_wait = (time_ns()-t0)/1e9
#
#       #add any new solvables
#       while isready(dashboard[:solvables]) && dashboard[:loopSolver]
#         dashboard[:solveInProgress] = SSMConsumingSolvables
#         @show tosolv = take!(dashboard[:solvables])
#         for sy in tosolv
#           # setSolvable!(dfg, sy, 1) # see DFG #221
#           # TODO temporary workaround
#           getfnc = occursin(r"f", string(sy)) ? getFactor : getVariable
#           getfnc(dfg, sy).solvable = 1
#         end
#       end
#       dt_solvable = (time_ns()-t0)/1e9
#
#       @info "Ensure all new variables initialized"
#       ensureAllInitialized!(dfg)
#       dt_init = (time_ns()-t0)/1e9
#       dt_disengage = 0.0
#       dt_save1 = 0.0
#       dt_solve = 0.0
#
#       dashboard[:solveInProgress] = SSMReady
#
#       # solve only every 10th pose
#       if 0 < length(dashboard[:poseSolveToken].data)
#       # if 10 <= dashboard[:poseStride]
#         @info "reduce problem size by disengaging older parts of factor graph"
#         setSolvableOldPoses!(dfg, youngest=getSolverParams(dfg).qfl+round(Int,dashboard[:SOLVESTRIDE]/2), oldest=100, solvable=0)
#         dt_disengage = (time_ns()-t0)/1e9
#
#         # set up state machine flags to allow overlapping or block
#         dashboard[:solveInProgress] = SSMSolving
#         # dashboard[:poseStride] = 0
#
#         # do the actual solve (with debug saving)
#         lasp = getLastPoses(dfg, filterLabel=r"x\d", number=1)[1]
#         !dbg ? nothing : saveDFG(dfg, joinpath(getLogPath(dfg), "fg_before_$(lasp)"))
#         dt_save1 = (time_ns()-t0)/1e9
#         # constrain solve with the latest pose at the top
#         # @show latestPose = intersect(getLastPoses(dfg, filterLabel=r"x\d", number=12), ls(dfg, r"x\d", solvable=1))[end]
#         tree, smt, hist = solveTree!(dfg, tree) # , variableConstraints=[latestPose;]
#         dt_solve = (time_ns()-t0)/1e9
#         !dbg ? nothing : saveDFG(dfg, joinpath(getLogPath(dfg), "fg_after_$(lasp)"))
#
#         # unblock LCMLog reader for next STRIDE segment
#         dashboard[:solveInProgress] = SSMReady
#         # de-escalate handler state machine
#         dashboard[:canTakePoses] = HSMHandling
#
#         # adjust latest RTT after solve, latest solved -- hard coded pose stride 10
#         lastList = sortDFG(ls(dfg, r"x\d+9\b|x9\b", solvable=1))
#         if 0 < length(lastList)
#           lastSolved = lastList[end]
#           dashboard[:drtCurrent] = (lastSolved, Symbol("drt_"*string(lastSolved)[2:end]))
#         end
#
#         # remove a token to allow progress to continue
#         gotToken = take!(dashboard[:poseSolveToken])
#         "end of solve cycle, token=$gotToken" |> println
#       else
#         "sleep a solve cycle" |> println
#         sleep(0.2)
#       end
#       dt_finish = (time_ns() - t0)/1e9
#
#       # store timing results
#       println(timinglog, "$solvecycle, $t0, $dt_wait, $dt_solvable, $dt_init, $dt_disengage, $dt_save1, $dt_solve, $(tree.buildTime), $dt_finish")
#     end
#   end
#   return ST
# end

#


text:
module TimerOutputs

#using Compat; import Compat.String when Compat is tagged

import Base: show, time_ns
export TimerOutput, @timeit, @timer, reset_timer!, print_timer, time_section, enter_section, exit_section

typealias SectionName UTF8String # String when Compat is tagged

type TimeData
    ncalls::Int
    tottime::UInt64
end

ncalls(td::TimeData) = td.ncalls
tottime(td::TimeData) = td.tottime
Base.isless(self::TimeData, other::TimeData) = self.tottime < other.tottime

function reset!(td::TimeData)
    td.ncalls = 0
    td.tottime = 0
end

abstract AbstractTimerOutput

start(to::AbstractTimerOutput) = to.start_time

function show(io::IO, to::AbstractTimerOutput)
    now = time_ns()
    since_start = now - start(to)
    print(io, "+--------------------------------+-----------+--------+---------+\n")
    print(io, "| Wall time elapsed since start  |")
    print(io, @sprintf("%8.3g s", since_start / 1e9))
    print(io,                                             " |        |         |\n")
    print(io, "|                                |           |        |         |\n")
    print(io, "| Section              | n calls | wall time | % tot  | % timed |\n")
    print(io, "+----------------------+---------+-----------+--------+---------+\n")
    print_sections(io, to, since_start)
    print(io, "+----------------------+---------+-----------+--------+---------+")
end

function print_section(io::IO, section::AbstractString, time_data::TimeData, since_start, tot_timed)
    if length(section) >= 20
        section = section[1:20-3] * "..."
    end

    print(io, @sprintf("| %-20s | %7d | %7.3g s | %5.3g%% | %6.3g%% |\n", section, ncalls(time_data),
                                                               tottime(time_data) / 1e9,
                                                               tottime(time_data) / since_start * 100,
                                                               tottime(time_data) / tot_timed * 100))
end

if !isdefined(Main, :DISABLE_TIMING)
    @eval begin
        macro timeit(args...)
            return timer_expr(args...)
        end
    end
else
    @eval begin
        macro timeit(args...)
            return timer_expr_do_nothing(args...)
        end
    end
end

function timer_expr_do_nothing(to::Symbol, label, ex::Expr)
    quote
        $(esc(ex))
    end
end

timer_expr(args...) = throw(ErrorException("Invalid macro usage for @timeit"))

include("runtime_timer.jl")

end # module


text:
export cw, chirp
export hanning, hamming, tukey, cosine, lanczos, triang, bartlett, gaussian, bartlett_hann, blackman, kaiser, dpss

"""
$(SIGNATURES)
Generates a sinusoidal signal with specified `freq` and `duration` at frame
rate `fs`. The starting `phase` and `window` type may be optionally specified.

# Examples:
```julia-repl
julia> x = cw(5kHz, 200ms, 44.1kHz)
8820-frame, 1-channel SampleBuf{Complex{Float64}, 1}
0.2s sampled at 44100.0Hz

julia> x = cw(5kHz, 200ms, 44.1kHz; window=hamming)
8820-frame, 1-channel SampleBuf{Complex{Float64}, 1}
0.2s sampled at 44100.0Hz

julia> x = cw(-5kHz, 200ms, 44.1kHz; phase=45°, window=(tukey, 0.05))
8820-frame, 1-channel SampleBuf{Complex{Float64}, 1}
0.2s sampled at 44100.0Hz
```
"""
function cw(freq, duration, fs; phase=0.0, window=nothing)
    abs(freq) > fs/2 && throw(ArgumentError("Frequency is beyond Nyquist"))
    t = (0:1/inHz(fs):inseconds(duration))[1:end-1]
    x = cis.(2π*inHz(freq).*t .+ phase)
    if window != nothing
      x .*= getwindow(window, length(t))
    end
    signal(x, fs)
end

"""
$(SIGNATURES)
Generates a frequency modulated chirp signal from `freq1` to `freq2` and
specified `duration` at frame rate `fs`. The type of frequency modulation may
be controlled using `shape` (`:linear` (default) or `:hyperbolic`). The
starting `phase` and `window` type may be optionally specified.

# Examples:
```julia-repl
julia> x = chirp(5kHz, 7kHz, 100ms, 44.1kHz)
4410-frame, 1-channel SampleBuf{Complex{Float64}, 1}
0.1s sampled at 44100.0Hz

julia> x = chirp(5kHz, 7kHz, 100ms, 44.1kHz; phase=45°, window=hamming)
4410-frame, 1-channel SampleBuf{Complex{Float64}, 1}
0.1s sampled at 44100.0Hz

julia> x = chirp(5kHz, 7kHz, 100ms, 44.1kHz; shape=:hyperbolic, window=(tukey,0.05))
4410-frame, 1-channel SampleBuf{Complex{Float64}, 1}
0.1s sampled at 44100.0Hz
```
"""
function chirp(freq1, freq2, duration, fs=2.0; shape=:linear, phase=0.0, window=nothing)
  f1 = inHz(freq1)
  f2 = inHz(freq2)
  d = inseconds(duration)
  t = (0:1/inHz(fs):d)[1:end-1]
  if shape == :linear
    cby2 = (f2-f1)/d/2.0
    x = cis.(2π .* (cby2.*t.^2 .+ f1.*t) .+ phase)
  elseif shape == :hyperbolic
    s = f2*d/(f2-f1)
    x = cis.(-2π*s*f1 .* log.(abs.(1.0 .- t./s)))
  else
    throw(ArgumentError("Unknown chirp shape: $shape"))
  end
  if window !== nothing
    x .*= getwindow(window, length(t))
  end
    signal(x, fs)
end

### utility functions

function getwindow(window, n)
  window === nothing && return ones(n)
  window isa Tuple && return window[1](n, window[2])
  window(n)
end


text:
const warned_once = Ref(false)
if VERSION >= v"1.5"
    function forced_depwarn(msg, sym)
        opts = Base.JLOptions()
        if !warned_once[] && !(opts.depwarn == 1)
            @warn msg
            @info """It is recommended that you fix this now to avoid breakage when a new version is released and this warning is removed.
                     Tip: to see all deprecation warnings together with code locations, launch Julia with `--depwarn=yes` and rerun your code."""
            warned_once[] = true
        else
            Base.depwarn(msg, sym)
        end
        return nothing
    end
else
    forced_depwarn(msg, sym) = Base.depwarn(msg, sym)
end

Base.@deprecate_binding ChannelView channelview

export ColorView

struct ColorView{C<:Colorant,N,A<:AbstractArray} <: AbstractArray{C,N}
    parent::A

    function ColorView{C,N,A}(parent::AbstractArray{T}) where {C,N,A,T<:Number}
        n = length(colorview_size(C, parent))
        n == N || throw(DimensionMismatch("for an $N-dimensional ColorView with color type $C, input dimensionality should be $n instead of $(ndims(parent))"))
        checkdim1(C, axes(parent))
        forced_depwarn("ColorView{C}(A) is deprecated, use colorview(C, A)", :ColorView)
        colorview(C, A)
    end
end

function ColorView{C}(A::AbstractArray) where C<:Colorant
    forced_depwarn("ColorView{C}(A) is deprecated, use colorview(C, A)", :ColorView)
    colorview(C, A)
end

ColorView(parent::AbstractArray) = error("must specify the colortype, use colorview(C, A)")

Base.@deprecate_binding squeeze1 true

import Base: convert

function cname(::Type{C}) where C
    io = IOBuffer()
    ColorTypes.colorant_string_with_eltype(io, C)
    return String(take!(io))
end

const _explain =
"""will soon switch to returning an array with non-concrete element type, which adds flexibility but
   with great cost to performance. To maintain the current behavior, use"""

function convert(::Type{Array{Cdest}}, img::AbstractArray{Csrc,n}) where {Cdest<:Colorant,n,Csrc<:Colorant}
    if isconcretetype(Cdest)
        # This mimics the Base implementation
        return img isa Array{Cdest} ? img : Array{Cdest}(img)
    end
    forced_depwarn("`convert(Array{$(cname(Cdest))}, img)` $_explain `$(cname(Cdest)).(img)` instead.", :convert)
    convert(Array, Cdest.(img))
end

function convert(::Type{Array{Cdest}}, img::AbstractArray{T,n}) where {Cdest<:Color1,n,T<:Real}
    if isconcretetype(Cdest)
        return img isa Array{Cdest} ? img : Array{Cdest}(img)
    end
    forced_depwarn("`convert(Array{$(cname(Cdest))}, img)` $_explain `$(cname(Cdest)).(img)` instead.", :convert)
    convert(Array, Cdest.(img))
end

function convert(::Type{OffsetArray{Cdest,n,A}}, img::AbstractArray{Csrc,n}) where {Cdest<:Colorant,n, A <:AbstractArray,Csrc<:Colorant}
    if isconcretetype(Cdest) && isconcretetype(A) && eltype(A) === Cdest
        return img isa OffsetArray{Cdest,n,A} ? img : (img isa OffsetArray ? OffsetArray(A(Cdest.(parent(img))), axes(img)) : OffsetArray(A(Cdest.(img)), axes(img)))
    end
    if img isa OffsetArray
        forced_depwarn("`convert(OffsetArray{$(cname(Cdest))}, img)` $_explain `$(cname(Cdest)).(img)` instead.", :convert)
    else
        forced_depwarn("`convert(OffsetArray{$(cname(Cdest))}, img)` $_explain `OffsetArray($(cname(Cdest)).(img), axes(img))` instead.", :convert)
    end
    OffsetArray(Cdest.(img), axes(img))
end

convert(::Type{OffsetArray{Cdest,n,A}}, img::OffsetArray{Cdest,n,A}) where {Cdest<:Colorant,n, A <:AbstractArray} = img

# a perhaps "permanent" deprecation
Base.@deprecate_binding permuteddimsview PermutedDimsArray