text:
# ---
# title: 1678. Goal Parser Interpretation
# id: problem1678
# author: Tian Jun
# date: 2020-10-31
# difficulty: Easy
# categories: String
# link: <https://leetcode.com/problems/goal-parser-interpretation/description/>
# hidden: true
# ---
#
# You own a **Goal Parser** that can interpret a string `command`. The `command`
# consists of an alphabet of `"G"`, `"()"` and/or `"(al)"` in some order. The
# Goal Parser will interpret `"G"` as the string `"G"`, `"()"` as the string
# `"o"`, and `"(al)"` as the string `"al"`. The interpreted strings are then
# concatenated in the original order.
#
# Given the string `command`, return _the **Goal Parser** 's interpretation of
# _`command`.
#
#
#
# **Example 1:**
#
#
#
#     Input: command = "G()(al)"
#     Output: "Goal"
#     Explanation:  The Goal Parser interprets the command as follows:
#     G -> G
#     () -> o
#     (al) -> al
#     The final concatenated result is "Goal".
#
#
# **Example 2:**
#
#
#
#     Input: command = "G()()()()(al)"
#     Output: "Gooooal"
#
#
# **Example 3:**
#
#
#
#     Input: command = "(al)G(al)()()G"
#     Output: "alGalooG"
#
#
#
#
# **Constraints:**
#
#   * `1 <= command.length <= 100`
#   * `command` consists of `"G"`, `"()"`, and/or `"(al)"` in some order.
#
#
## @lc code=start
using LeetCode

## add your code here:
## @lc code=end


text:
"""
Make a lattice with cubic structure.

# Arguments

 - **box** (Array) 3D Box to be filled with spheres of radius r. e.g. [[0,1],[1,2],[0,4]]
 - **r** (Number) Radius of the sphere

# Optional keyword arguments
 - **noiseRatio** (Number) Noise ratio to add to the center of the cells. Default 0.
 - **holesRatio** (Number) Probability of holes in lattice. Default 0.

# Returns
[posX,posY,posZ] Where pos are arrays with the positions of the cells for each component.
"""
function latticeCubic(box::Array{Array{Float64,1},1},r::Number;noiseRatio::Number=0.,holesRatio::Number=0)

    d = length(box)
    if !(d in [1,2,3])
        error("Incompatible number of dimensions ", d)
    end

    #Make first dimension
    lineX = Array(box[1][1]:2*r:box[1][2])

    #Make second dimension
    if d > 1
        lineY = fill(box[2][1]+r,length(lineX))
        nY = ceil(Int,(box[2][2]-box[2][1])/(2*r))
        areaX = Float64[]
        areaY = Float64[]
        dx = 2*r
        dy = 2*r
        for i in 0:nY-1
            append!(areaX,lineX)
            append!(areaY,lineY.+dy*i)
        end
    end

    #Make third dimension
    if d == 3
        areaZ = fill(box[2][1]+r,length(areaX))
        nZ = ceil(Int,(box[3][2]-box[3][1])/(2*r))
        volumeX = Float64[]
        volumeY = Float64[]
        volumeZ = Float64[]
        dy = 2*r
        dz = 2*r
        for i in 0:nZ-1
            append!(volumeX,areaX)
            append!(volumeY,areaY)
            append!(volumeZ,areaZ.+dz*i)
        end
    end

    #Add noise
    if noiseRatio > 0
        dist = Normal(0,r*noiseRatio)
        if d == 1
            n = length(lineX)
            lineX += rand(dist,n);
        elseif d == 2
            n = length(areaX)
            areaX += rand(dist,n);
            areaY += rand(dist,n);
        else
            n = length(volumeX)
            volumeX += rand(dist,n)
            volumeY += rand(dist,n);
            volumeZ += rand(dist,n)
        end
    end

    #Add holes
    if holesRatio > 0
        if d == 1
            l = rand(length(lineX))
            l = l .> holesRatio

            lineX = lineX[l]
        elseif d == 2
            l = rand(length(areaX))
            l = l .> holesRatio

            areaX = areaX[l]
            areaY = areaY[l]
        else
            l = rand(length(volumeX))
            l = l .> holesRatio

            volumeX = volumeX[l]
            volumeY = volumeY[l]
            volumeZ = volumeZ[l]
        end
    end

    #Return
    if d == 1
        return lineX
    elseif d == 2
        return areaX, areaY
    else
        return volumeX, volumeY, volumeZ
    end

end

ext: jl

max_stars_repo_name: gatocor/embryogenesisJulia

max_issues_repo_name: gatocor/embryogenesisJulia

max_forks_repo_name: gatocor/embryogenesisJulia


text:
module MJPlayGround

# package code goes here

using JuMP
a=2;
a
b
end # module


text:
# # 2D linear diffusion Julia MPI solver
using Plots, Printf, MAT
import MPI

# enable plotting by default
if !@isdefined do_save; do_save = true end

# MPI functions
@views function update_halo(A, neighbors_x, neighbors_y, comm)
    # Send to / receive from neighbor 1 in dimension x ("left neighbor")
    if neighbors_x[1] != MPI.MPI_PROC_NULL
        sendbuf = A[2,:]
        recvbuf = zeros(size(A[1,:]))
        MPI.Send(sendbuf,  neighbors_x[1], 0, comm)
        MPI.Recv!(recvbuf, neighbors_x[1], 1, comm)
        A[1,:] = recvbuf
    end
    # Send to / receive from neighbor 2 in dimension x("right neighbor")
    if neighbors_x[2] != MPI.MPI_PROC_NULL
        sendbuf = A[end-1,:]
        recvbuf = zeros(size(A[end,:]))
        MPI.Send(sendbuf,  neighbors_x[2], 1, comm)
        MPI.Recv!(recvbuf, neighbors_x[2], 0, comm)
        A[end,:] = recvbuf
    end
    # Send to / receive from neighbor 1 in dimension y ("bottom neighbor")
    if neighbors_y[1] != MPI.MPI_PROC_NULL
        sendbuf = A[:,2]
        recvbuf = zeros(size(A[:,1]))
        MPI.Send(sendbuf,  neighbors_y[1], 2, comm)
        MPI.Recv!(recvbuf, neighbors_y[1], 3, comm)
        A[:,1] = recvbuf
    end
    # Send to / receive from neighbor 2 in dimension y ("top neighbor")
    if neighbors_y[2] != MPI.MPI_PROC_NULL
        sendbuf = A[:,end-1]
        recvbuf = zeros(size(A[:,end]))
        MPI.Send(sendbuf,  neighbors_y[2], 3, comm)
        MPI.Recv!(recvbuf, neighbors_y[2], 2, comm)
        A[:,end] = recvbuf
    end
    return
end

@views function diffusion_2D_mpi(; do_save=false)
    # MPI
    MPI.Init()
    dims        = [0,0]
    comm        = MPI.COMM_WORLD
    nprocs      = MPI.Comm_size(comm)
    MPI.Dims_create!(nprocs, dims)
    comm_cart   = MPI.Cart_create(comm, dims, [0,0], 1)
    me          = MPI.Comm_rank(comm_cart)
    coords      = MPI.Cart_coords(comm_cart)
    neighbors_x = MPI.Cart_shift(comm_cart, 0, 1)
    neighbors_y = MPI.Cart_shift(comm_cart, 1, 1)
    if (me==0) println("nprocs=$(nprocs), dims[1]=$(dims[1]), dims[2]=$(dims[2])") end
    # Physics
    lx, ly     = 10.0, 10.0
    λ          = 1.0
    nt         = 100
    # Numerics
    nx, ny     = 32, 32                             # local number of grid points
    nx_g, ny_g = dims[1]*(nx-2)+2, dims[2]*(ny-2)+2 # global number of grid points
    # Derived numerics
    dx, dy     = lx/nx_g, ly/ny_g                   # global
    dt         = min(dx,dy)^2/λ/4.1
    # Array allocation
    qHx        = zeros(nx-1,ny-2)
    qHy        = zeros(nx-2,ny-1)
    # Initial condition
    x0, y0     = coords[1]*(nx-2)*dx, coords[2]*(ny-2)*dy
    xc         = [x0 + ix*dx - dx/2 - 0.5*lx  for ix=1:nx]
    yc         = [y0 + iy*dy - dy/2 - 0.5*ly  for iy=1:ny]
    H          = exp.(.-xc.^2 .-yc'.^2)
    t_tic = 0.0
    # Time loop
    for it = 1:nt
        if (it==11) t_tic = Base.time() end
        qHx .= .-λ*diff(H[:,2:end-1], dims=1)/dx
        qHy .= .-λ*diff(H[2:end-1,:], dims=2)/dy
        H[2:end-1,2:end-1] .= H[2:end-1,2:end-1] .- dt*(diff(qHx, dims=1)/dx .+ diff(qHy, dims=2)/dy)
        update_halo(H, neighbors_x, neighbors_y, comm_cart)
    end
    t_toc = (Base.time()-t_tic)
    if (me==0) @printf("Time = %1.4e s, T_eff = %1.2f GB/s \n", t_toc, round((2/1e9*nx*ny*sizeof(lx))/(t_toc/(nt-10)), sigdigits=2)) end
    # Save to visualise
    if do_save file = matopen("$(@__DIR__)/H_$(me).mat", "w"); write(file, "H", Array(H)); close(file) end
    MPI.Finalize()
    return
end

diffusion_2D_mpi(; do_save=do_save)

max_stars_repo_name: omlins/julia-gpu-course

max_issues_repo_name: omlins/julia-gpu-course

max_forks_repo_name: omlins/julia-gpu-course


text:
using GAP_pkg_factint
using Test

import GAP_pkg_factint
println("TODO")


text:
struct RecurrentRVPTestResult
    test::RecurrentRVPTest
    reward_pred::Float32
    value_pred::Float32
    policy_pred::Vector{Float32}
end

struct RecurrentRVPTestResultSVG
    result::RecurrentRVPTestResult
end

svg(x::RecurrentRVPTestResult) = RecurrentRVPTestResultSVG(x)
policypredsvg(state::AbstractState, ::RecurrentRVPTestResult) = @assert false OVERRIDE_MSG

function getdf(T::Type{RecurrentRVPTestResult}, results, limit=100)
    test_num = "Test #"

    rewpred_col = "RcRewardPred"
    rewtest_col = "RcRewardTest"

    valpred_col = "RcValuePred"
    valtest_col = "RcValueTest"

    actpred_col = "RcPolicyPred"
    acttest_col = "RcPolicyTest"
    test_pf = "RecPolicy P/F"

    d = Dict(
        test_num=>[],
        test_pf=>[],

        rewpred_col=>[],
        rewtest_col=>[],

        valpred_col=>[],
        valtest_col=>[],

        actpred_col=>[],
        acttest_col=>[],
    )
    for result in results
        key = result.test.key
        optimal = map(x->x.idx, result.test.actions)
        pred = result.policy_pred
        _, greedy_action = findmax(pred)
        pass = in(greedy_action, optimal)
        from = 1
        to = min(limit, length(pred))
        actions = reverse(sortperm(pred))[from:to]
        prs = pred[actions]
        action_prs = map(x->begin
            action, pr = x
            pr_s = @sprintf "%.2f" pr
            "$action ($(pr_s[2:end]))"
        end, zip(actions, prs))
        max_pred_idx = min(length(actions), 5)
        result_policy = join(actions[1:max_pred_idx], ",")

        push!(d[test_num], key)
        push!(d[test_pf], pass ? "Pass" : "Fail")

        push!(d[rewpred_col], result.reward_pred)
        push!(d[rewtest_col], result.test.reward)

        push!(d[valpred_col], result.value_pred)
        push!(d[valtest_col], result.test.value)

        push!(d[actpred_col], result_policy)
        push!(
            d[acttest_col],
            length(optimal) == 1 ? optimal[1] : "{$(join(optimal, ","))}"
        )
    end
    DataFrame(
        test_num=>d[test_num],
        rewpred_col=>d[rewpred_col],
        rewtest_col=>d[rewtest_col],
        valpred_col=>d[valpred_col],
        valtest_col=>d[valtest_col],
        actpred_col=>d[actpred_col],
        acttest_col=>d[acttest_col],
        test_pf=>d[test_pf],
    )
end

function Base.show(io::IO, m::MIME"text/plain", x::RecurrentRVPTestResult)
    println()
    pretty_results(
        io,
        getdf(RecurrentRVPTestResult, [x]);
        title="Recurrent RVP Test Result #$(x.test.idx)"
    )
end

function Base.show(io::IO, m::MIME"image/svg+xml", x::RecurrentRVPTestResultSVG)
    test = x.result.test
    pred = x.result.policy_pred
    s = test.state
    player_name = s.to_play.name
    actions = test.actions
    state_grid = getgrid(s; header="to play: $player_name", margin_left=0)
    next_states = Rect[]
    from = 1
    len = length(actions)
    to = min(len, 3)
    for (idx,a) in enumerate(actions[from:to])
        push!(
            next_states,
            getgrid(s, a, 0f0, getnextstate(s, a); header="action: $a", margin_left=0)
        )
    end
    if length(actions) > 3
        push!(next_states, Grid(1,1, (r,c)->"..."; line_thickness=0))
    end
    input_grid = Grid(
        [state_grid],
        :,
        1,
        header="INPUT",
        margin_left=0,
        line_thickness=0
    )
    policy_grid_header = "ACTUAL π*"
    policy_grid = Grid(
        next_states,
        :,
        1,
        header=(text=policy_grid_header, height=40),
        margin_left=0,
        line_thickness=0,
    )
    pred_states = Rect[]
    limit = 3
    from = 1
    to = min(limit, length(pred))
    pred_actions = reverse(sortperm(pred))[from:to]
    prs = pred[pred_actions]
    for (a,pr) in zip(pred_actions, prs)
        pr_str = @sprintf "%.2f" pr
        push!(
            pred_states,
            getgrid(
                s,
                a,
                0f0,
                getnextstate(s, a);
                margin_left=0,
                header="action: $a",
                subheader=(text=pr_str, color="#666"),
            )
        )
    end
    pred_grid = Grid(
        pred_states,
        :,
        1;
        header="PRED π*",
        margin_left=0,
        line_thickness=0,
    )
    g = Grid([input_grid,pred_grid,policy_grid]; cell_valign=:top, header="RECURRENT RVP TEST RESULT #$(test.key)", line_thickness=0)
    show(io, m, g)
end


text:
using NESSie.TestModel
using NESSie.TestModel: scalemodel, legendre, spherical_besseli, spherical_besselk

@testset "XieModel" begin
    for T in testtypes
        charges = [
            Charge(T[0, 0, 0, 1]...),
            Charge(T[1, 0, 0, 2]...),
            Charge(T[1, 1, 0, 3]...),
            Charge(T[0, 1, 0, 4]...)
        ]

        model = XieModel(2one(T), charges)
        @test typeof(model) == XieModel{T}
        @test model.radius == 2one(T)
        for (q1, q2) in zip(model.charges, scalemodel(charges, model.radius))
            @test q1.pos == q2.pos
            @test q1.val == q2.val
        end
        @test model.params == defaultopt(T)
    end
end

@testset "scalemodel" begin
    for T in testtypes
        charges = [
            Charge(T[0, 0, 0, 1]...),
            Charge(T[1, 0, 0, 2]...),
            Charge(T[1, 1, 0, 3]...),
            Charge(T[0, 1, 0, 4]...)
        ]

        # translation only
        scaled = scalemodel(charges, T(√(.5)/.8))
        @test typeof(scaled) == Vector{Charge{T}}
        @test scaled[1].pos ≈ T[-.5, -.5, 0]
        @test scaled[1].val == one(T)
        @test scaled[2].pos ≈ T[.5, -.5, 0]
        @test scaled[2].val == 2one(T)
        @test scaled[3].pos ≈ T[.5, .5, 0]
        @test scaled[3].val == 3one(T)
        @test scaled[4].pos ≈ T[-.5, .5, 0]
        @test scaled[4].val == 4one(T)

        # translation and scaling
        scaled = scalemodel(charges, T(1.25))
        @test typeof(scaled) == Vector{Charge{T}}
        @test scaled[1].pos ≈ T[-√.5, -√.5, 0]
        @test scaled[1].val == one(T)
        @test scaled[2].pos ≈ T[√.5, -√.5, 0]
        @test scaled[2].val == 2one(T)
        @test scaled[3].pos ≈ T[√.5, √.5, 0]
        @test scaled[3].val == 3one(T)
        @test scaled[4].pos ≈ T[-√.5, √.5, 0]
        @test scaled[4].val == 4one(T)
    end
end

@testset "legendre" begin
    for T in testtypes
        # 0-length
        p = legendre(0, one(T))
        @test isa(p, Function)
        @test_throws BoundsError p(-1)
        @test_throws BoundsError p(0)
        @test_throws BoundsError p(1)

        # one element
        p = legendre(1, one(T))
        @test isa(p, Function)
        @test typeof(p(0)) == T
        @test p(0) == one(T)
        @test_throws BoundsError p(-1)
        @test_throws BoundsError p(1)

        # more elements
        p = legendre(5, one(T)/2)
        @test isa(p, Function)
        @test typeof(p(0)) == T
        @test p(0) == one(T)
        @test typeof(p(1)) == T
        @test p(1) == one(T)/2
        @test typeof(p(2)) == T
        @test p(2) ≈ T(-0.125)
        @test typeof(p(3)) == T
        @test p(3) ≈ T(-0.4375)
        @test typeof(p(4)) == T
        @test p(4) ≈ T(-0.2890625)
        @test_throws BoundsError p(-1)
        @test_throws BoundsError p(5)
    end
end

@testset "spherical_besseli" begin
    for T in testtypes
        # 0-length
        i = spherical_besseli(-2, one(T))
        @test isa(i, Function)
        @test_throws BoundsError i(-2)
        @test_throws BoundsError i(-1)
        @test_throws BoundsError i(0)

        # some elements
        i = spherical_besseli(0, one(T)/2)
        @test isa(i, Function)
        @test typeof(i(-1)) == T
        @test i(-1) ≈ T(√π * 1.2723896474148502)
        @test typeof(i(0)) == T
        @test i(0) ≈ T(√π * 0.5879930867904171)
        @test_throws BoundsError i(-2)
        @test_throws BoundsError i(1)
    end
end

@testset "spherical_besselk" begin
    for T in testtypes
        # 0-length
        k = spherical_besselk(-2, one(T))
        @test isa(k, Function)
        @test_throws BoundsError k(-2)
        @test_throws BoundsError k(-1)
        @test_throws BoundsError k(0)

        # some elements
        k = spherical_besselk(0, one(T)/2)
        @test isa(k, Function)
        @test typeof(k(-1)) == T
        @test k(-1) ≈ T(√π * 1.0750476034999203)
        @test typeof(k(0)) == T
        @test k(0) ≈ T(√π * 1.0750476034999203)
        @test_throws BoundsError k(-2)
        @test_throws BoundsError k(1)
    end
end

@test_skip NonlocalXieModel1
@test_skip coefficients
@test_skip φΣ
@test_skip φΩ


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

using JuliaFEM
using JuliaFEM.Preprocess
using JuliaFEM.Postprocess
using JuliaFEM.Testing

#= TODO: Fix test.
@testset "test forwarddiff version + volume load." begin
    nodes = Dict{Int64, Node}(
        1 => [0.0, 0.0],
        2 => [10.0, 0.0],
        3 => [10.0, 1.0],
        4 => [0.0, 1.0])
    # constant volume load on nodes
    load = Dict(
        1 => [0.0, -10.0],
        2 => [0.0, -10.0],
        3 => [0.0, -10.0],
        4 => [0.0, -10.0])
    young = Dict(1 => 500.0, 2 => 500.0, 3 => 500.0, 4 => 500.0)
    poisson = Dict(1 => 0.3, 2 => 0.3, 3 => 0.3, 4 => 0.3)
    element = Quad4([1, 2, 3, 4])
    update!(element, "geometry", nodes)
    update!(element, "youngs modulus", young)
    update!(element, "poissons ratio", poisson)
    update!(element, "displacement load", load)
    boundary = Seg2([1, 4])
    update!(boundary, "geometry", nodes)
    update!(boundary, "displacement 1", 0.0)
    update!(boundary, "displacement 2", 0.0)

    body = Problem(Elasticity, "beam", 2)
    body.properties.formulation = :plane_stress
    body.properties.use_forwarddiff = true
    push!(body, element)
    bc = Problem(Dirichlet, "fixed left side", 2, "displacement")
    #bc.properties.formulation = :incremental
    push!(bc, boundary)

    solver = Solver()
    push!(solver, body, bc)
    solver()
    disp = element("displacement", [1.0, 1.0], 0.0)
    info("displacement at tip: $disp")
    # verified using Code Aster, verification/2015-10-22-plane-stress/cplan_grot_gdep_volume_force.resu
    @test isapprox(disp[2], -8.77303119819776)
end
=#

#= TODO: Fix test
@testset "test that stiffness matrix is same" begin
    nodes = Dict{Int64, Node}(
        1 => [0.0, 0.0],
        2 => [10.0, 0.0],
        3 => [10.0, 1.0],
        4 => [0.0, 1.0])
    displacement = Dict(
        1 => [0.1, 0.2],
        2 => [0.3, 0.4],
        3 => [0.5, 0.6],
        4 => [0.7, 0.8])
    displacement = Dict(
        1 => [0.0, 0.0],
        2 => [0.0, 0.0],
        3 => [0.0, 0.0],
        4 => [0.0, 0.0])
    load = Dict(
        1 => [0.0, -10.0],
        2 => [0.0, -10.0],
        3 => [0.0, -10.0],
        4 => [0.0, -10.0])
    element = Quad4([1, 2, 3, 4])
    update!(element, "geometry", nodes)
    update!(element, "displacement", displacement)
    update!(element, "youngs modulus", 288.0)
    update!(element, "poissons ratio", 1/3)
    update!(element, "displacement load", load)
    body = Problem(Elasticity, "beam", 2)
    body.properties.formulation = :plane_stress
    K1, f1 = assemble(body, element, 0.0, Val{:forwarddiff})
    K2, f2 = assemble(body, element, 0.0, Val{:plane})
    @test isapprox(K1, K2)
    @test isapprox(f1, f2)
end
=#


text:
using CSV
using CairoMakie
using Colors

color_lst = [colorant"#332288" colorant"#555555" colorant"#117733" colorant"#882255"]

f = CSV.File("DimensionTiming.csv")

timing = f.timing

f = CSV.File("DimensionTimingDynamic.csv")

timingDynamic = f.timing
dimensions = f.samples

noto_sans = "../resources/NotoSans-Regular.ttf"
noto_sans_bold = "../resources/NotoSans-Bold.ttf"

tickfontsize = 24
labelfontsize = 28

f = Figure(resolution = (1100,500), font=noto_sans)

ax = Axis(  f[1,1],
            xticklabelsize=tickfontsize,
            yticklabelsize=tickfontsize,
            yticklabelpad=2,
            xlabel="Ambient Dimension", ylabel = "Seconds",
            xlabelsize=labelfontsize,
            ylabelsize=labelfontsize,
#            yscale = log10,
#            xscale = log10,
            yminorticksvisible = true,
            yminorgridvisible = true,
            yminorticks = IntervalsBetween(10),
            xminorticksvisible = true,
            xminorgridvisible = true,
            xminorticks = IntervalsBetween(10),
            title="1D Limit Set",
            titlesize=labelfontsize)

l1 = lines!(ax, 2 .+ (1:length(timing)), timing, color = :black, linewidth=2)

ax2 = Axis(  f[1,2],
            xticklabelsize=tickfontsize,
            yticklabelsize=tickfontsize,
            yticklabelpad=2,
            xlabel="Sample Count", ylabel = "Seconds",
            xlabelsize=labelfontsize,
            ylabelsize=labelfontsize,
#            yscale = log10,
#            xscale = log10,
            yminorticksvisible = true,
            yminorgridvisible = true,
            yminorticks = IntervalsBetween(10),
            xminorticksvisible = true,
            xminorgridvisible = true,
            xminorticks = IntervalsBetween(10),
            title="Dynamic Programming",
           titlesize=labelfontsize)

l2 = lines!(ax2, dimensions, timingDynamic, color = :black, linewidth=2)

colgap!(f.layout,100)

Label(f[1,1,TopLeft()], "A", font=noto_sans_bold, textsize = 40, halign=:left, valign=:bottom, padding=(25,0,10,0))
Label(f[1,2,TopLeft()], "B", font=noto_sans_bold, textsize = 40, halign=:left, valign=:bottom, padding=(25,0,10,0))

save("TimingPlot.pdf",f)


text:
abstract type CalibrationErrorEstimator end

function check_size(predictions::AbstractMatrix{<:Real}, labels::AbstractVector{<:Integer})
    nclasses, nsamples = size(predictions)

    nsamples == length(labels) ||
        throw(DimensionMismatch("number of predictions and labels must be equal"))
    nclasses > 1 ||
        throw(ArgumentError("the number of classes has to be greater than 1"))

    nclasses, nsamples
end

function get_predictions_labels((predictions,labels)::Tuple{<:AbstractMatrix{<:Real},
                                                            <:AbstractVector{<:Integer}})
    # check size
    check_size(predictions, labels)

    predictions, labels
end

"""
    calibrationerror(estimator, data)

Estimate the calibration error of a model from the `data` set of predicted probabilities
and corresponding labels using the `estimator`.
"""
function calibrationerror(estimator::CalibrationErrorEstimator,
                          data::Tuple{<:AbstractMatrix{<:Real},<:AbstractVector{<:Integer}})
    # check whether the number of predictions and labels is equal
    predictions, labels = get_predictions_labels(data)

    # estimate the calibration error
    _calibrationerror(estimator, predictions, labels)
end


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

JLLWrappers.@generate_main_file_header("CVRPSEP")
JLLWrappers.@generate_main_file("CVRPSEP", UUID("708e8d2e-5bbf-55cc-b455-510884a304cf"))
end  # module CVRPSEP_jll


text:
## Page("SOme blurb",  (q1,q2,q3, ...);
#DBSubject="Calculus",
#KEYWORDS="limits",
#AuthorText="John  Verzani"
#AuthorText2="Joseph Maher"
#)
raw"""
    Page(intro, questions; context="",  meta...)

Create a page  which prints as a `pg`  file.

* `intro` may be marked  up using modified markdown
* `questions` is a tuple of questions or `QUESTIONS` object
* `context` optional value to create page context. Typical  usage: `context="Interval"`
* `answer_context`: Dictionary of context for all answers on the page, e.g
```
answer_context=Dict(:operators=>Dict(:undefine=>"'+','-','*','/','^'"),
                    :functions=>Dict(:disable=>"'All'"),
                    :constants=>Dict(:remove=>"\"e\"")
                   )
```
The context dictionary above, is aliased as `numbers_only`.

* `meta` for page meta data.

If `ENV["BRANDING"]` is set, it will be printed on each page generated.

Example:

```
using JuliaWeBWorK
meta=(AuthorText="Julia", Institution="JuliaAcademy", Question="1")
intro  = raw"# Problem 1"
q1 = numericq("What is  ``{{:a1}} + {{:a2}}``?",  (x,y)->x+y,  (1:5, 1:5))
p =  Page(intro, (q1,); meta...)
# open("mynew.pg","w") do io
#    print(io, p)
# end
```
"""
struct Page
    intro
    questions
    meta_information
    context
    answer_context
    function Page(intro, questions; context="",answer_context="", kwargs...)
        new(intro,  questions, Dict(kwargs...), context, answer_context)
    end
end

# utility function
function kv(io::IO, v,d, ops=[])
    if isa(d, Dict)
        if(v != nothing)
            push!(ops, v)
            for (vv, dd) in d
                kv(io, vv, dd, ops)
            end
        else
            for (kk,vv) in d
                kv(io, kk, vv)
            end
        end
    else
        println(io, """Context()->$(join(string.(ops), "->"))->$(v)($(d));\n""")
    end
end

"""
    numbers_only

Dictionary to pass to `answer_context` to turn off WeBWorK's simplification pass.
There is no means to turn this off per problem, only per page.
"""
numbers_only = Dict(:operators=>Dict(:undefine=>"'+','-','*','/','^'"),
                           :functions=>Dict(:disable=>"'All'"),
                           :constants=>Dict(:remove=>"\"e\"")
                           )

function Base.show(io::IO, p::Page)

    for (k,v) in p.meta_information
        println(io, "## $k('$v')")
    end

    println(io, raw"""
DOCUMENT();

loadMacros("PG.pl","PGbasicmacros.pl","PGanswermacros.pl");
loadMacros("PGstandard.pl");
loadMacros("MathObjects.pl");
loadMacros("Parser.pl");
loadMacros("AnswerFormatHelp.pl");
loadMacros("parserRadioButtons.pl");
loadMacros("PGchoicemacros.pl");
loadMacros("PGessaymacros.pl");
##loadMacros("PGML.pl");
##loadMacros("PGcourse.pl");

Context()->{format}{number} = "%.16g";
Context()->variables->add(y=>'Real', z=>'Real', t=>'Real', u=>'Real', m=>'Real', n=>'Real');
Context()->flags->set(ignoreEndpointTypes=> 1);

my %seen;  # hat tip to https://perlmaven.com/unique-values-in-an-array-in-perl;  filter Context->strings->add
$seen{"yes"} = 1; $seen{"no"}=1;$seen{"true"} = 1; $seen{"false"}=1;
Context()->strings->add(qq(yes)=>{},qq(no)=>{},qq(true)=>{},qq(false)=>{});
$ATSYMS  = qw"@syms";

""")

    println(io, "TEXT(beginproblem());")

    ## add in space  for popup  (called  by imagelink)
    println(io, raw"""
HEADER_TEXT(<<EOF);
  <script type="text/javascript" language="javascript">
  <!-- //
  function windowpopup(url) {
     var opt = "height=625,width=600,location=no,menubar=no," +
              "status=no,resizable=yes,scrollbars=yes," +
              "toolbar=no,";

    window.open(url,'newwindow',opt).focus();
  }
  // -->
  </script>
""")

    ## print javascript headers, as needed
    for T in unique(typeof.(p.questions))
        print(io, javascript_headers(T))
    end

    println(io, raw"""
EOF
""")
    ## add in somee missing formatting styles
    println(io,"""
\$BBLOCKQUOTE =  MODES(
HTML=>"<BlockQuote>",
TeX =>""
);

\$EBLOCKQUOTE  = MODES(
HTML=>"</BlockQuote>",
TeX=>""
);

\$ADMONITION = MODES(
HTML=>"☆ ",
TeX=>"\\(\\bigwhitestar)");
""")

    if length(p.context) > 0
        println(io,  "Context(\"$(p.context)\");")
    end

    println(io, "\n## ---------- create answer values ----------\n")
    for q  in p.questions
        print(io, create_answer(q))
        println(io, "")
    end

    println(io, "\n## ---------- show  questions  ----------\n")

    println(io, raw"""$branding_ = <<"END_BRANDING";""")
    println(io, get(ENV, "BRANDING",  ""))
    println(io, """END_BRANDING""")
    println(io, raw"""$branding = MODES(HTML=>$branding_, TeX=>"[nothing to see]");""")

    println(io, "BEGIN_TEXT\n")
    println(io, raw"""$branding""")

    #intro = replace(p.intro, "\\" => "\\\\") # had this, replaced with
    intro = Mustache.render(p.intro)
    print(io, escape_string(intro))

    println(io, "\n\n\$HR\$PAR\n")

    for q in  p.questions
        print(io,  show_question(q))
        println(io,"\$PAR\n")
    end

    println(io,  "END_TEXT")

    println(io, "\n## ---------- show  answers  ----------\n")

    ops = []
    if length(p.answer_context) > 0
        kv(io, nothing, p.answer_context)
    end

    for q in p.questions
        println(io, show_answer(q))
        println(io,"")
    end

    ## Solutions go at end (when added)
    soln_io = IOBuffer()
    for q in  p.questions
         print(soln_io,  show_solution(q))
    end
    solns = String(take!(soln_io))

    if length(solns) > 0

        println(io, "#***************************************** Solution: ")
        println(io, """
Context()->texStrings;
SOLUTION(EV3(<<"END_SOLUTION"));
""")
        println(io, escape_string(solns))

        println(io, """
END_SOLUTION
Context()->normalStrings;
""")
    end

   println(io, "ENDDOCUMENT();")

end

"""
    PAGE(SCRIPTNAME)

Write a page to a file name based on the value of `SCRIPTNAME`. Returns an anonymous function
which can be called repeatedly to write a page with a filename based on `SCRIPTNAME`.

This is designed to be used as `PAGE = JuliaWeBWorK.PAGE(@__FILE__)`. Then from one script file
several related `pg` files can be generated. This might be useful for authoring exams
where it is a good practice to have many separate problems and not one big one with many
parts.

```
using JuliaWeBWorK
PAGE = write_page(@__FILE__)

q = numericq(raw"What is \\({{:a1}} + {{:a2}}\\)?", (a,b) -> a+b, (1:4, 2:5))
PAGE("Addition", (q,))  # writes to SCRIPT_BASE_NAME-1.pg

q = numericq(raw"What is \\({{:a1}} - {{:a2}}\\)?", (a,b) -> a-b, (1:4, 2:5))
PAGE("subtraction", (q,))  # writes to SCRIPT_BASE_NAME-2.pg

q = numericq(raw"What is \\({{:a1}} * {{:a2}}\\)?", (a,b) -> a*b, (1:4, 2:5))
PAGE("multiplication", (q,))  # writes to SCRIPT_BASE_NAME-3.pg
```

"""
function PAGE(SCRIPTNAME)
    base_nm = replace(SCRIPTNAME, r".jl$" => "")
    ctr = Ref(1)
    # return an anonymous function for printing a page
    # to the numbered .pg file.
    (args...;kwargs...) -> begin
        fname = base_nm * "-$(ctr[]).pg"
        ctr[] += 1
        open(fname, "w") do io
            show(io, Page(args..., kwargs...))
        end
    end
end

### ------ CONVENIENCES ------------

# simple struct to hold questions
# * can be passed to `page`
# * the call method calls `push!(q, x)` so that questions can be piped into t
#   these objects, as in `numericq(...) |> qs`
struct Questions
    qs
end
QUESTIONS() = Questions(Any[])
Base.iterate(q::Questions) = iterate(q.qs)
Base.iterate(q::Questions, st) = iterate(q.qs, st)
Base.length(q::Questions) = length(q.qs)
Base.push!(q::Questions, x) = push!(q.qs, x)
## returning `x` allows use like `u = randomizer(...) |> qs`
(q::Questions)(x) = (push!(q, x); x)

## ----
"return iterator over the letters `(a)`, `(b)`, ... Calling function increments letters"
function LETTERS()
    letters = ["(a)", "(b)", "(c)", "(d)", "(e)", "(f)", "(g)", "(h)", "(i)", "(j)", "(k)", "(l)", "(m)", "(n)", "(o)", "(p)", "(q)", "(r)", "(s)", "(t)", "(u)", "(v)", "(w)", "(x)", "(y)", "(z)"]
    idx = Base.Ref(1)
    () -> begin
        idx[] = idx[] + 1
        letters[idx[]-1]
    end
end

### ------ HACKS ------------

## A total hack to print `@syms` in a block
## First \{\} are expanded, then $... and @... are substituted
## so we can't generalize through the \{...\} phase
ATSYMS = "\$ATSYMS"; export ATSYMS

# https://github.com/JuliaLang/julia/blob/master/stdlib/InteractiveUtils/src/clipboard.jl
function mac_clipboard(p)
    open(pipeline(`pbcopy`, stderr=stderr), "w") do io
        show(io, p)
    end
end
export mac_clipboard


text:
using LinearAlgebra

A = [3 1; 2 2]

e, u = eigen(A)

println("Eigenvalues=", e)
println("D=", u)


text:
# Bootstrap sampling functions
#=
Symbol conversion to Lahiri (2003)
X = data
n = Ndata
N = NpossibleBlocks
l = blockLength
k = Nblocks
B = NbootstrapReplicates
m = bootDataLength
=#
function MBBsample(data::Array{<:Real,1}, blockLength::Integer, Nblocks::Integer, NbootstrapReplicates::Integer)
    # Moving Block Bootstrap
    Ndata = length(data)
    NpossibleBlocks = Ndata - blockLength + 1
    bootDataLength = Nblocks*blockLength
    possibleIndex = collect(1:NpossibleBlocks)

    resampleIndex, resampleData = multipleSample(data, possibleIndex, NbootstrapReplicates, blockLength, Nblocks, bootDataLength, Ndata)
    return resampleIndex, resampleData
end
function NBBsample(data::Array{<:Real,1}, blockLength::Integer, Nblocks::Integer, NbootstrapReplicates::Integer)
    # Nonoverlapping Block Bootstrap
    Ndata = length(data)
    #Nblocks = floor(Int, Ndata/blockLength);
    NpossibleBlocks = Ndata
    bootDataLength = Nblocks*blockLength
    possibleIndex = collect(1:blockLength:bootDataLength)

    resampleIndex, resampleData = multipleSample(data, possibleIndex, NbootstrapReplicates, blockLength, Nblocks, bootDataLength, Ndata)
    return resampleIndex, resampleData
end
function CBBsample(data::Array{<:Real,1}, blockLength::Integer, Nblocks::Integer, NbootstrapReplicates::Integer)
    # Circular Block Bootstrap
    Ndata = length(data)
    NpossibleBlocks = Ndata
    bootDataLength = Nblocks*blockLength
    possibleIndex = collect(1:Ndata)

    resampleIndex, resampleData = multipleSample(data, possibleIndex, NbootstrapReplicates, blockLength, Nblocks, bootDataLength, Ndata)
    return resampleIndex, resampleData
end
function multipleSample(data::Array{<:Real,1}, possibleIndex::Array{<:Int,1}, NbootstrapReplicates::Integer, blockLength::Integer, Nblocks::Integer, bootDataLength::Integer, Ndata::Integer)
    # Multiple block bootstrap sample
    resampleIndex = Vector{Array}(undef,NbootstrapReplicates)
    resampleData = Vector{Array}(undef,NbootstrapReplicates)
    for ii in 1:NbootstrapReplicates
        resampleIndex[ii] = singleSampleIndex(bootDataLength, Nblocks, blockLength, possibleIndex, Ndata)
        resampleData[ii] = data[resampleIndex[ii]]
    end
    return resampleIndex, resampleData
end
function singleSampleIndex(bootDataLength::Integer, Nblocks::Integer, blockLength::Integer, possibleIndex::Array{<:Int,1}, Ndata::Integer)
    # Single bootsrap sample
    resampleIndex = Vector{Integer}(undef, bootDataLength)
    randomDraw = rand(possibleIndex, Nblocks, 1)
    for ii in 1:Nblocks
        startIndex = (ii-1)*blockLength+1
        lastIndex = ii*blockLength
        inIndex = UnitRange{Int}(randomDraw[ii], randomDraw[ii]+blockLength-1)
        modIndex = mod1.(inIndex, Ndata)
        resampleIndex[startIndex:lastIndex] = modIndex
    end
    return resampleIndex
end


text:
######################################################################
# Kiru-flavored general purpose utilities
# -----
# Copyright (c) Kiruse 2021. Licensed under MIT License
module KirUtil
using Reexport
export use

include("./Stubs.jl")
include("./Errors.jl")
include("./Macros.jl")

include("./Types.jl")
include("./Functions.jl")
include("./Functionals.jl")
include("./XCopy.jl")
include("./CancellableTasks.jl")
include("./Events.jl")

@reexport using .CancellableTasks

end # module


text:
struct FileCovariate{T<:AbstractFloat} <: AbstractCovariate{T}
    name::String
    length::Int64
    datapath::String
end

Base.length(covariate::FileCovariate{T}) where {T<:AbstractFloat} = covariate.length

function slice(covariate::FileCovariate{T}, fromobs::Integer, toobs::Integer, slicelength::Integer) where {T<:AbstractFloat}
    slicelength = verifyslicelength(fromobs, toobs, slicelength)
    sizeT = sizeof(T)
    iostream = open(covariate.datapath, "r")
    seek(iostream, sizeT * (fromobs - 1))
    buffer = Vector{T}(undef, slicelength)
    map(Seq(Vector{T}, (buffer, iostream, fromobs, toobs, slicelength), nextdatachunk), SubArray{T,1,Array{T,1},Tuple{UnitRange{Int64}},true}) do slice
        view(slice, 1:length(slice))
    end
end

function Base.map(covariate::FileCovariate, dataframe::AbstractDataFrame)
    dataframe[getname(covariate)]
end

max_stars_repo_name: Statfactory/JuML

max_issues_repo_name: Statfactory/JuML

max_forks_repo_name: Statfactory/JuML


text:
"""
$(TYPEDEF)
"""
mutable struct VelPoint2VelPoint2{T <: IIF.SamplableBelief} <: IIF.AbstractRelativeMinimize
  z::T
  VelPoint2VelPoint2{T}() where {T <: Distribution} = new{T}()
  VelPoint2VelPoint2{T}(z1::T) where {T <: Distribution} = new{T}(z1)
end
VelPoint2VelPoint2(z1::T) where {T <: Distribution} = VelPoint2VelPoint2{T}(z1)

getSample(cfo::CalcFactor{<:VelPoint2VelPoint2}, N::Int=1) = (rand(cfo.factor.z,N), )

function (cfo::CalcFactor{<:VelPoint2VelPoint2})(z, xi, xj)
  #
  #FIXME JT - I'm createing new res for simplicity, it may not hold up well though
  res = Vector{eltype(xi)}(undef, 4)

  # change in time from microseconds with DynPoint2(ut=1_000_000) to seconds
  dt = Dates.value(cfo.metadata.fullvariables[2].nstime - cfo.metadata.fullvariables[1].nstime)*1e-9     # roughly the intended use of userdata
  # change in psoition Xi \ Xj
  dp = (xj[1:2] .- xi[1:2])
  # change in velocity Xi \ Xj
  dv = (xj[3:4] .- xi[3:4])

  dp_dt = dp./dt

  res[1:2] .= z[1:2] .- dp # (meas - predicted) change in position error term
  res[3:4] .= (z[3:4] .- dv).^2 # (meas - predicted) change in velocity error term

  # now cross couple the change in position information, via timestamps to accompanying velocity
  # TODO validate that
  res[3:4] .+= (dp_dt - xi[3:4]).^2 # (meas - predicted) velocity error term
  res[3:4] .= sqrt.(res[3:4])

  return res
  # res[1] = 0.0
  # res[1] += sum((z[1:2] - dp).^2) # (meas - predicted) change in position error term
  # res[1] += sum((z[3:4] - dv).^2) # (meas - predicted) change in velocity error term

  # ## now cross couple the change in position information, via timestamps to accompanying velocity
  #  # recompute integration of velocity influence
  # # forward diff, "measured velocity"
  # # zeroth order integration
  # res[1] += sum((dp_dt - xi[3:4]).^2) # (meas - predicted) velocity error term

    # first order integration
    # res[1] += sum((dp/dt - 0.5*(xj[3:4]+xi[3:4])).^2)

  # return objective cost < IIF v0.21
  # return res[1]

  # IIF v0.21+
  # return residual
end

"""
$(TYPEDEF)
"""
mutable struct PackedVelPoint2VelPoint2 <: IncrementalInference.PackedInferenceType
  str::String
  PackedVelPoint2VelPoint2() = new()
  PackedVelPoint2VelPoint2(z1::String) = new(z1)
end

function convert(::Type{PackedVelPoint2VelPoint2}, d::VelPoint2VelPoint2)
  return PackedVelPoint2VelPoint2(convert(PackedSamplableBelief, d.z))
end
function convert(::Type{VelPoint2VelPoint2}, d::PackedVelPoint2VelPoint2)
  distr = convert(SamplableBelief, d.str)
  return VelPoint2VelPoint2(distr)
end


text:
# Structs and functions related to the codes_index type

export Index, addfile!, keycount, select!, destroy

mutable struct codes_index
end

struct Index
    ptr::Ptr{codes_index}
    keys::Vector{String}
end

"""
    Index(filename::AbstractString, keys...)

Create an index from a file with the given keys.
"""
function Index(filename::String, keys...)::Index
    eref = Ref(Int32(0))
    strkeys = join(keys, ",")
    ptr = ccall((:codes_index_new_from_file, eccodes), Ptr{codes_index},
                (Ptr{codes_context}, Cstring, Cstring, Ref{Cint}),
                C_NULL, filename, strkeys, eref)
    errorcheck(eref[])
    arrkeys = [k for k in keys]
    return Index(ptr, arrkeys)
end

"""
    Index(f::Function, filename::AbstractString, keys...)

Create an index from a file with the given keys and automatically close the file.

# Example
```Julia
Index(filename, "shortName", "level") do index
    # Do things with index
end
```
"""
function Index(f::Function, filename::String, keys...)
    index = Index(filename, keys...)
    try
        f(index)
    finally
        destroy(index)
    end
end

"""
    addfile!(index::Index, filename::AbstractString)
Index the file at `filename` using `index`.
"""
function addfile!(index::Index, filename::AbstractString)
    err = ccall((:codes_index_add_file, eccodes), Cint,
                (Ptr{codes_index}, Cstring), index.ptr, filename)
    errorcheck(err)
end

"""
    keycount(index::Index, key::AbstractString)
Get the number of distinct values of the key contained in the index.
"""
function keycount(index::Index, key::AbstractString)
    refsize = Ref(Csize_t(0))
    err = ccall((:codes_index_get_size, eccodes), Cint,
                (Ptr{codes_index}, Cstring, Ref{Csize_t}), index.ptr, key, refsize)
    errorcheck(err)
    return refsize[]
end

"""
    select!(index::Index, key::AbstractString, value::AbstractString)
    select!(index::Index, key::AbstractString, value::AbstractFloat)
    select!(index::Index, key::AbstractString, value::AbstractFloat)

Reduce the size of the index to messages that match the key-value pair.

# Examples
```Julia
Index(filename, "shortName") do index
    select!(index, "shortName", "tp")
    # Index now only has messages about total precipitation
end

Index(filename, "level") do index
    select!(index, "level", 850)
    # Index now only has messages at level 850
end
```
"""
function select!(index::Index, key::AbstractString, value::AbstractString)
    err = ccall((:codes_index_select_string, eccodes), Cint,
                (Ptr{codes_index}, Cstring, Cstring), index.ptr, key, value)
    errorcheck(err)
end

function select!(index::Index, key::AbstractString, value::AbstractFloat)
    err = ccall((:codes_index_select_double, eccodes), Cint,
                (Ptr{codes_index}, Cstring, Cdouble), index.ptr, key, value)
    errorcheck(err)
end

function select!(index::Index, key::AbstractString, value::Integer)
    err = ccall((:codes_index_select_long, eccodes), Cint,
                (Ptr{codes_index}, Cstring, Clong), index.ptr, key, value)
    errorcheck(err)
end

""" Iterate through the messages in the index. """
function Base.iterate(f::Index, state=())
    next = Message(f)
    if next == nothing
        return nothing
    else
        return (next, ())
    end
end

Base.eltype(f::Index) = Message

""" Safely destroy the index. """
function destroy(idx::Index)
    ccall((:codes_index_delete, eccodes), Cvoid, (Ptr{codes_index},), idx.ptr)
end

# Functions related to printing
function Base.show(io::IO, mime::MIME"text/plain", index::Index)
    str = "Index with keys [$(join(index.keys, ", "))]"
    print(io, str)
end


text:
module Pervasives
using MLStyle
using MLStyle.AbstractPatterns
using MLStyle.AbstractPatterns
struct Many end
struct Do end
struct GuardBy end
export Many, Do, GuardBy

@nospecialize
function MLStyle.pattern_uncall(
    ::typeof(:),
    self::Function,
    tparams::AbstractArray,
    targs::AbstractArray,
    args::AbstractArray,
)
    isempty(tparams) || error("A (:) pattern requires no type params.")
    isempty(targs) || error("A (:) pattern requires no type arguments.")
    guard() do target, scope, _
        rng = Expr(:call, :, args...)
        see_captured_vars(:($target in $rng), scope)
    end
end
@specialize

function MLStyle.pattern_uncall(
    ::Type{Dict},
    self::Function,
    tparams::AbstractArray,
    targs::AbstractArray,
    args::AbstractArray,
)

    isempty(tparams) || return begin
        call = Expr(:call, Dict, args...)
        ann = Expr(:curly, Dict, targs...)
        self(Where(call, ann, tparams))
    end

    pairs = Pair[]
    for arg in args
        @switch arg begin
            @case :($a => $b)
            push!(pairs, a => b)
            continue
            @case _
            error(
                "A Dict pattern's sub-pattern should be the form of `(a::Symbol) => b`.",
            )
        end
    end
    function dict_extract(expr::Any, i::Int, scope::ChainDict{Symbol, Symbol}, ::Any)
        # cannot avoid performance overhead due to
        # https://discourse.julialang.org/t/distinguish-dictionary-lookup-from-nothing-and-not-found/38654
        k, v = pairs[i]
        if k isa Union{Expr, Symbol}
            # how to reduce the generate code size?
            # most of the cases, see_captured_vars is unnecessary.
            k = see_captured_vars(k, scope)
        end
        :(haskey($expr, $k) ? Some($expr[$k]) : nothing)
    end

    tchk = isempty(targs) ? P_type_of(Dict) : self(:(::$Dict{$(targs...)}))
    decomp =
        decons(dict_extract, [self(Expr(:call, Some, pair.second)) for pair in pairs])
    and([tchk, decomp])
end

function _allow_assignment!(expr::Expr)
    if expr.head === :kw || expr.head === :(=)
        expr.head = :(=)
        @assert expr.args[1] isa Symbol
    end
end

function MLStyle.pattern_unref(::Type{E}, self::Function, args::AbstractArray) where E
    self(:([$(args...)] :: $AbstractVector{$E}))
end

function MLStyle.pattern_unref(::Type{Do}, self::Function, args::AbstractArray)
    foreach(_allow_assignment!, args)

    effect() do target, scope, ln
        ret = Expr(:block)
        for arg in args
            @switch arg begin
                @case :($sym = $value) && if sym isa Symbol
                end
                sym′ = get(scope, sym) do
                    nothing
                end
                bound = true
                if sym′ === nothing
                    sym′ = sym
                    bound = false
                elseif sym′ !== sym
                    mlstyle_add_deprecation_msg!(
                        "Deprecated use of pattern Do($sym=$value, ...): \n" *
                        "Chaning a variable $sym captured during pattern matching.\n" *
                        "This is dangerous and prevents optimizations, hence got deprecated.\n" *
                        "There might be similar cases that we couldn't detect from your code.\n" *
                        "Plesae avoid it! And remember not to change the variable bound during pattern matching, " *
                        "instead, mutate outer variables.",
                    )
                end
                assignment = Expr(:(=), sym′, see_captured_vars(value, scope))
                push!(ret.args, assignment)
                if !bound
                    scope[sym] = sym′
                end
                continue
                @case _
                push!(ret.args, see_captured_vars(arg, scope))
                continue
            end
        end
        ret
    end
end

@nospecialize
function MLStyle.pattern_uncall(
    ::Type{Do},
    self::Function,
    tparams::AbstractArray,
    targs::AbstractArray,
    args::AbstractArray,
)
    isempty(tparams) || error("A (:) pattern requires no type params.")
    isempty(targs) || error("A (:) pattern requires no type arguments.")
    MLStyle.pattern_unref(Do, self, args)
end

function MLStyle.pattern_uncall(
    ::Type{GuardBy},
    self::Function,
    tparams::AbstractArray,
    targs::AbstractArray,
    args::AbstractArray,
)
    isempty(tparams) || error("A (:) pattern requires no type params.")
    isempty(targs) || error("A (:) pattern requires no type arguments.")
    @assert length(args) === 1
    guard() do target, _, _
        :($(args[1])($target))
    end
end

function MLStyle.pattern_unref(::Type{Many}, self::Function, args::AbstractArray)
    @assert length(args) === 1
    arg = args[1]
    foreach(_allow_assignment!, args)

    let_pat = Expr(:let, Expr(:block, args...), Expr(:block))
    old = repr(Expr(:call, :Do, args...))
    new = repr(let_pat)
    guard() do target, scope, ln
        token = gensym("loop token")
        iter = gensym("loop iter")
        mk_case(x) = Expr(:macrocall, Symbol("@case"), ln, x)
        switch_body = quote
            $(mk_case(arg))
            continue
            $(mk_case(:_))
            $token = false
            break
        end
        switch_stmt =
            Expr(:macrocall, GlobalRef(MLStyle, Symbol("@switch")), ln, iter, switch_body)
        final = quote
            $token = true
            for $iter in $target
                $switch_stmt
            end
            $token
        end
        see_captured_vars!(final, scope)
    end
end

function MLStyle.pattern_uncall(
    ::Type{Many},
    self::Function,
    tparams::AbstractArray,
    targs::AbstractArray,
    args::AbstractArray,
)
    isempty(tparams) || error("A (:) pattern requires no type params.")
    isempty(targs) || error("A (:) pattern requires no type arguments.")
    MLStyle.pattern_unref(Many, self, args)
end

function MLStyle.pattern_unmacrocall(
    r_str::typeof(@eval $(Symbol("@", "r_str"))),
    self::Function,
    args::AbstractArray,
)
    @switch args begin
        @case [ln, m, s::String]
    end

    regex = r_str(ln, m, s)
    guard() do target, _, _
        :($match($regex, $target) !== nothing)
    end
end

@specialize

end


text:
"""
    RightHandSideFunction <: AbstractRightHandSideFunction

A composite type for the right-hand side of an [`AbstractInitialValueProblem`](@ref).

# Constructors
```julia
RightHandSideFunction(f, f!, Df, Df!)
RightHandSideFunction(f!_or_f)
RHS(args...; kwargs...)
```

# Arguments
- `f :: Function` : right-hand side derivative.
- `f! :: Function` : right-hand side derivative (in-place).
- `Df :: Function` : jacobian of right-hand side derivative.
- `Df! :: Function` : jacobian of right-hand side derivative (in-place).
- `f!_or_f :: Function` : function (in-place or not) from which all other fields will be constructed.

# Functions
- [`show`](@ref) : shows name and contents.
- [`summary`](@ref) : shows name.
"""
mutable struct RightHandSideFunction{f_T, f!_T, Df_T, Df!_T} <: AbstractRightHandSideFunction
    f::f_T
    f!::f!_T
    Df::Df_T
    Df!::Df!_T
end

function RightHandSideFunction(f!_or_f::Function; iscomplex = false)
    if iscomplex
        # Jacobian using Wirtinger derivatives: https://math.stackexchange.com/questions/2945446/understanding-the-chain-rule-in-the-wirtinger-calculus
        # possible alternative: use reinterpret
        if hasmethod(f!_or_f, NTuple{3, Any})
            f! = f!_or_f
            f = (u, t) -> f!_or_f(similar(u), u, t)
            Df = function (u, t)
                J_ = FiniteDifferences.jacobian(central_fdm(4, 1), u -> f(u, t), u)[1]
                n = length(u)
                P = kron(Matrix(I, n, n), 0.5 * [1.0 -1.0im; 1.0 1.0im])
                J = ((P * J_) / P)[1:2:2*n-1, 1:2:2*n-1]
                return J
            end
            Df! = function (J, du, u, t)
                J .= Df(u, t)
                return J
            end
            return RightHandSideFunction(f, f!, Df, Df!)
        # Check if f!_or_f has form f(u, t)
        elseif hasmethod(f!_or_f, NTuple{2, Any})
            f = f!_or_f
            f! = (du, u, t) -> du .= f!_or_f(u, t)
            Df = function (u, t)
                J_ = FiniteDifferences.jacobian(central_fdm(4, 1), u -> f(u, t), u)[1]
                n = length(u)
                P = kron(Matrix(I, n, n), 0.5 * [1.0 -1.0im; 1.0 1.0im])
                J = ((P * J_) / P)[1:2:2*n-1, 1:2:2*n-1]
                return J
            end
            Df! = function (J, du, u, t)
                J .= Df(u, t)
                return J
            end
            return RightHandSideFunction(f, f!, Df, Df!)
        end
    else
        # Check if f!_or_f has form f!(du, u, t)
        if hasmethod(f!_or_f, NTuple{3, Any})
            f! = f!_or_f
            f = (u, t) -> f!_or_f(similar(u), u, t)
            Df = (u, t) -> ForwardDiff.jacobian((du, u) -> f!_or_f(du, u, t), similar(u), u)
            Df! = (J, du, u, t) -> ForwardDiff.jacobian!(J, (du, u) -> f!_or_f(du, u, t), du, u)
            return RightHandSideFunction(f, f!, Df, Df!)
        # Check if f!_or_f has form f(u, t)
        elseif hasmethod(f!_or_f, NTuple{2, Any})
            f = f!_or_f
            f! = (du, u, t) -> du .= f!_or_f(u, t)
            Df = (u, t) -> ForwardDiff.jacobian(u -> f!_or_f(u, t), u)
            Df! = (J, du, u, t) -> ForwardDiff.jacobian!(J, u -> f!_or_f(u, t), u)
            return RightHandSideFunction(f, f!, Df, Df!)
        end
    end
end

@doc (@doc RightHandSideFunction) RHS(args...; kwargs...) = RightHandSideFunction(args...; kwargs...)

############################################################################################
#                                         PRINTING                                         #
############################################################################################

"""
    show(io::IO, rhs::RightHandSideFunction)

prints a full description of `rhs` and its contents to a stream `io`.
"""
Base.show(io::IO, rhs::RightHandSideFunction) = _show(io, rhs)
# function Base.show(io::IO, rhs::RightHandSideFunction)
#     print(io, "RightHandSideFunction:")
#     pad = get(io, :pad, "")
#     names = propertynames(rhs)
#     N = length(names)
#     args(n) = (n == 1 ? "(u, t)" : n == 2 ? "(du, u, t)" : n == 3 ? "(u, t)" : "(J, du, u, t)")
#     for (n, name) in enumerate(names)
#         field = getproperty(rhs, name)
#         if field !== nothing
#             print(io, "\n", pad, "   ‣ " * string(name), args(n))
#         end
#     end
# end

"""
    summary(io::IO, rhs::RightHandSideFunction)

prints a brief description of `rhs` to a stream `io`.
"""
Base.summary(io::IO, rhs::RightHandSideFunction) = _summary(io, rhs)


text:
const MAX_RANGES = 50

struct Range
    from::Int
    to::Int
end

function parse_split(line::String, sep::Char)
    ret = Int[]
    i::Int = 1
    j::Union{Nothing,Int} = findnext(sep, line, i + 1)
    while j !== nothing
        push!(ret, parse(Int, SubString(line, i, j - 1)))
        i = j + 1
        j = findnext(sep, line, i + 1)
    end
    push!(ret, parse(Int, SubString(line, i, lastindex(line))))
    return ret
end

function add_range(line::String, line_idx::Int, ranges::Array{Range,1})
    idx1 = findnext(':', line, 1) + 1
    idx2 = findnext('-', line, idx1 + 1) - 1
    idx3 = idx2 + 2
    idx4 = findnext(' ', line, idx3 + 1) - 1
    ranges[2 * line_idx - 1] = Range(
        parse(Int, SubString(line, idx1, idx2)),
        parse(Int, SubString(line, idx3, idx4))
    )
    idx1 = idx4 + 5
    idx2 = findnext('-', line, idx1 + 1) - 1
    idx3 = idx2 + 2
    idx4 = lastindex(line)
    ranges[2 * line_idx] = Range(
        parse(Int, SubString(line, idx1, idx2)),
        parse(Int, SubString(line, idx3, idx4))
    )
end

function is_valid(value::Int, ranges::Array{Range,1}, n_ranges::Int)::Bool
    return any(ranges[i].from <= value <= ranges[i].to for i in 1:n_ranges)
end

function run(s)
    ranges = Array{Range,1}(undef, MAX_RANGES)
    n_ranges::Int = 0

    counter::Int = 0
    lines = eachline(IOBuffer(s))
    for line in lines
        if isempty(line)
            break
        end
        n_ranges += 1
        add_range(line, n_ranges, ranges)
    end
    for line in lines
        if isempty(line)
            break
        end
    end
    for line in Iterators.drop(lines, 1)
        values = parse_split(line, ',')
        for v in values
            if !is_valid(v, ranges, n_ranges)
                counter += v
                break
            end
        end
    end
    return counter
end

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

function main()
    res, time, memory = @timed run(ARGS[1])
    println("_duration:$(time * 1000)")
    println(res)
end

main()


text:
import Base: iterate
import Base.Order.Forward

struct SIter{UA<:UnitRange,GA<:AbstractArray,UB<:UnitRange,GB<:AbstractArray}
    ra::UA
    ga::GA
    rb::UB
    gb::GB
end

Base.IteratorSize(::Type{<:SIter}) = Base.SizeUnknown()

function iterate(si::SIter)
    iterate(si, (first(si.ra), first(si.rb)))
end
function iterate(si::SIter, (ia, ib))
    ra, ga, rb, gb = si.ra, si.ga, si.rb, si.gb
    la = last(ra)
    lb = last(rb)
    while ia <= la && ib <= lb
        rga = ga[ia]
        rgb = gb[ib]
        rga == rgb && return (ia, ib), (ia+1, ib+1)
        if rga > rgb
            ib += 1
        else
            ia += 1
        end
    end
    nothing
end

function iterate_slower(si::SIter, (ia, ib))
    ra, ga, rb, gb = si.ra, si.ga, si.rb, si.gb
    la = last(ra)
    lb = last(rb)
    ia <= la && ib <= lb || return nothing
    rga = ga[ia]
    rgb = gb[ib]
    rga == rgb && return (ia, ib), (ia+1, ib+1)
    if rga > rgb
        ib = searchsortedfirst(gb, rga, ib+1, lb, Forward)
        ib <= lb || return nothing
        rgb = gb[ib]
        rgb == rga && return (ia, ib), (ia+1, ib+1)
    end
    while true
        ia = searchsortedfirst(ga, rgb, ia+1, la, Forward)
        ia <= la || return nothing
        rga = ga[ia]
        rgb == rga && return (ia, ib), (ia+1, ib+1)

        ib = searchsortedfirst(gb, rga, ib+1, lb, Forward)
        ib <= lb || return nothing
        rgb = gb[ib]
        rgb == rga && return (ia, ib), (ia+1, ib+1)
    end
    nothing
end

using SparseArrays
import SparseArrays: nzrange, rowvals, nonzeros, estimate_mulsize

SparseArrays.nzrange(A::SparseVector, j::Integer) = 1:(j == 1 ? length(A.nzind) : 0)
SparseArrays.rowvals(A::SparseVector) = A.nzind
#SparseArrays.nonzeros(A::SparseVector) = A.nzval

function syncsum(f, A, i, B, j)
    si = MatrixAlgebra.SIter(nzrange(A, i), rowvals(A), nzrange(B, j), rowvals(B))
    nza = nonzeros(A)
    nzb = nonzeros(B)
    s = 0.0
    for (ia, ib) in si
        s += f(nza[ia]) * nzb[ib]
    end
    s
end

function spmulatb(f, A, B)
    mA, nA = size(A)
    mA == size(B, 1) || throw(DimensionMismatch())
    nB = size(B, 2)
    nnzC = min(max(estimate_mulsize(mA, nnz(A), nA, nnz(B), nB) * 11 ÷ 10, mA), nA*nB)
    Ti = promote_type(eltype(rowvals(A)), eltype(rowvals(B)))
    Tv = promote_type(eltype(nonzeros(A)), eltype(nonzeros(B)))
    colptrC = Vector{Ti}(undef, nB+1)
    rowvalC = Vector{Ti}(undef, nnzC)
    nzvalC = Vector{Tv}(undef, nnzC)
    nza = nonzeros(A)
    nzb = nonzeros(B)

    Z = f(zero(eltype(A)))*zero(eltype(B))
    ip = 1
    @inbounds begin
        colptrC[1] = ip
        for i = 1:nB
            if ip + nA - 1 > nnzC
                nnzC += max(nA, nnzC>>2)
                resize!(rowvalC, nnzC)
                resize!(nzvalC, nnzC)
            end
            for j = 1:nA
                si = SIter(nzrange(A, j), rowvals(A), nzrange(B, i), rowvals(B))
                isempty(si) && continue
                s = Z
                for (ia, ib) in si
                    s += f(nza[ia]) * nzb[ib]
                end
                iszero(s) && continue
                rowvalC[ip] = j
                nzvalC[ip] = s
                ip += 1
            end
            colptrC[i+1] = ip
        end
        if ip < nnzC
            resize!(rowvalC, ip)
            resize!(nzvalC, ip)
        end
    end
    SparseMatrixCSC(nA, nB, colptrC, rowvalC, nzvalC)
end


text:
module EMLsepComp
	using DanaTypes
	using DotPlusInheritance
	using Reexport
	@reexport using ...streams.EMLstreams
	import EMLtypes.length
	include("sepComp/sepComp_n.jl")
	include("sepComp/sepComp.jl")
end


text:
# smaller plot recipes used to make more complicated plot recipes

const DEFAULT_RUG_SIZE = 8

"""
    rugplot(x; kwargs...)
    rugplot!(x; kwargs...)

Make a rugplot.

# Positional Arguments
- `x`: values

# Keyword Arguments
- `rugmarkershape=:auto`: shape of marker, defaulting to perpendicular to the data axis
- `rugsize=$DEFAULT_RUG_SIZE`: size (height) of marker
- `rugcolor=:auto`: color of marker
- `rugalpha=:auto`: alpha value (transparency) of marker
- `rugposition=0`: position of rug on non-data axis
- `kwargs`: Additional attributes understood by Plots.jl
"""
rugplot(x; kwargs...) = RecipesBase.plot(x; seriestype=:rugplot, kwargs...)
rugplot!(x; kwargs...) = RecipesBase.plot!(x; seriestype=:rugplot, kwargs...)

RecipesBase.@recipe function f(
    ::Type{Val{:rugplot}},
    x,
    y,
    z;
    rugmarkershape=:auto,
    rugsize=DEFAULT_RUG_SIZE,
    rugcolor=get(plotattributes, :seriescolor, :auto),
    rugalpha=get(plotattributes, :seriesalpha, :auto),
    rugposition=0,
)
    seriestype := :scatter
    xnew = y
    ynew = fill(rugposition, length(y))
    isrot = isrotated(plotattributes)
    if isrot
        xnew, ynew = ynew, xnew
    end
    x := xnew
    y := ynew
    if rugmarkershape === :auto
        rugmarkershape = isrot ? :hline : :vline
    end
    markershape := rugmarkershape
    markersize := rugsize
    markercolor := rugcolor
    markeralpha := rugalpha
    fill := false  # necessary in case fill=true passed to parent
    label := ""
    return ()
end


text:
# syntax: proto3
using ProtoBuf
import ProtoBuf.meta
import ._ProtoBuf_Top_.matrix_io

mutable struct DriverConfig <: ProtoType
    delay_between_updates::Float32
    timeout_after_last_ping::Float32
    image::matrix_io.malos.v1.io.EverloopImage
    malos_eye_config::matrix_io.malos.v1.maloseye.MalosEyeConfig
    zigbee_message::matrix_io.malos.v1.comm.ZigBeeMsg
    lirc::matrix_io.malos.v1.comm.LircParams
    servo::matrix_io.malos.v1.io.ServoParams
    gpio::matrix_io.malos.v1.io.GpioParams
    humidity::matrix_io.malos.v1.sense.HumidityParams
    micarray::matrix_io.malos.v1.io.MicArrayParams
    zwave::matrix_io.malos.v1.comm.ZWaveMsg
    wakeword::matrix_io.malos.v1.io.WakeWordParams
    matrix_device::matrix_io.malos.v1.io.MatrixDeviceParams
    uuid::AbstractString
    DriverConfig(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o)
end #mutable struct DriverConfig

mutable struct DriverInfo <: ProtoType
    driver_name::AbstractString
    base_port::Int32
    provides_updates::Bool
    delay_between_updates::Int32
    needs_pings::Bool
    timeout_after_last_ping::Int32
    notes_for_human::AbstractString
    DriverInfo(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o)
end #mutable struct DriverInfo

mutable struct MalosDriverInfo <: ProtoType
    info::Base.Vector{DriverInfo}
    MalosDriverInfo(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o)
end #mutable struct MalosDriverInfo

struct __enum_Status_MessageType <: ProtoEnum
    MESSAGE_TYPE_NOT_DEFINED::Int32
    STARTED::Int32
    STOPPED::Int32
    CONFIG_RECEIVED::Int32
    COMMAND_EXECUTED::Int32
    STATUS_CRITICAL::Int32
    STATUS_ERROR::Int32
    STATUS_WARNING::Int32
    STATUS_INFO::Int32
    STATUS_DEBUG::Int32
    __enum_Status_MessageType() = new(0,1,2,3,4,5,6,7,8,9)
end #struct __enum_Status_MessageType
const Status_MessageType = __enum_Status_MessageType()

mutable struct Status <: ProtoType
    _type::Int32
    uuid::AbstractString
    message::AbstractString
    Status(; kwargs...) = (o=new(); fillunset(o); isempty(kwargs) || ProtoBuf._protobuild(o, kwargs); o)
end #mutable struct Status

export DriverConfig, DriverInfo, MalosDriverInfo, Status_MessageType, Status


text:
using LoopVectorization, LinearAlgebra, OffsetArrays, ArrayInterface
BLAS.set_num_threads(1)

using LoopVectorization: Static
# TODO: remove this once this PR merges: https://github.com/JuliaArrays/OffsetArrays.jl/pull/170
@inline Base.unsafe_convert(::Type{Ptr{T}}, A::OffsetArray{T}) where {T} = pointer(parent(A))

struct SizedOffsetMatrix{T,LR,UR,LC,UC} <: DenseMatrix{T}
    data::Matrix{T}
end
Base.size(::SizedOffsetMatrix{<:Any,LR,UR,LC,UC}) where {LR,UR,LC,UC} = (UR-LR+1,UC-LC+1)
Base.axes(::SizedOffsetMatrix{T,LR,UR,LC,UC}) where {T,LR,UR,LC,UC} = (Static{LR}():Static{UR}(),Static{LC}():Static{UC}())
Base.parent(A::SizedOffsetMatrix) = A.data
Base.unsafe_convert(::Type{Ptr{T}}, A::SizedOffsetMatrix{T}) where {T} = pointer(A.data)
ArrayInterface.contiguous_axis(::Type{<:SizedOffsetMatrix}) = Static(1)
ArrayInterface.contiguous_batch_size(::Type{<:SizedOffsetMatrix}) = Static(0)
ArrayInterface.stride_rank(::Type{<:SizedOffsetMatrix}) = (Static(1), Static(2))
function ArrayInterface.strides(A::SizedOffsetMatrix{T,LR,UR,LC,UC}) where {T,LR,UR,LC,UC}
    (Static{1}(), (Static{UR}() - Static{LR}() + Static{1}()))
end
ArrayInterface.offsets(A::SizedOffsetMatrix{T,LR,UR,LC,UC}) where {T,LR,UR,LC,UC} = (Static{LR}(), Static{LC}())
Base.getindex(A::SizedOffsetMatrix, i, j) = LoopVectorization.vload(LoopVectorization.stridedpointer(A), (i,j))

function jgemm!(𝐂, 𝐀, 𝐁)
    𝐂 .= 0
    M, N = size(𝐂); K = size(𝐁,1)
    @inbounds for n ∈ 1:N, k ∈ 1:K
        @simd ivdep for m ∈ 1:M
            @fastmath 𝐂[m,n] += 𝐀[m,k] * 𝐁[k,n]
        end
    end
end
function jgemm!(𝐂, 𝐀ᵀ::Adjoint, 𝐁)
    𝐀 = parent(𝐀ᵀ)
    @inbounds for n ∈ 1:size(𝐂,2), m ∈ 1:size(𝐂,1)
        𝐂ₘₙ = zero(eltype(𝐂))
        @simd ivdep for k ∈ 1:size(𝐀,1)
            @fastmath 𝐂ₘₙ += 𝐀[k,m] * 𝐁[k,n]
        end
        𝐂[m,n] = 𝐂ₘₙ
    end
end
function jgemm!(𝐂, 𝐀, 𝐁ᵀ::Adjoint)
    𝐂 .= 0
    𝐁 = parent(𝐁ᵀ)
    M, N = size(𝐂); K = size(𝐁ᵀ,1)
    @inbounds for k ∈ 1:K, n ∈ 1:N
        @simd ivdep for m ∈ 1:M
            @fastmath 𝐂[m,n] += 𝐀[m,k] * 𝐁[n,k]
        end
    end
end
function jgemm!(𝐂, 𝐀ᵀ::Adjoint, 𝐁ᵀ::Adjoint)
    𝐂 .= 0
    𝐀 = parent(𝐀ᵀ)
    𝐁 = parent(𝐁ᵀ)
    M, N = size(𝐂); K = size(𝐁ᵀ,1)
    @inbounds for n ∈ 1:N, k ∈ 1:K
        @simd ivdep for m ∈ 1:M
            @fastmath 𝐂[m,n] += 𝐀[k,m] * 𝐁[n,k]
        end
    end
end
function gemmavx!(𝐂, 𝐀, 𝐁)
    @turbo for m ∈ indices((𝐀,𝐂),1), n ∈ indices((𝐁,𝐂),2)
        𝐂ₘₙ = zero(eltype(𝐂))
        for k ∈ indices((𝐀,𝐁),(2,1))
            𝐂ₘₙ += 𝐀[m,k] * 𝐁[k,n]
        end
        𝐂[m,n] = 𝐂ₘₙ
    end
end
function gemmavx!(Cc::AbstractMatrix{Complex{T}}, Ac::AbstractMatrix{Complex{T}}, Bc::AbstractMatrix{Complex{T}}) where {T}
    A = reinterpret(reshape, T, Ac)
    B = reinterpret(reshape, T, Bc)
    C = reinterpret(reshape, T, Cc)
    @turbo for m ∈ indices((A,C),2), n ∈ indices((B,C),3)
        Cre = zero(T)
        Cim = zero(T)
        for k ∈ indices((A,B),(3,2))
            Cre += A[1,m,k]*B[1,k,n] - A[2,m,k]*B[2,k,n]
            Cim += A[1,m,k]*B[2,k,n] + A[2,m,k]*B[1,k,n]
        end
        C[1,m,n] = Cre
        C[2,m,n] = Cim
    end
end
function gemmavxt!(𝐂, 𝐀, 𝐁)
    @tturbo for m ∈ indices((𝐀,𝐂),1), n ∈ indices((𝐁,𝐂),2)
        𝐂ₘₙ = zero(eltype(𝐂))
        for k ∈ indices((𝐀,𝐁),(2,1))
            𝐂ₘₙ += 𝐀[m,k] * 𝐁[k,n]
        end
        𝐂[m,n] = 𝐂ₘₙ
    end
end
function gemmavxt!(Cc::AbstractMatrix{Complex{T}}, Ac::AbstractMatrix{Complex{T}}, Bc::AbstractMatrix{Complex{T}}) where {T}
    A = reinterpret(reshape, T, Ac)
    B = reinterpret(reshape, T, Bc)
    C = reinterpret(reshape, T, Cc)
    @tturbo for m ∈ indices((A,C),2), n ∈ indices((B,C),3)
        Cre = zero(T)
        Cim = zero(T)
        for k ∈ indices((A,B),(3,2))
            Cre += A[1,m,k]*B[1,k,n] - A[2,m,k]*B[2,k,n]
            Cim += A[1,m,k]*B[2,k,n] + A[2,m,k]*B[1,k,n]
        end
        C[1,m,n] = Cre
        C[2,m,n] = Cim
    end
end
function jdot(a, b)
    s = zero(eltype(a))
    # @inbounds @simd ivdep for i ∈ eachindex(a,b)
    @inbounds @simd ivdep for i ∈ eachindex(a)
        s += a[i] * b[i]
    end
    s
end
function jdotavx(a, b)
    s = zero(eltype(a))
    # @turbo for i ∈ eachindex(a,b)
    @turbo for i ∈ eachindex(a)
        s += a[i] * b[i]
    end
    s
end
function jdotavxt(a, b)
    s = zero(eltype(a))
    # @turbo for i ∈ eachindex(a,b)
    @tturbo for i ∈ eachindex(a)
        s += a[i] * b[i]
    end
    s
end
function jselfdot(a)
    s = zero(eltype(a))
    @inbounds @simd ivdep for i ∈ eachindex(a)
        s += a[i] * a[i]
    end
    s
end
function jselfdotavx(a)
    s = zero(eltype(a))
    @turbo for i ∈ eachindex(a)
        s += a[i] * a[i]
    end
    s
end
function jdot3v2(x, A, y)
    M, N = size(A)
    s = zero(promote_type(eltype(x), eltype(A), eltype(y)))
    @inbounds @fastmath for n ∈ 1:N, m ∈ 1:M
        s += x[m] * A[m,n] * y[n]
    end
    s
end
function jdot3v2avx(x, A, y)
    M, N = size(A)
    s = zero(promote_type(eltype(x), eltype(A), eltype(y)))
    @turbo for n ∈ 1:N, m ∈ 1:M
        s += x[m] * A[m,n] * y[n]
    end
    s
end
function jdot3(x, A, y)
    s = zero(promote_type(eltype(x), eltype(A), eltype(y)))
    @inbounds @fastmath for n ∈ axes(A,2)
        t = zero(s)
        @simd ivdep for m ∈ axes(A,1)
            t += x[m] * A[m,n]
        end
        s += t * y[n]
    end
    s
end
function jdot3avx(x, A, y)
    s = zero(promote_type(eltype(x), eltype(A), eltype(y)))
    @turbo for n ∈ axes(A,2)
        t = zero(s)
        for m ∈ axes(A,1)
            t += x[m] * A[m,n]
        end
        s += t * y[n]
    end
    s
end
function jvexp!(b, a)
    @inbounds for i ∈ eachindex(a)
        b[i] = exp(a[i])
    end
end
function jvexpavx!(b, a)
    @turbo for i ∈ eachindex(a)
        b[i] = exp(a[i])
    end
end
function jsvexp(a)
    s = zero(eltype(a))
    @inbounds for i ∈ eachindex(a)
        s += exp(a[i])
    end
    s
end
function jsvexpavx(a)
    s = zero(eltype(a))
    @turbo for i ∈ eachindex(a)
        s += exp(a[i])
    end
    s
end
function jgemv!(y, 𝐀, x)
    y .= zero(eltype(y))
    @inbounds for j ∈ eachindex(x)
        @simd ivdep for i ∈ eachindex(y)
            @fastmath y[i] += 𝐀[i,j] * x[j]
        end
    end
end
function jgemv!(𝐲, 𝐀ᵀ::Adjoint, 𝐱)
    𝐀 = parent(𝐀ᵀ)
    @inbounds for i ∈ eachindex(𝐲)
        𝐲ᵢ = zero(eltype(𝐲))
        @simd ivdep for j ∈ eachindex(𝐱)
            @fastmath 𝐲ᵢ += 𝐀[j,i] * 𝐱[j]
        end
        𝐲[i] = 𝐲ᵢ
    end
end
function jgemvavx!(𝐲, 𝐀, 𝐱)
    @turbo for i ∈ eachindex(𝐲)
        𝐲ᵢ = zero(eltype(𝐲))
        for j ∈ eachindex(𝐱)
            𝐲ᵢ += 𝐀[i,j] * 𝐱[j]
        end
        𝐲[i] = 𝐲ᵢ
    end
end
function jvar!(𝐬², 𝐀, x̄)
    @. s² = zero(eltype(𝐬²))
    @inbounds @fastmath for i ∈ 1:size(𝐀,2)
        @simd for j ∈ eachindex(𝐬²)
            δ = 𝐀[j,i] - x̄[j]
            𝐬²[j] += δ*δ
        end
    end
end
function jvaravx!(𝐬², 𝐀, x̄)
    @turbo for j ∈ eachindex(𝐬²)
        𝐬²ⱼ = zero(eltype(𝐬²))
        x̄ⱼ = x̄[j]
        for i ∈ 1:size(𝐀,2)
            δ = 𝐀[j,i] - x̄ⱼ
            𝐬²ⱼ += δ*δ
        end
        𝐬²[j] = 𝐬²ⱼ
    end
end
japlucBc!(D, a, B, c) =      @. D = a + B * c';
japlucBcavx!(D, a, B, c) = @turbo @. D = a + B * c';

function jOLSlp(y, X, β)
    lp = zero(eltype(y))
    @inbounds @fastmath for i ∈ eachindex(y)
        δ = y[i]
        @simd for j ∈ eachindex(β)
            δ -= X[i,j] * β[j]
        end
        lp += δ * δ
    end
    lp
end
function jOLSlp_avx(y, X, β)
    lp = zero(eltype(y))
    @turbo for i ∈ eachindex(y)
        δ = y[i]
        for j ∈ eachindex(β)
            δ -= X[i,j] * β[j]
        end
        lp += δ * δ
    end
    lp
end
function randomaccess(P, basis, coeffs::Vector{T}) where {T}
    C = length(coeffs)
    A = size(P, 1)
    p = zero(T)
    @fastmath @inbounds for c ∈ 1:C
        pc = coeffs[c]
        for a = 1:A
            pc *= P[a, basis[a, c]]
        end
        p += pc
    end
   return p
end
function randomaccessavx(P, basis, coeffs::Vector{T}) where {T}
    C = length(coeffs)
    A = size(P, 1)
    p = zero(T)
    @turbo for c ∈ 1:C
        pc = coeffs[c]
        for a = 1:A
            pc *= P[a, basis[a, c]]
        end
        p += pc
    end
    return p
end
function jlogdettriangle(B::Union{LowerTriangular,UpperTriangular})
    ld = 0.0
    @inbounds @fastmath for n ∈ 1:size(B,1)
        ld += log(B[n,n])
    end
    ld
end
function jlogdettriangleavx(B::Union{LowerTriangular,UpperTriangular})
    A = parent(B) # No longer supported
    ld = zero(eltype(A))
    @turbo for n ∈ axes(A,1)
        ld += log(A[n,n])
    end
    ld
end

function filter2d!(out::AbstractMatrix, A::AbstractMatrix, kern)
    @inbounds @fastmath for J in CartesianIndices(out)
        tmp = zero(eltype(out))
        for I ∈ CartesianIndices(kern)
            tmp += A[I + J] * kern[I]
        end
        out[J] = tmp
    end
    out
end
function filter2davx!(out::AbstractMatrix, A::AbstractMatrix, kern)
    @turbo for J in CartesianIndices(out)
        tmp = zero(eltype(out))
        for I ∈ CartesianIndices(kern)
            tmp += A[I + J] * kern[I]
        end
        out[J] = tmp
    end
    out
end

function filter2dunrolled!(out::AbstractMatrix, A::AbstractMatrix, kern::SizedOffsetMatrix{T,-1,1,-1,1}) where {T}
    rng1,  rng2  = axes(out)
    Base.Cartesian.@nexprs 3 jk -> Base.Cartesian.@nexprs 3 ik -> kern_ik_jk = kern[ik-2,jk-2]
    @inbounds for j in rng2
        @simd ivdep for i in rng1
            tmp_0 = zero(eltype(out))
            Base.Cartesian.@nexprs 3 jk -> Base.Cartesian.@nexprs 3 ik -> tmp_{ik+(jk-1)*3} =  Base.FastMath.add_fast(Base.FastMath.mul_fast(A[i+(ik-2),j+(jk-2)], kern_ik_jk), tmp_{ik+(jk-1)*3-1})
            out[i,j] = tmp_9
        end
    end
    out
end
function filter2dunrolledavx!(out::AbstractMatrix, A::AbstractMatrix, kern::SizedOffsetMatrix{T,-1,1,-1,1}) where {T}
    rng1,  rng2  = axes(out)
    Base.Cartesian.@nexprs 3 jk -> Base.Cartesian.@nexprs 3 ik -> kern_ik_jk = kern[ik-2,jk-2]
    @turbo for j in rng2, i in rng1
        tmp_0 = zero(eltype(out))
        Base.Cartesian.@nexprs 3 jk -> Base.Cartesian.@nexprs 3 ik -> tmp_{ik+(jk-1)*3} = A[i+(ik-2),j+(jk-2)] * kern_ik_jk + tmp_{ik+(jk-1)*3-1}
        out[i,j] = tmp_9
    end
    out
end

# function smooth_line!(sl,nrm1,j,i1,rl,ih2,denom)
#     @fastmath @inbounds @simd ivdep for i=i1:2:nrm1
#         sl[i,j]=denom*(rl[i,j]+ih2*(sl[i,j-1]+sl[i-1,j]+sl[i+1,j]+sl[i,j+1]))
#     end
# end
# function smooth_line_avx!(sl,nrm1,j,i1,sl,rl,ih2,denom)
#     @turbo for i=i1:2:nrm1
#         sl[i,j]=denom*(rl[i,j]+ih2*(sl[i,j-1]+sl[i-1,j]+sl[i+1,j]+sl[i,j+1]))
#     end
# end


text: include("integrated_environments/integrated_environments.jl")


text:
#jl #! format: off
# # Sequential Simulations with [PowerSimulations.jl](https://github.com/NREL-SIIP/PowerSimulations.jl)

# **Originally Contributed by**: Clayton Barrows

# ## Introduction

# PowerSimulations.jl supports simulations that consist of sequential optimization problems
# where results from previous problems inform subsequent problems in a variety of ways. This
# example demonstrates some of these capabilities to represent electricity market clearing.
# This example is intended to be an extension of the
# [OperationsProblem example.](https://nbviewer.jupyter.org/github/NREL-SIIP/SIIPExamples.jl/blob/master/notebook/3_PowerSimulations_examples/01_operations_problems.ipynb)

# ## Dependencies
using SIIPExamples

# ### Modeling Packages
using PowerSystems
using PowerSimulations
const PSI = PowerSimulations
using PowerSystemCaseBuilder
using Dates

# ### Optimization packages
using HiGHS #solver

# ### Optimizer
# It's most convenient to define an optimizer instance upfront and pass it into the
# `DecisionModel` constructor. For this example, we can use the free HiGHS solver with a
# relatively relaxed MIP gap (`ratioGap`) setting to improve speed.

solver = optimizer_with_attributes(HiGHS.Optimizer, "mip_rel_gap" => 0.5)

# ### Hourly day-ahead system
# First, we'll create a `System` with hourly data to represent day-ahead forecasted wind,
# solar, and load profiles:
sys_DA = build_system(PSITestSystems, "modified_RTS_GMLC_DA_sys")

# ### 5-Minute system
# The RTS data also includes 5-minute resolution time series data. So, we can create another
# `System` to represent 15 minute ahead forecasted data for a "real-time" market:
sys_RT = build_system(PSITestSystems, "modified_RTS_GMLC_RT_sys")

# ## `ProblemTemplate`s define stages
# Sequential simulations in PowerSimulations are created by defining `OperationsProblems`
# that represent stages, and how information flows between executions of a stage and
# between different stages.
#
# Let's start by defining a two stage simulation that might look like a typical day-Ahead
# and real-time electricity market clearing process.

# ### Day-ahead unit commitment stage
# First, we can define a unit commitment template for the day ahead problem. We can use the
# included UC template, but in this example, we'll replace the `ThermalBasicUnitCommitment`
# with the slightly more complex `ThermalStandardUnitCommitment` for the thermal generators.
template_uc = template_unit_commitment()
set_device_model!(template_uc, ThermalStandard, ThermalStandardUnitCommitment)

# ### Define the reference model for the real-time economic dispatch
# In addition to the manual specification process demonstrated in the OperationsProblem
# example, PSI also provides pre-specified templates for some standard problems:
template_ed = template_economic_dispatch(
    network = NetworkModel(StandardPTDFModel, PTDF = PTDF(sys_DA), use_slacks = true),#NetworkModel(CopperPlatePowerModel, use_slacks = true),
)

# ### Define the `SimulationModels`
# `DecisionModel`s define the problems that are executed in the simulation.
# The actual problem will change as the stage gets updated to represent
# different time periods, but the formulations applied to the components is constant within
# a stage. In this case, we want to define two stages with the `ProblemTemplate`s
# and the `System`s that we've already created.
models = SimulationModels(
    decision_models = [
        DecisionModel(template_uc, sys_DA, optimizer = solver, name = "UC"),
        DecisionModel(template_ed, sys_RT, optimizer = solver, name = "ED"),
    ],
)

# ### `SimulationSequence`
# Similar to an `ProblemTemplate`, the `SimulationSequence` provides a template of
# how to execute a sequential set of operations problems.

#nb # print_struct(SimulationSequence)

# Let's review some of the `SimulationSequence` arguments.

# ### Chronologies
# In PowerSimulations, chronologies define where information is flowing. There are two types
# of chronologies.
#  - inter-stage chronologies: Define how information flows between stages. e.g. day-ahead
# solutions are used to inform economic dispatch problems
#  - intra-stage chronologies: Define how information flows between multiple executions of a
# single stage. e.g. the dispatch setpoints of the first period of an economic dispatch problem
# are constrained by the ramping limits from setpoints in the final period of the previous problem.

# ### `FeedForward`
# The definition of exactly what information is passed using the defined chronologies is
# accomplished with `FeedForward`. Specifically, `FeedForward` is used
# to define what to do with information being passed with an inter-stage chronology. Let's
# define a `FeedForward` that affects the semi-continuous range constraints of thermal generators
# in the economic dispatch problems based on the value of the unit-commitment variables.

feedforward = Dict(
    "ED" => [
        SemiContinuousFeedforward(
            component_type = ThermalStandard,
            source = OnVariable,
            affected_values = [ActivePowerVariable],
        ),
    ],
)

# ### Sequencing
# The stage problem length, look-ahead, and other details surrounding the temporal Sequencing
# of stages are controlled using the structure of the time series data in the `System`s.
# So, to define a typical day-ahead - real-time sequence:
#  - Day ahead problems should represent 48 hours, advancing 24 hours after each execution (24-hour look-ahead)
#  - Real time problems should represent 1 hour (12 5-minute periods), advancing 15 min after each execution (15 min look-ahead)
# We can adjust the time series data to reflect this structure in each `System`:
# - `transform_single_time_series!(sys_DA, 48, Hour(1))`
# - `transform_single_time_series!(sys_RT, 12, Minute(15))`
#
# Now we can put it all together to define a `SimulationSequence`

DA_RT_sequence = SimulationSequence(
    models = models,
    ini_cond_chronology = InterProblemChronology(),
    feedforwards = feedforward,
)

# ## `Simulation`
# Now, we can build and execute a simulation using the `SimulationSequence` and `Stage`s
# that we've defined.
sim = Simulation(
    name = "rts-test",
    steps = 2,
    models = models,
    sequence = DA_RT_sequence,
    simulation_folder = mktempdir(".", cleanup = true),
)

# ### Build simulation
build!(sim)

# ### Execute simulation
# the following command returns the status of the simulation (0: is proper execution) and
# stores the results in a set of HDF5 files on disk.
execute!(sim, enable_progress_bar = false)

# ## Results
# To access the results, we need to load the simulation result metadata and then make
# requests to the specific data of interest. This allows you to efficiently access the
# results of interest without overloading resources.
results = SimulationResults(sim);
uc_results = get_decision_problem_results(results, "UC"); # UC stage result metadata
ed_results = get_decision_problem_results(results, "ED"); # ED stage result metadata

# We can read all the result variables
read_variables(uc_results)

# or all the parameters
read_parameters(uc_results)

# We can just list the variable names contained in `uc_results`:
list_variable_names(uc_results)

# and a number of parameters (this pattern also works for aux_variables, expressions, and duals)
list_parameter_names(uc_results)

# Now we can read the specific results of interest for a specific problem, time window (optional),
# and set of variables, duals, or parameters (optional)

Dict([
    v => read_variable(uc_results, v) for v in [
        "ActivePowerVariable__RenewableDispatch",
        "ActivePowerVariable__HydroDispatch",
        "StopVariable__ThermalStandard",
    ]
])

# Or if we want the result of just one variable, parameter, or dual (must be defined in the
# problem definition), we can use:

read_parameter(
    ed_results,
    "ActivePowerTimeSeriesParameter__RenewableFix",
    initial_time = DateTime("2020-01-01T06:00:00"),
    count = 5,
)

# * note that this returns the results of each execution step in a separate dataframe *
# If you want the realized results (without lookahead periods), you can call `read_realized_*`:

read_realized_variables(
    uc_results,
    ["ActivePowerVariable__ThermalStandard", "ActivePowerVariable__RenewableDispatch"],
)

# ## Plotting
# Take a look at the [plotting examples.](https://nbviewer.jupyter.org/github/NREL-SIIP/SIIPExamples.jl/blob/master/notebook/3_PowerSimulations_examples/04_bar_stack_plots.ipynb)

max_stars_repo_name: NREL-SIIP/Examples

max_issues_repo_name: NREL-SIIP/Examples

max_forks_repo_name: NREL-SIIP/Examples


text:
struct BBK{TGV, TF<:AbstractFloat, TM} <: SecondOrderNonMetropolisSampler
    ∇V!::TGV
    β::TF
    γ::TF
    M::TM
    Δt::TF
    σ::TF
end

"""
    BBK(∇V!, β, γ, M, Δt)

Set up the BBK integrator for inertial Langevin.

### Fields

* ∇V!   - In place gradient of the potential
* β     - Inverse temperature
* γ     - Damping Coefficient
* M     - Mass (either scalar or vector)
* Δt    - Time step
"""
function BBK(∇V!::TGV, β::TF, γ::TF, M::TM, Δt::TF) where {TGV, TF<:AbstractFloat,TM}
    σ = sqrt(γ * Δt / β);
    return BBK(∇V!, β, γ, M, Δt, σ)
end

mutable struct BBKState{Tq, Tx<:AbstractVector{Tq}} <:SecondOrderNonMetropolisSamplerState
    x::Tx
    p_mid::Tq
    ∇V::Tq
end

function InitState!(x₀, sampler::BBK)
    ∇V = similar(x₀[1]);
    sampler.∇V!(∇V, x₀[1]);
    return BBKState(x₀, similar(x₀[1]), copy(∇V));
end

function InitState(x₀, sampler::BBK)

    ∇V = deepcopy(x₀[1]);
    sampler.∇V!(∇V, x₀[1]);
    return BBKState(deepcopy(x₀), similar(x₀[1]), copy(∇V));
end

function UpdateState!(state::BBKState, sampler::BBK)

    @. state.p_mid = state.x[2] - 0.5 * sampler.Δt * state.∇V - 0.5 * sampler.Δt * sampler.γ/sampler.M * state.x[2] + sampler.σ * randn();
    @. state.x[1] = state.x[1] + sampler.Δt/sampler.M * state.p_mid
    sampler.∇V!(state.∇V, state.x[1]);
    @. state.x[2] = (state.p_mid - 0.5 * sampler.Δt * state.∇V + sampler.σ * randn())/(1 + 0.5 * sampler.Δt * sampler.γ/sampler.M);

    state
end

max_stars_repo_name: cortner/JuBasicMD


text:
"""
    is_better(A, B)
    return true if A is better than B in a minimization problem.
    Feasibility rules and dominated criteria are used in comparison.
"""
function is_better(A::xf_indiv, B::xf_indiv)
    return A.f < B.f
end

# feasibility rules
function is_better(A::xfgh_indiv, B::xfgh_indiv)

    A_vio = A.sum_violations
    B_vio = B.sum_violations

    if A_vio < B_vio
        return true
    elseif B_vio < A_vio
        return false
    end

    return A.f < B.f

end

# is B dominated by A?
function is_better(
    A::xFgh_indiv,
    B::xFgh_indiv
)

    A_vio = A.sum_violations
    B_vio = B.sum_violations

    if A_vio < B_vio
        return true
    elseif B_vio < A_vio
        return false
    end

    compare(A.f, B.f) == 1

end

"""
    does A dominate B?
"""
dominates( A::xFgh_indiv, B::xFgh_indiv) = is_better(A, B)

"""
    get_best(population)
    return best element in population according to the `is_better` function.
"""
function get_best(population::Array)
    if isempty(population)
        return nothing
    end

    best = population[1]
    for i in 2:length(population)
        if is_better(population[i], best)
            best = population[i]
        end
    end

    return best
end

"""
    compare(a, b)
    compares whether two vectors are dominated or not.
    Output:
    `1` if argument 1 (a) dominates argument 2 (b).
    `2` if argument 2 (b) dominates argument 1 (a).
    `3` if both arguments 1 (a) and 2 (b) are incomparable.
    `0` if both arguments 1 (a) and 2 (b) are equal.
"""
function compare(a::Vector, b::Vector)
    k = length(a)
    @assert k == length(b)

    i = 1
    while i <= k && a[i] == b[i]
        i += 1;
    end

    if i > k
        return 0 # equals
    end

    if a[i] < b[i]

        for j = i+1:k# (j = i+1; j <= k; ++j)
            if b[j] < a[j]
                return 3 #a and b are incomparable
            end
        end

        return 1; #  a dominates b
    end

    for j = i+1:k #(j = i+1; j < k; ++j)
        if (a[j] < b[j])
            return 3 #; // a and b are incomparable
        end
    end

    return 2 # b dominates a

end

function compare(a::xFgh_indiv, b::xFgh_indiv)

    A_vio = a.sum_violations
    B_vio = b.sum_violations

    if A_vio < B_vio
        return 1
    elseif B_vio < A_vio
        return 2
    end

    compare(a.f, b.f)
end

"""
    argworst(population)
    return the index of the worst element in population
"""
function argworst(population::Array)
    if isempty(population)
        return -1
    end

    i_worst = 1
    for i in 2:length(population)
        if is_better(population[i_worst], population[i])
            i_worst = i
        end
    end

    return i_worst
end

"""
    argworst(population)
    return the index of the worst element in population
"""
function argbest(population::Array)
    if isempty(population)
        return -1
    end

    i_best = 1
    for i in 2:length(population)
        if is_better(population[i], population[i_best])
            i_best = i
        end
    end

    return i_best
end


text:
struct PipelineViewportStateCreateInfo
    mHandleRef::Ref{vk.VkPipelineViewportStateCreateInfo}
    mRefserve::Vector{Any}

    function PipelineViewportStateCreateInfo(;
        pNext::Ptr{Cvoid} = C_NULL,
        flags::vk.VkPipelineViewportStateCreateFlags = vk.VkFlags(0),
        viewports::Vector{vk.VkViewport} = Vector{vk.VkViewport}(),
        scissors::Vector{vk.VkRect2D} = Vector{vk.VkRect2D}()
    )
        this = new(Ref(vk.VkPipelineViewportStateCreateInfo(
            vk.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, #sType::VkStructureType
            pNext, #::Ptr{Cvoid}
            flags, #::VkPipelineViewportStateCreateFlags
            length(viewports), #viewportCount::UInt32
            pointer(viewports), #pViewports::Ptr{VkViewport}
            length(scissors), #scissorCount::UInt32
            pointer(scissors) #pScissors::Ptr{VkRect2D}
        )), [viewports, scissors])
    end
end

function handleRef(this::PipelineViewportStateCreateInfo)::Ref{vk.VkPipelineViewportStateCreateInfo}
    this.mHandleRef
end


text:
#!NOTE: This section defines functions that need to be overloaded in order for custom Kernel inside an existing Baytes AbstractAlgorithm to work with corresponding Baytes package.
############################################################################################

#########################################
"""
$(TYPEDEF)
Abstract super type for Algorithm Kernels. New Kernels needs to be inside corresponding `AbstractAlgorithm`.
"""
abstract type AbstractKernel end

"""
    $(FUNCTIONNAME)
Propagate algorithm one step forward.
"""
function propagate end

"""
    $(FUNCTIONNAME)
Inplace version of [`propagate`](@ref).
"""
function propagate! end

function infer end

"""
    $(FUNCTIONNAME)
Initialize struct.
"""
function init end

############################################################################################
# Export
export
    AbstractKernel,
    propagate,
    propagate!,
    init,
    infer