text:
using StaticCompiler
using Test
using Libdl
using LinearAlgebra
using LoopVectorization
using ManualMemory
using StrideArraysCore
using Distributed

addprocs(1)
@everywhere using StaticCompiler

remote_load_call(path, args...) = fetch(@spawnat 2 load_function(path)(args...))

@testset "Basics" begin

    simple_sum(x) = x + one(typeof(x))

    # This probably needs a macro
    for T ∈ (Int, Float64, Int32, Float32, Int16, Float16)
        _, path, = compile(simple_sum, (T,))
        @test remote_load_call(path, T(1)) == T(2)
    end
end

fib(n) = n <= 1 ? n : fib(n - 1) + fib(n - 2) # This needs to be defined globally due to https://github.com/JuliaLang/julia/issues/40990

@testset "Recursion" begin
    _, path = compile(fib, (Int,))
    @test remote_load_call(path, 10) == fib(10)

    # Trick to work around #40990
    _fib2(_fib2, n) = n <= 1 ? n : _fib2(_fib2, n-1) + _fib2(_fib2, n-2)
    fib2(n) = _fib2(_fib2, n)

    _, path = compile(fib2, (Int,))
    @test remote_load_call(path, 20) == fib(20)
    #@test compile(fib2, (Int,))[1](20) == fib(20)
end

# Call binaries for testing
# @testset "Generate binary" begin
#     fib(n) = n <= 1 ? n : fib(n - 1) + fib(n - 2)
#     libname = tempname()
#     generate_shlib(fib, (Int,), libname)
#     ptr = Libdl.dlopen(libname * "." * Libdl.dlext, Libdl.RTLD_LOCAL)
#     fptr = Libdl.dlsym(ptr, "julia_fib")
#     @assert fptr != C_NULL
#     # This works on REPL
#     @test_skip ccall(fptr, Int, (Int,), 10) == 55
# end

@testset "Loops" begin
    function sum_first_N_int(N)
        s = 0
        for a in 1:N
            s += a
        end
        s
    end
    _, path = compile(sum_first_N_int, (Int,))
    @test remote_load_call(path, 10) == 55

    function sum_first_N_float64(N)
        s = Float64(0)
        for a in 1:N
            s += Float64(a)
        end
        s
    end
    _, path = compile(sum_first_N_float64, (Int,))
    @test remote_load_call(path, 10) == 55.

    function sum_first_N_int_inbounds(N)
        s = 0
        @inbounds for a in 1:N
            s += a
        end
        s
    end
    _, path = compile(sum_first_N_int_inbounds, (Int,))
    @test remote_load_call(path, 10) == 55

    function sum_first_N_float64_inbounds(N)
        s = Float64(0)
        @inbounds for a in 1:N
            s += Float64(a)
        end
        s
    end
    _, path = compile(sum_first_N_float64_inbounds, (Int,))
    @test remote_load_call(path, 10) == 55.
end

# Arrays with different input types Int32, Int64, Float32, Float64, Complex?
@testset "Arrays" begin
    function array_sum(n, A)
        s = zero(eltype(A))
        for i in 1:n
            s += A[i]
        end
        s
    end
    for T ∈ (Int, Complex{Float32}, Complex{Float64})
        _, path = compile(array_sum, (Int, Vector{T}))
        @test remote_load_call(path, 10, T.(1:10)) == T(55)
    end

    # @test (10, Int.(1:10)) == 55
    # @test compile(array_sum, (Int, Vector{Complex{Float32}}))[1](10, Complex{Float32}.(1:10)) == 55f0 + 0f0im
    # @test compile(array_sum, (Int, Vector{Complex{Float64}}))[1](10, Complex{Float64}.(1:10)) == 55f0 + 0f0im
end

# Julia wants to treat Tuple (and other things like it) as plain bits, but LLVM wants to treat it as something with a pointer.
# We need to be careful to not send, nor receive an unwrapped Tuple to a compiled function.
# The interface made in `compile` should handle this fine.
@testset "Send and receive Tuple" begin
    foo(u::Tuple) = 2 .* reverse(u) .- 1

    _, path = compile(foo, (NTuple{3, Int},))
    @test remote_load_call(path, (1, 2, 3)) == (5, 3, 1)
end

# Just to call external libraries
@testset "BLAS" begin
    function mydot(a::Vector{Float64})
        N = length(a)
        BLAS.dot(N, a, 1, a, 1)
    end
    a = [1.0, 2.0]
    mydot_compiled, path = compile(mydot, (Vector{Float64},))
    @test_skip remote_load_call(path, a) == 5.0 # this needs a relocatable pointer to work
    @test mydot_compiled(a) == 5.0
end

@testset "Hello World" begin
    function hello(N)
        println("Hello World $N")
        N
    end
    # How do I test this?
    # Also ... this segfaults
    @test_skip ccall(generate_shlib_fptr(hello, (Int,)), Int, (Int,), 1) == 1
end

# I can't beleive this works.
@testset "LoopVectorization" begin
    function mul!(C, A, B)
        # note: @tturbo does NOT work
        @turbo for n ∈ indices((C,B), 2), m ∈ indices((C,A), 1)
            Cmn = zero(eltype(C))
            for k ∈ indices((A,B), (2,1))
                Cmn += A[m,k] * B[k,n]
            end
            C[m,n] = Cmn
        end
    end

    C = Array{Float64}(undef, 10, 12)
    A = rand(10, 11)
    B = rand(11, 12)

    _, path = compile(mul!, (Matrix{Float64}, Matrix{Float64}, Matrix{Float64},))
    # remote_load_call(path, C, A, B) This won't work because @spawnat copies C
    C .= fetch(@spawnat 2 (load_function(path)(C, A, B); C))
    @test C ≈ A*B
end

# This is a trick to get stack allocated arrays inside a function body (so long as they don't escape).
# This lets us have intermediate, mutable stack allocated arrays inside our
@testset "Alloca" begin
    function f(N)
        # this can hold at most 100 Int values, if you use it for more, you'll segfault
        buf = ManualMemory.MemoryBuffer{100, Int}(undef)
        GC.@preserve buf begin
            # wrap the first N values in a PtrArray
            arr = PtrArray(pointer(buf), (N,))
            arr .= 1 # mutate the array to be all 1s
            sum(arr) # compute the sum. It is very imporatant that no references to arr escape the function body
        end
    end
    _, path = compile(f, (Int,))
    @test remote_load_call(path, 20) == 20
end

# data structures, dictionaries, tuples, named tuples


text:
function load(path::String,
    modelType::Union{Type{CRRContractPremiumLatticeModel}, Type{CRRJITContractPremiumLatticeModel}})

    # load the BSON model -
    tmp_data = BSON.load(path, @__MODULE__)[:model_dictionary]

    # return -
    return build(modelType, tmp_data)
end

function save(path::String, model::CRRJITContractPremiumLatticeModel)::Bool

    # TODO: check: is this is legit path?

    # fields that need to be persisted -
    # underlying::Array{Float64,1}
    # strike::Union{Array{Float64,1}, Array{Float64,2}}
    # iv::Array{Float64,1}
    # dte::Array{Float64,1}
    # number_of_levels::Int64
    # μ::Float64 -> risk_free_rate
    # contractType::T where {T <: AbstractDerivativeContractModel}

    try

        # save -
        model_dictionary = Dict{String,Any}()
        model_dictionary["underlying"] = model.underlying
        model_dictionary["strike"] = model.strike
        model_dictionary["iv"] = model.iv
        model_dictionary["dte"] = model.dte
        model_dictionary["number_of_levels"] = model.number_of_levels
        model_dictionary["risk_free_rate"] = model.risk_free_rate
        model_dictionary["contractType"] = model.contractType

        # dump -
        @save path model_dictionary

        # return -
        return true
    catch ex
        @error showerror(stdout, ex, catch_backtrace())
        return false
    end
end

function save(path::String, model::CRRContractPremiumLatticeModel)::Bool

    # TODO: check: is this is legit path?

    # fields that need to be persisted -
    # grid::Dict{NamedTuple,Union{Float64, Array{Float64,1}}}
    # underlying::Array{Float64,1}
    # strike::Union{Array{Float64,1}, Array{Float64,2}}
    # iv::Array{Float64,1}
    # dte::Array{Float64,1}
    # number_of_levels::Int64
    # μ::Float64 -> risk_free_rate
    # contractType::T where {T <: AbstractDerivativeContractModel}

    try

        # save -
        model_dictionary = Dict{String,Any}()
        model_dictionary["grid"] = model.grid
        model_dictionary["underlying"] = model.underlying
        model_dictionary["strike"] = model.strike
        model_dictionary["iv"] = model.iv
        model_dictionary["dte"] = model.dte
        model_dictionary["number_of_levels"] = model.number_of_levels
        model_dictionary["risk_free_rate"] = model.risk_free_rate
        model_dictionary["contractType"] = model.contractType

        # dump -
        @save path model_dictionary

        # return -
        return true
    catch ex
        @error showerror(stdout, ex, catch_backtrace())
        return false
    end
end

ext: jl


text:
export reciprocal, reciprocalsum
export countnonzeros
## Utilities relevant for math ##

"""
    countnonzeros(x::AbstractVector{T}) where T<:Real
Return the number of non-zero values in a vector
"""
function countnonzeros(x::AbstractVector{T}) where T<:Real
    mapreduce(!iszero, +, x)
end

"""
reciprocal(num::T) where T <: Signed
Returns the reciprocal (1/number) of a number. Will return `0` when
the number is `0` instead of returning `Inf`.
"""
function reciprocal(num::T) where T <: Real
    !iszero(num) ? 1.0/float(num) : 0.0
end

"""
reciprocalsum(x::AbstractVector{T}) where T<:Real
Return the sum of the reciprocal values of `x`, skipping the `Inf` values
resulting from divide-by-zero errors.
"""
function reciprocalsum(x::AbstractVector{T}) where T<:Real
    mapreduce(reciprocal, +, x)
end


text:
function discretizelungs!(system::CVSystem)
    append!(system.lungs.Pp,zeros(system.solverparams.numsteps+1))

    system.lungs.Pa = zeros(system.solverparams.numsteps+1,3);
    system.lungs.Va = zeros(system.solverparams.numsteps+1,3);
    system.lungs.Qa = zeros(system.solverparams.numsteps+1,3);
    system.lungs.Pv = zeros(system.solverparams.numsteps+1,2);
    system.lungs.Vv = zeros(system.solverparams.numsteps+1,2);
    system.lungs.Qv = zeros(system.solverparams.numsteps+1,2);
end

max_stars_repo_name: dcanuto/CardioModeling

max_issues_repo_name: dcanuto/CardioModeling

max_forks_repo_name: dcanuto/CardioModeling


text:
using FastBEAST
using Plots
using StaticArrays
plotlyjs()

##
points2D = [@SVector rand(2) for i=1:100] + [SVector(1.0, 2.0) for i=1:100]

bbox2D = BoundingBox(points2D)
bboxframe2D = getboxframe(bbox2D)

scatter([points2D[i][1] for i=1:length(points2D)],
        [points2D[i][2] for i=1:length(points2D)])
plot!(bboxframe2D[:,1], bboxframe2D[:,2])

##
points3D = [@SVector rand(3) for i=1:100] + [SVector(0.0, 0.0, 0.0) for i=1:100]

bbox3D = BoundingBox(points3D)
bboxframe3D = getboxframe(bbox3D)

scatter([points3D[i][1] for i=1:length(points3D)],
        [points3D[i][2] for i=1:length(points3D)],
        [points3D[i][3] for i=1:length(points3D)],
        markersize = 2)

plot!(  bboxframe3D[:,1], bboxframe3D[:,2], bboxframe3D[:,3],
        line=(4, :black, :solid),
        label = nothing)

##
points2D = [@SVector rand(2) for i=1:100] + [SVector(1.0, 2.0) for i=1:100]

function collectleafboxframes(root::BoxTreeNode)
    bboxframe = getboxframe(root.boundingbox)
    bboxframes = typeof(bboxframe)[]

    function collectleafboxframes(node::BoxTreeNode, bboxframe_container)
        if node.children === nothing
            bboxframe = getboxframe(node.boundingbox)
            push!(bboxframe_container, bboxframe)
        else
            for child in node.children
                collectleafboxframes(child, bboxframe_container)
            end
        end
    end

    collectleafboxframes(root, bboxframes)

    return bboxframes
end

function plot_boxframes!(plt, boxframes)
    for boxframe in bboxframes
        if size(boxframe,2) == 2
            plot!(plt, boxframe[:,1], boxframe[:,2],
            line=(2, :black, :solid),
            label = nothing)
        else
            plot!(plt, boxframe[:,1], boxframe[:,2], boxframe[:,3],
            line=(2, :black, :solid),
            label = nothing)
        end
    end
end

tree = create_tree(points2D, treeoptions=BoxTreeOptions(nmin=4))

plt = scatter([points2D[i][1] for i=1:length(points2D)],
        [points2D[i][2] for i=1:length(points2D)])

bboxframes = collectleafboxframes(tree)

plot_boxframes!(plt, bboxframes)

##
points3D = [@SVector rand(3) for i=1:100] + [SVector(0.0, 0.0, 0.0) for i=1:100]

a = BoxTreeOptions(nmin=3)

tree = create_tree(points3D, treeoptions = BoxTreeOptions(nmin=3))

plt = scatter([points3D[i][1] for i=1:length(points3D)],
        [points3D[i][2] for i=1:length(points3D)],
        [points3D[i][3] for i=1:length(points3D)],
        markersize = 2)

bboxframes = collectleafboxframes(tree)

plot_boxframes!(plt, bboxframes)

max_stars_repo_name: JoshuaTetzner/FastBEAST

max_issues_repo_name: JoshuaTetzner/FastBEAST

max_forks_repo_name: JoshuaTetzner/FastBEAST


text:
using Printf: @sprintf
using ProgressMeter
using SharedArrays

function catAll(x, y)
    @sync begin
        @async x[1] = cat(dims=4, x[1], y[1])
        @async x[2] = cat(dims=2, x[2], y[2])
        @async x[3] = cat(dims=1, x[3], y[3])
    end
    return x
end

function progress_meter_string(p::Progress)
    if p.counter < p.n
        percentage_complete = round(Int, p.counter / p.n *100)
    elseif p.counter > p.n
        percentage_complete = 99
    else
        percentage_complete = 100
    end
    bar = ProgressMeter.barstring(60, percentage_complete, barglyphs=p.barglyphs)
    @sprintf "%s%3u%%  %s " p.desc percentage_complete bar
end

function pregress_to_string(id::Int, steps::Int, statu::Bool)
    pre = @sprintf "|   %2d   |  %2d   " id steps
    pre *= '|' * "❌⚪" ^ (steps÷2) * ('❌'^(steps % 2)) * ('⭐'^statu)
    @sprintf "%-80s" pre
end

function showProgressBar(sha::SharedArray, status::SharedArray)
    mainPro = Progress(BATCH_SIZE, dt=0.1, color=:black, output=stdout)
    mainPro.desc = "|  main  | "
    total = 0
    desc = "+-------------------------------- Self Playing --------------------------------+\n\n| Gameid | Steps | Time: "
    open("./logs/selfPlay.log", "a+") do io
        println(io, desc)
        print(io, Dates.format(now(), "mm-dd-HH:MM"))
    end
    finished_game = 0
    while finished_game < 17
        finished_game, total = sum(status), sum(sha)
        print_string = desc
        IJulia.clear_output(true)

        if finished_game == 16
            gap = " " ^ ((total - BATCH_SIZE) % 15)
            print_string *= gap*"saving data..."
        end

        print_string *= ProgressMeter.durationstring(time() - mainPro.tfirst) * "\n"

        if finished_game != 17
            mainPro.counter = total
            print_string *= progress_meter_string(mainPro) * "\n"
        else
            mainPro.counter = BATCH_SIZE
            print_string *= progress_meter_string(mainPro) * " Done!!\n"
        end

        for i=1:16
            print_string *= pregress_to_string(i, sha[i], status[i]) *"\n"
        end
        print_string *= "\n+-------------------------------- Self Playing --------------------------------+\n"
        println(print_string)
        sleep(0.2)
    end
    open("./logs/selfPlay.log", "a+") do io
        println(io, "Time: "*Dates.format(now(), "mm-dd-HH:MM"))
    end
end


text:
using Documenter
using AlgamesDriving  # your package name here

makedocs(
    sitename = "AlgamesDriving",  # your package name here
    format = Documenter.HTML(prettyurls = false),  # optional
    pages = [
        "Introduction" => "index.md",
        "Basics" => [
            "Creating a New Package" => "new_repo.md",
            "Adding Dependencies" => "deps.md",
            "Adding Tests" => "tests.md",
            "Setting up CI" => "CI.md",
            "Adding Code Coverage" => "codecov.md",
            "Building documentation" => "docs.md",
            "Registering a Package" => "registering.md"
        ],
        "Sample Documentation" => "package_docs.md"
    ]
)

deploydocs(
    repo = "github.com/simon-lc/AlgamesDriving.jl.git",
)


text:
module FluxModels

using Random

include("rnn_autoencoder.jl")

function split_data(data::Vector, n_train)
    n_data = length(data)
    @assert n_data > n_train
    shuffled_data = shuffle(data)
    return shuffled_data[1:n_train], shuffled_data[n_train+1:end]
end

export RNNAutoencoder
end # module

max_stars_repo_name: Soyukke/FluxModels

max_issues_repo_name: Soyukke/FluxModels

max_forks_repo_name: Soyukke/FluxModels


text:
export Kernel

abstract type AbstractKernel <: AbstractMeasure end

struct Kernel{T,S} <: AbstractKernel
    ops::S
end

"""
    kernel(f, M)
    kernel((f1, f2, ...), M)

A kernel `κ = kernel(f, m)` returns a wrapper around
a function `f` giving the parameters for a measure of type `M`,
such that `κ(x) = M(f(x)...)`
respective `κ(x) = M(f1(x), f2(x), ...)`

If the argument is a named tuple `(;a=f1, b=f1)`, `κ(x)` is defined as
`M(;a=f(x),b=g(x))`.

# Reference

* https://en.wikipedia.org/wiki/Markov_kernel
"""
function kernel end

export kernel
kernel(op, ::Type{M}) where {M} = Kernel{M,typeof(op)}(op)
kernel(::Type{M}; ops...) where {M} = Kernel{M,typeof(ops.data)}(ops.data)
mapcall(t, x) = map(func -> func(x), t)
(k::Kernel{M,<:Tuple})(x) where {M} = M(mapcall(k.ops, x)...)
(k::Kernel{M,<:NamedTuple})(x) where {M} = M(;mapcall(k.ops, x)...)
(k::Kernel{M})(x) where {M} = M(k.ops(x)...)

export kernelize

function kernelize(μ::M) where {N, M <: ParameterizedMeasure{N}}
    C = M.name.wrapper
    (kernel(NamedTuple{N}, C), values(getfield(μ, :par)))
end


text:
# Solve 2D Fisher-KPP equation with Dirichlet boundary conditions
# Alex Tam, 03/11/2021

"Solve Fisher-KPP equation"
function fkpp(D, U, ϕ, par, dx, dy, dt, i)
    # Manually assign value at grid points close to interface
    for gp in D
        if (gp.Ω == true) && (gp.dΩ == true)
            U[gp.xInd, gp.yInd] = par.u_f
        end
    end
    # Create vector from matrix data
    u = build_vector(U, D)
    # Construct and solve ODE problem using DifferentialEquations.jl
    prob = ODEProblem((du, u, p, t) -> fkpp_rhs!(du, u, p, t, D, ϕ, par, dx, dy), u, ((i-1)*dt, i*dt))
    sol = solve(prob, Tsit5(), reltol = 1e-3, abstol = 1e-6, saveat = i*dt)
    # Reshape solution to matrix
    U = build_u_matrix(sol[:,end], par, D)
    return U
end

"Construct right-hand vector for use in DifferentialEquations.jl"
function fkpp_rhs!(du, u, p, t, D, ϕ, par, dx, dy)
    U = build_u_matrix(u, par, D) # Generate matrix
    for i = 1:length(D) # Loop over interior grid points
        if (D[i].Ω == true) && (D[i].dΩ == false) # Grid points inside Ω, away from dΩ
            # Obtain density at stencil points
            u_mid = U[D[i].xInd, D[i].yInd]
            if ϕ[D[i].xInd-1, D[i].yInd] >= 0
                u_left = par.u_f
            else
                u_left = U[D[i].xInd-1, D[i].yInd]
            end
            if ϕ[D[i].xInd+1, D[i].yInd] >= 0
                u_right = par.u_f
            else
                u_right = U[D[i].xInd+1, D[i].yInd]
            end
            if ϕ[D[i].xInd, D[i].yInd-1] >= 0
                u_bottom = par.u_f
            else
                u_bottom = U[D[i].xInd, D[i].yInd-1]
            end
            if ϕ[D[i].xInd, D[i].yInd+1] >= 0
                u_top = par.u_f
            else
                u_top = U[D[i].xInd, D[i].yInd+1]
            end
            # Compute Laplacian and source term
            uxx = 2.0*( u_left/(D[i].θxm*(D[i].θxm+D[i].θxp)) - u_mid/(D[i].θxm*D[i].θxp) + u_right/(D[i].θxp*(D[i].θxm+D[i].θxp)) )/(dx^2)
            uyy = 2.0*( u_bottom/(D[i].θym*(D[i].θym+D[i].θyp)) - u_mid/(D[i].θym*D[i].θyp) + u_top/(D[i].θyp*(D[i].θym+D[i].θyp)) )/(dy^2)
            du[i] = par.D*(uxx + uyy) + par.λ*u_mid*(1-u_mid)
        else # Grid points outside Ω or close to dΩ
            du[i] = 0.0
        end
    end
end


text:
using ITensors,
  ITensorGPU,
  LinearAlgebra, # For tr()
  Combinatorics, # For permutations()
  CUDA,
  Test

# gpu tests!
@testset "cuITensor, Dense{$SType} storage" for SType in (Float64, ComplexF64)
  mi, mj, mk, ml, ma = 2, 3, 4, 5, 6, 7
  i = Index(mi, "i")
  j = Index(mj, "j")
  k = Index(mk, "k")
  l = Index(ml, "l")
  a = Index(ma, "a")
  @testset "Test add CuDense" begin
    A = [SType(1.0) for ii in 1:dim(i), jj in 1:dim(j)]
    dA = ITensorGPU.CuDense{SType,CuVector{SType}}(SType(1.0), dim(i) * dim(j))
    B = [SType(2.0) for ii in 1:dim(i), jj in 1:dim(j)]
    dB = ITensorGPU.CuDense{SType,CuVector{SType}}(SType(2.0), dim(i) * dim(j))
    dC = +(dA, IndexSet(i, j), dB, IndexSet(j, i))
    hC = collect(dC)
    @test collect(A + B) ≈ hC
  end
  @testset "Test subtract CuDense" begin
    A = [SType(1.0) for ii in 1:dim(i), jj in 1:dim(j)]
    dA = ITensorGPU.CuDense{SType,CuVector{SType}}(SType(1.0), dim(i) * dim(j))
    B = [SType(2.0) for ii in 1:dim(i), jj in 1:dim(j)]
    dB = ITensorGPU.CuDense{SType,CuVector{SType}}(SType(2.0), dim(i) * dim(j))
    dC = -(dA, IndexSet(i, j), dB, IndexSet(i, j))
    hC = collect(dC)
    @test A - B ≈ hC
  end
  @testset "Test permute CuDense" begin
    A = [SType(ii * jj) for ii in 1:dim(i), jj in 1:dim(j)]
    dA = ITensorGPU.CuDense{SType,CuVector{SType}}(NDTensors.Dense(vec(A)))
    B = [SType(0.0) for ii in 1:dim(j), jj in 1:dim(j)]
    dB = ITensorGPU.CuDense{SType,CuVector{SType}}(SType(0.0), dim(i) * dim(j))
    dC = permute!(dB, IndexSet(j, i), dA, IndexSet(i, j))
    hC = collect(dC)
    @test vec(transpose(A)) == hC
  end
  @testset "Test move CuDense on/off GPU" begin
    A = [SType(1.0) for ii in 1:dim(i), jj in 1:dim(j)]
    dA = ITensorGPU.CuDense{SType,CuVector{SType}}(NDTensors.Dense(vec(A)))
    dB = ITensorGPU.Dense{SType,Vector{SType}}(dA)
    @test NDTensors.data(dB) == vec(A)
  end
  @testset "Test basic CuDense features" begin
    @test NDTensors.Dense{SType,CuVector{SType}}(10) isa ITensorGPU.CuDense{SType}
    @test complex(NDTensors.Dense{SType,CuVector{SType}}) ==
      NDTensors.Dense{complex(SType),CuVector{complex(SType)}}
  end
  if SType == Float64
    @testset "Test CuDense complex" begin
      A = CUDA.rand(SType, dim(i) * dim(j))
      dA = ITensorGPU.CuDense{SType,CuVector{SType}}(A)
      dC = complex(dA)
      @test typeof(dC) !== typeof(dA)
      cdC = CuArray(dC)
      hC = collect(cdC)
      ccA = complex.(A)
      @test hC == collect(ccA)
    end
  end
end # End Dense storage test


text:
using PyPlot, ARFIMA, Random

Ns = [10_000, 50_000, 100_000]
σ = 0.5
φ = SVector(0.8)
θ = SVector(2.0)
d1 = 0.4; d2 = 2

xs = [zeros(length(Ns)) for i in 1:4]
args1 = (d1, nothing, nothing)
args2 = (d2, nothing, nothing)
args3 = (d1, φ, nothing)
args4 = (nothing, φ, θ)
args = [args1, args2, args3, args4]

labels = ["ARFIMA(0, d=$d1, 0)", "ARIMA(0, d=$d2, 0)",
 "ARFIMA(φ=$(φ[1]), d=$d1, 0)", "ARMA(φ=$(φ[1]), θ=$(θ[1]))"]

# compile
for (x, arg, label) in zip(xs, args, labels)
    t = arfima(MersenneTwister(5), 1000, σ, arg...)
end
time()

# %% Compute
println("Starting to bencmark:")
for (x, arg, label) in zip(xs, args, labels)
    println("\nProcess: $label")
    for (i, N) in enumerate(Ns)
        z = time()
        t = arfima(MersenneTwister(5), N, σ, arg...)
        x[i] = time() - z
        println("For N = $N, ", round(x[i], digits=7), " seconds")
        GC.gc()
    end
end

# %% Plot
# using PyPlot
# figure()
# subplot(121)
# for i in (1, 3)
#     x = xs[i]
#     loglog(Ns, x, label = labels[i], marker = "o")
# end
# legend()
# xlabel("timeseries length N")
# ylabel("time (sec)")
# subplot(122)
# for i in (2, 4)
#     x = xs[i]
#     semilogx(Ns, x, label = labels[i], marker = "o")
# end
# legend()
# xlabel("timeseries length N")
# ylabel("time (sec)")
# tight_layout()


text:
module PDIPS

using LinearAlgebra
using Printf
using SparseArrays

# LinearSolvers.jl
include("linalg/LinearSolvers.jl")

include("types.jl")
include("type_utils.jl")
include("algorithm_utils.jl")
include("algorithm.jl")

include("api.jl")

export
    # types
    AbstractProblem,
    AbstractStandardProblem,
    Problem,
    StandardProblem,
    Solution,

    # methods
    solve,
    load_problem!

end # module


text:
abstract type AbstractCodeCtx end

mutable struct LoggingBuilder
    builder::LLVM.Builder
    name::String
end

"""
The `CodeCtx` type holds the main state for code generation.
One instance is used per function being compiled.
"""
mutable struct CodeCtx <: AbstractCodeCtx
    builder::LoggingBuilder
    mod::LLVM.Module
    name::String
    code_info::CodeInfo
    result_type
    argtypes
    jfun
    sig
    nargs::Int
    slots::Vector{LLVM.Value}
    slotlocs::Vector{Any}
    ssas::Dict{Int, LLVM.Value}
    labels::Dict{Int, Any}
    meta::Dict{Symbol, Any}
    func::LLVM.Function
    extern::Dict{Symbol, Any}
    builtin::Dict{Symbol, LLVM.Function}
    datatype::Dict{Type, Any}
    CodeCtx(mod::LLVM.Module, name, ci::CodeInfo, result_type, argtypes, jfun, sig) =
        new(LoggingBuilder(LLVM.Builder(ctx), name),
            mod,
            name,
            ci,
            result_type,
            argtypes,
            jfun,
            sig,
            length(argtypes.parameters),
            Vector{LLVM.Value}(uninitialized, length(ci.slotnames)),
            Vector{Any}(uninitialized, length(ci.slotnames)),
            Dict{Int, LLVM.Value}(),
            Dict{Int, Any}(),
            Dict{Symbol, Any}()
            )
end

function CodeCtx(name, ci::CodeInfo, result_type, argtypes, jfun, sig; triple = nothing, datalayout = nothing)
    cg = CodeCtx(LLVM.Module("JuliaCodeGenModule", ctx), name, ci, result_type, argtypes, jfun, sig)
    global CG = cg
    M = cg.mod
    triple != nothing && triple!(cg.mod, triple)
    datalayout != nothing && datalayout!(cg.mod, datalayout)
    cg.builtin = setup_builtins!(cg)
    cg.extern = setup_externs!(cg.mod)
    cg.datatype = setup_types!(cg)
    return cg
end

CodeCtx(; triple = nothing, datalayout = nothing) =
    cg = CodeCtx(LLVM.Module("JuliaCodeGenModule", ctx), "", CodeInfo(), Nothing, Tuple{}, "", Tuple{}, triple = triple, datalayout = datalayout)

function CodeCtx(orig_cg::CodeCtx, name, ci::CodeInfo, result_type, argtypes, jfun, sig)
    cg = CodeCtx(orig_cg.mod, name, ci, result_type, argtypes, jfun, sig)
    cg.builtin = orig_cg.builtin
    cg.extern = orig_cg.extern
    cg.datatype = orig_cg.datatype
    return cg
end

function CodeCtx(@nospecialize(fun), @nospecialize(argtypes); optimize_lowering = true, triple = nothing, datalayout = nothing)
    ci, dt = code_typed(fun, argtypes, optimize = optimize_lowering)[1]
    sig = first(methods(fun, argtypes)).sig
    funname = string(Base.function_name(fun))
    cg = CodeCtx(funname, ci, dt, fun, argtypes)
    codegen!(cg)
    return cg
end

# This is for testing
function CodeCtx_init(@nospecialize(fun), @nospecialize(argtypes); optimize_lowering = true, triple = nothing, datalayout = nothing)
    ci, dt = code_typed(fun, argtypes, optimize = optimize_lowering)[1]
    sig = first(methods(fun, argtypes)).sig
    funname = string(Base.function_name(fun))
    cg = CodeCtx(funname, ci, dt, argtypes, fun, sig)
    # @info "## $(cg.name)"
    ci = cg.code_info
    argtypes = LLVMType[llvmtype(p) for p in cg.argtypes.parameters]
    for i in 1:length(argtypes)
        if isa(argtypes[i], LLVM.VoidType)
            argtypes[i] = int32_t
        end
    end
    func_type = LLVM.FunctionType(llvmtype(cg.result_type), argtypes)
    cg.func = LLVM.Function(cg.mod, cg.name, func_type)
    cg.nargs = length(argtypes)
    LLVM.linkage!(cg.func, LLVM.API.LLVMExternalLinkage)
    entry = LLVM.BasicBlock(cg.func, "entry", ctx)
    LLVM.position!(cg.builder, entry)
    return cg
end

Base.show(io::IO, cg::CodeCtx) = print(io, "CodeCtx")


text:
using PhotoOrganizer

dry_run = false
rm_src = false
dst_root="/home/hertz/Pictures/Pictures"

src_dirs = String[]
#push!(src_dirs, "/run/user/1000/gvfs/mtp:host=%5Busb%3A002%2C009%5D/Samsung SD card/CameraZOOM")
#push!(src_dirs, "/run/user/1000/gvfs/mtp:host=%5Busb%3A002%2C009%5D/Samsung SD card/DCIM/Camera")
#push!(src_dirs, "/home/hertz/Documents/Glen/backups/Google/Takeout/Google Photos")
#push!(src_dirs, "/home/hertz/Documents/Erin/backups/Google/Takeout/Google Photos")
#src_dirs = readlines(`/home/hertz/bin/ls_phone_backup_dirs.jl`)

src_dirs = ["/home/hertz/Documents.local/Pictures"]
if length(src_dirs) > 0
    organize_photos(src_dirs, dst_root, rm_src, dry_run)
else
    warn("No directories found to backup")
end


text:
# Use baremodule to shave off a few KB from the serialized `.ji` file
baremodule MbedTLS_jll
using Base
using Base: UUID
import JLLWrappers

JLLWrappers.@generate_main_file_header("MbedTLS")
JLLWrappers.@generate_main_file("MbedTLS", UUID("c8ffd9c3-330d-5841-b78e-0817d7145fa1"))
end  # module MbedTLS_jll


text:
# This file is a part of TextSearch.jl

#####
using CategoricalArrays
export EntropyWeighting

"""
    EntropyWeighting(; smooth=0.0, lowerweight=0.0, weights=:balance)

Entropy weighting uses the empirical entropy of the vocabulary along classes to produce a notion of importance for each token
"""
struct EntropyWeighting <: GlobalWeighting end

function entropy(dist)
    e = 0.0
    ipop = 1/sum(dist)

    for x in dist
        p = x * ipop

        if p > 0.0
            e -= p * log2(p)
        end
    end

    e
end

"""
    VectorModel(ent::EntropyWeighting, lw::LocalWeighting, corpus::BOW, labels;
        mindocs::Integer=1,
        smooth::Float64=0.0,
        weights=:balance,
        lowerweight=0.0
    )

Creates a vector model using the input corpus.
"""
function VectorModel(ent::EntropyWeighting, lw::LocalWeighting, voc::Vocabulary, corpus::AbstractVector{BOW}, labels;
            mindocs=1,
            smooth::Float64=0.0,
            weights=:balance
        )
    nclasses = length(levels(labels))
    D = fill(smooth, nclasses, vocsize(voc))

    for (i, bow) in enumerate(corpus)
        code = levelcode(labels[i])
        for (tokenID, _) in bow
            D[code, tokenID] += 1 # occs/M # log2(1 + occs)
        end
    end

    weights = _compute_weights(weights, D, nclasses)
    _compute_entropy(voc, D, weights, nclasses, mindocs)
    VectorModel(ent, lw, voc; mindocs)
end

function VectorModel(ent::EntropyWeighting, lw::LocalWeighting, textconfig::TextConfig, corpus::AbstractVector, labels;
            mindocs=1,
            smooth::Float64=0.0,
            weights=:balance,
            minbatch=0
        )
    nclasses = length(levels(labels))
    corpus_tokens = tokenize_corpus(textconfig, corpus; minbatch)
    voc = Vocabulary(textconfig, corpus_tokens)
    D = fill(smooth, nclasses, length(voc))
    bow = BOW()

    for (i, tokens) in enumerate(corpus_tokens)
        empty!(bow)
        vectorize(voc, tokens, bow)

        code = levelcode(labels[i])
        for (tokenID, _) in bow
            D[code, tokenID] += 1 # occs/M # log2(1 + occs)
        end
    end

    weights = _compute_weights(weights, D, nclasses)
    _compute_entropy(voc, D, weights, nclasses, mindocs)
    VectorModel(ent, lw, voc; mindocs)
end

function _compute_weights(weights, D, nclasses)
    weights isa String ? Symbol(weights) : weights

    if weights === :balance
        weights = vec(sum(D, dims=2))
        weights .= sum(weights) ./ weights
    elseif weights === :none
        weights = ones(Float64, nclasses)
    end

    weights
end

function _compute_entropy(voc, D, weights, nclasses, mindocs)
    maxent = log2(nclasses)

    @inbounds for tokenID in eachindex(voc)
        if voc.ndocs[tokenID] < mindocs
            voc.weight[tokenID] = 0.0
        else
            dist = @view D[:, tokenID]
            dist .= dist .* weights
            e = 1.0 - entropy(dist) / maxent
            voc.weight[tokenID] = e
        end
    end
end

@inline global_weighting(model::VectorModel{EntropyWeighting}, tokenID) = weight(model, tokenID)

max_stars_repo_name: sadit/TextModel

max_issues_repo_name: sadit/TextModel

max_forks_repo_name: sadit/TextModel


text:
using ..Collocation: GrevilleSiteIterator

"""
    VariationDiminishing <: AbstractApproxMethod

Schoenberg's variation diminishing spline approximation.

Approximates a function ``f`` by setting the B-spline coefficients as
``c_i = f(x_i)``, where the locations ``x_i`` are chosen as the Greville sites:

```math
x_i = \\frac{1}{k - 1} ∑_{j = 1}^{k - 1} t_{i + j}.
```

This method is expected to preserve the shape of the function.
However, it may be very inaccurate as an actual approximation of it.

For details, see e.g. de Boor 2001, chapter XI.

!!! warning

    Currently, this method is not guaranteed to work well with recombined
    B-spline bases (of type [`RecombinedBSplineBasis`](@ref)).

"""
struct VariationDiminishing <: AbstractApproxMethod end

function approximate(f, B::AbstractBSplineBasis, m::VariationDiminishing)
    T = typeof(f(first(knots(B))))
    S = Spline{T}(undef, B)
    A = SplineApproximation(m, S, nothing)
    approximate!(f, A)
end

function _approximate!(f, A, m::VariationDiminishing)
    @assert method(A) === m
    B = basis(A)
    S = spline(A)
    cs = coefficients(S)
    for (i, x) in zip(eachindex(cs), GrevilleSiteIterator(B))
        @inbounds cs[i] = f(x)
    end
    A
end

max_stars_repo_name: jipolanco/BasisSplines

max_issues_repo_name: jipolanco/BasisSplines

max_forks_repo_name: jipolanco/BasisSplines


text:
## ExoplanetsSysSim/src/mission_constants.jl
## (c) 2015 Eric B. Ford

#module KeplerConstants
 const num_channels = 84
 const num_modules = 42
 const num_quarters = 17              # QUERY:  I'm favoring leaving out quarter 0, since that was engineering data.  Agree?
 const cdpp_durations = [1.5,2.,2.5,3.,3.5,4.5,5.,6.,7.5,9.,10.5,12.,12.5,15.]
 const num_cdpp_timescales = length(cdpp_durations) # TODO SCI DETAIL: Increase if implement separate CDPPs for each quarter and/or use SC
 const mission_data_span = 1459.789   # maximum(ExoplanetsSysSim.StellarTable.df[:dataspan])
 const mission_duty_cycle = 0.8751    # median(ExoplanetsSysSim.StellarTable.df[:dutycycle])

 const kepler_exp_time_internal  =  6.019802903/(24*60*60)    # https://archive.stsci.edu/kepler/manuals/archive_manual.pdf
 const kepler_read_time_internal = 0.5189485261/(24*60*60)    # https://archive.stsci.edu/kepler/manuals/archive_manual.pdf
 const num_exposures_per_LC = 270
 const num_exposures_per_SC = 9
 const LC_integration_time = kepler_exp_time_internal*num_exposures_per_LC
 const SC_integration_time = kepler_exp_time_internal*num_exposures_per_SC
 const LC_read_time = kepler_read_time_internal*num_exposures_per_LC
 const SC_read_time = kepler_read_time_internal*num_exposures_per_SC
 const LC_duration = LC_integration_time +  LC_read_time
 const SC_duration = SC_integration_time +  SC_read_time
 const LC_rate = 1.0/LC_duration
 const SC_rate = 1.0/SC_duration

# export num_channels,num_modules,num_quarters,num_cdpp_timescales,mission_data_span,mission_duty_cycle
# export kepler_exp_time_internal,kepler_read_time_internal,num_exposures_per_LC,num_exposures_per_SC
# export LC_integration_time,SC_integration_time,LC_read_time,SC_read_time,LC_duration,SC_duration,LC_rate,SC_rate
#end

#using KeplerConstants

# Standard conversion factors on which unit system is based
const global AU_in_m_IAU2012 = 149597870700.0
 const global G_in_mks_IAU2015 = 6.67384e-11
 const global G_mass_sun_in_mks = 1.3271244e20
 const global G_mass_earth_in_mks = 3.986004e14
 const global sun_radius_in_m_IAU2015 = 6.9566e8
 const global earth_radius_eq_in_m_IAU2015 = 6.3781e6
 const global sun_mass_in_kg_IAU2010 = 1.988547e30

# Constants used by this code
const global sun_mass = 1.0
 const global earth_mass = G_mass_earth_in_mks/G_mass_sun_in_mks  # about 3.0024584e-6
 const global earth_radius = earth_radius_eq_in_m_IAU2015 / sun_radius_in_m_IAU2015 # about 0.0091705248
 const global rsol_in_au = sun_radius_in_m_IAU2015 / AU_in_m_IAU2012  # about 0.00464913034
 const global sec_in_day = 24*60*60
 const global grav_const = G_in_mks_IAU2015 * sec_in_day^2 * sun_mass_in_kg_IAU2010 / AU_in_m_IAU2012^3 # about 2.9591220363e-4 in AU^3/(day^2 Msol)
 const global day_in_year = 365.25


text:
using Distributions
using JLD2 # extra dependency
using LinearAlgebra
using SurvivalSignature

adj = gridnetwork(5, 5)
types = Dict(1 => collect(1:2:25), 2 => collect(2:2:25))
φ = s_t_connectivity([1:25;], [1], [25])

# Load exact solution
@load "demo/data/grid_55_exact.jld2"

## Percolation error
signature_percolation = copy(signature_55_exact)
percolation_preprocessor!(signature_percolation, adj)

absolute_error_percolation = norm(signature_55_exact .- signature_percolation)
relative_error_percolation = absolute_error_percolation / norm(signature_55_exact)

# Approximation error
signature_monte_carlo, _ =
    survivalsignature(adj, types, φ, 10000, 0.0, percolation_preprocessor!)

absolute_error_monte_carlo = norm(signature_percolation .- signature_monte_carlo) # Don't repeat the percolation error
relative_error_monte_carlo = absolute_error_monte_carlo / norm(signature_percolation)

# Reliability error

dists = Dict(1 => Exponential(1), 2 => Weibull(2, 1))
t = [0:0.001:1;]

P_exact = reliability(t, signature_55_exact, dists)
P_monte_carlo = reliability(t, signature_monte_carlo, dists)

absolute_reliability_error = norm(P_exact .- P_monte_carlo)
relative_reliability_error = absolute_reliability_error / norm(P_exact)

println("Absolute percolation error: $absolute_error_percolation")
println("Relative percolation error: $relative_error_percolation")

println("Absolute Monte Carlo error: $absolute_error_monte_carlo")
println("Relative Monte Carlo error: $relative_error_monte_carlo")

println("Absolute reliability error: $absolute_reliability_error")
println("Relative reliability error: $relative_reliability_error")


text:
module Slack

using HTTP
using CodecZlib
using JSON

# Message object in the threaded form
mutable struct threadedMessage
    edited::Bool
    ts::String
    thread_ts::String
    user::String
    text::String
end

# A thread is an array of threadMessage's
mutable struct thread
    thread::Array{threadedMessage}
end

mutable struct message
    edited::Bool
    ts::String
    user::String
    text::String
end

include("send.jl")
export
    sendtoslack,
    sendattachmenttoslack,
    sendfiletoslack

include("channel.jl")
export
    getchannels

include("history.jl")
export
    getchannelhistory

include("threads.jl")
export
    getthreads

end # module


text:
using Hungarian

"""
    assignment, cost = solveLAP(costmatrix::Matrix{Float32})

Solve the linear assignment problem designated by `costmatrix`.

# Description
Solve the linear assignment problem (LAP) defined by `costmatrix` using the
package Hungarian.jl.  For now, this method is just a wrapper around
Hungarian.jl, however the intention is to add more checks and options to this
method in the future.
"""
function solveLAP(costmatrix::Matrix{Float32})
    # If the input costmatrix is empty we shouldn't continue.
    if isempty(costmatrix)
        assignment = []
        cost = []
        return assignment, cost
    end

    # Solve the LAP.
    assignment, cost = Hungarian.hungarian(costmatrix)

    return assignment, cost
end


text:
using OpenCV
const cv = OpenCV
size0 = Int32(300)
# take the model from https://github.com/opencv/opencv_extra/tree/master/testdata/dnn
net = cv.dnn_DetectionModel("opencv_face_detector.pbtxt", "opencv_face_detector_uint8.pb")

cv.dnn.setPreferableTarget(net, cv.dnn.DNN_TARGET_CPU)
cv.dnn.setInputMean(net, (104, 177, 123))
cv.dnn.setInputScale(net, 1.)
cv.dnn.setInputSize(net, size0, size0)

cap = cv.VideoCapture(Int32(0))
while true
    ok, frame = cv.read(cap)
    if ok == false
        break
    end
    classIds, confidences, boxes = cv.dnn.detect(net, frame, confThreshold=Float32(0.5))

    for i in 1:size(boxes,1)
        confidence = confidences[i]
        x0 = Int32(boxes[i].x)
        y0 = Int32(boxes[i].y)
        x1 = Int32(boxes[i].x+boxes[i].width)
        y1 = Int32(boxes[i].y+boxes[i].height)
        cv.rectangle(frame, cv.Point{Int32}(x0, y0), cv.Point{Int32}(x1, y1), (100, 255, 100); thickness = Int32(5))
        label = "face: " * string(confidence)
        lsize, bl = cv.getTextSize(label, cv.FONT_HERSHEY_SIMPLEX, 0.5, Int32(1))
        cv.rectangle(frame, cv.Point{Int32}(x0,y0), cv.Point{Int32}(x0+lsize.width, y0+lsize.height+bl), (100,255,100); thickness = Int32(-1))
        cv.putText(frame, label, cv.Point{Int32}(x0, y0 + lsize.height),
        cv.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0); thickness = Int32(1), lineType = cv.LINE_AA)
    end

    cv.imshow("detections", frame)
    if cv.waitKey(Int32(30)) >= 0
        break
    end
end


text:
# export AirfoilData, readaerodyn

# import Interpolations: interpolate, Gridded, Linear, GriddedInterpolation
import Dierckx: Spline1D, evaluate

# type AirfoilData
#     alpha::Array{Float64,1}
#     cl::Array{Float64,1}
#     cd::Array{Float64,1}
# end

# type AirfoilData
#     cl::GriddedInterpolation
#     cd::GriddedInterpolation
# end

function readaerodyn(filename)
    """currently only reads one Reynolds number if multiple exist"""

    alpha = Float64[]
    cl = Float64[]
    cd = Float64[]

    open(filename) do f

        # skip header
        for i = 1:13
            readline(f)
        end

        # read until EOT
        while true
            line = readline(f)
            if occursin(line, "EOT")
                break
            end
            parts = split(line)
            push!(alpha, parse(Float64,parts[1]))
            push!(cl, parse(Float64,parts[2]))
            push!(cd, parse(Float64,parts[3]))
        end
    end

    # af = AirfoilData(alpha*pi/180.0, cl, cd)

    # 1D interpolations for now.  ignoring Re dependence (which is very minor)
    # afcl = interpolate((alpha*pi/180.0,), cl, Gridded(Linear()))
    # afcd = interpolate((alpha*pi/180.0,), cd, Gridded(Linear()))
    # af = AirfoilData(afcl, afcd)

    afcl = Spline1D(alpha*pi/180, cl, s=0.1)
    afcd = Spline1D(alpha*pi/180, cd, s=0.001)

    function af(alpha)

        cl = evaluate(afcl, alpha)
        cd = evaluate(afcd, alpha)

        return cl, cd
    end

    return af#, alpha*pi/180, cl, cd
end

# end

# filename = "airfoils/naca0015-wt.dat"
# af, a0, cl0, cd0 = readaerodyn(filename)
# alpha = LinRange(-pi, pi, 2000)
# cl, cd = af(alpha)
# using PyPlot
# figure()
# plot(alpha, cl)
# plot(a0, cl0, "o")
# figure()
# plot(alpha, cd)
# plot(a0, cd0, "o")
# show()

max_stars_repo_name: kevmoor/vawt-ac

max_issues_repo_name: kevmoor/vawt-ac

max_forks_repo_name: kevmoor/vawt-ac


text:
"""
Task is to copy content from the input tape to
the output tape. http://arxiv.org/abs/1511.07275
"""

using DataStructures: CircularBuffer
include("AlgorithmicEnv.jl")

RealOrNothing = Union{Float32, Nothing}

mutable struct CopyEnv <: TapeAlgorithmicEnv
    MIN_REWARD_SHORTFALL_FOR_PROMOTION::Float32
    base::Int8  # Number of distinct characters
    episode_total_reward::RealOrNothing  # Cumulative reward earned this episode

    # Running tally of reward shortfalls. eg If there were 10 points to earn
    # and we got 8, we'd append -2
    reward_shortfalls::CircularBuffer{Float32}

    charmap::Array{Char, 1}  # Array of all the characters used while rendering
    min_length::Int8  # Minimum length of the input tape
    action_space::TupleSpace
    observation_space::Discrete

    MOVEMENTS::NTuple # Possible directions to move in.
    READ_HEAD_START::Int8  # Starting position of the read head

    target::Array{N, 1} where N <: Union{Char, Integer}  # target tape
    input_data::Array{N, 1} where N <: Union{Char, Integer}
    time::Int8
    read_head_position::Int8  # current position of the read head.
    write_head_position::Int8
    last_action
    last_reward::Float32
end

function CopyEnv(base::Int=5, chars::Bool=true)
    starting_char = chars ? 'A' : '0'
    CopyEnv(-1f0, # MIN_REWARD_SHORTFALL_FOR_PROMOTION
            base,
            0f0, # episode_total_reward
            CircularBuffer{Float32}(10),  # reward_shortfalls
            push!([starting_char+i for i=0:base-1], ' '),  # charmap
            2,  # starting min_length
            TupleSpace([Discrete(2), Discrete(2), Discrete(base)]),  # action_space
            Discrete(base+1),  # observation_space
            (:left, :right), 1,  # MOVEMENTS and READ_HEAD_START
            Array{(chars ? Char : Int8), 1}(), # target
            Array{(chars ? Char : Int8), 1}(), # input_data
            0,  # time
            1,  # read_head_posiion
            1,  # write_head_position
            nothing,  # last_action
            0.0)  # last_reward
end

target_from_input_data!(env::CopyEnv) = env.target = env.input_data


text:
# I think it makes more sense to let the array into the function.
# That way the coefficient conversions happen once.
#=
function cauchy{S,T}(f::Fun{S,T},z::Array)
    ret=Array(Complex{Float64},size(z)...)
    for k=1:size(z,1),j=1:size(z,2)
        @inbounds ret[k,j]=cauchy(f,z[k,j])
    end
    ret
end
=#

for op in (:(stieltjes),:(cauchy),:(logkernel),:(stieltjesintegral),:(cauchyintegral))
    @eval begin
        $op(S::PiecewiseSpace,v,z) = mapreduce(f->$op(f,z),+,components(Fun(S,v)))
        function $op(f::Fun{S,T}) where {S<:PiecewiseSpace,T}
            v = map($op,components(f))
            Fun(ApproxFun.SumSpace(map(space,v)),vec(permutedims(coefficientmatrix(v))))
        end
        $op(S::PiecewiseSpace,v) = depiece($op(components(Fun(S,v))))

        # directed is usually analytic continuation, so we need to unwrap
        # directd
        $op(S::PiecewiseSpace,v,z::Directed) =
            mapreduce(f-> (z ∈ domain(f)) ? $op(f,z) : $op(f,z.x),+,components(Fun(S,v)))
    end
end

hilbert(v::Vector{F},x) where {F<:Union{Fun,Any}} =

hilbert(S::PiecewiseSpace,v,z) = mapreduce(f->(x in domain(f)) ? hilbert(f,x) : -stieltjes(f,x)/π,
                                           +, components(Fun(S,v)))

stieltjes(S::ArraySpace,v,z::Number) = stieltjes.(Array(Fun(S,v)),z)
stieltjes(S::ArraySpace,v) = Fun(stieltjes.(Array(Fun(S,v))))


text:
using LsqFit
using Calculus

# a simple wrapper for Levenberg-Marquardt with finite differencing for the
# Jacobian
lmdif(f, x0; show_trace::Bool=false) = LsqFit.levenberg_marquardt(f, jacobian(f), x0, show_trace=show_trace)


text:
# This file is a part of Julia. License is MIT: https://julialang.org/license

module Multimedia

export Display, display, pushdisplay, popdisplay, displayable, redisplay,
    MIME, @MIME_str, reprmime, stringmime, istextmime,
    mimewritable, TextDisplay

###########################################################################
# We define a singleton type MIME{mime symbol} for each MIME type, so
# that Julia's dispatch and overloading mechanisms can be used to
# dispatch show and to add conversions for new types.

# defined in sysimg.jl for bootstrapping:
# struct MIME{mime} end
# macro MIME_str(s)
import Base: MIME, @MIME_str

import Base: show, print, string, convert
MIME(s) = MIME{Symbol(s)}()
show(io::IO, ::MIME{mime}) where {mime} = print(io, "MIME type ", string(mime))
print(io::IO, ::MIME{mime}) where {mime} = print(io, mime)

###########################################################################
# For any type T one can define show(io, ::MIME"type", x::T) = ...
# in order to provide a way to export T as a given mime type.

"""
    mimewritable(mime, x)

Returns a boolean value indicating whether or not the object `x` can be written as the given
`mime` type. (By default, this is determined automatically by the existence of the
corresponding [`show`](@ref) method for `typeof(x)`.)

# Examples
```jldoctest
julia> mimewritable(MIME("text/plain"), rand(5))
true

julia> mimewritable(MIME("img/png"), rand(5))
false
```
"""
mimewritable(::MIME{mime}, x) where {mime} =
    method_exists(show, Tuple{IO, MIME{mime}, typeof(x)})

"""
    show(stream, mime, x)

The [`display`](@ref) functions ultimately call `show` in order to write an object `x` as a
given `mime` type to a given I/O `stream` (usually a memory buffer), if possible. In order
to provide a rich multimedia representation of a user-defined type `T`, it is only necessary
to define a new `show` method for `T`, via: `show(stream, ::MIME"mime", x::T) = ...`,
where `mime` is a MIME-type string and the function body calls `write` (or similar) to write
that representation of `x` to `stream`. (Note that the `MIME""` notation only supports
literal strings; to construct `MIME` types in a more flexible manner use
`MIME{Symbol("")}`.)

For example, if you define a `MyImage` type and know how to write it to a PNG file, you
could define a function `show(stream, ::MIME"image/png", x::MyImage) = ...` to allow
your images to be displayed on any PNG-capable `Display` (such as IJulia). As usual, be sure
to `import Base.show` in order to add new methods to the built-in Julia function
`show`.

The default MIME type is `MIME"text/plain"`. There is a fallback definition for `text/plain`
output that calls `show` with 2 arguments. Therefore, this case should be handled by
defining a 2-argument `show(stream::IO, x::MyType)` method.

Technically, the `MIME"mime"` macro defines a singleton type for the given `mime` string,
which allows us to exploit Julia's dispatch mechanisms in determining how to display objects
of any given type.

The first argument to `show` can be an [`IOContext`](@ref) specifying output format properties.
See [`IOContext`](@ref) for details.
"""
show(stream, mime, x)

# it is convenient to accept strings instead of ::MIME
show(io::IO, m::AbstractString, x) = show(io, MIME(m), x)
mimewritable(m::AbstractString, x) = mimewritable(MIME(m), x)

verbose_show(io, m, x) = show(IOContext(io, :limit => false), m, x)

"""
    reprmime(mime, x)

Returns an `AbstractString` or `Vector{UInt8}` containing the representation of
`x` in the requested `mime` type, as written by `show` (throwing a
`MethodError` if no appropriate `show` is available). An `AbstractString` is
returned for MIME types with textual representations (such as `"text/html"` or
`"application/postscript"`), whereas binary data is returned as
`Vector{UInt8}`. (The function `istextmime(mime)` returns whether or not Julia
treats a given `mime` type as text.)

As a special case, if `x` is an `AbstractString` (for textual MIME types) or a
`Vector{UInt8}` (for binary MIME types), the `reprmime` function assumes that
`x` is already in the requested `mime` format and simply returns `x`. This
special case does not apply to the `"text/plain"` MIME type. This is useful so
that raw data can be passed to `display(m::MIME, x)`.
"""
reprmime(m::MIME, x) = istextmime(m) ? _textreprmime(m, x) : _binreprmime(m, x)

# strings are shown escaped for text/plain
_textreprmime(m::MIME, x) = sprint(verbose_show, m, x)
_textreprmime(::MIME, x::AbstractString) = x
_textreprmime(m::MIME"text/plain", x::AbstractString) =
    sprint(verbose_show, m, x)

function _binreprmime(m::MIME, x)
    s = IOBuffer()
    verbose_show(s, m, x)
    take!(s)
end
_binreprmime(m::MIME, x::Vector{UInt8}) = x

"""
    stringmime(mime, x)

Returns an `AbstractString` containing the representation of `x` in the
requested `mime` type. This is similar to [`reprmime`](@ref) except
that binary data is base64-encoded as an ASCII string.
"""
stringmime(m::MIME, x) = istextmime(m) ? reprmime(m, x) : _binstringmime(m, x)

_binstringmime(m::MIME, x) = base64encode(verbose_show, m, x)
_binstringmime(m::MIME, x::Vector{UInt8}) = base64encode(write, x)

"""
    istextmime(m::MIME)

Determine whether a MIME type is text data. MIME types are assumed to be binary
data except for a set of types known to be text data (possibly Unicode).

# Examples
```jldoctest
julia> istextmime(MIME("text/plain"))
true

julia> istextmime(MIME("img/png"))
false
```
"""
istextmime(m::MIME) = startswith(string(m), "text/")

# it is convenient to accept strings instead of ::MIME
istextmime(m::AbstractString) = istextmime(MIME(m))
reprmime(m::AbstractString, x) = reprmime(MIME(m), x)
stringmime(m::AbstractString, x) = stringmime(MIME(m), x)

for mime in ["application/atom+xml", "application/ecmascript",
             "application/javascript", "application/julia",
             "application/json", "application/postscript",
             "application/rdf+xml", "application/rss+xml",
             "application/x-latex", "application/xhtml+xml", "application/xml",
             "application/xml-dtd", "image/svg+xml", "model/vrml",
             "model/x3d+vrml", "model/x3d+xml"]
    global istextmime(::MIME{Symbol(mime)}) = true
end

###########################################################################
# We have an abstract Display class that can be subclassed in order to
# define new rich-display output devices.  A typical subclass should
# overload display(d::Display, m::MIME, x) for supported MIME types m,
# (typically using reprmime or stringmime to get the MIME
# representation of x) and should also overload display(d::Display, x)
# to display x in whatever MIME type is preferred by the Display and
# is writable by x.  display(..., x) should throw a MethodError if x
# cannot be displayed.  The return value of display(...) is up to the
# Display type.

abstract type Display end

# it is convenient to accept strings instead of ::MIME
display(d::Display, mime::AbstractString, x) = display(d, MIME(mime), x)
display(mime::AbstractString, x) = display(MIME(mime), x)

"""
    displayable(mime) -> Bool
    displayable(d::Display, mime) -> Bool

Returns a boolean value indicating whether the given `mime` type (string) is displayable by
any of the displays in the current display stack, or specifically by the display `d` in the
second variant.
"""
displayable(d::Display, mime::AbstractString) = displayable(d, MIME(mime))
displayable(mime::AbstractString) = displayable(MIME(mime))

# simplest display, which only knows how to display text/plain

"""
    TextDisplay(io::IO)

Returns a `TextDisplay <: Display`, which displays any object as the text/plain MIME type
(by default), writing the text representation to the given I/O stream. (This is how
objects are printed in the Julia REPL.)
"""
struct TextDisplay <: Display
    io::IO
end
display(d::TextDisplay, M::MIME"text/plain", x) = show(d.io, M, x)
display(d::TextDisplay, x) = display(d, MIME"text/plain"(), x)

# if you explicitly call display("text/foo", x), it should work on a TextDisplay:
displayable(d::TextDisplay, M::MIME) = istextmime(M)
function display(d::TextDisplay, M::MIME, x)
    displayable(d, M) || throw(MethodError(display, (d, M, x)))
    show(d.io, M, x)
end

import Base: close, flush
flush(d::TextDisplay) = flush(d.io)
close(d::TextDisplay) = close(d.io)

###########################################################################
# We keep a stack of Displays, and calling display(x) uses the topmost
# Display that is capable of displaying x (doesn't throw an error)

const displays = Display[]

"""
    pushdisplay(d::Display)

Pushes a new display `d` on top of the global display-backend stack. Calling `display(x)` or
`display(mime, x)` will display `x` on the topmost compatible backend in the stack (i.e.,
the topmost backend that does not throw a [`MethodError`](@ref)).
"""
function pushdisplay(d::Display)
    global displays
    push!(displays, d)
end

"""
    popdisplay()
    popdisplay(d::Display)

Pop the topmost backend off of the display-backend stack, or the topmost copy of `d` in the
second variant.
"""
popdisplay() = pop!(displays)
function popdisplay(d::Display)
    for i = length(displays):-1:1
        if d == displays[i]
            return splice!(displays, i)
        end
    end
    throw(KeyError(d))
end
function reinit_displays()
    empty!(displays)
    pushdisplay(TextDisplay(STDOUT))
end

xdisplayable(D::Display, args...) = applicable(display, D, args...)

"""
    display(x)
    display(d::Display, x)
    display(mime, x)
    display(d::Display, mime, x)

Display `x` using the topmost applicable display in the display stack, typically using the
richest supported multimedia output for `x`, with plain-text [`STDOUT`](@ref) output as a fallback.
The `display(d, x)` variant attempts to display `x` on the given display `d` only, throwing
a [`MethodError`](@ref) if `d` cannot display objects of this type.

There are also two variants with a `mime` argument (a MIME type string, such as
`"image/png"`), which attempt to display `x` using the requested MIME type *only*, throwing
a `MethodError` if this type is not supported by either the display(s) or by `x`. With these
variants, one can also supply the "raw" data in the requested MIME type by passing
`x::AbstractString` (for MIME types with text-based storage, such as text/html or
application/postscript) or `x::Vector{UInt8}` (for binary MIME types).
"""
function display(x)
    for i = length(displays):-1:1
        if xdisplayable(displays[i], x)
            try
                return display(displays[i], x)
            catch e
                isa(e, MethodError) && e.f in (display, show) ||
                    rethrow()
            end
        end
    end
    throw(MethodError(display, (x,)))
end

function display(m::MIME, x)
    for i = length(displays):-1:1
        if xdisplayable(displays[i], m, x)
            try
                return display(displays[i], m, x)
            catch e
                isa(e, MethodError) && e.f == display ||
                    rethrow()
            end
        end
    end
    throw(MethodError(display, (m, x)))
end

displayable(d::D, ::MIME{mime}) where {D<:Display,mime} =
    method_exists(display, Tuple{D,MIME{mime},Any})

function displayable(m::MIME)
    for d in displays
        displayable(d, m) && return true
    end
    return false
end

###########################################################################
# The redisplay method can be overridden by a Display in order to
# update an existing display (instead of, for example, opening a new
# window), and is used by the IJulia interface to defer display
# until the next interactive prompt.  This is especially useful
# for Matlab/Pylab-like stateful plotting interfaces, where
# a plot is created and then modified many times (xlabel, title, etc.).

"""
    redisplay(x)
    redisplay(d::Display, x)
    redisplay(mime, x)
    redisplay(d::Display, mime, x)

By default, the `redisplay` functions simply call [`display`](@ref).
However, some display backends may override `redisplay` to modify an existing
display of `x` (if any).
Using `redisplay` is also a hint to the backend that `x` may be redisplayed
several times, and the backend may choose to defer the display until
(for example) the next interactive prompt.
"""
function redisplay(x)
    for i = length(displays):-1:1
        if xdisplayable(displays[i], x)
            try
                return redisplay(displays[i], x)
            catch e
                isa(e, MethodError) && e.f in (redisplay, display, show) ||
                    rethrow()
            end
        end
    end
    throw(MethodError(redisplay, (x,)))
end

function redisplay(m::Union{MIME,AbstractString}, x)
    for i = length(displays):-1:1
        if xdisplayable(displays[i], m, x)
            try
                return redisplay(displays[i], m, x)
            catch e
                isa(e, MethodError) && e.f in (redisplay, display) ||
                    rethrow()
            end
        end
    end
    throw(MethodError(redisplay, (m, x)))
end

# default redisplay is simply to call display
redisplay(d::Display, x) = display(d, x)
redisplay(d::Display, m::Union{MIME,AbstractString}, x) = display(d, m, x)

###########################################################################

end # module

max_stars_repo_name: visr/julia

max_issues_repo_name: visr/julia

max_forks_repo_name: visr/julia


text:
module Day1

using Base.Iterators

mutable struct Scanner
    prev::Int64
    count::Int64
end

struct WindowIterator{I}
    iter::I
    size::Integer
end

function Base.iterate(w::WindowIterator{I}) where I
    result = iterate(w.iter)
    if result == nothing
        return nothing
    end
    (e, state) = result
    len = min(w.size, length(w.iter))
    if len == 0
        return nothing
    end
    window = Vector{eltype(w.iter)}(undef, len)
    window[1] = e
    for i in 2:length(window)
        (e, state) = iterate(w.iter, state)
        window[i] = e
    end
    (window, (window, state))
end

function Base.iterate(w::WindowIterator{I}, state) where I
    (window, state) = state
    result = iterate(w.iter, state)
    if result == nothing
        return nothing
    else
        (next_elem, state) = result
        window = vcat(window[2:w.size], [next_elem])
        return (window, (window, state))
    end
end

Base.IteratorSize(::WindowIterator{I}) where I = Base.HasLength()
Base.IteratorEltype(::WindowIterator{I}) where I = Base.HasEltype()
Base.eltype(w::WindowIterator{I}) where I = Vector{eltype(I)}
Base.length(w::WindowIterator{I}) where I = length(w.iter) == 0 ? 0 : max(length(w.iter) - w.size + 1, 1)

window(iter::I, size::Integer) where I = WindowIterator(iter, size)

cmp(s::Scanner, value::Int64) = s.prev < value
function tick!(s::Scanner, value::Int64)
    if cmp(s, value)
        s.count += 1
    end
    s.prev = value
    s
end

function num_increases(itr)
    (first, rest) = Iterators.peel(itr)
    scan = Scanner(first, 0)
    for x in rest
        tick!(scan, x)
    end
    scan.count
end

function read(f::String)::Array{Int64}
    map(x -> parse(Int64, x), readlines(f))
end

run_part1(data_dir::String) = joinpath(data_dir, "day1.txt") |> read |> num_increases

run_part2(data_dir::String) = joinpath(data_dir, "day1.txt") |>
    read |>
    arr -> window(arr, 3) |>
    x -> Iterators.map(sum, x) |>
    num_increases
end


text:
export HLine, RandomHLine, point_on_line, ∨
export perpendicular, points_on_line

struct HLine <: HObject
    s::Float64
    t::Float64
    attr::Dict{Symbol,Any}
    function HLine(a::Real,b::Real)
        a = mod(a,2pi)
        b = mod(b,2pi)
        @assert a!=b "Invalid line"

        if a>b
            a,b = b,a
        end
        L = new(a,b,Dict{Symbol,Any}())
        set_color(L)
        set_thickness(L)
        set_line_style(L)
        return L
    end
end
HLine(L::HLine) = HLine(H.s,H.t) # copy constructor
HLine() = HLine(0,pi)  #default line is a horizontal diameter

(==)(L::HLine, LL::HLine) = abs(L.s-LL.s)<=THRESHOLD*eps(1.) && abs(L.t-LL.t)<=THRESHOLD*eps(1.)

function show(io::IO, L::HLine)
    s = L.s
    t = L.t
    print(io,"HLine($s,$t)")
end

"""
`HLine(P,Q)` creates a new line from the given two points.
"""
function HLine(P::HPoint, Q::HPoint)
    @assert P != Q "Need two distinct points to determine a line"
    f = move2xplus(P,Q)
    g = inv(f)
    a = angle(g(-1))
    b = angle(g(1))
    return HLine(a,b)
end

(∨)(P::HPoint, Q::HPoint) = HLine(P,Q)

"""
`HLine(S::HSegment)` extends the segment `S` to give a (new) line.
"""
function HLine(S::HSegment)
    P,Q = endpoints(S)
    return HLine(P,Q)
end

"""
`RandomHLine()` returns a random line in the hyperbolic plane.

Algorithm: choose two values `s,t` in `[0,2pi)` uniformly at random
and then make the line from `exp(s*im)` to `exp(t*im)`.
"""
function RandomHLine()::HLine
    x = 2*pi*rand()
    y = 2*pi*rand()
    return HLine(x,y)
end

"""
`point_on_line(L)` returns a point on the hyperbolic line `L`.

See also: `points_on_line`.
"""
function point_on_line(L::HLine)
    PP = points_on_line(L,1)
    return PP[1]
end

"""
`points_on_line(L,n)` returns a list of `n`
distinct points on the line `L`.

See also: `point_on_line`.
"""
function points_on_line(L::HLine,n::Int=2)
    @assert n>0 "$n must be positive"
    s = L.s
    t = L.t
    a = exp(s*im)
    b = exp(t*im)
    ab = exp(im*(s+t)/2)

    # move the three ideal points to -1, 0, 1
    f = LFT(a,-1,ab,0,b,1)
    g = inv(f)

    tlist = [ pi*j/(n+1) for j=1:n ]
    zlist = [ exp(t*im) for t in tlist ]
    Plist = [ HPoint(g(z)) for z in zlist ]
    return Plist
end

# Find the complex point that's the euclidean center of the line as drawn
function e_center(L::HLine)::Complex
    s = L.s
    t = L.t

    if abs((t-s)-pi) <= THRESHOLD*eps(1.0)
        return Inf + Inf*im
    end
    P = point_on_line(L)
    a = exp(im*s)
    b = exp(im*t)
    c = getz(P)
    return find_center(a,b,c)
end

# Fine the euclidean radius
function e_radius(L::HLine)::Real
    s = exp(im*L.s)
    t = exp(im*L.t)
    z = e_center(L)
    if isinf(z)
        return Inf
    end
    r1 = abs(z-s)
    r2 = abs(z-t)
    return (r1+r2)/2
end

function in(P::HPoint, L::HLine)
    PP = reflect_across(P,L)
    return P == PP
end

function issubset(S::HSegment, L::T) where T <: Union{HSegment,HLine}
    P,Q = endpoints(S)
    return in(P,L) && in(Q,L)
end

"""
`perpendicular(L::HLine, P::HPoint)` returns a line that is
perpendicular to `L` and contains `P`.
"""
function perpendicular(L::HLine, P::HPoint)::HLine
    if in(P,L)   # case when the point is on L
        f = move2zero(P)
        g = inv(f)
        LL = f(L)
        s = LL.s + pi/2
        t = LL.t + pi/2
        return g(HLine(s,t))
    end
    # case when P is not on L
    PP = reflect_across(P,L)
    return HLine(P,PP)
end

"""
`perpendicular(L)` returns an arbitrary line that is perpendicular to `L`.
"""
perpendicular(L::HLine)::HLine = perpendicular(L, point_on_line(L))
perpendicular(P::HPoint, L::HLine) = perpendicular(L,P)

"""
`dist(P::HPoint,L::HLine)` is the distance from `P`
to the nearest point on `L`.
"""
function dist(P::HPoint,L::HLine)
    LP = perpendicular(L,P)
    Q = meet(LP,L)
    return dist(P,Q)
end

dist(L::HLine, P::HPoint) = dist(P,L)


text:
@testset "1013.partition-array-into-three-parts-with-equal-sum.jl" begin
    @test can_three_parts_equal_sum([0, 2, 1, -6, 6, 7, 9, -1, 2, 0, 1]) == false
    @test can_three_parts_equal_sum([0, 2, 1, -6, 6, -7, 9, 1, 2, 0, 1]) == true
    @test can_three_parts_equal_sum([3, 3, 6, 5, -2, 2, 5, 1, -9, 4]) == true
    @test can_three_parts_equal_sum([0, 0, 0]) == true
    @test can_three_parts_equal_sum([0, 0]) == false
end


text:
using Spring
using Spring: getvalues,advance_nδtpf,initialize_arrays
using CUDA
using Makie
using PlotUtils #for colorant and color gradient (cgrad)

"""
    density_shift!(dc,xc,yc,ls)

Approximate density variation for the 2D mass system :

    dc[i,j]=δρij≃1/(Sij)-1/(4ls) where

        Sij is the surounding surface related to ij mass
        Sij= (xc[i+1,j]-xc[i-1,j])*(yc[i,j+1]-yc[i-1,j])

        and

        4ls is the steady surrounding surface

"""
function density_shift!(dc,xc,yc,ls)
    ns=size(xc,1) #assuming square array
    r0,r1,r2=1:ns-2,2:ns-1,3:ns # UnitRange
    ds=1/(4ls^2)  #steady density
    @views @. dc[r1,r1] = 1/((xc[r2,r1] - xc[r0,r1])*(yc[r1,r2] - yc[r1,r0])) - ds
end

function setup_scene(xaxis,dc,nf)
    scene = Scene(resolution = (800, 800))
    dcnode = Node(dc)

    xM=maximum(xaxis)
    dM=maximum(dc)*0.1
    lim=FRect3D((0,0,0),(xM,xM,dM))

    surface!(scene,xaxis,xaxis,lift(d->d,dcnode),limits=lim,colormap=corporate_gradient(),colorrange = (-dM,dM))
    scale!(scene, 1, 1, 0.1*xM/dM)

    #   translate_cam!(scene,(10,10,2))
    #     update_cam!(scene, Vec3f0(0, 0, 5), Vec3f0(0.01, 0.01, 0))
    #     rotate_cam!(scene,(π/4 ,-π/2 ,0))
    #     αstep=-(π/4)/(nf÷2)
    #     lift(d->rotate_cam!(scene,(0 ,αstep ,0)),dcnode)

    scene,dcnode
end

#Triscale colors ;)
corporate_gradient() = cgrad([colorant"#177272",colorant"#fafafa",colorant"#ee6f40"])

function animate_makie(sp,ip,ap,V)
    δt,nδt,nδtperframe=Spring.getvalues(ap)
    xs,xc,xp,xt,fx,ys,yc,yp,yt,fy=initialize_arrays(sp,ip,ap,V)

    dc=zero(xc)
    cdc=Array(xc)
    density_shift!(dc,xc,yc,sp.ls)
    @. cdc = dc
    xaxis=Array(xs[:,1])
    yaxis=Array(ys[1,:])
    nf=nδt÷nδtperframe

    scene,dcnode=setup_scene(xaxis,cdc,nf)
    display(scene)

    t=0.0
    tdynamic=0.0
    # Makie.record(scene, "output.gif", 1:nf, framerate=15) do i
    for i ∈ 1:nf
        tdynamic+= @elapsed CUDA.@sync begin
            xc,xp,xt=advance_nδtpf(xc,xp,xt,fx,sp,ap)
            yc,yp,yt=advance_nδtpf(yc,yp,yt,fy,sp,ap)
        end
        # @. dc = sqrt((xc - xs)^2+(yc - ys)^2)
        density_shift!(dc,xc,yc,sp.ls)
        @. cdc = dc
        dcnode[] = cdc
        sleep(0.01)
        t+=nδtperframe*δt
    end
end

function go()
    sp=SpringParam(ls=0.1,ms=1,ks=2.5,ns=1000)
    ip=InitParam(λ=3.0,shift=0.1,pos=sp.ls*sp.ns/2)
    ap=AnimParam(δt=0.2,nδt=5000,nδtperframe=40)

    CUDA.allowscalar(false)
    # V=Array{Float64,2}
    V=CuArray{Float64,2}

    @time animate_makie(sp,ip,ap,V)
end
go()


text:
module Experiments

import ..Zoo: Zoo

# Make a data directory if needed
function __init__()
    for dir in (DATADIR, CACHEDIR)
        !ispath(dir) && mkdir(dir)
    end
end

# Common Paths
const EXPERIMENTS_DIR = @__DIR__
const SRCDIR = dirname(EXPERIMENTS_DIR)
const PKGDIR = dirname(SRCDIR)
const REPODIR = dirname(PKGDIR)
const DATADIR = joinpath(REPODIR, "data")
const CACHEDIR = joinpath(DATADIR, "caches")

const CPU_CACHE = joinpath(CACHEDIR, "single_cpu_profile.jls")
const GPU_CACHE = joinpath(CACHEDIR, "gpu_profile.jls")

const GPU_MAX_MEMORY = 11_000_000_000

# Got this number from looking at nvidia-smi after all the GPU initialization code
# in ngraph runs.
#
# Probably worth double-checking
const GPU_MEMORY_OVERHEAD = 561_000_000
const GPU_ADJUSTED_MEMORY = GPU_MAX_MEMORY - GPU_MEMORY_OVERHEAD

# fallback for naming
name(x) = "unknown_network"

#####
##### Convenience wrappers for common models
#####

conventional_inception()    = Inception_v4(1024)
conventional_resnet()       = Resnet200(512)
conventional_vgg()          = Vgg19(2048)
conventional_densenet()     = DenseNet(512)
conventional_transformer()  = Transformer(512, 150)
test_vgg()                  = Vgg19(16)

# Large Models
large_inception() = Inception_v4(6144)      # 659 GB
large_vgg() = Vgg416(320)                   # 658 GB
large_resnet() = Resnet200(2560)            # 651 GB
large_densenet() = DenseNet(3072)           # 688 GB

#####
##### Model Implementations
#####

# Resnet
struct Resnet{T}
    batchsize::Int
    zoo::T
end
Resnet50(batchsize) = Resnet(batchsize, Zoo.Resnet50())
Resnet200(batchsize) = Resnet(batchsize, Zoo.Resnet200())

_sz(::Zoo.Resnet50) = "50"
_sz(::Zoo.Resnet200) = "200"
name(R::Resnet) = "resnet$(_sz(R.zoo))_batchsize_$(R.batchsize)"
titlename(R::Resnet) = "Resnet$(_sz(R.zoo))"
(R::Resnet)() = Zoo.resnet_training(R.zoo, R.batchsize)

# VGG
struct Vgg{T}
    batchsize::Int
    zoo::T
end
Vgg19(batchsize) = Vgg(batchsize, Zoo.Vgg19())
Vgg416(batchsize) = Vgg(batchsize, Zoo.Vgg416())

_sz(::Zoo.Vgg19) = "19"
_sz(::Zoo.Vgg416) = "416"
name(R::Vgg) = "vgg$(_sz(R.zoo))_batchsize_$(R.batchsize)"
titlename(R::Vgg) = "Vgg$(_sz(R.zoo))"
(R::Vgg)() = Zoo.vgg_training(R.zoo, R.batchsize)

# Inception
struct Inception_v4
    batchsize::Int
end
name(R::Inception_v4) = "inception_v4_batchsize_$(R.batchsize)"
titlename(::Inception_v4) = "Inception v4"
(R::Inception_v4)() = Zoo.inception_v4_training(R.batchsize)

# DenseNet
struct DenseNet
    batchsize::Int
end
titlename(R::DenseNet) = "DenseNet 264"
name(R::DenseNet) = "densenet264_batchsize_$(R.batchsize)"
(R::DenseNet)() = Zoo.densenet_training(R.batchsize)

struct Transformer
    batchsize::Int
    sequence_length::Int
end
titlename(T::Transformer) = "Transformer"
name(T::Transformer) = "transformer_batchsize_$(T.batchsize)_seqlen_$(T.sequence_length)"
(T::Transformer)() = Zoo.transformer_training(T.batchsize, T.sequence_length)

end #module

max_stars_repo_name: darchr/AutoTM

max_issues_repo_name: darchr/AutoTM

max_forks_repo_name: darchr/AutoTM


text:
# SimLynx/src/notice.jl
# Licensed under the MIT License. See LICENSE.md file in the project root for
# full license information.

"""
    Notice

Represents the execution of an event at some (simulated) future time. Note that
an event may be an active element: Event, Activity, or Process.

# Fields
- `time::Float64`: the (simulated) time for the event to be executed
- `element::Union{ActiveElement, Nothing}`: the ActiveElement to be executed or
      nothing (as a placeholder)

We need to check if nothing is ever an actual value that is used.
"""
mutable struct Notice
    time::Float64
    element::Union{ActiveElement, Nothing}
end

"Ascending order function for event lists."
islessorequal(notice_1::Notice, notice_2::Notice) =
    notice_1.time <= notice_2.time


text:
using Winston
using DASSL

# test the convergence of dasslSolve.  dasslTestConvergence returns a
# tuple of relative and absolute L^Inf norms of a difference of
# analytic and numerical solutions.  The third element in the returned
# touple is the time it took to obtain the numerical solution.
function dasslTestConvergence{T<:Number}(F          :: Function,  # equation to solve
                                         y0         :: Vector{T}, # initial data
                                         tspan      :: Vector{T}, # time span of a solution
                                         sol        :: Function,  # analytic solution, for comparison with numerical solution
                                         rtol_range :: Vector{T}, # vector of relative tolerances
                                         atol_range :: Vector{T}) # vector of absolute tolerances

    if length(rtol_range) != length(atol_range)
        error("The table of relative errors and absolute errors should be of the same size.")
    end

    n = length(rtol_range)

    norms_abs = zeros(T,n)
    norms_rel = zeros(T,n)
    times     = zeros(T,n)

    for i = 1:n
        times[i] = @elapsed (tn,yn)=dasslSolve(F,y0,tspan,
                                               rtol = rtol_range[i],
                                               atol = atol_range[i])
        k = length(tn)
        delta_rel = zeros(T,k)
        delta_abs = zeros(T,k)

        for j = 1:k
            t = tn[j]
            delta_abs[j] = norm(sol(t)-yn[:,j], Inf)
            delta_rel[j] = norm(sol(t)-yn[:,j], Inf)/norm(sol(t), Inf)
        end

        norms_abs[i]=norm(delta_abs,Inf)
        norms_rel[i]=norm(delta_rel,Inf)

    end

    return norms_rel, norms_abs, times
end

function dasslDrawConvergence{T<:Number}(F     :: Function,  # equation to solve
                                         y0    :: Vector{T}, # initial data
                                         tspan :: Vector{T}, # time span of a solution
                                         sol   :: Function,  # analytic solution, for comparison with numerical solution
                                         rtol  :: Vector{T}, # vector of relative tolerances
                                         atol  :: Vector{T}) # vector of absolute tolerances

    # run the dasslSolve to trigger the compilation
    dasslSolve(F,y0,tspan)

    # run the convergence tests
    (rerr,aerr,time) = dasslTestConvergence(F,y0,tspan,sol,rtol,atol)

    tbl = Table(1,3)

    tbl[1,1] = FramedPlot(title  = "Absolute error",
                          xlabel = "Absolute tolerance",
                          ylabel = "Absolute error",
                          xlog   = true,
                          ylog   = true)
    tbl[1,2] = FramedPlot(title  = "Relative error",
                          xlabel = "Relative tolerance",
                          ylabel = "Relative error",
                          xlog   = true,
                          ylog   = true)
    tbl[1,3] = FramedPlot(title  = "Execution time",
                          xlabel = "Relative error",
                          ylabel = "Elapsed time",
                          xlog   = true,
                          ylog   = true)

    add(tbl[1,1], Points(atol,aerr))
    add(tbl[1,2], Points(rtol,rerr))
    add(tbl[1,3], Points(rerr,time))

    setattr(tbl, aspect_ratio=0.3)

    return tbl

end

#------------------------------------------------------------
# index-1 example
#------------------------------------------------------------

function F1{T<:Number}(t::T,y::Array{T,1},dy::Array{T,1})
    a=10.0
    [-dy[1]+(a-1/(2-t))*y[1]+(2-t)*a*y[3]+exp(t)*(3-t)/(2-t),
     -dy[2]+(1-a)/(t-2)*y[1]-y[2]+(a-1)*y[3]+2*exp(t),
     (t+2)*y[1]+(t^2-4)*y[2]-(t^2+t-2)*exp(t)]
end

function sol1{T<:Number}(t::T)
    a=10.0
    [exp(t),
     exp(t),
     -exp(t)/(2-t)]
end

const y1     = sol1(0.0)
const tspan1 = [0.0, 1.0]

const rtol=10.0.^-[1.0:0.1:5.0]
const atol=0.01*rtol

tbl=dasslDrawConvergence(F1,y1,tspan1,sol1,rtol,atol)
display(tbl)


text:
let
    order = 2

    # Haverly1 standard pooling instance
    x14, x24, x35, x36, x45, x46, w4 = variables(["x_{14}"; "x_{24}"; "x_{35}"; "x_{36}"; "x_{45}"; "x_{46}"; "w_4"])

    c14, c24, c35, c36, c45, c46 = [6; 16; 1; -9; -5; -15]
    q1, q2, q3, q5, q6 = [ 3; 1; 2; 5//2; 3//2 ]
    ub1, ub2, ub3, ub4, ub5, ub6 = [ 300; 300; 300; 300; 100; 200 ] // 300

    flow_eq    = [ x14+x24-(x45+x46) ]
    blend_eq   = [ w4*(x45+x46)-(q1*x14+q2*x24) ]
    qual_bnd   = [ q5*(x45+x36)-(w4*x45+q3*x35); q6*(x46+x36)-(w4*x46+q3*x36) ]
    cap_bnd    = [ ub1-x14; ub2-x24; ub3-(x35+x36); ub4-(x45+x46); ub5-(x35+x45); ub6-(x36+x46) ]
    flow_bnd   = [ x14; x24; x35; x36; x45; x46 ]

    obj = dot([c14; c24; c35; c36; c45; c46], [x14; x24; x35; x36; x45; x46])
    prob = momentprob(order, obj, [qual_bnd; cap_bnd; flow_bnd], [flow_eq; blend_eq])

    X, Z, t, y, solsta = solve_mosek(prob)
    xo = Polyopt.vectorize([x14,x24,x35,x36,x45,x46,w4],2*order)*y

    @test norm(xo-[0; 1/3; 0; 1/3; 0; 1/3; 1]) < 1e-4

    probc = momentprob_chordalembedding(order, obj, [qual_bnd; cap_bnd; flow_bnd], [flow_eq; blend_eq])
    Xc, Zc, tc, yc, solstac = solve_mosek(probc)
    xo = Polyopt.vectorize([x14,x24,x35,x36,x45,x46,w4],2*order)*yc

    @test norm(xo-[0; 1/3; 0; 1/3; 0; 1/3; 1]) < 1e-4
end


text:
using StatsBase, Plots; pyplot()

faces, N = 1:6, 10^6
mcEstimate = counts(rand(faces,N), faces)/N

plot(faces, mcEstimate,
	line=:stem, marker=:circle,
	c=:blue, ms=10, msw=0, lw=4, label="MC estimate")
plot!([i for i in faces], [1/6 for _ in faces],
	line=:stem, marker=:xcross, c=:red,
	ms=6, msw=0, lw=2, label="PMF",
	xlabel="Face number", ylabel="Probability", ylims=(0,0.22))

max_stars_repo_name: Yoshinobu-Ishizaki/StatsWithJuliaBook

max_issues_repo_name: Yoshinobu-Ishizaki/StatsWithJuliaBook

max_forks_repo_name: Yoshinobu-Ishizaki/StatsWithJuliaBook


text:
"""
	TVdenoise!(output::Vector{Float64}, y::Vector{Float64}, λ::Float64)

	Solve a Total Variation problem with noisy input signal `input` and
	regularization tension `λ`.

	Straight implementation of L. Condat's algorithm, from 	'A Direct Algorithm
	for	1D Total Variation Denoising'
	(http://www.gipsa-lab.grenoble-inp.fr/~laurent.condat/publis/Condat-fast_TV-SPL-2013.pdf)

"""
function TVdenoise!(output::Vector{Float64}, y::Vector{Float64}, λ::Float64)
	n = length(y)

	k = k0 = kmin = kplus = 1
	vmin = y[1] - λ
	vmax = y[1] + λ
	umin = -λ
	umax = λ

	while true
		## 1.
		if k == n
			output[n] = vmin + umin
			return
		end

		if y[k+1] + umin < vmin-λ
			output[k0:kmin] .= vmin
			k = k0 = kplus = kmin = kmin+1
			vmin = y[k]
			vmax = y[k]+2λ
			umin = λ
			umax = -λ
		elseif y[k+1] + umax > vmax+λ
			output[k0:kplus] .= vmax
			k = k0 = kplus = kmin = kplus+1
			vmin = y[k]-2λ
			vmax = y[k]
			umin = λ
			umax = -λ
		else
			k = k+1
			umin += y[k]-vmin
			umax += y[k]-vmax
			if umin ≥ λ
				vmin += (umin-λ) / (k-k0+1)
				umin = λ
				kmin = k
			end
			if umax ≤ -λ
				vmax += (umax+λ) / (k-k0+1)
				umax = -λ
				kplus = k
			end
		end

		k < n && continue

		if umin < 0
			output[k0:kmin] .= vmin
			k = k0 = kmin = kmin+1
			vmin = y[k]
			umin = λ
			umax = y[k] + λ - vmax
			continue
		elseif umax > 0
			output[k0:kplus] .= vmax
			k = k0 = kplus = kplus+1
			vmax = y[k]
			umax = -λ
			umin = y[k] - λ - vmin
			continue
		else
			output[k0:end] .= vmin + umin/(k-k0+1)
			return
		end
	end
end


text:
using ConferenceCall
using Test

@testset "ConferenceCall.jl" begin
    @confcall function foo end
    @confcall 1 foo() = :a
    @confcall 2 foo() = :b
    @test foo() == [:a, :b]

    @confcall function describe_object end
    @confcall 1 describe_object(x) = "Something"
    @confcall 2 describe_object(x::Number) = "Some number"
    @confcall 3 describe_object(x::Int) = "An Int"
    @test describe_object(3.0) == ["Something", "Some number"]

    @confcall_fast function describe_object2 end
    @confcall 1 describe_object2(x) = "Something"
    @confcall 2 describe_object2(x::Number) = "Some number"
    @confcall 3 describe_object2(x::Int) = "An Int"
    @test describe_object2(3.0) == ("Something", "Some number")
end


text:
#=
Code to process the binaries from the harp board.
=#

using ArgParse
using Glob

include("harp_binary_functions.jl")

function parse_commandline()
    s = ArgParseSettings()
    @add_arg_table s begin
        "--new_fold", "-n"
            help = "Set to write .csv into a new folder for each file"
            action = :store_true
        "dir"
            help = "Positional - Directory or file to parse.  If string ends with .bin then the program will execute the single binary"
            required = true
    end

    return parse_args(s)
end

function main()
    parsed_args = parse_commandline()
    spec_flag = 0
    ## Now turn string arguments into what they actually should be
    dir = parsed_args["dir"]
    # Now start parsing the data
    to_analyse = Vector{String}()
    if occursin(".bin",dir)
        push!(to_analyse,dir)
    elseif isdir(dir)
        dir_files = readdir(dir)
        for cur_file in dir_files
            if occursin(".bin",cur_file)
                push!(to_analyse,joinpath(dir,cur_file))
            end
        end
    else
        ArgumentError("Invalid path provided")
    end
    for cur_path in to_analyse
        if check_exist(cur_path,parsed_args["new_fold"])
            println("Processing $cur_path")
        else
            println("Output files for $cur_path already exist - moving on")
            continue
        end
        Message, Timestamp, Addresses,Payloads, Types = read_harp_bin(cur_path)
        events,writes = track_state(Message, Timestamp, Addresses,Payloads, Types)
        if parsed_args["new_fold"]
            sink_folder(events,writes,cur_path)
        else
            sink_data(events,writes,cur_path)
        end
    end
end

function check_exist(dir,new_fold)
    base_title = replace(dir,".bin"=>"")
    if new_fold
        file_names = glob(joinpath(base_title,"*.csv"))
    else
        file_names = glob(string(base_title,"*.csv"))
    end
    return isempty(file_names)
end

main()

max_stars_repo_name: Peter-Vincent/Harpist

max_issues_repo_name: Peter-Vincent/Harpist

max_forks_repo_name: Peter-Vincent/Harpist


text:
"""
    CustomCallback(f, Event, [TPhase = Phase, access = (;)])

A callback that runs `f(learner)` every time an event of type `Event`
during a phase of type in `Phase`.

If `f` needs to access learner state, pass `access`, a named tuple
in the same form as [`stateaccess`](#).

Instead of using [`CustomCallback`](#) it is recommended to properly
implement a [`Callback`](#).

## Examples

We can get a quick idea of when a new epoch starts as follows:

```julia
cb = CustomCallback(learner -> println("New epoch!"), EpochBegin)
```
"""
mutable struct CustomCallback{E<:Event,P<:Phase} <: Callback
    f::Any
    access
end

function CustomCallback(f, E::Type{<:Event}, P::Type{<:Phase} = Phase, access = (;))
    return CustomCallback{E, P}(f, access)
end

stateaccess(cc::CustomCallback) = cc.access

function on(::E, ::P, cb::CustomCallback{E,P}, learner) where {E<:Event,P<:Phase}
    cb.f(learner)
end

@testset "CustomCallback" begin
    @testset "Basic" begin
        x = 0
        cb = CustomCallback(learner -> (x += 1;), StepBegin)
        learner = testlearner(cb)
        epoch!(learner, TrainingPhase())
        @test x == 16
    end

    @testset "Interrupt" begin
        cb = CustomCallback(Events.StepEnd, TrainingPhase) do learner
            throw(CancelFittingException("test"))
        end
        learner = testlearner(Recorder(), cb, coeff = 3)
        @test_throws CancelFittingException epoch!(learner, TrainingPhase())
        @test learner.cbstate.history[TrainingPhase()].epochs == 0
        @test learner.cbstate.history[TrainingPhase()].steps == 0
    end
end


text:
using AMDGPU
using AMDGPU: HSA, AS
if AMDGPU.functional(:hip)
    using AMDGPU: HIP
end
using GPUCompiler
using LinearAlgebra
using LLVM, LLVM.Interop
using InteractiveUtils
using SpecialFunctions
using Test

using Random
Random.seed!(1)

include("util.jl")

# GPUArrays has a testsuite that isn't part of the main package.
# Include it directly.
import GPUArrays
gpuarrays = pathof(GPUArrays)
gpuarrays_root = dirname(dirname(gpuarrays))
include(joinpath(gpuarrays_root, "test", "testsuite.jl"))
testf(f, xs...; kwargs...) = TestSuite.compare(f, ROCArray, xs...; kwargs...)

import AMDGPU: allowscalar, @allowscalar
allowscalar(false)

CI = parse(Bool, get(ENV, "CI", "false"))

@testset "AMDGPU" begin

@testset "Core" begin
include("pointer.jl")
end

@test AMDGPU.functional()
@assert AMDGPU.functional()

@test length(get_agents()) > 0

@info "Testing using device $(get_default_agent())"

@testset "HSA" begin
    include("hsa/error.jl")
    include("hsa/agent.jl")
    include("hsa/memory.jl")
    include("hsa/utils.jl")
end
@testset "Codegen" begin
    include("codegen/synchronization.jl")
    include("codegen/trap.jl")
end
@testset "Device Functions" begin
    include("device/launch.jl")
    include("device/vadd.jl")
    include("device/memory.jl")
    include("device/indexing.jl")
    include("device/hostcall.jl")
    include("device/output.jl")
    include("device/globals.jl")
    include("device/math.jl")
    include("device/wavefront.jl")
    include("device/execution_control.jl")
    include("device/exceptions.jl")
    include("device/deps.jl")
    include("device/queries.jl")
end
@testset "ROCArray" begin
    include("rocarray/base.jl")
    include("rocarray/broadcast.jl")
    @testset "GPUArrays test suite" begin
        TestSuite.test(ROCArray)
    end
    @testset "ROCm External Libraries" begin
        if CI
            @test AMDGPU.functional(:rocblas)
            @test AMDGPU.functional(:rocrand)
            @test AMDGPU.functional(:rocfft)
        end
        if AMDGPU.functional(:rocblas)
            include("rocarray/blas.jl")
        else
            @test_skip "rocBLAS"
        end
        if AMDGPU.functional(:rocrand)
            include("rocarray/random.jl")
        else
            @test_skip "rocRAND"
        end
        if AMDGPU.functional(:rocfft)
            include("rocarray/fft.jl")
        else
            @test_skip "rocFFT"
        end
        if AMDGPU.functional(:rocblas)
            include("rocarray/nmf.jl")
        else
            @test_skip "NMF"
        end
    end
end
@testset "External Packages" begin
    include("external/forwarddiff.jl")
end

end


text:
module UAParser

export parsedevice, parseuseragent, parseos, DeviceResult, OSResult, UAResult, DataFrame

##############################################################################
##
## Dependencies
##
##############################################################################

using YAML, DataFrames
import DataFrames.DataFrame

##############################################################################
##
## Load YAML file
##
##############################################################################

const REGEXES = YAML.load(open(joinpath(dirname(@__FILE__), "..", "regexes.yaml")));

##############################################################################
##
## Create custom types to hold parsed YAML output
##
##############################################################################

# helper function used by constructors
_check_missing_string(s::AbstractString) = isempty(s) ? missing : String(s)
_check_missing_string(::Missing) = missing
_check_missing_string(::Nothing) = missing
_check_missing_string(x) = ArgumentError("Invalid string or missing passed: $x")

struct UserAgentParser
    user_agent_re::Regex
    family_replacement::Union{String, Missing}
    v1_replacement::Union{String, Missing}
    v2_replacement::Union{String, Missing}

    function UserAgentParser(user_agent_re::Regex, family_replacement, v1_replacement,
                             v2_replacement)
        new(user_agent_re, _check_missing_string(family_replacement),
            _check_missing_string(v1_replacement), _check_missing_string(v2_replacement))
    end
end

struct OSParser
    user_agent_re::Regex
    os_replacement::Union{String, Missing}
    os_v1_replacement::Union{String, Missing}
    os_v2_replacement::Union{String, Missing}

    function OSParser(user_agent_re::Regex, os_replacement, os_v1_replacement, os_v2_replacement)
        new(user_agent_re, _check_missing_string(os_replacement), _check_missing_string(os_v1_replacement),
            _check_missing_string(os_v2_replacement))
    end
end

struct DeviceParser
    user_agent_re::Regex
    device_replacement::Union{String, Missing}
    brand_replacement::Union{String, Missing}
    model_replacement::Union{String, Missing}

    function DeviceParser(user_agent_re::Regex, device_replacement, brand_replacement,
                          model_replacement)
        new(user_agent_re, _check_missing_string(device_replacement),
            _check_missing_string(brand_replacement), _check_missing_string(model_replacement))
    end
end

##############################################################################
##
## Create custom types to hold function results
##
##############################################################################

struct DeviceResult
    family::String
    brand::Union{String, Missing}
    model::Union{String, Missing}

    function DeviceResult(family::AbstractString, brand, model)
        new(string(family), _check_missing_string(brand), _check_missing_string(model))
    end
end

struct UAResult
    family::String
    major::Union{String, Missing}
    minor::Union{String, Missing}
    patch::Union{String, Missing}

    function UAResult(family::AbstractString, major, minor, patch)
        new(string(family), _check_missing_string(major), _check_missing_string(minor),
            _check_missing_string(patch))
    end
end

struct OSResult
    family::String
    major::Union{String, Missing}
    minor::Union{String, Missing}
    patch::Union{String, Missing}
    patch_minor::Union{String, Missing}

    function OSResult(family::AbstractString, major, minor, patch, patch_minor)
        new(string(family), _check_missing_string(major), _check_missing_string(minor),
            _check_missing_string(patch), _check_missing_string(patch_minor))
    end
end

##############################################################################
##
## Create USER_AGENT_PARSERS, OS_PARSERS, and DEVICE_PARSERS arrays
##
##############################################################################

"Compile the regex with flagss"
function _load_regex_and_flags(yaml_data)
    Regex(yaml_data["regex"], get(yaml_data, "regex_flag", ""))
end

function loadua()
  #Create empty array to hold user-agent information
  temp = []

  #Loop over entire set of user_agent_parsers, add to USER_AGENT_PARSERS
  for _ua_parser in REGEXES["user_agent_parsers"]
      _user_agent_re = _load_regex_and_flags(_ua_parser)
      _family_replacement = get(_ua_parser, "family_replacement", missing)
      _v1_replacement = get(_ua_parser, "v1_replacement", missing)
      _v2_replacement = get(_ua_parser, "v2_replacement", missing)

    #Add values to array
      push!(temp, UserAgentParser(_user_agent_re,
                                  _family_replacement,
                                  _v1_replacement,
                                  _v2_replacement
                                  ))
  end
  return temp
end #End loadua

const USER_AGENT_PARSERS = loadua()

function loados()
  #Create empty array to hold os information
  temp = []

  #Loop over entire set of os_parsers, add to OS_PARSERS
  for _os_parser in REGEXES["os_parsers"]
    _user_agent_re = _load_regex_and_flags(_os_parser)
    _os_replacement = get(_os_parser, "os_replacement", missing)
    _os_v1_replacement = get(_os_parser, "os_v1_replacement", missing)
    _os_v2_replacement = get(_os_parser, "os_v2_replacement", missing)

    #Add values to array
    push!(temp, OSParser(_user_agent_re,
                         _os_replacement,
                         _os_v1_replacement,
                         _os_v2_replacement
                         ))

  end
  return temp
end #End loados

const OS_PARSERS = loados()

function loaddevice()
  #Create empty array to hold device information
  temp = []

  #Loop over entire set of device_parsers, add to DEVICE_PARSERS
  for _device_parser in REGEXES["device_parsers"]
      _user_agent_re = _load_regex_and_flags(_device_parser)
      _device_replacement = get(_device_parser, "device_replacement", missing)
      _brand_replacement = get(_device_parser, "brand_replacement", missing)
      _model_replacement = get(_device_parser, "model_replacement", missing)

    #Add values to array
      push!(temp, DeviceParser(_user_agent_re, _device_replacement, _brand_replacement,
                               _model_replacement))
  end
  return temp
end #End loaddevice

const DEVICE_PARSERS = loaddevice()

##############################################################################
##
## Functions for parsing user agent strings
##
##############################################################################

# helper function for parsedevice
function _inner_replace(str::AbstractString, group)
    # TODO this rather dangerously assumes that strings are $ followed by ints
    idx = parse(Int, str[2:end])
    if idx ≤ length(group) && group[idx] ≠ nothing
        group[idx]
    else
        ""
    end
end

# helper function for parsedevice
function _multireplace(str::AbstractString, mtch::RegexMatch)
    _str = replace(str, r"\$(\d)" => m -> _inner_replace(m, mtch.captures))
    _str = replace(_str, r"^\s+|\s+$" => "")
    length(_str) == 0 ? missing : _str
end

function parsedevice(user_agent_string::AbstractString)
    for value in DEVICE_PARSERS
        _match = match(value.user_agent_re, user_agent_string)
        if !isnothing(_match)

            # family
            if !ismissing(value.device_replacement)
                device = _multireplace(value.device_replacement, _match)
            else
                device = _match.captures[1]
            end

            # brand
            if !ismissing(value.brand_replacement)
                brand = _multireplace(value.brand_replacement, _match)
            elseif length(_match.captures) > 1
                brand = match_vals[2]
            else
                brand = missing
            end

            # model
            if !ismissing(value.model_replacement)
                model = _multireplace(value.model_replacement, _match)
            elseif length(_match.captures) > 2
                model = match_vals[3]
            else
                model = missing
            end

            return DeviceResult(device, brand, model)
        end
    end
    DeviceResult("Other",missing,missing)  #Fail-safe for no match
end # parsedevice
parsedevice(::Missing) = missing

function parseuseragent(user_agent_string::AbstractString)
  for value in USER_AGENT_PARSERS
    _match = match(value.user_agent_re, user_agent_string)
    if !isnothing(_match)

      match_vals = _match.captures

      #family
      if !ismissing(value.family_replacement)
        family = _multireplace(value.family_replacement, _match)
      else
        family = match_vals[1]
      end

      #major
      if !ismissing(value.v1_replacement)
        v1 = _multireplace(value.v1_replacement, _match)
      elseif length(match_vals) > 1
        v1 = match_vals[2]
      else
        v1 = missing
      end

      #minor
      if !ismissing(value.v2_replacement)
        v2 = _multireplace(value.v2_replacement, _match)
      elseif length(match_vals) > 2
        v2 = match_vals[3]
      else
        v2 = missing
      end

      #patch
      if length(match_vals) > 3
        v3 = match_vals[4]
      else
        v3 = missing
      end

      return UAResult(family, v1, v2, v3)

    end
  end

return UAResult("Other", missing, missing, missing) #Fail-safe for no match
end #End parseuseragent
parseuseragent(::Missing) = missing

function parseos(user_agent_string::AbstractString)
    for value in OS_PARSERS
        _match = match(value.user_agent_re, user_agent_string)
        if !isnothing(_match)
            match_vals = _match.captures

            #os
            if !ismissing(value.os_replacement)
                os = _multireplace(value.os_replacement, _match)
            else
                os = match_vals[1]
            end

            #os_v1
            if !ismissing(value.os_v1_replacement)
                os_v1 = _multireplace(value.os_v1_replacement, _match)
            elseif length(match_vals) > 1
                os_v1 = match_vals[2]
            else
                os_v1 = missing
            end

            #os_v2
            if !ismissing(value.os_v2_replacement)
                os_v2 = _multireplace(value.os_v2_replacement, _match)
            elseif length(match_vals) > 2
                os_v2 = match_vals[3]
            else
                os_v2 = missing
            end

            #os_v3
            if length(match_vals) > 3
                os_v3 = match_vals[4]
            else
                os_v3 = missing
            end

            #os_v4
            if length(match_vals) > 4
                os_v4 = match_vals[5]
            else
                os_v4 = missing
            end

            return OSResult(os, os_v1, os_v2, os_v3, os_v4)

        end
    end

return OSResult("Other", missing, missing, missing, missing) #Fail-safe if no match
end #End parseos
parseos(::Missing) = missing

##############################################################################
##
## Extend DataFrames to include UAParser methods
##
##############################################################################

#DeviceResult to DataFrame method
function DataFrame(x::AbstractVector{DeviceResult})
    temp = DataFrame()

    temp["device"] = String[element.family for element in x]

    temp["brand"] = Union{String,Missing}[element.brand for element in x]

    temp["model"] = Union{String,Missing}[element.model for element in x]

    temp
end

#OSResult to DataFrame method
function DataFrame(x::AbstractVector{OSResult})
    temp = DataFrame()

    #Family - Can use comprehension since family always String
    temp["os_family"] = String[element.family for element in x]

    #Major
    temp["os_major"] = Union{String,Missing}[element.major for element in x]

    #Minor
    temp["os_minor"] = Union{String,Missing}[element.minor for element in x]

    #Patch
    temp["os_patch"] = Union{String,Missing}[element.patch for element in x]

    #Patch_Minor
    temp["os_patch_minor"] = Union{String,Missing}[element.patch_minor for element in x]

    temp
end

#UAResult to DataFrame method
function DataFrame(x::AbstractVector{UAResult})
  #Pre-allocate size of DataFrame based on array passed in
  temp = DataFrame()

  #Family - Can use comprehension since family always String
  temp["browser_family"] = String[element.family for element in x]

  #Major
  temp["browser_major"] = Union{String,Missing}[element.major for element in x]

  #Minor
  temp["browser_minor"] = Union{String,Missing}[element.minor for element in x]

  #Patch
  temp["browser_patch"] = Union{String,Missing}[element.patch for element in x]

  temp
end

end # module