text:
function _biLanczosIterations!(A, stepsize, αs, βs, U, V, μs, νs, maxνs, maxμs, τ, reorth_in, tolreorth, debug)

    m, n = size(A)
    reorth_μ = reorth_in
    nReorth = 0
    nReorthVecs = 0

    T = eltype(eltype(U))
    Tr = real(T)

    iter = length(αs)

    u = U[iter + 1]
    v = V[iter]
    β = βs[iter]

    for j = iter .+ (1:stepsize)
        # The v step
        vOld = v
        ## apply operator
        v = A'u
        axpy!(T(-β), vOld, v)
        α = norm(v)

        ## update norm(A) estimate. FixMe! Use tighter bounds, see Larsen's thesis page 33
        τ = max(τ, eps(Tr) * (α + β))
        debug && @show τ

        ## run ω recurrence
        reorth_ν = false
        for i = 1:j - 1
            ν = βs[i]*μs[i + 1] + αs[i]*μs[i] - β*νs[i]
            ν = (ν + copysign(τ, ν))/α
            if abs(ν) > tolreorth
                reorth_ν |= true
            end
            νs[i] = ν
        end
        if j > 1
            push!(maxνs, maximum(abs, νs))
        end
        push!(νs, 1)

        ## reorthogonalize if necessary
        if reorth_ν || reorth_μ
            debug && println("Reorth v")
            for i in 1:j - 1
                axpy!(-dot(V[i], v), V[i], v)
                νs[i] = eps(Tr)
                nReorthVecs += 1
            end
            α = norm(v)
        end

        ## update the result vectors
        push!(αs, α)
        rmul!(v, inv(α))
        push!(V, v)

        # The u step
        uOld = u
        ## apply operator
        u = A*v
        axpy!(T(-α), uOld, u)
        β = norm(u)

        ## update norm(A) estimate. FixMe! Use tighter bounds, see Larsen's thesis page 33
        τ = max(τ, eps(Tr) * (α + β))
        debug && @show τ

        ## run ω recurrence
        reorth_μ = false
        for i = 1:j
            μ = αs[i]*νs[i] - α*μs[i]
            if i > 1
                μ += βs[i - 1]*νs[i-1]
            end
            μ = (μ + copysign(τ, μ))/β
            if abs(μ) > tolreorth
                reorth_μ |= true
            end
            μs[i] = μ
        end
        push!(maxμs, maximum(μs))
        push!(μs, 1)

        ## reorthogonalize if necessary
        if reorth_ν || reorth_μ
            debug && println("Reorth u")
            for i in 1:j
                axpy!(-dot(U[i], u), U[i], u)
                μs[i] = eps(Tr)
                nReorthVecs += 1
            end
            β = norm(u)
            nReorth += 1
        end

        ## update the result vectors
        push!(βs, β)
        rmul!(u, inv(β))
        push!(U, u)
    end

    return reorth_μ
end

function biLanczos(A,
    nvals = 1;
    maxiter = 1000,
    initvec = convert(Vector{float(eltype(A))}, randn(size(A,1))),
    tolconv = sqrt(eps(real(eltype(initvec)))),
    tolreorth = sqrt(eps(real(eltype(initvec)))),
    stepsize = max(1, div(nvals, 10)),
    debug = false)

    Tv = eltype(initvec)
    Tr = real(Tv)

    # I need to append βs with a zero at each iteration. Tt is much easier for type inference if it is a vector with the right element type
    z = zeros(Tr, 1)

    # initialize the αs, βs, U and V. Use result of first matvec to infer the correct types.
    # So the first iteration is run here, but slightly differently from the rest of the iterations
    nrmInit = norm(initvec)
    v = A'initvec
    rmul!(v, inv(nrmInit))
    α = norm(v)
    if isone(α)
        # We need v to change when scaled with α.
        # Otherwise the basis generation might break down.
        α = nextfloat(α)
    end
    rmul!(v, inv(α))
    V = fill(v, 1)
    αs = fill(α, 1)

    u = A*v
    uOld = similar(u)
    copyto!(uOld, initvec)
    rmul!(uOld, inv(nrmInit))
    axpy!(eltype(u)(-α), uOld, u)
    β = norm(u)
    rmul!(u, inv(β))
    U = typeof(u)[uOld, u]
    βs = fill(β, 1)

    # error estimate used in ω recurrence
    τ = eps(Tr)*(α + β)
    ν = 1 + τ/α
    μ = τ/β

    # Arrays for saving the estimates of the maximum angles between Lanczos vectors
    maxμs = Tr[]
    maxνs = Tr[]

    μs = Tr[μ, 1]
    νs = Tr[one(μ)]

    reorth_μ = _biLanczosIterations!(A, nvals - 1, αs, βs, U, V, μs, νs, maxμs, maxνs, τ, false, tolreorth, debug)

    # Iteration count
    iter = nvals

    # Save the estimates of the maximum angles between Lanczos vectors
    # append!(maxμs, maxμ)

    hasConv = false
    while iter <= maxiter

        reorth_μ = _biLanczosIterations!(A, stepsize, αs, βs, U, V, μs, νs, maxμs, maxνs, τ, reorth_μ, tolreorth, debug)
        iter += stepsize

        # This is more expensive than necessary because we only need the last components. However, LAPACK doesn't support this.
        UU, ss, VV = svd(Bidiagonal([αs;z], βs, :L))

        debug && @show βs[end]

        # Test for convergence. A Ritzvalue is considered converged if
        # either the last component of the corresponding vector is (relatively)
        # small or if the last component in βs is small (or both)
        if all(abs.(UU[end, 1:nvals])*βs[end] .< tolconv*ss[1:nvals]) &&
           all(abs.(VV[end, 1:nvals])*βs[end] .< tolconv*ss[1:nvals])
            hasConv = true
            break
        end

        τ = eps(eltype(ss))*ss[1]

        debug && @show iter
        debug && @show τ
    end
    if !hasConv
        error("no convergence")
    end

    # Form upper bidiagonal square matrix
    # m = length(U[1])
    # for j = 1:length(αs)
    #     # Calculate Givens rotation
    #     c, s, αs[j] = givensAlgorithm(αs[j], βs[j])

    #     # Update left vector
    #     # for i = 1:m
    #     #     uij       = U[j][i]
    #     #     uij1      = U[j+1][i]
    #     #     U[j][i]   = uij*c + uij1*s'
    #     #     U[j+1][i] = uij1*c - uij*s
    #     # end

    #     # Update bidiagonal matrix
    #     if j < length(αs)
    #         αj1 = αs[j + 1]
    #         αs[j + 1] = c*αj1
    #         βs[j] = s*αj1
    #     end
    # end

    return U, Bidiagonal(αs, βs[1:end-1], :L), V, maxμs, maxνs
end

function _tsvd(A,
    nvals = 1;
    maxiter = 1000,
    # The initial vector is critical in determining the output type.
    # We use the result of A*initvec to detemine the storage type for
    # the Lanczos vectors. Hence, the user would need to either
    # have an appropriate multiplication method defined or supply
    # an appropriate initial vector.
    initvec = convert(Vector{float(eltype(A))}, randn(size(A,1))),
    tolconv = sqrt(eps(real(eltype(initvec)))),
    tolreorth = sqrt(eps(real(eltype(initvec)))),
    stepsize = max(1, div(nvals, 10)),
    debug = false)

    U, B, V, maxμs, maxνs = biLanczos(A,
        nvals;
        maxiter = maxiter,
        initvec = initvec,
        tolconv = tolconv,
        tolreorth = tolreorth,
        stepsize = stepsize,
        debug = debug)

    # Calculate the bidiagonal SVD
    smU, sms, smV = svd(B)

    # Create matrices from the Vectors of vectors and update U and V
    mU = hcat(U[1:end-1])
    mV = hcat(V)

    # Adapt the matrix type of the (LAPACK) SVD matrices to the type of mU and mV
    # E.g. if the vectors have been stored on a GPU device or on a distributed
    # system, this step will ensure that the result ends up where A/initvec is stored
    mUall = mU*adapt(typeof(initvec), smU)
    mVall = mV*adapt(typeof(initvec), smV)
    msall = adapt(typeof(initvec), sms)

    return mUall[:,1:nvals],
        sms[1:nvals],
        mVall[:,1:nvals],
        B,
        maxμs,
        maxνs
end

"""
    tsvd(A, nvals = 1; [maxiter, initvec, tolconv, tolreorth, debug])

Computes the truncated singular value decomposition (TSVD) by Lanczos bidiagonalization of the operator `A`. The Lanczos vectors are partially orthogonalized as described in

R. M. Larsen, *Lanczos bidiagonalization with partial reorthogonalization*, Department of Computer Science, Aarhus University, Technical report, DAIMI PB-357, September 1998.

# Positional arguments:

- `A`: Anything that supports the in place update operations

    mul!(y::AbstractVector, A, x::AbstractVector, α::Number, β::Number)

and

    mul!(y::AbstractVector, A::Adjoint, x::AbstractVector, α::Number, β::Number)

corresponding to the operations `y := α*op(A)*x + β*y` where `op` can be either the identity or the conjugate transpose of `A`. If the `initvec` argument is not supplied then it is furthermore required that `A` supports `eltype` and `size`.

- `nvals`: The number of singular values and vectors to compute. Default is one (the largest).

# Keyword arguments:

- `maxiter`: The maximum number of iterations of the Lanczos bidiagonalization. Default is 1000, but usually much fewer iterations are needed.

- `initvec`: Initial `U` vector for the Lanczos procesdure. Default is a vector of Gaussian random variates. The `length` and `eltype` of the `initvec` will control the size and element types of the basis vectors in `U` and `V`.

- `tolconv`: Relative convergence criterion for the singular values. Default is `sqrt(eps(real(eltype(A))))`.

- `tolreorth`: Absolute tolerance for the inner product of the Lanczos vectors as measured by the ω recurrence. Default is `sqrt(eps(real(eltype(initvec))))`. `0.0` and `Inf` correspond to complete and no reorthogonalization respectively.

- `debug`: Boolean flag for printing debug information

# Output:

The output of the procesure it the truple tuple `(U, s, V)`

- `U`: `size(A, 1)` times `nvals` matrix of left singular vectors.
- `s`: Vector of length `nvals` of the singular values of `A`.
- `V`: `size(A, 2)` times `nvals` matrix of right singular vectors.

# Examples

```jldoctest
julia> A = matrixdepot("LPnetlib/lp_osa_30")
4350×104374 SparseArrays.SparseMatrixCSC{Float64, Int64} with 604488 stored entries:
⠙⠮⠷⠶⠽⠶⠽⠶⠮⠷⠮⠷⠶⠽⠶⠽⠶⠬⠷⠮⠷⠦⠽⠶⠽⠶⠽⠶⠮⠷⠮⠷⠶⠽⠶⠽⠶⠭⠷⠦

julia> U, s, V = tsvd(A, 5);

julia> round.(s, digits=7)
5-element Vector{Float64}:
 1365.8944098
 1033.2125634
  601.3524529
  554.107656
  506.0414587
```
"""
function tsvd(
    A,
    nvals = 1;
    maxiter = 1000,
    initvec = convert(Vector{float(eltype(A))}, randn(size(A,1))),
    tolconv = sqrt(eps(real(eltype(initvec)))),
    tolreorth = sqrt(eps(real(eltype(initvec)))),
    stepsize = max(1, div(nvals, 10)),
    debug = false)

    result = _tsvd(A, nvals, maxiter = maxiter, initvec = initvec, tolconv = tolconv,
            tolreorth = tolreorth, debug = debug)
    return (result[1], result[2], result[3])
end

### SVD by Lanczos on A'A

mutable struct AtA{T,S<:AbstractMatrix,V<:AbstractVecOrMat} <: AbstractMatrix{T}
    matrix::S
    vector::V
end
function AtA(A::AbstractMatrix, x::AbstractVecOrMat)
    y = A*x
    return AtA{eltype(y),typeof(A),typeof(y)}(A,y)
end

function size(A::AtA, i::Integer)
    if i < 1
        error("arraysize: dimension out of range")
    elseif i < 3
        return size(A.matrix, 2)
    else
        return 1
    end
end
size(A::AtA) = (size(A, 1), size(A, 2))

# Split Vector and Matrix to avoid ambiguity
function mul!(y::AbstractVector{T},
              A::AtA{T,S,V},
              x::AbstractVector{T},
              α::T = one(T),
              β::T = zero(T)) where {T<:Number,S,V}
    mul!(A.vector, A.matrix, x, one(T), zero(T))
    mul!(y, A.matrix', A.vector, α, β)
    return y
end
function mul!(y::AbstractMatrix{T},
              A::AtA{T,S,V},
              x::AbstractMatrix{T},
              α::T = one(T),
              β::T = zero(T)) where {T<:Number,S,V}
    mul!(A.vector, A.matrix, x, one(T), zero(T))
    mul!(y, A.matrix', A.vector, α, β)
    return y
end
(*)(A::AtA, x::AbstractVector) = mul!(similar(A.vector, size(x)), A, x)
(*)(A::AtA, x::AbstractMatrix) = mul!(similar(A.vector, size(x)), A, x)

function tsvd2(A,
    nvals = 1;
    maxiter = min(size(A)...),
    initvec = convert(Vector{eltype(A)}, randn(size(A,2))),
    tolconv = sqrt(eps(real(eltype(A)))),
    stepsize = max(1, div(nvals, 10)),
    debug = false)
    values, vectors, S, lanczosVecs = _teig(AtA(A, initvec), nvals, maxiter = maxiter,
        initvec = initvec, tolconv = tolconv, stepsize = stepsize, debug = debug)
    mV = hcat(lanczosVecs[1:end-1])*vectors
    return sqrt.(reverse(values)[1:nvals]), mV[:,end:-1:1][:,1:nvals]
end


text:
abstract type Canvas <: GraphicsArea end

origin(c::Canvas) = (origin_x(c), origin_y(c))
Base.size(c::Canvas) = (width(c), height(c))
pixel_size(c::Canvas) = (pixel_width(c), pixel_height(c))

function pixel!(c::Canvas, pixel_x::Integer, pixel_y::Integer; color::Union{Int, Symbol} = :normal)
    pixel!(c, pixel_x, pixel_y, color)
end

function points!(c::Canvas, x::Number, y::Number, color::Union{Int, Symbol})
    origin_x(c) <= x <= origin_x(c) + width(c) || return c
    origin_y(c) <= y <= origin_y(c) + height(c) || return c
    plot_offset_x = x - origin_x(c)
    pixel_x = plot_offset_x / width(c) * pixel_width(c)
    plot_offset_y = y - origin_y(c)
    pixel_y = pixel_height(c) - plot_offset_y / height(c) * pixel_height(c)
    pixel!(c, floor(Int, pixel_x), floor(Int, pixel_y), color)
end

function points!(c::Canvas, x::Number, y::Number; color::Union{Int, Symbol} = :normal)
    points!(c, x, y, color)
end

function points!(c::Canvas, X::AbstractVector, Y::AbstractVector, color::Union{Int, Symbol})
    length(X) == length(Y) || throw(DimensionMismatch("X and Y must be the same length"))
    for I in eachindex(X, Y)
        points!(c, X[I], Y[I], color)
    end
    c
end

function points!(c::Canvas, X::AbstractVector, Y::AbstractVector, color::AbstractVector{T}) where {T <: Union{Int, Symbol}}
    (length(X) == length(color) && length(X) == length(Y)) || throw(DimensionMismatch("X, Y, and color must be the same length"))
    for i in 1:length(X)
        points!(c, X[i], Y[i], color[i])
    end
    c
end

function points!(c::Canvas, X::AbstractVector, Y::AbstractVector; color::Union{Int, Symbol} = :normal)
    points!(c, X, Y, color)
end

# Implementation of the digital differential analyser (DDA)
function lines!(c::Canvas, x1::Number, y1::Number, x2::Number, y2::Number, color::Union{Int, Symbol})
    if (x1 < origin_x(c) && x2 < origin_x(c)) ||
        (x1 > origin_x(c) + width(c) && x2 > origin_x(c) + width(c))
        return c
    end
    if (y1 < origin_y(c) && y2 < origin_y(c)) ||
        (y1 > origin_y(c) + height(c) && y2 > origin_y(c) + height(c))
        return c
    end
    toff = x1 - origin_x(c)
    px1 = toff / width(c) * pixel_width(c)
    toff = x2 - origin_x(c)
    px2 = toff / width(c) * pixel_width(c)
    toff = y1 - origin_y(c)
    py1 = pixel_height(c) - toff / height(c) * pixel_height(c)
    toff = y2 - origin_y(c)
    py2 = pixel_height(c) - toff / height(c) * pixel_height(c)
    dx = px2 - px1
    dy = py2 - py1
    nsteps = abs(dx) > abs(dy) ? abs(dx) : abs(dy)
    inc_x = dx / nsteps
    inc_y = dy / nsteps
    cur_x = px1
    cur_y = py1
    fpw = Float64(pixel_width(c))
    fph = Float64(pixel_height(c))
    pixel!(c, floor(Int, cur_x), floor(Int, cur_y), color)
    for i = 1:nsteps
        cur_x += inc_x
        cur_y += inc_y
        pixel!(c, floor(Int, cur_x), floor(Int, cur_y), color)
    end
    c
end

function lines!(c::Canvas, x1::Number, y1::Number, x2::Number, y2::Number; color::Union{Int, Symbol} = :normal)
    lines!(c, x1, y1, x2, y2, color)
end

function lines!(c::Canvas, X::AbstractVector, Y::AbstractVector, color::Union{Int, Symbol})
    length(X) == length(Y) || throw(DimensionMismatch("X and Y must be the same length"))
    for i in 1:(length(X)-1)
        lines!(c, X[i], Y[i], X[i+1], Y[i+1], color)
    end
    c
end

function lines!(c::Canvas, X::AbstractVector, Y::AbstractVector; color::Union{Int, Symbol} = :normal)
    lines!(c, X, Y, color)
end

function get_canvas_dimensions_for_matrix(canvas::Type{T}, nrow::Int, ncol::Int, maxwidth::Int, maxheight::Int, width::Int, height::Int, margin::Int, padding::Int; extra_rows::Int = 0, extra_cols::Int = 0) where {T <: Canvas}
    min_canvheight = ceil(Int, nrow / y_pixel_per_char(T))
    min_canvwidth  = ceil(Int, ncol / x_pixel_per_char(T))
    aspect_ratio = min_canvwidth / min_canvheight
    height_diff = extra_rows
    width_diff  = margin + padding + length(string(ncol)) + extra_cols

    term_height, term_width = Base.displaysize()
    maxheight = maxheight > 0 ? maxheight : term_height - height_diff
    maxwidth  = maxwidth > 0 ? maxwidth : term_width - width_diff

    if nrow == 0 && ncol == 0
        return (0, 0, maxwidth, maxheight)
    end

    # Check if the size of the plot should be derived from the matrix
    # Note: if both width and height are 0, it means that there are no
    #       constraints and the plot should resemble the structure of
    #       the matrix as close as possible
    if width == 0 && height == 0
        # If the interactive code did not take care of this then try
        # to plot the matrix in the correct aspect ratio (within specified bounds)
        if min_canvheight > min_canvwidth
            # long matrix (according to pixel density)
            height = min_canvheight
            width  = height * aspect_ratio
            if width > maxwidth
                width  = maxwidth
                height = width / aspect_ratio
            end
            if height > maxheight
                height = maxheight
                width  = min(height * aspect_ratio, maxwidth)
            end
        else
            # wide matrix
            width  = min_canvwidth
            height = width / aspect_ratio
            if height > maxheight
                height = maxheight
                width  = height * aspect_ratio
            end
            if width > maxwidth
                width = maxwidth
                height = min(width / aspect_ratio, maxheight)
            end
        end
    end
    if width == 0 && height > 0
        width  = min(height * aspect_ratio, maxwidth)
    elseif width > 0 && height == 0
        height = min(width / aspect_ratio, maxheight)
    end
    width  = round(Int, width)
    height = round(Int, height)

    (width, height, maxwidth, maxheight)
end

ext: jl


text:
using MD5

data = readline()

function solve_1()
    for i in 0:10^7
        md = bytes2hex(md5("$(data)$(i)"))
        if startswith(md, "0"^6)
            return i
        end
    end
end

solve_1() |> println

max_stars_repo_name: pLOPeGG/JuliaOfCode

max_issues_repo_name: pLOPeGG/JuliaOfCode

max_forks_repo_name: pLOPeGG/JuliaOfCode


text:
# Copyright (c) 2015, Intel Corporation
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
#     * Redistributions of source code must retain the above copyright notice,
#       this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of Intel Corporation nor the names of its contributors
#       may be used to endorse or promote products derived from this software
#       without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

"""
Convert from an internal Latte tiled_loop to a normal Julia :for expression
"""
function unpack_tiled_loop(node::Expr)
    @assert node.head == :for
    range = node.args[1].args[2]
    node.args[1].args[2] = range.args[2]
    node
end

"""
Check if `node` is an internal Latte tiled_loop
"""
function is_tiled_loop(node)
    if !(isa(node, Expr) && node.head == :for)
        return false
    end
    range = node.args[1].args[2]
    isa(range, Expr) && range.head == :call && range.args[1] == :tiled_loop
end

"""
TODO: doc
"""
function get_tile_fusion_factor_forward(expr)
    return expr.args[3]
end

"""
TODO: doc
"""
function get_tile_fusion_factor_backward(expr)
    return expr.args[4]
end

"""
Replace indexing expressions with `tile_var` with the proper tiled expression
When `inputs` are not copied, the neuron transformer appends :NOTILE to the
index expression to force Latte not to tile the expression.
"""
function update_tile_var(node, tile_var, index, top_level, read)
    if isa(node, Expr) && node.head == :ref && contains(string(node.args[1]), "inputs")
        if node.args[end] != :NOTILE
            for i in 2:length(node.args)-1
                if node.args[i] == tile_var
                    node.args[i] = :(($(node.args[i]) - 1) % TILE_SIZE + 1)
                end
            end
            node.args[end] = :(_omp_get_thread_num() + 1)
        end
        return node
    end
    ASTWALK_RECURSE
end

"""
TODO: doc
"""
function inner_loop_tiler(node, cbdata, index, top_level, read)
    if isa(node, Expr) && node.head == :for && isa(get_loopvar(node), Symbol)
        loopvar = string(get_loopvar(node))
        if contains(loopvar, "_neuron_index_") && parse(Int, loopvar[end]) == 2
            loop_idx = parse(Int, loopvar[end])
            loop_range = node.args[1].args[2]
            loop_end = loop_range.args[2]
            unshift!(cbdata[:loop_lengths], loop_end)
            unshift!(cbdata[:loop_vars], symbol(loopvar, "_tile_idx"))
            loop_range.args[1] = :((($(symbol(loopvar, "_tile_idx")) - 1) * TILE_SIZE + 1))
            loop_range.args[2] = :(min($(symbol(loopvar, "_tile_idx")) * TILE_SIZE, $loop_end))
            node.args[2] = AstWalk(node.args[2], update_tile_var, get_loopvar(node))
            return node
        end
    end
    ASTWALK_RECURSE
end

global unique_id = 0

"""
TODO: doc
"""
function get_inner_loop_tiler(tile_fusion_factors)
    global unique_id += 1
    function tile_inner_loops(statement)
        if isa(statement, Expr) && statement.head == :for
            loopvar = string(get_loopvar(statement))
            if contains(loopvar, "_neuron_index_") && parse(Int, loopvar[end]) >= 4
                loop_lengths = []
                loop_vars = []
                cbdata = Dict(:loop_lengths => loop_lengths,
                              :TILE_SIZE => TILE_SIZE,
                              :loop_vars => loop_vars)
                statement = AstWalk(statement, inner_loop_tiler, cbdata)
                body = statement.args[2]
                num_tiles = []
                for len in loop_lengths
                    n_tiles = div(len, TILE_SIZE)
                    if len % TILE_SIZE != 0
                        n_tiles += 1
                    end
                    push!(num_tiles, n_tiles)
                end
                tile_loop = quote
                    $(body.args...)
                end
                for (loopvar, n_tiles, factor) in zip(loop_vars, num_tiles, tile_fusion_factors)
                    tile_loop = quote
                        for $loopvar = tiled_loop(1:$n_tiles, $(factor...), $unique_id)
                            $(tile_loop.args...)
                        end
                    end
                end
                statement.args[2] = tile_loop
            end
        end
        statement
    end
end

"""
TODO: doc
"""
function tile_size_inliner(node, cbdata, index, top_level, read)
    if isa(node, Expr)
        if node.head == :(*=) && node.args[1] == :TILE_SIZE
            cbdata[1] *= node.args[2]
            return ASTWALK_REMOVE
        elseif node.head == :(/=) && node.args[1] == :TILE_SIZE
            cbdata[1] /= node.args[2]
            return ASTWALK_REMOVE
        elseif is_tiled_loop(node)
            node = unpack_tiled_loop(node)
            node.args[2] = AstWalk(node.args[2], tile_size_inliner, cbdata)
            node.args[1] = AstWalk(node.args[1], tile_size_inliner, cbdata)
            return node
        elseif node.head == :ref && node.args[end] == :NOTILE
            pop!(node.args)
            return node
        elseif node.head in [:loophead, :parallel_loophead, :loopend, :parallel_loopend]
            return node
        end
    elseif isa(node, Symbol) && node == :TILE_SIZE
        return cbdata[1]
    end
    ASTWALK_RECURSE
end

function inline_tile_size(statements)
    map((x) -> AstWalk(x, tile_size_inliner, [TILE_SIZE]), statements)
end

"""
Tile loop variables use `_tile_idx` loopvars.
"""
function get_tile_loops(node, cbdata, index, top_level, read)
    if isa(node, Expr) && node.head == :for && isa(get_loopvar(node), Symbol)
        loopvar = string(get_loopvar(node))
        if contains(loopvar, "_tile_idx")
            push!(cbdata, node)
        end
    elseif isa(node, Expr) && node.head in [:loophead, :parallel_loophead, :loopend, :parallel_loopend]
        return node
    end
    ASTWALK_RECURSE
end


text:
module SessionActions

import ..Pluto: ServerSession, Notebook, Cell, emptynotebook, tamepath, new_notebooks_directory, without_pluto_file_extension, numbered_until_new, readwrite, update_save_run!, putnotebookupdates!, putplutoupdates!, load_notebook, clientupdate_notebook_list, WorkspaceManager, @asynclog

struct NotebookIsRunningException <: Exception
    notebook::Notebook
end

abstract type AbstractUserError <: Exception end
struct UserError <: AbstractUserError
    msg::String
end
function Base.showerror(io::IO, e::UserError)
    print(io, e.msg)
end

function open_url(session::ServerSession, url::AbstractString; kwargs...)
    path = download(url, emptynotebook().path)
    open(session, path; kwargs...)
end

function open(session::ServerSession, path::AbstractString; run_async=true, compiler_options=nothing, as_sample=false)
    if as_sample
        new_filename = "sample " * without_pluto_file_extension(basename(path))
        new_path = numbered_until_new(joinpath(new_notebooks_directory(), new_filename); suffix=".jl")

        readwrite(path, new_path)
        path = new_path
    end

    for nb in values(session.notebooks)
        if realpath(nb.path) == realpath(tamepath(path))
            throw(NotebookIsRunningException(nb))
        end
    end

    nb = load_notebook(tamepath(path); disable_writing_notebook_files=session.options.server.disable_writing_notebook_files)

    # overwrites the notebook environment if specified
    if compiler_options !== nothing
        nb.compiler_options = compiler_options
    end

    session.notebooks[nb.notebook_id] = nb
    if session.options.evaluation.run_notebook_on_load
        for c in nb.cells
            c.queued = true
        end
        update_save_run!(session, nb, nb.cells; run_async=run_async, prerender_text=true)
    end

    if run_async
        @asynclog putplutoupdates!(session, clientupdate_notebook_list(session.notebooks))
    else
        putplutoupdates!(session, clientupdate_notebook_list(session.notebooks))
    end

    nb
end

function save_upload(content::Vector{UInt8})
    save_path = emptynotebook().path
    Base.open(save_path, "w") do io
        write(io, content)
    end

    save_path
end

function new(session::ServerSession; run_async=true)
    nb = if session.options.server.init_with_file_viewer

        file_viewer_code = """html\"\"\"

        <script>

        const nbfile_url = window.location.href.replace("edit", "notebookfile")

        const pre = html`<pre style="font-size: .6rem;">Loading...</pre>`

        const handle = setInterval(async () => {

        pre.innerText = await (await fetch(nbfile_url)).text()
        }, 500)

        invalidation.then(() => {
        clearInterval(handle)
        })

        return pre

        </script>

        \"\"\"
        """
        Notebook([Cell(), Cell(code=file_viewer_code, code_folded=true)])

    else
        emptynotebook()
    end
    update_save_run!(session, nb, nb.cells; run_async=run_async, prerender_text=true)
    session.notebooks[nb.notebook_id] = nb

    if run_async
        @asynclog putplutoupdates!(session, clientupdate_notebook_list(session.notebooks))
    else
        putplutoupdates!(session, clientupdate_notebook_list(session.notebooks))
    end

    nb
end

function shutdown(session::ServerSession, notebook::Notebook; keep_in_session=false, async=false)
    notebook.nbpkg_restart_recommended_msg = nothing
    notebook.nbpkg_restart_required_msg = nothing

    if !keep_in_session
        listeners = putnotebookupdates!(session, notebook) # TODO: shutdown message
        delete!(session.notebooks, notebook.notebook_id)
        putplutoupdates!(session, clientupdate_notebook_list(session.notebooks))
        for client in listeners
            @async close(client.stream)
        end
    end
    WorkspaceManager.unmake_workspace((session, notebook); async=async)
end

end


text:
using IterableTables
using IterableTables: getiterator
using Phylo.API

"""
    getinternalnodes(t::AbstractTree)
Function to retrieve only the internal nodes from a tree, `t`, which does not
include tips or root.

"""
getinternalnodes(t::AbstractTree) = collect(nodenamefilter(isinternal, t))

"""
    droptips!(tree::AbstractTree{OneTree}, tips)

Function to drop tips from a phylogenetic tree `tree`, which are found in
the vector of tips or tip names, `tips`.
"""
function droptips! end
@traitfn function droptips!(tree::T, tips::AbstractVector{N}) where
    {N, RT, T <: AbstractTree{OneTree, RT, N}; !MatchNodeType{T, N}}
    return droptips!(tree, [getnode(tree, tip) for tip in tips])
end

@traitfn function droptips!(tree::T, tips::AbstractVector{N}) where
    {N, RT, T <: AbstractTree{OneTree, RT}; MatchNodeType{T, N}}
    keep_tips = [tip for tip in getleaves(tree) if tip ∉ tips]
    tipnames = [getnodename(tree, tip) for tip in tips]

    # Remove nodes that are not in tip names
    for tip in tips
        _deletenode!(tree, tip)
    end

    # Remove nodes that are related to the cut tips
    while length(setdiff(collect(nodefilter(isleaf, tree)), keep_tips)) > 0
        nodes = setdiff(collect(nodefilter(isleaf, tree)), keep_tips)
        map(x -> deletenode!(tree, x), nodes)
    end

    # Merge internal nodes that no longer have multiple children
    while any(map(x -> length(getchildren(tree, x)) .< 2,
                  getinternalnodes(tree)))
        inner_nodes = getinternalnodes(tree)
        remove_nodes = findall(map(x->length(getchildren(tree, x)) .< 2,
                                   inner_nodes))
        for i in remove_nodes
            parent = getparent(tree, inner_nodes[i])
            parentbranch = getinbound(tree, inner_nodes[i])

            child = getchildren(tree, inner_nodes[i])[1]
            childbranch = getoutbounds(tree, getnode(tree, inner_nodes[i]))[1]

            len = distance(tree, parent, child)

            deletebranch!(tree, parentbranch)
            deletebranch!(tree, childbranch)
            deletenode!(tree, inner_nodes[i])

            createbranch!(tree, parent, child, len)
        end
    end

    # Remove root if it no longer has two branches
    root = first(nodefilter(isroot, tree))
    if length(getchildren(tree, root)) < 2
        deletenode!(tree, root)
    end

    if !isempty(getleafinfo(tree))
        li = leafinfotype(typeof(tree))(Iterators.
                                        filter(line -> line[1] ∉ tipnames,
                                               getiterator(getleafinfo(tree))))
        setleafinfo!(tree, li)
    end
    return tipnames
end

"""
    keeptips!(tree::AbstractTree{OneTree}, tips)

Function to keep only the tips in a phylogenetic tree, `tree`, that are found in
the vector of tips or tip names, `tips`.
"""
function keeptips! end
@traitfn function keeptips!(tree::T, tips::AbstractVector{N}) where
    {N, RT, T <: AbstractTree{OneTree, RT, N}; !MatchNodeType{T, N}}
    return keeptips!(tree, [getnode(tree, tip) for tip in tips])
end

@traitfn function keeptips!(tree::T, tips::AbstractVector{N}) where
    {N, RT, T <: AbstractTree{OneTree, RT}; MatchNodeType{T, N}}
    drop_tips = [tip for tip in getleaves(tree) if tip ∉ tips]
    return droptips!(tree, drop_tips)
end


text:
using LinearAlgebra
using SparseArrays
using PartitionedArrays
using Test
using IterativeSolvers

function test_fem_sa(parts)

  u(x) = 1.0 #x[1]+x[2]
  lx = 2.0
  ls = (lx,lx)
  nx = 10
  ns = (nx,nx)
  n = prod(ns)
  h = lx/nx
  D = length(ns)
  Ae = (h/6)*[
    4.0  -1.0  -1.0  -2.0
   -1.0   4.0  -2.0  -1.0
   -1.0  -2.0   4.0  -1.0
   -2.0  -1.0  -1.0   4.0
  ]

  cis_gcells = CartesianIndices(ns)
  cis_gnodes = CartesianIndices(ns.+1)
  cis_enodes = CartesianIndices(ntuple(i->2,Val(D)))
  lis_enodes = LinearIndices(cis_enodes)
  lis_gnodes = LinearIndices(cis_gnodes)
  c1 = CartesianIndex(ntuple(i->1,Val(D)))

  cells = PRange(parts,ns)

  # Loop over owned cells, and fill the coo-vectors
  # Note that during the process we will touch remote rows and cols
  # This will be fixed later with an assembly.
  I,J,V = map_parts(cells.partition) do cells
    I = Int[]
    J = Int[]
    V = Float64[]
    for ocell in cells.oid_to_lid
      gcell = cells.lid_to_gid[ocell]
      ci_gcell = cis_gcells[gcell]
      for ci_erow in cis_enodes
        ci_grow = ci_gcell + (ci_erow - c1)
        grow = lis_gnodes[ci_grow]
        erow = lis_enodes[ci_erow]
        boundary = any(s->(1==s||s==(nx+1)),Tuple(ci_grow))
        if boundary
          push!(I,grow)
          push!(J,grow)
          push!(V,1)
        else
          for ci_ecol in cis_enodes
            ci_gcol = ci_gcell + (ci_ecol - c1)
            gcol = lis_gnodes[ci_gcol]
            ecol = lis_enodes[ci_ecol]
            push!(I,grow)
            push!(J,gcol)
            push!(V,Ae[erow,ecol])
          end
        end
      end
    end
    I,J,V
  end

  # Create rows and cols without ghost layer
  rows = PRange(parts,ns.+1)
  cols = PRange(parts,ns.+1)

  # Add remote row gids to the rows ghost layer
  add_gids!(rows,I)

  # Start an assembly of the COO Vectors,
  # i.e., send and add the triplets (i,j,v) to the part that owns i.
  t = async_assemble!(I,J,V,rows)

  # Meanwhile we can fill the rhs.
  # Allocate it.
  b = PVector(0.0,rows)

  # Fill it.
  # we use `global_view` in order to be able to index
  # b with global ids from within the parts.
  # Note that we touch non owned rows.
  map_parts(global_view(b,b.rows),cells.partition) do b, cells
    for ocell in cells.oid_to_lid
      gcell = cells.lid_to_gid[ocell]
      ci_gcell = cis_gcells[gcell]
      for ci_erow in cis_enodes
        ci_grow = ci_gcell + (ci_erow - c1)
        grow = lis_gnodes[ci_grow]
        erow = lis_enodes[ci_erow]
        boundary = any(s->(1==s||s==(nx+1)),Tuple(ci_grow))
        if boundary
          x = (Tuple(ci_grow) .- 1) .* h
          b[grow] += u(x)
        end
      end
    end
  end

  # Wait the assembly of the coo vectors to finish
  map_parts(wait∘schedule,t)

  # Now we can add off processor col ids to the ghost layer of cols.
  add_gids!(cols,J)

  # Compress the coo vectors and build the matrix
  A = PSparseMatrix(I,J,V,rows,cols,ids=:global)

  # When filling b we have touched remote rows.
  # Send and add their contribution to the owner part
  # NOTE: calling this assembly before the previous one finishes can be
  # problematic since we can have wrongly matching snd/rcv in MPI.
  assemble!(b)

  # Setup initial and exact solution
  x = PVector(0.0,cols)
  x̂ = similar(x)
  map_parts(x.values,x̂.values,x.rows.partition) do x,x̂,rows
    for lid in rows.oid_to_lid
      grow = rows.lid_to_gid[lid]
      ci_grow = cis_gnodes[grow]
      xi = (Tuple(ci_grow) .- 1) .* h
      x̂[lid] = u(xi)
      boundary = any(s->(1==s||s==(nx+1)),Tuple(ci_grow))
      if boundary
        x[lid] = u(xi)
      end
    end
  end

  # Solve!
  IterativeSolvers.cg!(x,A,b,verbose=i_am_main(parts))

  @test norm(x-x̂) < 1.0e-5

end


text:
#!/usr/env/bin julia
using ProgressMeter
using HDF5
using HDF5Utils
using MPI
using ArgParse
using Statistics
using SortingAlgorithms
using Parameters
using Mmap

function part(x::AbstractArray{T, N}; dims = -1) where {T, N}
    dims = dims > 0 ? dims : N + dims + 1
    dsize = size(x, dims)
    rank = MPI.Comm_rank(MPI.COMM_WORLD)
    wsize = MPI.Comm_size(MPI.COMM_WORLD)
    @assert wsize <= dsize
    chunk = ceil(Int, dsize / wsize)
    is = (rank * chunk + 1):min(dsize, (rank + 1) * chunk)
    view(x, ntuple(x -> x == dims ? is : (:), N)...)
end

function discretize!(x8, x)
    bin_edges = [Float32[] for f in 1:size(x, 1)]
    prob = range(0, 1, length = 256 + 1)[2:(end - 1)]
    prob′ = range(0, 1, length = 2560 + 1)[2:(end - 1)]
    prog = Progress(size(x, 1), desc = "BinEdges: ")
    for f in 1:size(x, 1)
        xf = filter(z -> !isnan(z) & !isinf(z), x[f, :])
        sort!(xf, alg = RadixSort)
        v = quantile(xf, prob′, sorted = true)
        v = MPI.Allgather(v, MPI.COMM_WORLD)
        bin_edges[f] = quantile(v, prob)
        if MPI.Comm_rank(MPI.COMM_WORLD) == 0
            next!(prog)
        end
    end
    prog = Progress(size(x, 2), desc = "Discretize: ")
    for n in 1:size(x, 2)
        @inbounds for f in 1:size(x, 1)
            edge = bin_edges[f]
            x8[f, n] = searchsortedfirst(edge, x[f, n]) - 1
        end
        if MPI.Comm_rank(MPI.COMM_WORLD) == 0
            next!(prog)
        end
    end
    MPI.Barrier(MPI.COMM_WORLD)
    return bin_edges
end

MPI.Init()

setting = ArgParseSettings()
@add_arg_table setting begin
    "--name"
        arg_type = String
        required = true
    "--inplace"
        arg_type = Int
        default = 0
    "h5"
        arg_type = String
        required = true
end
@unpack name, inplace, h5 = parse_args(ARGS, setting)
h5′ = replace(h5, ".h5" => "_UInt8.h5")

x = h5readmmap(h5, name, mode = "r")
if eltype(x) == UInt8
    MPI.Finalize()
    exit()
end

if MPI.Comm_rank(MPI.COMM_WORLD) == 0
    h5open(h5′, "w", "alignment", (0, 8)) do fid′
        h5open(h5, "r") do fid
            for dset in names(fid)
                dset == name && continue
                o_copy(fid[dset], fid′, dset)
            end
        end
        d_zeros(fid′, name, UInt8, size(x))
    end
end
MPI.Barrier(MPI.COMM_WORLD)

x8 = h5readmmap(h5′, name, mode = "r+")
x = reshape(x, size(x, 1), :)
x8 = reshape(x8, size(x8, 1), :)

bin_edges = discretize!(part(x8), part(x))

if MPI.Comm_rank(MPI.COMM_WORLD) == 0
    Mmap.sync!(x8)
    h5open(h5′, "r+") do fid′
        fid′["bin_edges"] = hcat(bin_edges...)
    end
    inplace == 1 && mv(h5′, h5, force = true)
end

MPI.Finalize()


text:
using ClimaCoupler
using Documenter, Literate, Pkg

const COUPLER_DIR = joinpath(@__DIR__, "..")
const EXPERIMENTS_DIR = joinpath(@__DIR__, "..", "experiments")
const OUTPUT_DIR = joinpath(@__DIR__, "src/generated")

# tutorials & experiments
# - generate tutorial files
# tutorial_dir = joinpath(EXPERIMENTS_DIR, "ClimaCore/tc1_heat-diffusion-with-slab/")
# tutorial_name = "run.jl"
# Pkg.activate(tutorial_dir)
# Pkg.instantiate()
# include(joinpath(tutorial_dir, tutorial_name))
# Literate.markdown(joinpath(tutorial_dir, tutorial_name), OUTPUT_DIR; execute = true, documenter = false)

# - move tutorial files to docs/src
# IMAGE_DIR = joinpath(tutorial_dir, "images/")
# files = readdir(IMAGE_DIR)
# png_files = filter(endswith(".png"), files)
# for file in png_files
#     mkpath(joinpath(OUTPUT_DIR, "images/"))
#     cp(joinpath(IMAGE_DIR, file), joinpath(OUTPUT_DIR, "images/", file), force = true)
# end

# pages layout
experiment_pages = []
interface_pages = ["couplerstate.md", "timestepping.md"]

pages = Any["Home" => "index.md", "Examples" => experiment_pages, "Coupler Interface" => interface_pages]

makedocs(sitename = "ClimaCoupler.jl", format = Documenter.HTML(), modules = [ClimaCoupler], pages = pages)

# Documenter can also automatically deploy documentation to gh-pages.
# See "Hosting Documentation" and deploydocs() in the Documenter manual
# for more information.
deploydocs(repo = "<github.com/CliMA/ClimaCoupler.jl.git>", push_preview = true, devbranch = "main", forcepush = true)

max_stars_repo_name: CliMA/ClimaCoupler

max_issues_repo_name: CliMA/ClimaCoupler

max_forks_repo_name: CliMA/ClimaCoupler


text:
export FPGA

abstract type RHD2000 end
abstract type Task end
abstract type IC end

mutable struct Debug
    state::Bool
    m::String
    filepath::String
    data::Array{Float64,1}
    ind::Int64
    maxind::Int64
    delay::Bool
    delay_t::Float64
end

mutable struct Intan_Filter
    chan::Int64
    output::Int64
    wn1::Int64
    wn2::Int64
    f_type::Int64
    filt::MyFilter
end

mutable struct SaveOpt
    record_mode::Bool
    save_full::Bool
    v::String

    ts_s::Bool
    ts::String

    adc_s::Bool
    adc::String

    #Intan board ttls
    ttl_s::Bool
    ttl::String
    ttl_out::String

    #Local field potential could be saved if it is calculated in real time
    lfp_s::Bool
    lfp::String

    #Location for saved files
    folder::String
    backup::String
end

function make_save_structure(save_full::Bool)
    @static if is_unix()
        t=string("./",now())
        out=SaveOpt(false,save_full,string(t,"/v.bin"),false,string(t,"/ts.bin"),false,string(t,"/adc.bin"),false,string(t,"/ttl.bin"),string(t,"/ttl_out.bin"),false,string(t,"/lfp.bin"),t,string(t,"/.backup/"))
    end

    @static if is_windows()
        t=Dates.format(now(),"yyyy-mm-dd-HH-MM-SS")
        out=SaveOpt(false,save_full,string(t,"\\v.bin"),false,string(t,"\\ts.bin"),false,string(t,"\\adc.bin"),false,string(t,"\\ttl.bin"),string(t,"\\ttl_out.bin"),false,string(t,"\\lfp.bin"),t,string(t,"\\.backup\\"))
    end
    out
end

mutable struct register
    sampleRate::Cdouble

    #Register 0 variables
    adcReferenceBw::Int32
    ampFastSettle::Int32
    ampVrefEnable::Int32
    adcComparatorBias::Int32
    adcComparatorSelect::Int32

    #Register 1 variables
    vddSenseEnable::Int32
    adcBufferBias::Int32

    #Register 2 variables
    muxBias::Int32

    #Register 3 variables
    muxLoad::Int32
    tempS1::Int32
    tempS2::Int32
    tempEn::Int32
    digOutHiZ::Int32
    digOut::Int32

    #Register 4 variables
    weakMiso::Int32
    twosComp::Int32
    absMode::Int32
    dspEn::Int32
    dspCutoffFreq::Int32

    #Register 5 variables
    zcheckDacPower::Int32
    zcheckLoad::Int32
    zcheckScale::Int32
    zcheckConnAll::Int32
    zcheckSelPol::Int32
    zcheckEn::Int32

    #Register 6 variables

    #Register 7 variables
    zcheckSelect::Int32

    #Register 8-13 variables
    offChipRH1::Int32
    offChipRH2::Int32
    offChipRL::Int32
    adcAux1En::Int32
    adcAux2En::Int32
    adcAux3En::Int32
    rH1Dac1::Int32
    rH1Dac2::Int32
    rH2Dac1::Int32
    rH2Dac2::Int32
    rLDac1::Int32
    rLDac2::Int32
    rLDac3::Int32

    #Register 14-17 variables
    aPwr::Array{Int32,1}
end

mutable struct DigOut
    channel::Int32

    pulseOrTrain::Int32 #0 = single Pulse, 1 = pulse train

    triggerEnabled::Bool
    triggerOnLow::Bool # 0 = High Trigger, 1 = Low trigger
    edgeTriggered::Bool # 0 = edge, 1 = Level triggered
    triggerSource::Int32 #0 - 15 corresponds to digital in 1 through 16, 16-23 is analog inputs, 24 through 31 is keypresses

    shapeInt::Int32 # 0 = Biphasic, 1 = Biphasic with delay, 2 = Triphasic, 3 = monophasic
    negStimFirst::Bool # 0 = negative first, 1 = positive first
    numPulses::Int32

    postTriggerDelay::Int32 #after trigger, before pulse
    firstPhaseDuration::Int32
    refractoryPeriod::Int32
    pulseTrainPeriod::Int32

    repeatBurst::Bool
end

function DigOut()
    DigOut(0,0,false,false,false,0,3,false,1,0,1000,5000,5000,false)
end

mutable struct FPGA <: IC
    id::Int64
    board::Ptr{Void}
    lib::Ptr{Void}
    shift::Int64
    sampleRate::Int64
    numDataStreams::Int64
    dataStreamEnabled::Array{Int64,2}
    usbBuffer::Array{UInt8,1}
    numWords::Int64
    numBytesPerBlock::Int64
    amps::Array{Int64,1}
    adc::Array{Int16,2}
    ttlin::Array{UInt16,1}
    ttlout::Array{UInt16,1}
    ttloutput::UInt16
    usb3::Bool
    r::register
    d::Array{DigOut,1}
end

function FPGA(board_id::Int64,amps::Array{Int64,1};usb3=false)
    board = Ptr{Void}(1)
    mylib = Ptr{Void}(1)
    if board_id==1
        FPGA(1,board,mylib,0,30000,0,zeros(Int64,1,MAX_NUM_DATA_STREAMS),zeros(UInt8,USB_BUFFER_SIZE),0,0,amps,zeros(Int16,SAMPLES_PER_DATA_BLOCK,8),zeros(UInt16,SAMPLES_PER_DATA_BLOCK),zeros(UInt16,SAMPLES_PER_DATA_BLOCK),0,usb3,CreateRHD2000Registers(30000),[DigOut() for i=1:16])
    elseif board_id==2
        FPGA(2,board,mylib,0,30000,0,zeros(Int64,1,MAX_NUM_DATA_STREAMS),zeros(UInt8,USB_BUFFER_SIZE),0,0,amps,zeros(Int16,SAMPLES_PER_DATA_BLOCK,8),zeros(UInt16,SAMPLES_PER_DATA_BLOCK),zeros(UInt16,SAMPLES_PER_DATA_BLOCK),0,usb3,CreateRHD2000Registers(30000),[DigOut() for i=1:16])
    end
end

mutable struct RHD_Single <: RHD2000
    v::Array{Int16,2}
    buf::Array{Spike,2}
    nums::Array{UInt16,1}
    debug::Debug
    reads::Int64
    cal::Int64
    save::SaveOpt
    sr::Int64
    refs::Array{Int64,1}
    ttl_state::Bool
    time::Array{UInt32,2}
    filts::Array{Array{Intan_Filter,1},1}
    lfps::Array{Int16,2}
    initialized::Bool
end

function RHD_Single(fpga,num_channels,s,buf,nums,debug)
    if VERSION > v"0.7-"
        the_filters = [Array{Intan_Filter}(undef, 0) for i=1:num_channels]
    else
        the_filters = [Array{Intan_Filter}(0) for i=1:num_channels]
    end
    RHD_Single(zeros(Int16,SAMPLES_PER_DATA_BLOCK,num_channels),buf,nums,debug,0,0,make_save_structure(false),30000,zeros(Int64,num_channels),false,zeros(UInt32,SAMPLES_PER_DATA_BLOCK,length(fpga)),the_filters,zeros(Int16,SAMPLES_PER_DATA_BLOCK,num_channels),false)
end

mutable struct RHD_Parallel <: RHD2000
    v::SharedArray{Int16,2}
    buf::SharedArray{Spike,2}
    nums::SharedArray{UInt16,1}
    debug::Debug
    reads::Int64
    cal::Int64
    save::SaveOpt
    sr::Int64
    refs::Array{Int64,1}
    ttl_state::Bool
    time::SharedArray{UInt32,2}
    filts::Array{Array{Intan_Filter,1},1}
    lfps::SharedArray{Int16,2}
    initialized::Bool
end

function RHD_Parallel(fpga,num_channels,s,buf,nums,debug)
    if VERSION > v"0.7-"
        the_filters = [Array{Intan_Filter}(undef, 0) for i=1:num_channels]
    else
        the_filters = [Array{Intan_Filter}(0) for i=1:num_channels]
    end
    RHD_Parallel(convert(SharedArray{Int16,2},zeros(Int16,SAMPLES_PER_DATA_BLOCK,num_channels)),buf,nums,debug,0,0,make_save_structure(false),30000,zeros(Int64,num_channels),false,convert(SharedArray{UInt32,2},zeros(UInt32,SAMPLES_PER_DATA_BLOCK,length(fpga))),the_filters,zeros(Int16,SAMPLES_PER_DATA_BLOCK,num_channels),false)
end

default_sort=Algorithm[DetectNeg(),ClusterTemplate(49),AlignMin(),FeatureTime(),ReductionNone(),ThresholdMeanN()]

debug_sort=Algorithm[DetectNeg(),ClusterTemplate(49),AlignProm(),FeatureTime(),ReductionNone(),ThresholdMeanN()]

default_debug=Debug(false,"off","",zeros(Float64,1),0,0,false,0.0)

function makeRHD(fpga::Array{FPGA,1}; params=default_sort, parallel=false, debug=default_debug,
    sr=30000,wave_time=1.6,single_channel_mode=false,emg=false)

    c_per_fpga=[length(fpga[i].amps)*32 for i=1:length(fpga)]

    if length(c_per_fpga)>1
        for i=2:length(c_per_fpga)
            fpga[i].shift=c_per_fpga[i-1]
        end
    end

    numchannels=sum(c_per_fpga)

    #Single Channel
    if single_channel_mode
        numchannels=1
        fpga[1].amps[1]=255
    end

    if debug.state==true
        params=debug_sort
    end

    wave_points=get_wavelength(sr,wave_time)

    if parallel==false
        s=create_multi(params...,numchannels,wave_points)
        (buf,nums)=output_buffer(numchannels)
        fpgas=fpga
        rhd=RHD_Single(fpgas,numchannels,s,buf,nums,debug)
    else
        s=create_multi(params...,numchannels,workers()[1]:workers()[end],wave_points)
        (buf,nums)=output_buffer(numchannels,true)
        fpgas=distribute(fpga)
        rhd=RHD_Parallel(fpgas,numchannels,s,buf,nums,debug)
    end

    rhd.sr=sr

    (rhd,s,fpgas)
end

get_wavelength(sr,timewin)=round(Int,sr*timewin/1000)

mutable struct mytime
    h::Int8
    h_l::Gtk.GtkLabelLeaf
    m::Int8
    m_l::Gtk.GtkLabelLeaf
    s::Int8
    s_l::Gtk.GtkLabelLeaf
end

mutable struct SoftScope
    v::Array{Float64,1}
    ind::Int64
    last::Array{Float64,1}
    v_div::Float64
    t_div::Float64
    draws::Int64
    spikes::Array{Int64,1}
    num_spikes::Int64
    prev_spikes::Array{Int64,1}
    prev_num_spikes::Int64
    thres_on::Bool
    signal_type::Int64
    ctx::Cairo.CairoContext
end

function SoftScope(sr,ctx,sz)
    SoftScope(zeros(Float64,sz*10),1,zeros(Float64,sz),1.0/1000,1.0,1,zeros(Int64,500),0,zeros(Int64,500),0,false,1,ctx)
end

mutable struct Spectrogram
    f_max::Int64
    t_max::Int64
    win_width_t::Float64
    win_overlap_t::Float64
    win_width_s::Int64
    win_overlap_s::Int64
    out::Array{Float64,2}
    f_div::Float64
    t_div::Float64
    fs::Int64
end

function Spectrogram(fs; win_width_t = .01,win_overlap_t = .002, f_max = 15000)

    win_width_s=convert(Int, win_width_t*fs)
    win_overlap_s=convert(Int, win_overlap_t*fs)

    S = spectrogram(rand(Float64,fs),win_width_s,win_overlap_s; fs=fs, window=hanning)
    P = power(S)

    f_div=freq(S).multiplier
    t_div=time(S).step

    f_max = ceil(Int64,f_max / f_div)

    f_max = (f_max > size(P,1)) ? size(P,1) : f_max
    t_max = size(P,2)

    out=zeros(Float64,f_max,t_max)

    Spectrogram(f_max,t_max,win_width_t,win_overlap_t,win_width_s,win_overlap_s,out,f_div,t_div,fs)
end

mutable struct Band_Widgets
    win::Gtk.GtkWindowLeaf
    sb1::Gtk.GtkSpinButtonLeaf #Hardware Low Cut
    sb2::Gtk.GtkSpinButtonLeaf #Hardware High Cut
    sb3::Gtk.GtkSpinButtonLeaf #Hardware DSP High Pass
    b1::Gtk.GtkButtonLeaf #Button to update Headstage Hardware Filters
    sw_box::Gtk.GtkComboBoxTextLeaf
    wn_sb1::Gtk.GtkSpinButtonLeaf #Software Filter Bandwidth Low
    wn_sb2::Gtk.GtkSpinButtonLeaf #Software Filter Bandwidth High

    sw_chan_sb::Gtk.GtkSpinButtonLeaf #channel number to apply software filter to

    add_b::Gtk.GtkButtonLeaf #Add software filter
    re_b::Gtk.GtkButtonLeaf #Replace software Filter
    delete_b::Gtk.GtkButtonLeaf

    sw_check::Gtk.GtkCheckButtonLeaf #Apply filter to all channels

    wn_sb1_l::Gtk.GtkLabelLeaf
    wn_sb2_l::Gtk.GtkLabelLeaf

    output_box::Gtk.GtkComboBoxTextLeaf
    filt_num_sb::Gtk.GtkSpinButtonLeaf #filter number
    c::Gtk.GtkCanvasLeaf

    wn1::Int64
    wn2::Int64
    f_type::Int64
    f_pos::Int64
    f_out::Int64
    chan::Int64
    lfp_en::Array{Bool,1}

    tv::Gtk.GtkTreeViewLeaf
    list::Gtk.GtkListStoreLeaf
end

mutable struct Sort_Widgets
    b1::Gtk.GtkButtonLeaf
    b2::Gtk.GtkButtonLeaf
    b3::Gtk.GtkButtonLeaf
    b4::Gtk.GtkToggleButtonLeaf
    check::Gtk.GtkCheckButtonLeaf
    slider_active::Bool
end

mutable struct Spike_Widgets
    refresh::Gtk.GtkButtonLeaf
    pause::Gtk.GtkToggleButtonLeaf
end

mutable struct Table_Widgets
    win::Gtk.GtkWindowLeaf
    tv::Gtk.GtkTreeViewLeaf
    list::Gtk.GtkListStoreLeaf
    gain_text::Gtk.GtkCellRendererText
    thres_text::Gtk.GtkCellRendererText
    ref_text::Gtk.GtkCellRendererText
    enabled_toggle::Gtk.GtkCellRendererToggle
end

mutable struct Save_Widgets
    win::Gtk.GtkWindowLeaf
    volt::Gtk.GtkCheckButtonLeaf
    lfp::Gtk.GtkCheckButtonLeaf
    ttlin::Gtk.GtkCheckButtonLeaf
    ts::Gtk.GtkCheckButtonLeaf
    adc::Gtk.GtkCheckButtonLeaf
    input::Gtk.GtkEntryLeaf
end

mutable struct Reference_Widgets
    win::Gtk.GtkWindowLeaf
    tv1::Gtk.GtkTreeViewLeaf
    tv2::Gtk.GtkTreeViewLeaf
    list1::Gtk.GtkListStoreLeaf
    list2::Gtk.GtkListStoreLeaf
    select_button::Gtk.GtkButtonLeaf
    apply_button::Gtk.GtkButtonLeaf
end

mutable struct Gui_Handles
    win::Gtk.GtkWindowLeaf

    run::Gtk.GtkToggleButtonLeaf
    init::Gtk.GtkButtonLeaf
    #cal::Gtk.GtkCheckButtonLeaf
    record::Gtk.GtkToggleButtonLeaf

    slider::Gtk.GtkScaleLeaf
    adj::Gtk.GtkAdjustmentLeaf
    slider2::Gtk.GtkScaleLeaf
    adj2::Gtk.GtkAdjustmentLeaf

    c::Gtk.GtkCanvasLeaf

    num::Int64 #currently selected spike from multi display
    num16::Int64 #currently selected group of spikes in multi display

    scale::Array{Float64,2}
    offset::Array{Int64,1}

    mim::NTuple{2,Float64} #saved x,y position of mouse input on multi-channel display

    total_clus::Array{Int64,1}

    draws::Int64 #how many displays have occured since the last refresh

    events::Array{Int64,1}

    enabled::Array{Bool,1}

    time::mytime

    wave_points::Int64

    c_right_top::UInt8 #flag to indicate the drawing method to be displayed on top part of right display
    c_right_bottom::UInt8 #flag to indicate the drawing method to be displayed on the bottom part of right display

    popup_ed::Gtk.GtkMenuLeaf
    popup_event::Gtk.GtkMenuLeaf
    popup_spect::Gtk.GtkMenuLeaf

    rb1::Array{Gtk.GtkRadioButton,1}
    rb2::Array{Gtk.GtkRadioButton,1}

    scope::Array{Float64,2}

    spike_changed::Bool
    chan_per_display::Int64

    c_changed::Bool

    slider_sort::Gtk.GtkScaleLeaf

    isi_ind::Int64
    isi_count::Int64
    isi_clus_ID::Array{Int64,1}
    isi_last_time::Array{UInt32,1}
    isi::Array{UInt32,1}
    isi_hist::Array{Int64,1}

    soft::SoftScope
    popup_scope::Gtk.GtkMenuLeaf

    sort_widgets::Sort_Widgets
    spike_widgets::Spike_Widgets
    sortview_widgets::SortView
    band_widgets::Band_Widgets
    table_widgets::Table_Widgets
    spect::Spectrogram
    save_widgets::Save_Widgets
    ref_widgets::Reference_Widgets
    b::Gtk.GtkBuilder

    sc::SpikeSorting.Single_Channel

    buf::SpikeSorting.Buffer

    v_s::Array{Int16,1}
end

#=
C_Right Top Flags

1 = 16 channel
2 = 32 channels
3 = 64 channels
4 = 64 channels raster
5 = blank

C_Right Bottom Flags

1 = events/analog
2 = 16 channel raster
3 = 32 channel raster
4 = soft scope
5 = 64 channel
6 = 64 channel raster
7 = blank

=#


text:
module ShowTree

export show_tree

show_tree(x) = show_tree(STDOUT, x)

function show_tree(io::IO, x, indent_root="", indent_leaf="")
    print(io, indent_root)
    if iscompact(x)
        _show_compact(io, x)
        println(io)
    else
        _show_root(io, x)
        print(io, '\n')
        cs = _children(x)
        for (i,c) in enumerate(cs)
            if i < length(cs)
                show_tree(io, c, indent_leaf*rootsyms(x)[1], indent_leaf*leafsyms(x)[1])
            else
                show_tree(io, c, indent_leaf*rootsyms(x)[2], indent_leaf*leafsyms(x)[2])
            end
        end
    end
end

rootsyms(x) = ("├─","└─")
leafsyms(x) = ("│ ","  ")

isvarargs(x::DataType) = x <: Tuple && x.parameters[end] <: Vararg{Any}
_show_root(io::IO, x::DataType) = print(io, x.name)
function _children(x::DataType)
    params = isvarargs(x) ? [x.parameters[1:end-1]...,x.parameters[end].body.parameters[1]] : x.parameters
    map(strip_typebounds, params)
end

struct ParamTypeVar
name::Symbol
end

_show_root(io::IO, x::ParamTypeVar) = print_with_color(:light_magenta, io, x.name)

strip_typebounds(x) = x
strip_typebounds(x::TypeVar) = TypeVar(x.name)

iscompact(x::Union) = false
iscompact(x::DataType) = !isvarargs(x) && all(iscompact ∘ strip_typebounds, x.parameters)
iscompact(x::TypeVar) = x.lb === Base.Bottom && x.ub === Any
iscompact(x::UnionAll) = iscompact(x.var) && iscompact(x.body)
iscompact(x::ParamTypeVar) = true
iscompact(x) = true

_show_compact(io, x) = show(io,x)
function _show_compact(io, x::DataType)
    show(io, x.name)
    if length(x.parameters) > 0
        print(io, "{")
        _show_compact(io, x.parameters[1])
        for i = 2:length(x.parameters)
            print(io,",")
            _show_compact(io, x.parameters[i])
        end
        print(io, "}")
    end
end

unionall_body(x) = x
unionall_body(x::UnionAll) = unionall_body(x.body)

unionall_vars(x) = []
unionall_vars(x::UnionAll) = [x.var, unionall_vars(x.body)...]

function _show_compact(io, x::UnionAll)
    print_with_color(:cyan, io, "UnionAll ")
    _show_compact(io, unionall_body(x))
    print(io," ")
    print_with_color(:cyan, io, "where")
    print(io," {")
    params = unionall_vars(x)
    _show_compact(io, params[1])
    for i = 2:length(params)
        print(io,",")
        _show_compact(io, params[i])
    end
    print(io, "}")
end

rootsyms(x::DataType) = isvarargs(x) ? ("├─","⧆─") : ("├─","└─")
leafsyms(x::DataType) = isvarargs(x) ? ("│ ","┊ ") : ("│ ","  ")

_show_root(io::IO, x) = print(io, x)
_children(x) = []

_show_root(io::IO, x::Union) = print_with_color(:cyan, io, "Union")
_children(x::Union) = x.b isa Union ? [x.a, _children(x.b)...] : [x.a, x.b]

_show_root(io::IO, x::UnionAll) = print_with_color(:cyan, io, "UnionAll")
_children(x::UnionAll) = x.body isa UnionAll ? [_children(x.body)..., x.var] : [x.body, x.var]

_show_root(io::IO, x::TypeVar) = print_with_color(:magenta, io, x.name)
_children(x::TypeVar) = x.lb !== Base.Bottom ? [x.lb, x.ub] : x.ub !== Any ? [x.ub] : []
_show_compact(io, x::TypeVar) = print_with_color(:magenta, io, x.name)

leafsyms(x::TypeVar) = ("│  ","   ")
rootsyms(x::TypeVar) = ("├>:","└<:")

# show_tree(StridedVecOrMat)

struct IndentedIO{T} <: IO
    io::T
    indent::String
end

function Base.write(ind::IndentedIO, c::Char)
    j = write(ind.io, c)
    if c == '\n'
        j += write(ind.io, ind.indent)
    end
    j
end

function Base.write(ind::IndentedIO, s::String)
    j = 0
    for l = readlines(IOBuffer(s), chomp=false)
        j += write(ind.io, l)
        if endswith(l, '\n')
            j += write(ind.io, ind.indent)
        end
    end
    j
end

end # module


text:
# TODO: Make FutureArray a subtype of AbstractArray
struct FutureArray{T,N}
    data::Future
    size::Future
end

# Defining a method like the following is helpful if the Future in a data type
# isn't just the first field of the type that is a Future. In such a case,
# a custom future function may be defined but users of this data type must
# be sure to first call future on their data type before calling
# annotations functions like `mem`/`val`/`pt`/`pc`/`mut`/`loc`/`src`/`dst`.
Banyan.future(ba::T) where {T<:FutureArray} = ba.data

function partitioned_vector(ba::FutureArray{T,1}) where {T}
    res_data = future()
    res_size = future()
    target_size = ba.size

    mem(ba, res_data)

    pt(ba, Block())
    pt(res_data, Block())
    pt(res_size, Replicate())
    pt(target_size, Replicate())

    pc(Match(ba, res_data))
    pc(Match(res_size, target_size))
    mutated(res_data)
    mutated(res_size)

    return ba, res_data, res_size, target_size
end

function partitioned_vector_by_vector(
    ba::FutureArray{T,1},
    other::FutureArray{T,1},
) where {T}
    res_data = future()
    res_size = future()
    target_size = ba.size
    mem(ba, other, res_data)

    pt(ba, BlockBalanced())
    pt(other, BlockBalanced())
    pt(res_data, Block())
    pt(res_size, Replicate())
    pt(target_size, Replicate())

    pc(Match(ba, other, res_data))
    pc(Match(res_size, target_size))
    mutated(res_data)
    mutated(res_size)

    return ba, other, res_data, res_size, target_size
end

function partitioned_vector_by_scalar(ba::FutureArray{T,1}, other::T) where {T}
    other = future(other)
    res_data = future()
    res_size = future()
    target_size = ba.size
    # TODO: See whether ba.size is keeping arrays around for longer

    mem(ba, res_data)
    val(other)

    pt(ba, Block())
    pt(res_data, Block())
    pt(other, Replicate())
    pt(res_size, Replicate())
    pt(target_size, Replicate())

    pc(Match(ba, res_data))
    pc(Match(res_size, target_size))
    mutated(res_data)
    mutated(res_size)

    return ba, other, res_data, res_size, target_size
end

function partitioned_replicated_value(x)
    x = future(x)
    val(x)
    pt(x, Replicate())
    return x
end

function ones(::Type{T}, len::Integer)::FutureArray{T,1} where {T<:Number}
    data = future()
    data_size = future((len))
    created_size = future(len) # TODO: Support n-dimensional arrays with Match
    ty = future(T)

    mem(data, len, Float64)
    val(data_size)
    val(created_size)
    val(ty)

    pt(data, Block())
    pt(created_size, Div())
    pt(ty, Replicate())
    mutated(data)

    @partitioned data created_size ty begin
        data = ones(ty, created_size)
        x = DataFrame()
        # error("Hello!")
    end

    FutureArray{T,1}(data, data_size)
end

# Binary vector-vector operations
for op in (:+, :-)
    @eval begin
        function Base.$op(
            ba::FutureArray{T,1},
            other::FutureArray{T,1},
        )::FutureArray{T,1} where {T}
            ba, other, res_data, res_size, target_size =
                partitioned_vector_by_vector(ba, other)
            op = partitioned_replicated_value($op)
            @partitioned op ba other res_data res_size target_size begin
                res_data = op(ba, other)
                res_size = target_size
            end

            FutureArray{T,1}(res_data, res_size)
        end
    end
end

# Binary vector-scalar operations

for op in (:*, :/)
    @eval begin
        function Base.$op(
            ba::FutureArray{T,1},
            other::T,
        )::FutureArray{T,1} where {T}
            ba, other, res_data, res_size, target_size =
                partitioned_vector_by_scalar(ba, other)
            op = partitioned_replicated_value($op)
            @partitioned op ba other res_data res_size target_size begin
                res_data = op(ba, other)
                res_size = target_size
            end

            FutureArray{T,1}(res_data, res_size)
        end
    end
end

for op in (:*,)
    @eval begin
        function Base.$op(
            other::T,
            ba::FutureArray{T,1},
        )::FutureArray{T,1} where {T}
            ba, other, res_data, res_size, target_size =
                partitioned_vector_by_scalar(ba, other)
            op = partitioned_replicated_value($op)
            @partitioned op ba other res_data res_size target_size begin
                res_data = op(other, ba)
                res_size = target_size
            end

            FutureArray{T,1}(res_data, res_size)
        end
    end
end

# Broadcasting vector-vector operations
function Base.broadcasted(
    op,
    ba::FutureArray{T,1},
    other::FutureArray{T,1},
)::FutureArray{T,1} where {T}
    ba, other, res_data, res_size, target_size =
        partitioned_vector_by_vector(ba, other)
    op = partitioned_replicated_value(op)
    @partitioned op ba other res_data res_size target_size begin
        res_data = Base.broadcast(op, ba, other)
        res_size = target_size
    end

    FutureArray{T,1}(res_data, res_size)
end

# Broadcasting vector-scalar operations

function broadcasted(
    op,
    ba::FutureArray{T,1},
    other::T,
)::FutureArray{T,1} where {T}
    ba, other, res_data, res_size, target_size =
        partitioned_vector_by_scalar(ba, other)
    op = partitioned_replicated_value(op)
    @partitioned op ba other res_data res_size target_size begin
        res_data = Base.broadcast(op, ba, other)
        res_size = target_size
    end

    FutureArray{T,1}(res_data, res_size)
end

broadcasted(op, ba::FutureArray{T,1}, ::Val{V}) where {T,V} =
    broadcasted(op, ba, T(V))

Base.broadcasted(op, ba::FutureArray, other) where {T} =
    broadcasted(op, ba, other)

# specialized_wrapper might be Base.literal_pow
Base.broadcasted(specialized_wrapper, op, ba::FutureArray, other) =
    broadcasted(op, ba, other)

function Base.broadcasted(
    op,
    other::T,
    ba::FutureArray{T,1},
)::FutureArray{T,1} where {T}
    ba, other, res_data, res_size, target_size =
        partitioned_vector_by_scalar(ba, other)
    op = partitioned_replicated_value(op)
    @partitioned op ba other res_data res_size target_size begin
        res_data = Base.broadcast(op, other, ba)
        res_size = target_size
    end

    FutureArray{T,1}(res_data, res_size)
end

function Base.broadcasted(op, ba::FutureArray{T,1})::FutureArray{T,1} where {T}
    ba, res_data, res_size, target_size = partitioned_vector(ba)
    op = partitioned_replicated_value(op)
    @partitioned op ba res_data res_size target_size begin
        res_data = Base.broadcast(op, ba)
        res_size = target_size
    end

    FutureArray{T,1}(res_data, res_size)
end

# Unary operators
for op in (:-, :+)
    @eval begin
        function Base.$op(ba::FutureArray{T,1})::FutureArray{T,1} where {T}
            ba, res_data, res_size, target_size = partitioned_vector(ba)
            op = partitioned_replicated_value($op)
            @partitioned op ba res_data res_size target_size begin
                res_data = op(ba)
                res_size = target_size
            end

            FutureArray{T,1}(res_data, res_size)
        end
    end
end

function run_bs(size::Integer)
    price = ones(Float64, size) * 4.0
    strike = ones(Float64, size) * 4.0
    t = ones(Float64, size) * 4.0
    rate = ones(Float64, size) * 4.0
    vol = ones(Float64, size) * 4.0

    evaluate(price)

    # c05 = Float64(3.0)
    # c10 = Float64(1.5)
    # invsqrt2 = 1.0 / sqrt(2.0)

    # # rsig = rate + (vol.^2) * c05
    # rsig = vol .^ 2 # TODO: Fix issue in FutureArray where operands are same
    # rsig = rsig .* c05
    # rsig = rsig .+ rate

    # # rsig

    # # vol_sqrt = vol .* sqrt.(t)
    # vol_sqrt = sqrt.(t)
    # vol_sqrt = vol_sqrt .* vol

    # # d1 = (log.(price ./ strike) + rsig .* t) ./ vol_sqrt
    # d1 = price ./ strike
    # d1 = log.(d1)
    # tmp = rsig .* t
    # d1 = d1 .+ tmp
    # d1 = d1 ./ vol_sqrt

    # # d1

    # d2 = d1 .- vol_sqrt

    # # d2

    # # d1 = c05 .+ c05 .* exp.(d1 .* invsqrt2)
    # # d2 = c05 .+ c05 .* exp.(d2 .* invsqrt2)
    # d1 = d1 * invsqrt2
    # d1 = exp.(d1)
    # d1 = d1 .* c05
    # d1 = d1 .+ c05
    # d2 = d2 .* invsqrt2
    # d2 = exp.(d2)
    # d2 = d2 .* c05
    # d2 = d2 .+ c05

    # # e_rt = exp.((-rate) .* t)
    # e_rt = -rate
    # e_rt = e_rt .* t
    # e_rt = exp.(e_rt)

    # # call = price .* d1 - e_rt .* strike .* d2
    # call = price .* d1
    # tmp = e_rt .* strike
    # tmp = tmp .* d2
    # call = call .- tmp

    # put = e_rt .* strike .* (c10 .- d2) - price .* (c10 .- d1)

    # evaluate(call)
end

#@testset "Black Scholes" begin
#    run_with_job("Black Scholes", j -> begin
#        size = Integer(1e9)
#        run_bs(size)
#        # evaluate(put)
#    end)
#end

max_stars_repo_name: banyan-team/banyan-julia

max_issues_repo_name: banyan-team/banyan-julia

max_forks_repo_name: banyan-team/banyan-julia


text:
# Note that this script can accept some limited command-line arguments, run
# `julia build_tarballs.jl --help` to see a usage message.
using BinaryBuilder, Pkg

name = "Aria2"
version = v"1.36.0"

# Collection of sources required to complete build
sources = [
    ArchiveSource("https://github.com/aria2/aria2/releases/download/release-$(version)/aria2-$(version).tar.xz",
                  "58d1e7608c12404f0229a3d9a4953d0d00c18040504498b483305bcb3de907a5"),
]

# Bash recipe for building across all platforms
script = raw"""
cd $WORKSPACE/srcdir/aria2-*/

export CPPFLAGS="-I${includedir}"
export LDFLAGS="-L${libdir}"

./configure \
    --prefix=${prefix} --build=${MACHTYPE} --host=${target} \
    --with-pic --enable-shared --enable-libaria2 \
    --with-openssl --with-libxml2 --with-libz --with-libssh2

make -j${nproc}
make install

install_license COPYING
install_license LICENSE.OpenSSL
"""

# These are the platforms we will build for by default, unless further
# platforms are passed in on the command line
platforms = supported_platforms(; experimental=true)
platforms = expand_cxxstring_abis(platforms)

# The products that we will ensure are always built
products = [
    ExecutableProduct("aria2c", :aria2c),
    LibraryProduct("libaria2", :libaria2)
]

# Dependencies that must be installed before this package can be built
dependencies = [
    Dependency(PackageSpec(name="Cares_jll")),
    Dependency(PackageSpec(name="LibSSH2_jll")),
    # `MbedTLS_jll` is a dependency of `LibSSH2_jll`.  Strangely, we
    # are getting a newer version in the build than the one
    # `LibSSH2_jll` was compiled with.  So we explicitly select the
    # right version here.
    BuildDependency(PackageSpec(name="MbedTLS_jll", version="2.24")),
    Dependency(PackageSpec(name="OpenSSL_jll")),
    Dependency(PackageSpec(name="XML2_jll")),
    Dependency(PackageSpec(name="Zlib_jll")),
]

# Build the tarballs, and possibly a `build.jl` as well.
build_tarballs(ARGS, name, version, sources, script, platforms, products, dependencies;
               julia_compat="1.6", preferred_gcc_version = v"7")

max_stars_repo_name: sharanry/Yggdrasil

max_issues_repo_name: sharanry/Yggdrasil

max_forks_repo_name: sharanry/Yggdrasil


text:
# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.

using UnitCommitment, Test, LinearAlgebra

@testset "_susceptance_matrix" begin
    instance = UnitCommitment.read_benchmark("test/case14")
    actual = UnitCommitment._susceptance_matrix(instance.lines)
    @test size(actual) == (20, 20)
    expected = Diagonal([
        29.5,
        7.83,
        8.82,
        9.9,
        10.04,
        10.2,
        41.45,
        8.35,
        3.14,
        6.93,
        8.77,
        6.82,
        13.4,
        9.91,
        15.87,
        20.65,
        6.46,
        9.09,
        8.73,
        5.02,
    ])
    @test round.(actual, digits = 2) == expected
end

@testset "_reduced_incidence_matrix" begin
    instance = UnitCommitment.read_benchmark("test/case14")
    actual = UnitCommitment._reduced_incidence_matrix(
        lines = instance.lines,
        buses = instance.buses,
    )
    @test size(actual) == (20, 13)
    @test actual[1, 1] == -1.0
    @test actual[3, 1] == 1.0
    @test actual[4, 1] == 1.0
    @test actual[5, 1] == 1.0
    @test actual[3, 2] == -1.0
    @test actual[6, 2] == 1.0
    @test actual[4, 3] == -1.0
    @test actual[6, 3] == -1.0
    @test actual[7, 3] == 1.0
    @test actual[8, 3] == 1.0
    @test actual[9, 3] == 1.0
    @test actual[2, 4] == -1.0
    @test actual[5, 4] == -1.0
    @test actual[7, 4] == -1.0
    @test actual[10, 4] == 1.0
    @test actual[10, 5] == -1.0
    @test actual[11, 5] == 1.0
    @test actual[12, 5] == 1.0
    @test actual[13, 5] == 1.0
    @test actual[8, 6] == -1.0
    @test actual[14, 6] == 1.0
    @test actual[15, 6] == 1.0
    @test actual[14, 7] == -1.0
    @test actual[9, 8] == -1.0
    @test actual[15, 8] == -1.0
    @test actual[16, 8] == 1.0
    @test actual[17, 8] == 1.0
    @test actual[16, 9] == -1.0
    @test actual[18, 9] == 1.0
    @test actual[11, 10] == -1.0
    @test actual[18, 10] == -1.0
    @test actual[12, 11] == -1.0
    @test actual[19, 11] == 1.0
    @test actual[13, 12] == -1.0
    @test actual[19, 12] == -1.0
    @test actual[20, 12] == 1.0
    @test actual[17, 13] == -1.0
    @test actual[20, 13] == -1.0
end

@testset "_injection_shift_factors" begin
    instance = UnitCommitment.read_benchmark("test/case14")
    actual = UnitCommitment._injection_shift_factors(
        lines = instance.lines,
        buses = instance.buses,
    )
    @test size(actual) == (20, 13)
    @test round.(actual, digits = 2) == [
        -0.84 -0.75 -0.67 -0.61 -0.63 -0.66 -0.66 -0.65 -0.65 -0.64 -0.63 -0.63 -0.64
        -0.16 -0.25 -0.33 -0.39 -0.37 -0.34 -0.34 -0.35 -0.35 -0.36 -0.37 -0.37 -0.36
        0.03 -0.53 -0.15 -0.1 -0.12 -0.14 -0.14 -0.14 -0.13 -0.13 -0.12 -0.12 -0.13
        0.06 -0.14 -0.32 -0.22 -0.25 -0.3 -0.3 -0.29 -0.28 -0.27 -0.25 -0.26 -0.27
        0.08 -0.07 -0.2 -0.29 -0.26 -0.22 -0.22 -0.22 -0.23 -0.25 -0.26 -0.26 -0.24
        0.03 0.47 -0.15 -0.1 -0.12 -0.14 -0.14 -0.14 -0.13 -0.13 -0.12 -0.12 -0.13
        0.08 0.31 0.5 -0.3 -0.03 0.36 0.36 0.28 0.23 0.1 -0.0 0.02 0.17
        0.0 0.01 0.02 -0.01 -0.22 -0.63 -0.63 -0.45 -0.41 -0.32 -0.24 -0.25 -0.36
        0.0 0.01 0.01 -0.01 -0.12 -0.17 -0.17 -0.26 -0.24 -0.18 -0.14 -0.14 -0.21
        -0.0 -0.02 -0.03 0.02 -0.66 -0.2 -0.2 -0.29 -0.36 -0.5 -0.63 -0.61 -0.43
        -0.0 -0.01 -0.02 0.01 0.21 -0.12 -0.12 -0.17 -0.28 -0.53 0.18 0.15 -0.03
        -0.0 -0.0 -0.0 0.0 0.03 -0.02 -0.02 -0.03 -0.02 0.01 -0.52 -0.17 -0.09
        -0.0 -0.01 -0.01 0.01 0.11 -0.06 -0.06 -0.09 -0.05 0.02 -0.28 -0.59 -0.31
        -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -1.0 -0.0 -0.0 -0.0 -0.0 -0.0 0.0
        0.0 0.01 0.02 -0.01 -0.22 0.37 0.37 -0.45 -0.41 -0.32 -0.24 -0.25 -0.36
        0.0 0.01 0.02 -0.01 -0.21 0.12 0.12 0.17 -0.72 -0.47 -0.18 -0.15 0.03
        0.0 0.01 0.01 -0.01 -0.14 0.08 0.08 0.12 0.07 -0.03 -0.2 -0.24 -0.6
        0.0 0.01 0.02 -0.01 -0.21 0.12 0.12 0.17 0.28 -0.47 -0.18 -0.15 0.03
        -0.0 -0.0 -0.0 0.0 0.03 -0.02 -0.02 -0.03 -0.02 0.01 0.48 -0.17 -0.09
        -0.0 -0.01 -0.01 0.01 0.14 -0.08 -0.08 -0.12 -0.07 0.03 0.2 0.24 -0.4
    ]
end

@testset "_line_outage_factors" begin
    instance = UnitCommitment.read_benchmark("test/case14")
    isf_before = UnitCommitment._injection_shift_factors(
        lines = instance.lines,
        buses = instance.buses,
    )
    lodf = UnitCommitment._line_outage_factors(
        lines = instance.lines,
        buses = instance.buses,
        isf = isf_before,
    )
    for contingency in instance.contingencies
        for lc in contingency.lines
            prev_susceptance = lc.susceptance
            lc.susceptance = 0.0
            isf_after = UnitCommitment._injection_shift_factors(
                lines = instance.lines,
                buses = instance.buses,
            )
            lc.susceptance = prev_susceptance
            for lm in instance.lines
                expected = isf_after[lm.offset, :]
                actual =
                    isf_before[lm.offset, :] +
                    lodf[lm.offset, lc.offset] * isf_before[lc.offset, :]
                @test norm(expected - actual) < 1e-6
            end
        end
    end
end


text:
cd("/Users/adrienpajon/Documents/all.nosync/git_repo/pulse_analysis/2020-11-12 xp pulse all seuil/Julia_analysis")

using CSV
using DataFrames
using JLD

# include("functions/prony.jl")
include("functions/pronyAlgo.jl")
include("functions/deleterows.jl")

#using Pyplot
pyplot()

##
Ts_MTiXsens=0.01
Ts_IBS = 0.02
Ts_Xsensor=1/55.2; #correctif dans la pratique on est plus vers 55.2Hz
convertlbpo2Nm = 0.11298482933333

## MTiXsens
#filenameMTiXsens : namefile of each experiment
#filenameMTiXsensID : name ID of each sensor with keys that refers to the position on the body
#sensorXsensNames : keys of each sensor equivalent to their position on the body
# include("imports/Import_filename_MTiXsens.jl")
filenameMTiXsens=load("imports/import_filename_MTiXsens_gel.jld")["filenameMTiXsens"]
sensorXsensNames=load("imports/import_filename_MTiXsens_gel.jld")["sensorXsensNames"]
filenameMTiXsensID=load("imports/import_filename_MTiXsens_gel.jld")["filenameMTiXsensID"]

## Xsensor
#filenameXsensor : namefile of each experiment
# include("imports/Import_filename_Xsensor.jl")
filenameXsensor=load("imports/Import_filename_Xsensor_gel.jld")["filenameXsensor"]

## Instrumented_backseat
#filenameIBS : namefile of each experiment
# include("imports/Import_filename_IBS.jl")
filenameIBS=load("imports/Import_filename_IBS_gel.jld")["filenameIBS"]

println("FileName import finished")

## ##################################################################
#script to read CSV and store in
# MTiXsens
# Xsensor
# IBS
encoderFolderPath="../measures/gel/encoder_file/"
IBSFolderPath="../measures/gel/IBS/"
XsensorFolderPath="../measures/gel/Xsensor/"
MTiXsensFolderPath="../measures/gel/MTiXsens/"
include("scripts/script_read_CSV.jl")

## ##################################################################
#script to extract data from MTiXsens and Xsensor in
# AccFree_MTiXsens
# Xsensor_reduce
include("scripts/script_data_extract.jl")

Treduce=12
Vreduce=Int(Treduce/Ts_IBS)
include("scripts/script_reduce_IBS.jl")

badFileMTiXsens=[43]
filenameMTiXsens=deleterows(filenameMTiXsens,badFileMTiXsens)
# filenameXsensor=deleterows(filenameMTiXsens,badFile)
badFileIBS=[41 63 67]
filenameIBS=deleterows(filenameIBS,badFileIBS)

sync=Dict()

sync[1]=(MTiXsens=0,Xsensor=0,Instrumented_backseat=0)
sync[2]=(MTiXsens=0,Xsensor=0,Instrumented_backseat=0)
#MTiXsens est en Packet counter

## ######
index_test_MTiXsens_1cm=searchAllSynchroMTiXsens(AccFree_MTiXsens,filenameMTiXsens[1:30,:],20,20,2,2,10,100)
index_test_MTiXsens_2cm=searchAllSynchroMTiXsens(AccFree_MTiXsens,filenameMTiXsens[31:60,:],20,50)
index_test_MTiXsens_3cm=searchAllSynchroMTiXsens(AccFree_MTiXsens,filenameMTiXsens[61:90,:],20,30)
index_test_MTiXsens_4cm=searchAllSynchroMTiXsens(AccFree_MTiXsens,filenameMTiXsens[91:end,:],20,30)
# index_test_MTiXsens_dda=searchAllSynchroMTiXsens(AccFree_MTiXsens,filenameMTiXsens[121:end,:],20,30)

index_test_MTiXsens=[index_test_MTiXsens_1cm;
                    index_test_MTiXsens_2cm;
                    index_test_MTiXsens_3cm;
                    index_test_MTiXsens_4cm]#
                    # index_test_MTiXsens_dda]

println(index_test_MTiXsens)
## ####
# index_test_Xsensor=[]
if size(Xsensor_reduce[filenameXsensor[1,1]],2)>6
    m=10
else
    m=4
end
index_test_Xsensor_1cm=searchAllSynchro(Xsensor_reduce,m,filenameXsensor[1:30,:],20,5*10^3)
index_test_Xsensor_2cm=searchAllSynchro(Xsensor_reduce,m,filenameXsensor[31:60,:],20,1*10^4)
index_test_Xsensor_3cm=searchAllSynchro(Xsensor_reduce,m,filenameXsensor[61:90,:],20,1*10^4)
index_test_Xsensor_4cm=searchAllSynchro(Xsensor_reduce,m,filenameXsensor[91:end,:],20,1*10^4)
# index_test_Xsensor=searchAllSynchro(Xsensor_reduce,m,filenameXsensor,20,1*10^4)

index_test_Xsensor=[index_test_Xsensor_1cm;
                    index_test_Xsensor_2cm;
                    index_test_Xsensor_3cm;
                    index_test_Xsensor_4cm]#
                    # index_test_MTiXsens_dda]
println(index_test_Xsensor)

## ####
index_test_IBS_01=searchAllSynchro(IBS,2,filenameIBS[1:49,:],20,2*10^5)
index_test_IBS_02=searchAllSynchro(IBS,2,filenameIBS[50:end,:],20,1*10^6)
index_test_IBS=[index_test_IBS_01;
                    index_test_IBS_02]

index_test_IBS_03=searchAllSynchro(IBS,2,filenameIBS[74,:],20,2*10^6)
index_test_IBS[74]=index_test_IBS_03[1]

index_test_IBS_04=searchAllSynchro(IBS,2,filenameIBS[39,:],20,1.5*10^6)
index_test_IBS[39]=index_test_IBS_04[1]

index_test_IBS.+=(Vreduce-1)

println(index_test_IBS)

## #
# sync = Dict{String, Int64}()
sync=Dict()
sync_=Dict()
# for k=1:length(index_test_MTiXsens)
#     sync[k]=(MTiXsens=index_test_MTiXsens[k]-100,
#                 Xsensor=index_test_Xsensor[k]-55,
#                 IBS=index_test_IBS[k]-50)
#     sync_[k]=(MTiXsens=index_test_MTiXsens[k]-100,Xsensor=1,IBS=1)
# end

sync=(MTiXsens=index_test_MTiXsens.-100,
                Xsensor=index_test_Xsensor.-55,
                IBS=index_test_IBS.-50)
sync_=(MTiXsens=index_test_MTiXsens.-100,Xsensor=index_test_Xsensor.*0 .+1,IBS=index_test_IBS.*0 .+1)

step_max_perturb=400

save("imports/import_synchro_gel.jld", "sync", sync)
save("imports/Import_synchro_perturb_gel.jld", "sync_", sync_,
                                            "step_max_perturb",step_max_perturb)