text:
function integralimage(img, bins; minval = 0, maxval = 1)
    # if typeof(img) == Array{RGB{Normed{UInt8,8}},2}
    #     arrayimg = float.(Gray.(img))
    # elseif typeof(img) == Array{Float64,2}
    #     arrayimg = img
    # end

    row, col = size(img)
    integral_image = zeros(row, col, bins)
    #edges = range(0, step = 1/bins, stop = 1)
    #edges = range(minval, step = maxval/bins, stop = maxval)
    edges = StatsBase.histrange([minval, maxval], bins) # Make this work
    @show collect(edges)

    for i = 1:row
        for j = 1:col
            bin = searchsortedlast(edges, img[i,j])
            @show bin, img[i,j]
            integral_image[i, j, bin] = 1
            # Cummulative sum for each layer at that pixel
            for b = 1:bins
                if i == 1 && j == 1
                    left = 0
                    top = 0
                    topleft = 0
                elseif i == 1 && j != 1
                    left = 0
                    topleft = 0
                    top = integral_image[i, j - 1, b]
                elseif i != 1 && j == 1
                    top = 0
                    topleft = 0
                    left = integral_image[i - 1, j, b]
                else
                    left = integral_image[i - 1, j, b]
                    top = integral_image[i, j - 1, b]
                    topleft = integral_image[i - 1, j - 1, b]
                end
                integral_image[i, j, b] = left + top - topleft + integral_image[i, j, b]
            end
        end
    end

    return integral_image

end

function integralhistogram(interal_image, k, m, l, n)
    if k == 1
        k = 2
    end

    if m == 1
        m = 2
    end

    bins = size(integral_image)[3]
    hist = zeros(bins)
    for b = 1:bins
        hist[b] = integral_image[k - 1, m - 1, b] + integral_image[l, n, b]

            - integral_image[k - 1, n, b] - integral_image[l, m - 1, b]
    end

    return hist

end


text:
using Documenter, Query

# Install dependencies and precompile everything
Pkg.add("DataFrames")
Pkg.add("TypedTables")
using DataFrames
using NamedTuples
using TypedTables

makedocs(
	modules = [Query],
	format = Documenter.Formats.HTML,
	sitename = "Query.jl",
	pages = [
		"Introduction" => "index.md",
		"Query Commands" => "querycommands.md",
		"Examples" => "examples.md",
		"Internals" => "internals.md"]
)

deploydocs(
    deps = nothing,
    make = nothing,
    target = "build",
    repo = "github.com/davidanthoff/Query.jl.git",
    julia = "0.5"
)

ext: jl


text:
using Mocking

delete_scaling_policy_1_patch = @patch function delete_scaling_policy(a...; b...)
    return Dict{String, Any}()
end

deregister_scalable_target_1_patch = @patch function deregister_scalable_target(a...; b...)
    return Dict{String, Any}()
end

describe_scalable_targets_1_patch = @patch function describe_scalable_targets(a...; b...)
    return Dict{String, Any}("ScalableTargets" => Any[Dict{String, Any}("SuspendedState" => Dict{String, Any}("DynamicScalingInSuspended" => false, "DynamicScalingOutSuspended" => false, "ScheduledScalingSuspended" => false), "CreationTime" => "2019-05-06T11:21:46.199Z", "MinCapacity" => 1, "MaxCapacity" => 10, "ResourceId" => "service/default/web-app", "RoleARN" => "arn:aws:iam::012345678910:role/aws-service-role/ecs.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_ECSService", "ScalableDimension" => "ecs:service:DesiredCount", "ServiceNamespace" => "ecs")])
end

describe_scaling_activities_1_patch = @patch function describe_scaling_activities(a...; b...)
    return Dict{String, Any}("ScalingActivities" => Any[Dict{String, Any}("StartTime" => "2019-05-06T16:03:58.171Z", "Description" => "Setting desired count to 1.", "EndTime" => "2019-05-06T16:04:32.111Z", "ActivityId" => "e6c5f7d1-dbbb-4a3f-89b2-51f33e766399", "StatusCode" => "Successful", "ResourceId" => "service/default/web-app", "ServiceNamespace" => "ecs", "ScalableDimension" => "ecs:service:DesiredCount", "Cause" => "monitor alarm web-app-cpu-lt-25 in state ALARM triggered policy web-app-cpu-lt-25", "StatusMessage" => "Successfully set desired count to 1. Change successfully fulfilled by ecs.")])
end

describe_scaling_policies_1_patch = @patch function describe_scaling_policies(a...; b...)
    return Dict{String, Any}("NextToken" => "", "ScalingPolicies" => Any[Dict{String, Any}("PolicyName" => "web-app-cpu-gt-75", "PolicyType" => "StepScaling", "CreationTime" => "2019-05-06T12:11:39.230Z", "Alarms" => Any[Dict{String, Any}("AlarmName" => "web-app-cpu-gt-75", "AlarmARN" => "arn:aws:cloudwatch:us-west-2:012345678910:alarm:web-app-cpu-gt-75")], "ResourceId" => "service/default/web-app", "PolicyARN" => "arn:aws:autoscaling:us-west-2:012345678910:scalingPolicy:6d8972f3-efc8-437c-92d1-6270f29a66e7:resource/ecs/service/default/web-app:policyName/web-app-cpu-gt-75", "ServiceNamespace" => "ecs", "ScalableDimension" => "ecs:service:DesiredCount", "StepScalingPolicyConfiguration" => Dict{String, Any}("StepAdjustments" => Any[Dict{String, Any}("ScalingAdjustment" => 200, "MetricIntervalLowerBound" => 0)], "Cooldown" => 60, "AdjustmentType" => "PercentChangeInCapacity"))])
end

put_scaling_policy_1_patch = @patch function put_scaling_policy(a...; b...)
    return Dict{String, Any}("Alarms" => Any[Dict{String, Any}("AlarmName" => "TargetTracking-service/default/web-app-AlarmHigh-d4f0770c-b46e-434a-a60f-3b36d653feca", "AlarmARN" => "arn:aws:cloudwatch:us-west-2:012345678910:alarm:TargetTracking-service/default/web-app-AlarmHigh-d4f0770c-b46e-434a-a60f-3b36d653feca"), Dict{String, Any}("AlarmName" => "TargetTracking-service/default/web-app-AlarmLow-1b437334-d19b-4a63-a812-6c67aaf2910d", "AlarmARN" => "arn:aws:cloudwatch:us-west-2:012345678910:alarm:TargetTracking-service/default/web-app-AlarmLow-1b437334-d19b-4a63-a812-6c67aaf2910d")], "PolicyARN" => "arn:aws:autoscaling:us-west-2:012345678910:scalingPolicy:6d8972f3-efc8-437c-92d1-6270f29a66e7:resource/ecs/service/default/web-app:policyName/cpu75-target-tracking-scaling-policy")
end


text:
# Copyright (c) 2020: Matthew Wilhelm & Matthew Stuber.
# This work is licensed under the Creative Commons Attribution-NonCommercial-
# ShareAlike 4.0 International License. To view a copy of this license, visit
# http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative
# Commons, PO Box 1866, Mountain View, CA 94042, USA.
#############################################################################
# Dynamic Bounds - pODEs Discrete
# A package for discretize and relax methods for bounding pODEs.
# See https://github.com/PSORLab/DynamicBoundspODEsDiscrete.jl
#############################################################################
# src/DiscretizeRelax/method/hermite_obreschkoff.jl
# Defines functions needed to perform a hermite_obreshkoff iteration.
#############################################################################

"""
HermiteObreschkoff

A structure that stores the cofficient of the (P,Q)-Hermite-Obreschkoff method.
(Offset due to method being zero indexed and Julia begin one indexed). The
constructor `HermiteObreschkoff(p::Val{P}, q::Val{Q}) where {P, Q}` or
`HermiteObreschkoff(p::Int, q::Int)` are used for the (P,Q)-method.

$(TYPEDFIELDS)
"""
struct HermiteObreschkoff <: AbstractStateContractorName
    "Cpq[i=1:p] index starting at i = 1 rather than 0"
    cpq::Vector{Float64}
    "Cqp[i=1:q] index starting at i = 1 rather than 0"
    cqp::Vector{Float64}
    "gamma for method"
    γ::Float64
    "Explicit order Hermite-Obreschkoff"
    p::Int64
    "Implicit order Hermite-Obreschkoff"
    q::Int64
    "Total order Hermite-Obreschkoff"
    k::Int64
end

function HermiteObreschkoff(p::Val{P}, q::Val{Q}) where {P, Q}
    temp_cpq = 1.0
    temp_cqp = 1.0
    cpq = zeros(P + 1)
    cqp = zeros(Q + 1)
    cpq[1] = temp_cpq
    cqp[1] = temp_cqp
    for i = 1:P
        temp_cpq *= (P - i + 1.0)/(P + Q - i + 1)
        cpq[i + 1] = temp_cpq
    end
    γ = 1.0
    for i = 1:Q
        temp_cqp *= (Q - i + 1.0)/(Q + P - i + 1)
        cqp[i + 1] = temp_cqp
        γ *= -i/(P+i)
    end
    K = P + Q + 1
    HermiteObreschkoff(cpq, cqp, γ, P, Q, K)
end
HermiteObreschkoff(p::Int, q::Int) = HermiteObreschkoff(Val(p), Val(q))

"""
HermiteObreschkoffFunctor

A functor used in computing bounds and relaxations via Hermite-Obreschkoff's method. The
implementation of the parametric Hermite-Obreschkoff's method based on the non-parametric
version given in (1).

1. [Nedialkov NS, and Jackson KR. "An interval Hermite-Obreschkoff method for
computing rigorous bounds on the solution of an initial value problem for an
ordinary differential equation." Reliable Computing 5.3 (1999): 289-310.](https://link.springer.com/article/10.1023/A:1009936607335)
2. [Nedialkov NS. "Computing rigorous bounds on the solution of an
initial value problem for an ordinary differential equation." University
of Toronto. 2000.](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.633.9654&rep=rep1&type=pdf)
"""
mutable struct HermiteObreschkoffFunctor{F <: Function, Pp1, Qp1, K, T <: Real, S <: Real, NY} <: AbstractStateContractor
    hermite_obreschkoff::HermiteObreschkoff
    η::Interval{T}
    μX::Vector{S}
    ρP::Vector{S}
    gⱼ₊₁::Vector{S}
    nx::Int64
    set_tf!_pred::TaylorFunctor!{F, K, T, S}
    real_tf!_pred::TaylorFunctor!{F, Pp1, T, T}
    Jf!_pred::JacTaylorFunctor!{F, Pp1, T, S, NY}
    Rⱼ₊₁::Vector{S}
    mRⱼ₊₁::Vector{T}
    f̃val_pred::Vector{Vector{T}}
    f̃_pred::Vector{Vector{S}}
    Vⱼ₊₁::Vector{Float64}
    X_predict::Vector{S}
    q_predict::Int64
    real_tf!_correct::TaylorFunctor!{F, Qp1, T, T}
    Jf!_correct::JacTaylorFunctor!{F, Qp1, T, S, NY}
    xval_correct::Vector{T}
    f̃val_correct::Vector{Vector{T}}
    sum_p::Vector{S}
    sum_q::Vector{S}
    Δⱼ₊₁::Vector{S}
    pred_Jxmat::Matrix{S}
    pred_Jxvec::Vector{S}
    pred_Jpvec::Vector{S}
    δⱼ₊₁::Vector{S}
    precond::Matrix{Float64}
    precond2::Matrix{Float64}
    correct_B::Matrix{S}
    correct_Bvec::Vector{S}
    correct_C::Matrix{S}
    Inx::UniformScaling{Bool}
    Uj::Vector{S}
    Jpdiff::Matrix{S}
    Cp::Matrix{S}
    CprP::Vector{S}
    correct_Jmid::Matrix{S}
    Uj2::Vector{S}
    B2::Matrix{S}
    B2vec::Vector{S}
    rX::Vector{S}
    Yδⱼ₊₁::Vector{S}
    Y2δⱼ₊₁::Vector{S}
    Y2Jpdiff::Matrix{S}
    Y2Jpvec::Vector{S}
    YC::Matrix{S}
    YUj2::Vector{S}
end
function HermiteObreschkoffFunctor(f!::F, nx::Int, np::Int, p::Val{P}, q::Val{Q},
                                   s::S, t::T) where {F,P,Q,S,T}

    K = P + Q + 1
    hermite_obreschkoff = HermiteObreschkoff(p, q)
    η = Interval{T}(0.0,1.0)
    μX = zeros(S, nx)
    ρP = zeros(S, np)
    gⱼ₊₁ = zeros(S, nx)
    set_tf!_pred = TaylorFunctor!(f!, nx, np, Val(K), zero(S), zero(T))
    real_tf!_pred = TaylorFunctor!(f!, nx, np, Val(P), zero(T), zero(T))
    Jf!_pred = JacTaylorFunctor!(f!, nx, np, Val(P), zero(S), zero(T))
    Rⱼ₊₁ = zeros(S, nx)
    mRⱼ₊₁ = zeros(Float64, nx)

    f̃val_pred = Vector{Float64}[]
    for i = 1:(P + 1)
        push!(f̃val_pred, zeros(Float64, nx))
    end

    f̃_pred = Vector{S}[]
    for i = 1:(K + 1)
        push!(f̃_pred, zeros(S, nx))
    end

    Vⱼ₊₁ = zeros(nx)
    X_predict = zeros(S, nx)
    q_predict = P

    real_tf!_correct = TaylorFunctor!(f!, nx, np, Val(Q), zero(T), zero(T))
    Jf!_correct = JacTaylorFunctor!(f!, nx, np, Val(Q), zero(S), zero(T))
    xval_correct = zeros(Float64, nx)

    f̃val_correct = Vector{Float64}[]
    for i = 1:(Q + 1)
        push!(f̃val_correct, zeros(Float64, nx))
    end

    sum_p = zeros(S, nx)
    sum_q = zeros(S, nx)
    P1 = P + 1
    Q1 = Q + 1

    Δⱼ₊₁ = zeros(S, nx)

    pred_Jxmat = zeros(S, nx, nx)
    pred_Jxvec = zeros(S, nx)
    pred_Jpvec = zeros(S, nx)

    δⱼ₊₁ = zeros(S, nx)
    precond = zeros(Float64, nx, nx)
    precond2 = zeros(Float64, nx, nx)
    correct_B = zeros(S, nx, nx)
    correct_Bvec = zeros(S, nx)
    correct_C = zeros(S, nx, nx)
    Inx = I

    Uj = zeros(S, nx)
    Jpdiff = zeros(S, nx, np)
    Cp = zeros(S, nx, np)
    CprP = zeros(S, nx)

    correct_Jmid = zeros(S, nx, nx)
    Uj2 = zeros(S, nx)
    B2 = zeros(S, nx, nx)
    B2vec = zeros(S, nx)
    rX = zeros(S, nx)
    Yδⱼ₊₁ = zeros(S, nx)

    Y2δⱼ₊₁ = zeros(S, nx)
    Y2Jpdiff = zeros(S, nx, np)
    Y2Jpvec = zeros(S, nx)
    YC = zeros(S, nx, nx)
    YUj2 = zeros(S, nx)

    HermiteObreschkoffFunctor{F, P1, Q1, K+1, T, S, nx + np}(hermite_obreschkoff, η, μX, ρP, gⱼ₊₁, nx,
                                                             set_tf!_pred, real_tf!_pred, Jf!_pred, Rⱼ₊₁,
                                                             mRⱼ₊₁, f̃val_pred, f̃_pred, Vⱼ₊₁,
                                                             X_predict, q_predict, real_tf!_correct,
                                                             Jf!_correct, xval_correct, f̃val_correct,
                                                             sum_p, sum_q, Δⱼ₊₁, pred_Jxmat, pred_Jxvec,
                                                             pred_Jpvec, δⱼ₊₁, precond, precond2,
                                                             correct_B, correct_Bvec, correct_C, Inx,
                                                             Uj, Jpdiff, Cp,
                                                             CprP, correct_Jmid, Uj2, B2, B2vec, rX, Yδⱼ₊₁,
                                                             Y2δⱼ₊₁, Y2Jpdiff, Y2Jpvec, YC, YUj2)
end

function state_contractor(m::HermiteObreschkoff, f, Jx!, Jp!, nx, np, style, s, h)
    HermiteObreschkoffFunctor(f, nx, np, Val(m.p), Val(m.q), style, s)
end
state_contractor_k(m::HermiteObreschkoff) = m.k
state_contractor_γ(m::HermiteObreschkoff) = m.γ
state_contractor_steps(m::HermiteObreschkoff) = 2
state_contractor_integrator(m::HermiteObreschkoff) = CVODE_Adams()

function _pred_compute_Rj!(d, c, t)
    q = d.q_predict
    d.set_tf!_pred(d.f̃_pred, c.Xj_apriori, c.P, t)
    hq = c.hj_computed^(d.q_predict + 1)
    for i = 1:d.nx
        @inbounds d.Rⱼ₊₁[i] = hq*d.f̃_pred[q + 2][i]
    end
    return nothing
end

function _pred_compute_real_pnt!(d, c, t)
    d.real_tf!_pred(d.f̃val_pred, c.xval, c.pval, t)
    @__dot__ d.Vⱼ₊₁ = c.xval
    for i = 1:d.q_predict
        h = c.hj_computed^i
        @__dot__ d.Vⱼ₊₁ += h*d.f̃val_pred[i + 1]
    end
    return nothing
end

function _pred_compute_rhs_jacobian!(d, c::ContractorStorage{S}, t) where S
    hⱼ = c.hj_computed
    Jf!_pred = d.Jf!_pred
    μ!(d.μX, c.Xj_0, c.xval, d.η)
    ρ!(d.ρP, c.P, c.pval, d.η)
    set_JxJp!(Jf!_pred, d.μX, d.ρP, t)
    for i = 1:d.q_predict
        hji1 = hⱼ^i
        if i == 1
            fill!(Jf!_pred.Jxsto, zero(S))
            for j = 1:d.nx
                Jf!_pred.Jxsto[j,j] = one(S)
            end
        else
            @__dot__ Jf!_pred.Jxsto += hji1*Jf!_pred.Jx[i+1]
        end
        @__dot__ Jf!_pred.Jpsto += hji1*Jf!_pred.Jp[i+1]
    end
    return nothing
end

function _hermite_obreschkoff_predictor!(d::HermiteObreschkoffFunctor{F,P1,Q1,K,T,S,NY},
                                         c::ContractorStorage{S}) where {F,P1,Q1,K,T,S,NY}

    _pred_compute_Rj!(d, c, c.times[1])
    _pred_compute_real_pnt!(d, c, c.times[1])
    _pred_compute_rhs_jacobian!(d, c, c.times[1])

    mul_split!(d.pred_Jxmat, d.Jf!_pred.Jxsto, c.A_Q[2], d.nx)
    mul_split!(d.pred_Jxvec, d.pred_Jxmat,     c.Δ[2],   d.nx)
    mul_split!(d.pred_Jpvec, d.Jf!_pred.Jpsto, c.rP,     d.nx)
    @__dot__ d.X_predict = d.Vⱼ₊₁ + d.Rⱼ₊₁ + d.pred_Jxvec + d.pred_Jpvec

    return nothing
end

function (d::HermiteObreschkoffFunctor{F,P1,Q1,K,T,S,NY})(contract::ContractorStorage{S},
                                                          result::StepResult{S},
                                                          count::Int) where {F, P1, Q1, K, T, S, NY}

    _hermite_obreschkoff_predictor!(d, contract)

    map!(mid, d.xval_correct, d.X_predict)     # GOOD

    # extract method constants
    ho = d.hermite_obreschkoff
    γ = ho.γ
    p = ho.p                     # GOOD
    q = ho.q                     # GOOD
    k = ho.k                     # GOOD
    nx = d.nx                    # GOOD
    np = length(contract.pval)   # GOOD

    hⱼ = contract.hj_computed    # GOOD
    t = contract.times[1]        # GOOD
    hjk = hⱼ^k                   # GOOD
    _sum_pred(y, i) = y[i+1]*ho.cpq[i+1]*hⱼ^(i)
    _sum_q(y, i) = (ho.cqp[i+1]*(-hⱼ)^i)*y[i+1]

    d.sum_p .= mapreduce(i -> _sum_pred(d.f̃val_pred, i), +, 1:p)

    d.real_tf!_correct(d.f̃val_correct, d.xval_correct, contract.pval, t)
    d.sum_q .=  mapreduce(i -> _sum_q(d.f̃val_correct, i), +, 1:q)

    @__dot__ d.δⱼ₊₁ = contract.xval - d.xval_correct + d.sum_p - d.sum_q + γ*hjk*d.f̃_pred[k + 1]   # Looks wrong based on impact....

    d.Jf!_pred.Jxsto .= mapreduce(i -> _sum_pred(d.Jf!_pred.Jx, i), +, 1:p)
    d.Jf!_pred.Jpsto .= mapreduce(i -> _sum_pred(d.Jf!_pred.Jp, i), +, 1:p)
    d.Jf!_pred.Jxsto += d.Inx

    μ!(d.μX, d.X_predict, d.xval_correct, d.η)
    ρ!(d.ρP, contract.P, contract.pval, d.η)
    set_JxJp!(d.Jf!_correct, d.μX, d.ρP, t)
    d.Jf!_correct.Jxsto .= mapreduce(i -> _sum_q(d.Jf!_correct.Jx, i), +, 1:q)
    d.Jf!_correct.Jpsto .= mapreduce(i -> _sum_q(d.Jf!_correct.Jp, i), +, 1:q)
    d.Jf!_correct.Jxsto += d.Inx

    map!(mid, d.precond, d.Jf!_correct.Jxsto)
    lu!(d.precond)

    mul_split!(d.pred_Jxmat, d.Jf!_pred.Jxsto, contract.A_Q[2], nx)
    d.correct_B = d.precond\d.pred_Jxmat
    mul_split!(d.correct_Bvec, d.correct_B, contract.Δ[2], nx)

    d.correct_C = d.precond\d.Jf!_correct.Jxsto
    @__dot__ d.correct_C *= -1.0
    d.correct_C += d.Inx

    @__dot__ d.rX = d.X_predict - d.xval_correct
    mul_split!(d.Uj, d.correct_C, d.rX, nx)

    @__dot__ d.Jpdiff = d.Jf!_pred.Jpsto - d.Jf!_correct.Jpsto
    d.Cp = d.precond\d.Jpdiff
    mul_split!(d.CprP, d.Cp, contract.rP, nx)
    mul_split!(d.Yδⱼ₊₁, d.precond, d.δⱼ₊₁, nx)
    @__dot__ contract.X_computed = d.xval_correct + d.correct_Bvec + d.Uj + d.CprP + d.Yδⱼ₊₁

    @__dot__ contract.X_computed = contract.X_computed ∩ d.X_predict

    affine_contract!(contract.X_computed, contract.P, contract.pval, nx, np)
    @__dot__ contract.xval_computed = mid(contract.X_computed)

    # calculation block for computing Aⱼ₊₁ and inv(Aⱼ₊₁)
    mul_split!(d.correct_Jmid, d.Jf!_correct.Jxsto, contract.A_Q[2], nx)
    @__dot__ contract.B = mid(d.correct_Jmid)
    calculateQ!(contract.A_Q[1], contract.B, nx)
    calculateQinv!(contract.A_inv[1], contract.A_Q[1], nx)

    mul_split!(d.precond2, contract.A_inv[1], d.precond, nx)
    @__dot__ d.Uj2 = contract.X_computed - d.xval_correct
    mul_split!(d.B2, d.precond, d.correct_Jmid, nx)
    mul_split!(d.B2vec, d.B2, contract.Δ[2], nx)

    mul_split!(d.Y2δⱼ₊₁, d.precond2, d.δⱼ₊₁, nx)
    mul_split!(d.Y2Jpdiff, d.precond2, d.Jpdiff, nx)
    mul_split!(d.Y2Jpvec, d.Y2Jpdiff, contract.rP, nx)
    mul_split!(d.YC, contract.A_inv[1], d.correct_C, nx)
    mul_split!(d.YUj2, d.YC, d.Uj2, nx)

    @__dot__ d.Δⱼ₊₁ = d.Y2δⱼ₊₁ + d.Y2Jpvec + d.B2vec + d.YUj2

    contract.Δ[1] = copy(d.Δⱼ₊₁)

    return RELAXATION_NOT_CALLED
end

get_Δ(f::HermiteObreschkoffFunctor) = f.Δⱼ₊₁
advance_contractor_buffer!(lf::HermiteObreschkoffFunctor) = nothing


text:
#####
##### Dycore API
#####

abstract type FieldLocation end
struct CentField <: FieldLocation end
struct FaceField <: FieldLocation end

field_loc(::CentField) = :cent
field_loc(::FaceField) = :face

#=
This file provides a list of methods that TurbulenceConvection.jl
expects that the host dycore supports. This is experimental, as
we're not sure how the data structures / flow control will shake out.
=#

#####
##### Grid mean fields
#####

""" Prognostic fields for the host model """
prognostic(state, fl) = getproperty(state.prog, field_loc(fl))

center_prog_grid_mean(state) = prognostic(state, CentField())
face_prog_grid_mean(state) = prognostic(state, FaceField())

""" Auxiliary fields for the host model """
aux(state, fl) = getproperty(state.aux, field_loc(fl))

center_aux_grid_mean(state) = aux(state, CentField())
face_aux_grid_mean(state) = aux(state, FaceField())

""" Tendency fields for the host model """
tendencies(state, fl) = getproperty(state.tendencies, field_loc(fl))

center_tendencies_grid_mean(state) = tendencies(state, CentField())

""" Reference state fields for the host model """
ref_state(state, fl) = aux(state, fl).ref_state

face_ref_state(state) = ref_state(state, FaceField())
center_ref_state(state) = ref_state(state, CentField())

#####
##### TurbulenceConvection fields
#####

#= Prognostic fields for TurbulenceConvection =#
prognostic_turbconv(state, fl) = prognostic(state, fl).turbconv

center_prog_updrafts(state) = prognostic_turbconv(state, CentField()).up
face_prog_updrafts(state) = prognostic_turbconv(state, FaceField()).up
center_prog_environment(state) = prognostic_turbconv(state, CentField()).en
center_prog_precipitation(state) = prognostic_turbconv(state, CentField()).pr

#= Auxiliary fields for TurbulenceConvection =#
aux_turbconv(state, fl) = aux(state, fl).turbconv

center_aux_turbconv(state) = aux_turbconv(state, CentField())
face_aux_turbconv(state) = aux_turbconv(state, FaceField())
center_aux_updrafts(state) = aux_turbconv(state, CentField()).up
face_aux_updrafts(state) = aux_turbconv(state, FaceField()).up
center_aux_environment(state) = aux_turbconv(state, CentField()).en
center_aux_bulk(state) = aux_turbconv(state, CentField()).bulk
face_aux_bulk(state) = aux_turbconv(state, FaceField()).bulk
center_aux_environment_2m(state) = aux_turbconv(state, CentField()).en_2m
face_aux_environment(state) = aux_turbconv(state, FaceField()).en

#= Tendency fields for TurbulenceConvection =#
tendencies_turbconv(state, fl) = tendencies(state, fl).turbconv

center_tendencies_turbconv(state) = tendencies_turbconv(state, CentField())
face_tendencies_turbconv(state) = tendencies_turbconv(state, FaceField())
center_tendencies_updrafts(state) = tendencies_turbconv(state, CentField()).up
center_tendencies_environment(state) = tendencies_turbconv(state, CentField()).en
center_tendencies_precipitation(state) = tendencies_turbconv(state, CentField()).pr
face_tendencies_updrafts(state) = tendencies_turbconv(state, FaceField()).up


text:
include("nodecalc.jl")

order = parse(ARGS[1])
sbp = TetSBP{Float64}(degree=order, reorder=false, internal=true)
#ref_verts = [0. 1 0; 0 0 1]

xi, coords = nodecalc(sbp, true)

nnodes = sbp.numnodes
println("size(coords) = ", size(coords))
for i=1:nnodes
  println("node $i xi coordinates = ", xi[:, i])
end
print("\n")
for i=1:nnodes
  println("node $i xy coordinates = ", coords[:, i])
end

println("coords = ", coords)


text:
# Autogenerated wrapper script for LibTorchCAPI_jll for x86_64-linux-gnu-cxx11
export libtorch_capi

JLLWrappers.@generate_wrapper_header("LibTorchCAPI")
JLLWrappers.@declare_library_product(libtorch_capi, "libtorch_capi.so")
function __init__()
    JLLWrappers.@generate_init_header()
    JLLWrappers.@init_library_product(
        libtorch_capi,
        "lib/libtorch_capi.so",
        nothing,
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
struct TimeoutException <: Exception
    timeout::Float64 # seconds
end

"""
    timeout_call(f, timeout; pollint=0.1)

Execute function `f()` with a maximum timeout `timeout` seconds.

An `TimeoutException(timeout)` exception will be thrown if it exceeds
the maximum timeout. If `f()` exits with error, it will be rethrown.
"""
function timeout_call(f::Function, timeout::Real; pollint=0.1)
    start = now()

    t = @task f()
    schedule(t)

    while !istaskdone(t)
        if (now()-start).value >= 1000timeout
            schedule(t, TimeoutException(timeout), error=true)
            sleep(pollint) # wait a while for the task to update its state
            break
        end
        sleep(pollint)
    end

    if t.state == :failed
        throw(t.exception)
    else
        return t.result
    end
end

"""
    with_cache_dir(f, cache_dir; by=isdir) -> Bool

Conditionally run function `f()` based on the status of `by(cache_dir)`.

If `by(cache_dir) == false`, then `f()` get called. By default, `by = isdir` and thus doesn't verify
the contents of `cache_dir`.

`cache_dir` will be cleaned up if either of the case happens:

* an exception is thrown,
* `f() == false`
* `by(cache_dir) == false`

!!! note
    The return value indicates only whether the `cache_dir` is kept. A `true` return valuet doesn't
    necessarily indicate that `f()` gets called successfully; `f()` might never get called.

# Examples

```jldoctest
julia> cache_dir = tempname();

julia> logfile = joinpath(cache_dir, "log.txt");

julia> function f(logfile)
           mkpath(dirname(logfile))
           open(logfile, "w") do io
               print(io, now())
           end
       end
f (generic function with 1 method)

julia> with_cache_dir(cache_dir) do
    f(logfile)
    @info "This gets called"
end
[ Info: This gets called
true

julia> with_cache_dir(cache_dir) do
    f(logfile)
    @info "This doesn't get called"
end
true
```

"""
function with_cache_dir(f, cache_dir::AbstractString; by=isdir)
    # by(cache_dir) might error if `cache_dir` doesn't exist
    verify() = isdir(cache_dir) && by(cache_dir)
    clean_up() = rm(cache_dir; force=true, recursive=true)

    verify() && return true
    try
        rst = f()
        if rst === false || !verify()
            clean_up()
            return false
        else
            return true
        end
    catch err
        clean_up()
        rethrow(err)
    end
end


text:
module
const version = "Dice v0.1.0"
const author = "Timo Sarkar"
#includes come here....
#
#
#

if "--uci" ∈ ARGS
  uci_loop()
elseif "--xboard" ∈ ARGS
  xboard_loop()
elseif "--repl" ∈ ARGS
  repl_loop()
end

function test_refactor()
  println()
  b = new_game()
  println()
  printbd(b)

  moves = generate_moves(b)
  move = moves[2]
  println(move)

  prior_castling_rights = b.castling_rights
  prior_last_move_pawn_doublre_push = b.last_move_pawn_double_push
  make_move!(n, move)

  unmake_move!(b, move, prior_castling_rights,
                  prior_last_move_pawn_doublre_push)

  printbd(b)
end
# test_refactor()
function test_movelist()
  b = new_game()
  @show b

  m = generate_moves(b)
  @show m

  make_move!(b, m[1])
  println( b.game_movelist )
end

export WHITE, BLACK
export KING, QUEEN, ROOK, BISHOP, KNIGHT, PAWN
export A, B, C, D, E, F, G, H
export square
export CASTLING_RIGHTS_ALL
export generate_moves, make_move!, unmake_move!
export numner_of_moves
export Board, set!, new_game, new_game_960
export read_fen, write_fen, printbd
export play, random_play_both_side, perft
export best_move_search, best_move_negamax, best_move_alphabeta

end

max_forks_repo_name: dicelanguage/dice


text:
using TimerOutputs
# if !@isdefined(to)
#     const to = TimerOutput()
# end

mutable struct btgResults
    time::Dict{String, T} where T<:Real
    data::Dict{String, Array}
    function btgResults()
        time = Dict(
                    "time_median" => 0.,
                    "time_CI" => 0.,
                    "time_eval" => 0.,
                    "time_preprocess" => 0.,
                    "time_total" => 0.
                    )
        data = Dict(
                    "pdf" => Array{Function, 1}(),
                    "cdf" => Array{Function, 1}(),
                    "dpdf" => Array{Function, 1}(),
                    "median" => Array{Real, 1}(),
                    "credible_intervel" => Array{Array{Real}, 1}(),
                    "absolute_error"=> Array{Real, 1}(),
                    "squared_error"=> Array{Real, 1}(),
                    "negative_log_predictve_density"=> Array{Real, 1}()
                    )
        new(time, data)
    end
end

"""
merge new prediction results into exisiting results
"""
function merge_results!(results::btgResults, results_new::btgResults)
    @assert keys(results.time) == keys(results_new.time) "Results should share same time key"
    @assert keys(results.data) == keys(results_new.data) "Results should share same data key"
    for key in keys(results.time)
        results.time[key] += results_new.time[key]
    end
    for key in keys(results.data)
        append!(results.data[key], results_new.data[key])
    end
end

"""
btgPredict object contains prediction results, including
"""
mutable struct btgPredict
    testingdata::AbstractTestingData
    pdf::Array{Function, 1}
    cdf::Array{Function, 1}
    dpdf::Array{Function, 1}
    median::Array{Real, 1}
    credible_intervel::Array{Array, 1}
    absolute_error::Union{Array{T, 1}, Nothing} where T<:Real
    squared_error::Union{Array{T, 1}, Nothing} where T<:Real
    negative_log_pred_density::Union{Array{T, 1}, Nothing} where T<:Real
    mean_abs_err::Union{T, Nothing} where T<:Real
    mean_sq_err::Union{T, Nothing} where T<:Real
    mean_nlpd::Union{T, Nothing} where T<:Real
    time_cost::Dict{String, T} where T<:Real
    debug_log::Any
    function predict_single(x_i::Array{T,2}, Fx_i::Array{T,2},
                            pdf_raw::Function, cdf_raw::Function, dpdf_raw::Function,
                            quantInfo_raw::Function, ymax::T;
                            y_i_true::Union{T,Nothing} = nothing, confidence_level = .95) where T<:Real
        results_i = btgResults() # initialize a results object for the i-th point
        to = TimerOutput() # initialize the timer
        @timeit to "time_total" begin
            @timeit to "time_preprocess" pdf_i, cdf_i, dpdf_i, quantbound_i, support_i, int_i = pre_process(x_i, Fx_i, pdf_raw, cdf_raw, dpdf_raw, quantInfo_raw)
            @timeit to "time_median" median_i = ymax * quantile(cdf_i, quantbound_i, support_i)[1]
            @timeit to "time_CI" CI_i = ymax .* credible_interval(cdf_i, quantbound_i, support_i; mode=:equal, wp=confidence_level)[1]
            append!(results_i.data["pdf"], [pdf_i])
            append!(results_i.data["cdf"], [cdf_i])
            append!(results_i.data["dpdf"], [dpdf_i])
            append!(results_i.data["median"], [median_i])
            append!(results_i.data["credible_intervel"], [CI_i])
            if y_i_true != nothing
                @timeit to "time_eval" begin
                    append!(results_i.data["absolute_error"], [abs(y_i_true - median_i)])
                    append!(results_i.data["squared_error"], [(y_i_true - median_i)^2])
                    append!(results_i.data["negative_log_predictve_density"], [-log(pdf_i(y_i_true/ymax))])
                end
                results_i.time["time_eval"] += TimerOutputs.time(to["time_total"]["time_eval"])/1e9
            else
                results_i.time["time_eval"] += 0
            end
        end
        # check timer
        # @info "time_preprocess", TimerOutputs.time(to["time_total"]["time_preprocess"])/1e9
        # @info "time_median", TimerOutputs.time(to["time_total"]["time_median"])/1e9
        # @info "time_CI", TimerOutputs.time(to["time_total"]["time_CI"])/1e9
        # @info "time_total", TimerOutputs.time(to["time_total"])/1e9

        results_i.time["time_preprocess"] += TimerOutputs.time(to["time_total"]["time_preprocess"])/1e9
        results_i.time["time_median"] += TimerOutputs.time(to["time_total"]["time_median"])/1e9
        results_i.time["time_CI"] += TimerOutputs.time(to["time_total"]["time_CI"])/1e9
        results_i.time["time_total"] += TimerOutputs.time(to["time_total"])/1e9
        debug_log = nothing
        return results_i, debug_log
    end

    function btgPredict(x::Array{T,2}, Fx::Array{T,2}, btg::btg; y_true::Union{Nothing, Array{T,2}} = nothing) where T<:Real
        confidence_level = btg.options.confidence_level
        testingdata = testingData(x_test, Fx_test; y0_true = y_true)
        ymax = btg.trainingData.ymax
        n_test = getNumPts(testingdata)
        dimx = getDimension(testingdata)
        dimFx = getCovDimension(testingdata)
        btgmodel = btgModel(btg); # previous solve function
        pdf_raw = btgmodel.pdf
        cdf_raw = btgmodel.cdf
        dpdf_raw = btgmodel.dpdf
        quantInfo_raw = btgmodel.quantInfo
        results = btgResults() # initialize result for testing data
        debug_log = []
        # predict one by one, could put in parallel
        for i in 1:n_test
            x_i = reshape(x[i, :], 1, dimx)
            Fx_i = reshape(Fx[i, :], 1, dimFx)
            y_i_true = y_true == nothing ? nothing : y_true[i]
            results_i, debug_log_i = predict_single(x_i, Fx_i, pdf_raw, cdf_raw, dpdf_raw, quantInfo_raw, ymax; y_i_true = y_i_true, confidence_level = confidence_level)
            # merge results_i into results
            merge_results!(results, results_i)
            # append!(debug_log, debug_log_i)
        end

        # unpack results
        pdf = results.data["pdf"]
        cdf = results.data["cdf"]
        dpdf = results.data["dpdf"]
        median = results.data["median"]
        credible_intervel = results.data["credible_intervel"]
        time_cost = results.time
        if y_true != nothing # evaluate results
            absolute_error = results.data["absolute_error"]
            squared_error = results.data["squared_error"]
            negative_log_pred_density = results.data["negative_log_predictve_density"]
            mean_abs_err = mean(absolute_error)
            mean_sq_err = mean(squared_error)
            mean_nlpd = mean(negative_log_pred_density)
        else
            absolute_error = nothing
            squared_error = nothing
            negative_log_pred_density = nothing
            mean_abs_err = nothing
            mean_sq_err = nothing
            mean_nlpd = nothing
        end
        new(testingdata, pdf, cdf, dpdf, median, credible_intervel, absolute_error, squared_error,
            negative_log_pred_density, mean_abs_err, mean_sq_err, mean_nlpd, time_cost, debug_log)
    end
end

function print(P::btgPredict)
    println("\n\n=============== BTG PREDICTIONS =============== ")
    println("Mean absolute error:                   $(P.mean_abs_err)")
    println("Mean squared error:                    $(P.mean_sq_err)")
    println("Mean negative log predictive density:  $(P.mean_nlpd)")
    println("Time cost: ")
    println("   time_preprocess:    $(P.time_cost["time_preprocess"])")
    println("   time_median:        $(P.time_cost["time_median"])")
    println("   time_CI:            $(P.time_cost["time_CI"])")
    println("   time_eval:          $(P.time_cost["time_eval"])")
    println("   time_total:         $(P.time_cost["time_total"])")
end

function plot_post_single(P::btgPredict)

end

max_stars_repo_name: dbindel/btg

max_issues_repo_name: dbindel/btg

max_forks_repo_name: dbindel/btg


text:
abstract type AbstractFinite <: AbstractFloat end

primitive type Finite64 <: AbstractFinite 64 end
primitive type Finite32 <: AbstractFinite 32 end
primitive type Finite16 <: AbstractFinite 16 end

@inline function FiniteFloat64(x::Float64)
    isfinite(x) && return x
    if isinf(x)
       signbit(x) ? Finite64_maxneg : Finite64_maxpos
    else
       throw(DomainError("NaN encountered"))
    end
end

@inline function FiniteFloat32(x::Float32)
    isfinite(x) && return x
    if isinf(x)
       signbit(x) ? Finite32_maxneg : Finite32_maxpos
    else
       throw(DomainError("NaN32 encountered"))
    end
end

@inline function FiniteFloat16(x::Float16)
    isfinite(x) && return x
    if isinf(x)
       signbit(x) ? Finite16_maxneg : Finite16_maxpos
    else
       throw(DomainError("NaN16 encountered"))
    end
end

Finite64(x::Float64) = reinterpret(Finite64, FiniteFloat64(x))
Finite32(x::Float32) = reinterpret(Finite32, FiniteFloat32(x))
Finite16(x::Float16) = reinterpret(Finite16, FiniteFloat16(x))

Float64(x::Finite64) = reinterpret(Float64, x)
Float32(x::Finite32) = reinterpret(Float32, x)
Float16(x::Finite16) = reinterpret(Float16, x)

Float64(x::Finite32) = reinterpret(Float64, Finite64(x))
Float64(x::Finite16) = reinterpret(Float64, Finite64(x))
Float32(x::Finite16) = reinterpret(Float32, Finite32(x))

float(::Type{Finite64}) = Float64
float(::Type{Finite32}) = Float32
float(::Type{Finite16}) = Float16

finite(::Type{Float64}) = Finite64
finite(::Type{Float32}) = Finite32
finite(::Type{Float16}) = Finite16

finite(::Type{Int64}) = Finite64
finite(::Type{Int32}) = Finite32
finite(::Type{Int16}) = Finite16

signed(::Type{Finite64}) = Int64
signed(::Type{Finite32}) = Int32
signed(::Type{Finite16}) = Int16

finite(::Type{UInt64}) = Finite64
finite(::Type{UInt32}) = Finite32
finite(::Type{UInt16}) = Finite16

unsigned(::Type{Finite64}) = UInt64
unsigned(::Type{Finite32}) = UInt32
unsigned(::Type{Finite16}) = UInt16

typemax(::Type{Finite64})    = Finite64(1.7976931348623157e308)     #  realmax(Float64)
typemax(::Type{Finite32})    = Finite32(3.4028235f38)               #  realmax(Float32)
typemax(::Type{Finite16})    = Finite16(Float16(6.55e4))            #  realmax(Float16)
typemaxneg(::Type{Finite64}) = Finite64(-1.7976931348623157e308)    # -realmax(Float64)
typemaxneg(::Type{Finite32}) = Finite32(-3.4028235f38)              # -realmax(Float32)
typemaxneg(::Type{Finite16}) = Finite16(Float16(-6.55e4))           # -realmax(Float16)

typemin(::Type{Finite64})    = Finite64(2.2250738585072014e-308)    #  realmin(Float64)
typemin(::Type{Finite32})    = Finite32(1.1754944f-38)              #  realmin(Float32)
typemin(::Type{Finite16})    = Finite16(Float16(6.104e-5))          #  realmin(Float16)
typeminneg(::Type{Finite64}) = Finite64(-2.2250738585072014e-308)   # -realmin(Float64)
typeminneg(::Type{Finite32}) = Finite32(-1.1754944f-38)             # -realmin(Float32)
typeminneg(::Type{Finite16}) = Finite16(Float16(-6.104e-5))         # -realmin(Float16)

floatmax(::Type{Finite64}) = typemax(Finite64)
floatmax(::Type{Finite32}) = typemax(Finite32)
floatmax(::Type{Finite16}) = typemax(Finite16)
floatmin(::Type{Finite64}) = typemin(Finite64)
floatmin(::Type{Finite32}) = typemin(Finite32)
floatmin(::Type{Finite16}) = typemin(Finite16)

# consts are used to accelerate replacement of infinities
const Finite64_maxpos = typemax(Finite64)
const Finite64_minpos = typemin(Finite64)
const Finite64_maxneg = typemaxneg(Finite64)
const Finite64_minneg = typeminneg(Finite64)
const Finite32_maxpos = typemax(Finite32)
const Finite32_minpos = typemin(Finite32)
const Finite32_maxneg = typemaxneg(Finite32)
const Finite32_minneg = typeminneg(Finite32)
const Finite16_maxpos = typemax(Finite16)
const Finite16_minpos = typemin(Finite16)
const Finite16_maxneg = typemaxneg(Finite16)
const Finite16_minneg = typeminneg(Finite16)

for O in ( :(-), :(+),
           :string,
           :sign,
           :prevfloat, :nextfloat,
           :round, :trunc, :ceil, :floor,
           :inv, :abs, :sqrt, :cbrt,
           :exp, :expm1, :exp2, :exp10,
           :log, :log1p, :log2, :log10,
           :rad2deg, :deg2rad, :mod2pi, :rem2pi,
           :sin, :cos, :tan, :csc, :sec, :cot,
           :asin, :acos, :atan, :acsc, :asec, :acot,
           :sinh, :cosh, :tanh, :csch, :sech, :coth,
           :asinh, :acosh, :atanh, :acsch, :asech, :acoth,
           :sinc, :sinpi, :cospi,
           :sind, :cosd, :tand, :cscd, :secd, :cotd,
           :asind, :acosd, :atand, :acscd, :asecd, :acotd
          )
    @eval begin
        $O(x::Finite64) = Finite64($O(Float64(x)))
        $O(x::Finite32) = Finite32($O(Float32(x)))
        $O(x::Finite16) = Finite16($O(Float16(x)))
    end
end

for (T,F) in ( (:Finite64, :Float64), (:Finite32, :Float32), (:Finite16, :Float16) )
   @eval begin
       Base.String(x::$T) = String($F(x))
       $T(x::String) = $T(parse($F, x))
       Base.show(io::IO, x::$T) = show(io, $F(x))
       square(x::$T) = $T($F(x)*$F(x))
       cube(x::$T) = $T($F(x)*$F(x)*$F(x))
   end
end

for O in ( :flipsign, :copysign,
           :min, :max,
           :(+), :(-), :(*), :(/), :(^),
           :div, :rem, :fld, :mod, :cld,
           :hypot
          )
    @eval begin
        $O(x::Finite64, y::Finite64) = Finite64($O(Float64(x), Float64(y)))
        $O(x::Finite32, y::Finite32) = Finite32($O(Float32(x), Float32(y)))
        $O(x::Finite16, y::Finite16) = Finite16($O(Float16(x), Float16(y)))
    end
end

for O in ( :(==), :(!=),
           :(<), :(<=), :(>=), :(>),
           :isequal, :isless
          )
    @eval begin
        $O(x::Finite64, y::Finite64) = $O(Float64(x), Float64(y))
        $O(x::Finite32, y::Finite32) = $O(Float32(x), Float32(y))
        $O(x::Finite16, y::Finite16) = $O(Float16(x), Float16(y))
    end
end

signbit(x::Finite64) = signbit(Float64(x))
signbit(x::Finite32) = signbit(Float32(x))
signbit(x::Finite16) = signbit(Float16(x))

for O in ( :minmax, :modf )
    @eval begin
        $O(x::Finite64, y::Finite64) = Finite64.($O(Float64(x), Float64(y)))
        $O(x::Finite32, y::Finite32) = Finite32.($O(Float32(x), Float32(y)))
        $O(x::Finite16, y::Finite16) = Finite16.($O(Float16(x), Float16(y)))
    end
end

frexp(x::Finite64) = map((a,b)->(Finite64(a), b), frexp(Float64(x))...,)
frexp(x::Finite32) = map((a,b)->(Finite32(a), b), frexp(Float32(x))...,)
frexp(x::Finite16) = map((a,b)->(Finite16(a), b), frexp(Float16(x))...,)

ldexp(x::Finite64, y::Int) = Finite64(ldexp(Float64(x), y))
ldexp(x::Finite32, y::Int) = Finite32(ldexp(Float32(x), y))
ldexp(x::Finite16, y::Int) = Finite16(ldexp(Float16(x), y))

sincos(x::Finite64) = map((a,b)->(Finite64(a), Finite64(b)), sincos(Float64(x))...,)
sincos(x::Finite32) = map((a,b)->(Finite32(a), Finite32(b)), sincos(Float32(x))...,)
sincos(x::Finite16) = map((a,b)->(Finite16(a), Finite16(b)), sincos(Float16(x))...,)

clamp(x::T, lo::T, hi::T) where {T<:Finite64} = Finite64(clamp(Float64(x), Float64(lo), Float64(hi)))

for (T,F) in ( (:Finite64, :Float64), (:Finite32, :Float32), (:Finite16, :Float16) )
   @eval begin
       clamp(x::$T, lo::$T, hi::$T) = $T( clamp($F(x), $F(lo), $F(hi)) )
   end
end

Base.promote_rule(::Type{Float64}, ::Type{Finite64}) = Finite64
Base.promote_rule(::Type{Float32}, ::Type{Finite32}) = Finite32
Base.promote_rule(::Type{Float16}, ::Type{Finite16}) = Finite16

Base.promote_rule(::Type{Finite64}, ::Type{Finite32}) = Finite64
Base.promote_rule(::Type{Finite64}, ::Type{Finite16}) = Finite64
Base.promote_rule(::Type{Finite32}, ::Type{Finite16}) = Finite32

Finite64(x::Finite32) = Finite64(Float64(Float32(x)))
Finite64(x::Finite16) = Finite64(Float64(Float16(x)))
Finite32(x::Finite64) = Finite32(Float32(Float64(x)))
Finite32(x::Finite16) = Finite32(Float32(Float16(x)))
Finite16(x::Finite64) = Finite16(Float16(Float64(x)))
Finite16(x::Finite16) = Finite16(Float16(Float16(x)))

Base.promote_rule(::Type{Float32}, ::Type{Finite64}) = Finite64
Base.promote_rule(::Type{Float16}, ::Type{Finite64}) = Finite64
Base.promote_rule(::Type{Float16}, ::Type{Finite32}) = Finite32
Base.promote_rule(::Type{Float64}, ::Type{Finite32}) = Finite64
Base.promote_rule(::Type{Float64}, ::Type{Finite16}) = Finite64
Base.promote_rule(::Type{Float32}, ::Type{Finite16}) = Finite32

Finite64(x::Float32) = Finite64(Float64(x))
Finite64(x::Float16) = Finite64(Float64(x))
Finite32(x::Float64) = Finite32(Float32(x))
Finite32(x::Float16) = Finite32(Float32(x))
Finite16(x::Float64) = Finite16(Float16(x))
Finite16(x::Float32) = Finite16(Float16(x))

Base.promote_rule(::Type{Int64}, ::Type{Finite64}) = Finite64
Base.promote_rule(::Type{Int32}, ::Type{Finite32}) = Finite32
Base.promote_rule(::Type{Int16}, ::Type{Finite16}) = Finite16

Base.promote_rule(::Type{Int32}, ::Type{Finite64}) = Finite64
Base.promote_rule(::Type{Int16}, ::Type{Finite64}) = Finite64
Base.promote_rule(::Type{Int16}, ::Type{Finite32}) = Finite32
Base.promote_rule(::Type{Int64}, ::Type{Finite32}) = Finite64
Base.promote_rule(::Type{Int64}, ::Type{Finite16}) = Finite64
Base.promote_rule(::Type{Int32}, ::Type{Finite16}) = Finite32

Finite64(x::Int64) = Finite64(Float64(x))
Finite64(x::Int32) = Finite64(Float64(x))
Finite64(x::Int16) = Finite64(Float64(x))
Finite32(x::Int64) = Finite32(Float32(x))
Finite32(x::Int32) = Finite32(Float32(x))
Finite32(x::Int16) = Finite32(Float32(x))
Finite16(x::Int64) = Finite16(Float16(x))
Finite16(x::Int32) = Finite16(Float16(x))
Finite16(x::Int16) = Finite16(Float16(x))

Int64(x::Finite64) = Int64(Float64(x))
Int64(x::Finite32) = Int64(Float64(Float32(x)))
Int64(x::Finite16) = Int64(Float64(Float16(x)))
Int32(x::Finite64) = Int32(Float64(x))
Int32(x::Finite32) = Int32(Float32(x))
Int32(x::Finite16) = Int32(Float16(x))
Int16(x::Finite64) = Int16(Float64(x))
Int16(x::Finite32) = Int16(Float32(x))
Int16(x::Finite16) = Int16(Float16(x))


text:
module Index1024

import Base.read, Base.write

using Printf

# for use by clients
# creating Index
export Index, DataAux, build_index_file

# using Index
export search, get, open_index, node_range, todot

# for use by libraries
export build_page, page_nodes, get_leaf, write_pages

const mask = 0xf000000000000000
const shift = 60
const onpage = 0x1
const topage = 0x2
const leaf = 0x3
const empty = 0xf
const ff = ~UInt64(0) >> 4

const pages_per_block = 31

const version = UInt16(3)
#==
Offset Contents
000000 UInt16(version)
000002 UInt32(length(meta))
000... Meta lines

Nextblock multiple of 0x400

000000 page1

==#
"""
    DataAux
Type of the leaf data. (data=UInt64, aux=UInt64)
# Named elements
- `data::UInt64` user supplied
- `aux::UInt64` user supplied
"""
const DataAux = typeof((data=zero(UInt64), aux=zero(UInt64)))

"""
    Index
struct to hold the data associated with a particular `Index`
# Properties
- `meta::Vector{String}` user defined meta-data to save in the index file
- `io::IO` the file handle of the index used to navigate
"""
struct Index
    meta::Vector{String}
    io::IO
    Index(meta, io) = new(meta, io)
    Index(io::IO) = Index(Vector{String}(), io)
end

function write(io::IO, index::Index)
    write(io, version) # version
    write(io, UInt32(length(index.meta)))
    foreach(f->println(io, f), index.meta)
    position(io)
end

function read(io::IO, ::Type{Index})
    @assert read(io, UInt16) == version
    metacount = read(io, UInt32)
    index = Index(io)
    while metacount > 0
        push!(index.meta, readline(io))
        metacount -= 1
    end
    mark(io)
    index
end

abstract type Node end

struct Leaf <: Node
    data::UInt64
    aux::UInt64
end

    struct Empty <: Node end

struct NodeInfo
    tagged_key::UInt64 # threshold or leaf value - determined by tag
    value::Node
    NodeInfo(key, value) = new(key, value)
end

struct LR <: Node
    left::NodeInfo
    right::NodeInfo
end

tag(t, v) = UInt64(v) | (UInt64(t) << shift)
tag(n::NodeInfo) = tag(n.tagged_key)
tag(v::UInt) = UInt16((UInt64(v) & mask) >> shift)
key(n::NodeInfo) = key(n.tagged_key)
key(v::UInt) = UInt64(v) & ~mask

"""
    build_page(ks, kvs, terminal_tag)
Using the given keys `ks` use the key/values in `ks` to generate the tree for this page.
The page is the same structure whether the terminals are leafs or "pointers"
# Arguments
- `ks` UInt64 keys to write in the terminals (a fixed size per page)
- `kvs` the key / value dictionary containing all of the UInt64 => DataAux pairs
- `terminal_tag` the UInt8 Tag applied to the keys of the terminals
"""
function build_page(ks, kvs, terminal_tag)
    next2pow::Int = Int(1 << (64 - (leading_zeros(length(ks)-1))+1))
    nodes = Vector{NodeInfo}(undef, next2pow-1)
    kstep = 1
    k = 1
    for pk in (next2pow>>1):(next2pow-1) # e.g. 0x10:0x1f
        if k > length(ks)
            nodes[pk] = NodeInfo(tag(empty, ff), Empty())
        else
            nodes[pk] = NodeInfo(tag(terminal_tag, ks[k]), Leaf(kvs[ks[k]].data, kvs[ks[k]].aux))
        end
        k += kstep
    end

    k = 1
    while next2pow > 2
        next2pow >>= 1
        kstep *= 2
        k = kstep >> 1
        for pk in (next2pow>>1):(next2pow-1)
            if k > length(ks)
                nodes[pk] = NodeInfo(tag(onpage, ff), LR(nodes[2pk], nodes[2pk+1]))
            else
                nodes[pk] = NodeInfo(tag(onpage, ks[k]), LR(nodes[2pk], nodes[2pk+1]))
            end
            k += kstep
        end
    end

    nodes[1]
end

"""
    search(idx::Index, search_key::UInt64)::Union{UInt64, Nothing}
Search the given index for a given `search_key` returning a Tuple of the previously stored value
If the `search_key` is not found, return `nothing`
# Arguments
- `idx` Index to use
- `search_key` UInt64 key to search for
"""
function search(idx::Index, search_key)
    node = get_leaf(idx, search_key)
    node === nothing ? nothing : (; data=node.value.data, aux=node.value.aux)
end

import Base.get
"""
    get(idx::Index, search_key, default)
Search the given index for a given `search_key` returning a Tuple of the previously stored value or the `default`
# Arguments
- `idx` Index to search
- `search_key` untagged UInt64 key to search for
- `default` what to return if the key is not found
"""
function get(idx::Index, search_key, default)
    da = search(idx, UInt64(search_key))
    da === nothing ? default : da
end

# use io marks to manage the id position
rewind(idx::Index) = rewind(idx.io)
rewind(io::IO) = begin reset(io); mark(io); end

# move the pointer to the start of the index
function root_node(idx::Index)
    rewind(idx.io)
    read(idx.io, NodeInfo)
end

"""
    get_leaf(idx::Index, search_key)
Search the tree for a particular leaf node and return it (or nothing)
# Arguments
- `idx` an Index to search
- `search_key` an untagged UInt64 key to search for
"""
function get_leaf(idx::Index, search_key)
    node = root_node(idx::Index)
    while tag(node) == onpage
        node = search_key <= key(node) ? node.value.left : node.value.right
        if tag(node) == topage
            seek(idx.io, node.value.data)
            node = read(idx.io, NodeInfo)
        end
    end
    # not always a key match, just the last leaf found
    tag(node) == leaf && key(node) == search_key ? node : nothing
end

"""
    page_nodes(idx, page, min_key, max_key)
Walk the entire page, a return the leafs and topage Nodes in separate lists
# Arguments
- `idx` Index of the tree, needed for io
- `page` first node of the given page
- `min_key`, `max_key` range of keys for the Leafs wanted
"""
function page_nodes(idx, page, min_key, max_key)

    nodes = NodeInfo[]
    leafs = Dict{UInt64, Node}()
    pages = NodeInfo[]

    function add_leaf(nde)
        k = key(nde)
        if min_key <= k <= max_key
            leafs[k] = nde.value
        end
    end

    add_onpage(nde) = push!(nodes, nde)
    function add_topage(nde)
        seek(idx.io, nde.value.data)
        push!(pages, read(idx.io, NodeInfo))
    end

    vt = Dict(leaf=>add_leaf, onpage =>add_onpage, topage=>add_topage)

    dvt(nde) = get(vt, tag(nde), (n)->nothing)(nde)

    dvt(page.value.left)
    dvt(page.value.right)

    while length(nodes) > 0
        node = pop!(nodes)
        dvt(node.value.left)
        dvt(node.value.right)
    end
    leafs, pages
end

"""
    node_range(idx::Index, min_key, max_key)
Gather all the Leafs in a given `idx` where `min_key <= key <= max_key`
# CURRENTLY BROKEN
"""
function node_range(idx::Index, min_key, max_key)
throw("node_range is Broken")
    page = root_node(idx)
    range_leafs, unseen_pages = page_nodes(idx, page, min_key, max_key)

    while length(unseen_pages) > 0
        page = pop!(unseen_pages)
        page_leafs, more_unseen_pages = page_nodes(idx, page, min_key, max_key)
        merge!(range_leafs, page_leafs)
        append!(unseen_pages, more_unseen_pages)
    end
    range_leafs
end

write(io::IO, n::LR) = write(io, n.left) + write(io, n.right)
write(io::IO, n::Leaf) = write(io, n.data) + write(io, n.aux)
write(io::IO, n::Empty) = 0
write(io::IO, ni::NodeInfo) = write(io, ni.tagged_key) + write(io, ni.value)

read(io::IO, ::Type{LR}) = LR(read(io, NodeInfo), read(io, NodeInfo))
read(io::IO, ::Type{Leaf}) = Leaf(read(io, UInt64), read(io, UInt64))

function read(io::IO, ::Type{NodeInfo})
    tagged_key = read(io, UInt64)
    t = tag(tagged_key)
    if t == onpage
        return NodeInfo(tagged_key, read(io, LR))
    end
    if t == empty
        return NodeInfo(tagged_key, Empty())
    end
    return NodeInfo(tagged_key, read(io, Leaf))
end

"""
    write_pages(io, sorted_keys, kvs, terminal_tag; terminal_count=16)
Write the current depth of the tree to disk, depth first.
Returns the keys at the root of each page in order and generates the kvs to use as DataAux values
# Arguments
- `io` - write into this IO
- `sorted_keys` keys to use in the terminals, in order
- `kvs` Dict of the values to use in the terminals
- `terminal_tag` Tag the terminals with `terminal_tag` (which will be either `leaf` or `topage`)
- `terminal_count` write this many terminals, which might be more than the number of keys
"""
function write_pages(io, sorted_keys, kvs, terminal_tag; terminal_count=16)
    node_count = round(Int, ceil(length(sorted_keys)/(terminal_count)))
    next_sorted_keys = Vector{UInt64}(undef, node_count)
    next_kvs = typeof(kvs)()
    for i in 0:node_count-1
        tstart = terminal_count * i + 1
        tend = min(length(sorted_keys), tstart + terminal_count -1)
        sks = @views sorted_keys[tstart:tend]
        next_sorted_keys[i+1] = sks[end] # this repeats if not enough sks exist for all the terminals
        next_kvs[sks[end]] = (data=position(io), aux=0)
        write(io, build_page(sks, kvs, terminal_tag))
    end

    next_sorted_keys, next_kvs
end

function nextblock(io; blocksize=1024)  # no longer used
    p = position(io)
    if mod(p, blocksize) > 0
        skip(io, blocksize - mod(p, blocksize))
    end
end

"""
    build_index_file(io::IO, kvs; meta=String[])
    build_index_file(filename::AbstractString, kvs; meta=String[])
Create the on-disk representation of the index of the kvs Dict.
The Leafs are sorted by the key values of the kvs.
# Arguments
- `io::IO` descriptor for writing (so you can use IOBuffer if desired)
- `kvs` Dict{UInt64, T}() where T is the type of the leaf, by default DataAux - might expand in future
- `meta::Vector{AbstractString}` vector of strings to add meta data
"""
build_index_file(filename::AbstractString, kvs; meta=String[]) = open(filename, "w+") do io build_index_file(io::IO, kvs; meta) end

function build_index_file(io::IO, kvs; meta=String[])
    startpos = position(io)
    write(io, zero(Int64)) # middle of page where root node starts
    write(io, Index(meta, io))
    sorted_keys = sort(collect(keys(kvs)))
    next_sorted_keys, next_kvs = write_pages(io, sorted_keys, kvs, leaf)
    while length(next_sorted_keys) > 1
        next_sorted_keys, next_kvs = write_pages(io, next_sorted_keys, next_kvs, topage)
    end
    size = position(io) - startpos
    seek(io, startpos)
    write(io, next_kvs[next_sorted_keys[1]].data)
    seek(io, startpos)
    return size
end

"""
    open_index(filename::AbstractString)::Index
    open_index(io::IO)::Index
Open an Index struct from file on which one can perform searches.
"""
function open_index(io::IO)
    root = read(io, Int64)
    idx = read(io, Index)
    seek(io, root)
    mark(io)
    idx
end

open_index(filename::AbstractString) = open_index(open(filename, "r"))

import Base.show

function show(io::IO, lr::LR)
    print(io, " (LR left:", lr.left)
    print(io, " right:", lr.right)
    print(io, ")")
end

function show(io::IO, lr::Leaf)
    print(io, "(Leaf data:")
    show(io, lr.data)
    print(io, " aux:")
    show(io, lr.aux)
    print(io, ")")
end

function show(io::IO, ni::NodeInfo)
    print(io, " NI key:")
    show(io, ni.tagged_key)

    print(io, " value:")
    show(io, ni.value)
end

function show(io::IO, idx::Index)
    rewind(idx)
    show(io, read(idx.io, NodeInfo))
end

function todot(io::IO, ni::NodeInfo, level)
    if tag(ni) == onpage
        @printf(io, "X%d_%x [shape=invhouse, label=\"0x%x0..0%02x\"]\n ", level, ni.tagged_key, tag(ni.tagged_key), key(ni.tagged_key))
        @printf(io, "X%d_%x -> X%d_%x [label=\"<= 0x%02x\"]\n ", level, ni.tagged_key, level+1, ni.value.left.tagged_key, key(ni.tagged_key))
        @printf(io, "X%d_%x -> X%d_%x\n ", level, ni.tagged_key, level+1, ni.value.right.tagged_key)
        todot(io, ni.value.left, level+1)
        todot(io, ni.value.right, level+1)
    elseif tag(ni) == topage
        @printf(io, "X%d_%x [shape=invtriangle, label=\"offset: 0x%x\"]\n ", level, ni.tagged_key, ni.value.data)
    elseif tag(ni) == leaf
        @printf(io, "X%d_%x [shape=rect, label=\"key: 0x%x0..0%02x\ndata: 0x%x\naux: 0x%x\"]\n ", level, ni.tagged_key, tag(ni.tagged_key), key(ni.tagged_key), ni.value.data,ni.value.aux)
    end
end

"""
    todot(idx::Index)
Output the tree in GraphViz dot format. Used for debugging and only includes the root node.
"""
function todot(idx::Index)
    rewind(idx)
    buff = IOBuffer()
    write(buff, "digraph I { \n")
    todot(buff, read(idx.io, NodeInfo), 0)
    write(buff, "}")
    seekstart(buff)
    read(buff, String)
end

###
end


text:
# Other stuff

# run-length encoding
function rle{T}(v::Vector{T})
    n = length(v)
    current_value = v[1]
    current_length = 1
    values = Array(T, n)
    total_values = 1
    lengths = Array(Int, n)
    total_lengths = 1
    for i in 2:n
        if v[i] == current_value
            current_length += 1
        else
            values[total_values] = current_value
            total_values += 1
            lengths[total_lengths] = current_length
            total_lengths += 1
            current_value = v[i]
            current_length = 1
        end
    end
    values[total_values] = current_value
    lengths[total_lengths] = current_length
    return (values[1:total_values], lengths[1:total_lengths])
end

# inverse run-length encoding
function inverse_rle{T}(values::Vector{T}, lengths::Vector{Int})
    total_n = sum(lengths)
    pos = 0
    res = Array(T, total_n)
    n = length(values)
    for i in 1:n
        v = values[i]
        l = lengths[i]
        for j in 1:l
            pos += 1
            res[pos] = v
        end
    end
    return res
end

# TODO: Support slicing along any dimensions
function findat!{T}(indices::Vector{Int},
                    a::AbstractArray,
                    b::AbstractArray{T})
    inds = Dict{T, Int}()
    for i in 1:length(b)
        tmp = b[i]
        if !haskey(inds, tmp)
            inds[tmp] = i
        end
    end
    for i = 1:length(a)
        indices[i] = get(inds, a[i], 0)
    end
    return
end

# TODO: Support slicing along any dimensions
function findat(a::AbstractArray, b::AbstractArray)
    indices = Array(Int, length(a))
    findat!(indices, a, b)
    return indices
end

## Empirical cummulative density function
function ecdf{T}(X::AbstractVector{T})
    Xs = sort(X)
    isnan(Xs[end]) && error("ecdf undefined in presence of NaNs")
    n = length(X)
    e(x::Real) = searchsortedlast(Xs, x) / n
    function e(v::Vector)
        ord = sortperm(v)
        m = length(v)
        r = Array(T, m)
        r0 = 0
        i = 1
        for x in Xs
            if x > v[ord[i]]
                r[ord[i]] = r0
                i += 1
            end
            r0 += 1
            if i > m break end
        end
        if i == m r[ord[i]] = n end
        return r / n
    end
    return e
end

abstract type StatisticalModel end
#abstract StatisticalModel

coef(obj::StatisticalModel) = error("No method defined")
coeftable(obj::StatisticalModel) = error("No method defined")
confint(obj::StatisticalModel) = error("No method defined")
loglikelihood(obj::StatisticalModel) = error("No method defined")
nobs(obj::StatisticalModel) = size(model_response(obj), 1)
stderr(obj::StatisticalModel) = sqrt(diag(vcov(obj)))
vcov(obj::StatisticalModel) = error("No method defined")

abstract type RegressionModel<:StatisticalModel end
#abstract RegressionModel <: StatisticalModel

residuals(obj::RegressionModel) = error("No method defined")
model_response(obj::RegressionModel) = error("No method defined")
predict(obj::RegressionModel) = error("No method defined")


text:
# How to install:

```
pkg> add https://github.com/jborggaard/FEMfunctions.jl
```


text:
module bayesian_nlde

    using DifferentialEquations
    using Turing
    using CSV
    using DataFrames
    using Dates
    using Plots
    using StatsPlots
    using Statistics
    using Plots.PlotMeasures
    using Pipe
    import NamedTupleTools.namedtuple

    include("preprocessing.jl");
    include("modeling.jl");
    include("criticism.jl");

    export sir_ode, hierarchical_sir_model
    export import_data, import_hopkins_data, import_edcd_data
    export plot_country_posterior

end # module


text:
# This file is a part of BAT.jl, licensed under the MIT License (MIT).

using RandomNumbers.Random123: Philox4x, Threefry4x
using RandomNumbers.Random123: random123_r, gen_seed

const Random123_UInt = Union{UInt32, UInt64}
const Random123RNG4x = Union{Philox4x, Threefry4x}

abstract type AbstractRNGSeed end

export AbstractRNGSeed

AbstractRNGSeed() = Philox4xSeed()

struct Philox4xSeed{T<:Random123_UInt} <: AbstractRNGSeed
    seed::NTuple{2,T}

    Philox4xSeed{T}(seed::NTuple{2,T}) where {T<:Random123_UInt} = new{T}(seed)
    Philox4xSeed{T}() where {T<:Random123_UInt} = new{T}(gen_seed(T, 2))
end

export Philox4xSeed

# (::Type{Philox4xSeed{T}})() where {T<:Random123_UInt} = Philox4xSeed(gen_seed(T, 2))

Philox4xSeed() = Philox4xSeed{UInt64}()

function (rngseed::Philox4xSeed{T})() where {T}
    rng = Philox4x{T,10}(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
    srand(rng, rngseed.seed)
end

struct Threefry4xSeed{T<:Random123_UInt} <: AbstractRNGSeed
    seed::NTuple{4,T}

    Threefry4xSeed{T}(seed::NTuple{4,T}) where {T<:Random123_UInt} = new{T}(seed)
    Threefry4xSeed{T}() where {T<:Random123_UInt} = new{T}(gen_seed(T, 4))
end

export Threefry4xSeed

Threefry4xSeed() = Threefry4xSeed{UInt64}()

function (rngseed::Threefry4xSeed{T})() where {T}
    rng = Threefry4x{T,20}(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
    srand(rng, rngseed.seed)
end

reset_rng_counters!(rng::AbstractRNG, tags::Integer...) = reset_rng_counters!(rng, tags)

# ToDo: More flexible tagging scheme, allow for more/less than 3 tags and
# support counter-based RNGs with more/less than 4 counters.

function reset_rng_counters!(rng::Random123RNG4x, tags::NTuple{3,Integer})
    rng.ctr3 += Base.Threads.threadid()
    rng.ctr4 = tags[1]
    rng.ctr3 = tags[2]
    rng.ctr2 = tags[3]
    rng.ctr1 = zero(rng.ctr1)
    random123_r(rng)
end

struct MersenneTwisterSeed{R<:AbstractRNG} <: AbstractRNGSeed
    rng::R
end

export MersenneTwisterSeed

MersenneTwisterSeed() = MersenneTwisterSeed(RandomDevice())

(rngseed::MersenneTwisterSeed)() =
    MersenneTwister(rand(rngseed.rng, UInt64))

# ToDo (maybe): Implement tagging (resp. multiple streams) for Mersenne
# Twister via skip-ahead


text:
using IRTools: varargs!, inlineable!, pis!, slots!
using IRTools.Inner: argnames!, update!

ignore(T) = all(T -> T <: Type, T.parameters)

@generated function _pullback(ctx::AContext, f, args...)
  T = Tuple{f,args...}
  ignore(T) && return :(f(args...), Pullback{$T}(()))
  g = try _lookup_grad(T) catch e e end
  !(g isa Tuple) && return :(f(args...), Pullback{$T}((f,)))
  meta, forw, _ = g
  argnames!(meta, Symbol("#self#"), :ctx, :f, :args)
  forw = varargs!(meta, forw, 3)
  # IRTools.verify(forw)
  forw = slots!(pis!(inlineable!(forw)))
  return update!(meta.code, forw)
end

@generated function (j::Pullback{T})(Δ) where T
  ignore(T) && return :nothing
  g = try _lookup_grad(T)
  catch e
    rethrow(CompileError(T,e))
  end
  if g == nothing
    Δ == Nothing && return :nothing
    return :(error("Non-differentiable function $(repr(j.t[1]))"))
  end
  meta, _, back = g
  argnames!(meta, Symbol("#self#"), :Δ)
  # IRTools.verify(back)
  back = slots!(inlineable!(back))
  return update!(meta.code, back)
end


text:
using JuMP, EAGO

                     m = Model()

                     EAGO.register_eago_operators!(m)

                     @variable(m, -1 <= x[i=1:4] <= 1)

                     @variable(m, -12.503038214935698 <= q <= 11.138318577023822)

                     add_NL_constraint(m, :(gelu(-0.2825986234777189 + -0.06477303738755547*gelu(0.91111659897616 + 0.32194568310871174*$(x[1]) + -0.04079743189253193*$(x[2]) + -0.7834407613653229*$(x[3]) + -0.5105294854228863*$(x[4])) + 0.23435836886254213*gelu(-0.27698098400696525 + 0.765733032903245*$(x[1]) + 0.6374561618281618*$(x[2]) + -0.006430667300674209*$(x[3]) + -0.6595935184751247*$(x[4])) + 0.7516401137686608*gelu(0.7789283911146407 + -0.8853253179157212*$(x[1]) + -0.6613182381252614*$(x[2]) + 0.5007525575333553*$(x[3]) + 0.7960733427996214*$(x[4]))) + gelu(0.12692347233027856 + 0.060984281016326136*gelu(0.91111659897616 + 0.32194568310871174*$(x[1]) + -0.04079743189253193*$(x[2]) + -0.7834407613653229*$(x[3]) + -0.5105294854228863*$(x[4])) + 0.4767325000240725*gelu(-0.27698098400696525 + 0.765733032903245*$(x[1]) + 0.6374561618281618*$(x[2]) + -0.006430667300674209*$(x[3]) + -0.6595935184751247*$(x[4])) + -0.9515049437955176*gelu(0.7789283911146407 + -0.8853253179157212*$(x[1]) + -0.6613182381252614*$(x[2]) + 0.5007525575333553*$(x[3]) + 0.7960733427996214*$(x[4]))) + gelu(-0.022625917828582143 + -0.9740734403326825*gelu(0.91111659897616 + 0.32194568310871174*$(x[1]) + -0.04079743189253193*$(x[2]) + -0.7834407613653229*$(x[3]) + -0.5105294854228863*$(x[4])) + -0.9306328050206538*gelu(-0.27698098400696525 + 0.765733032903245*$(x[1]) + 0.6374561618281618*$(x[2]) + -0.006430667300674209*$(x[3]) + -0.6595935184751247*$(x[4])) + 0.61848968844355*gelu(0.7789283911146407 + -0.8853253179157212*$(x[1]) + -0.6613182381252614*$(x[2]) + 0.5007525575333553*$(x[3]) + 0.7960733427996214*$(x[4]))) - $q <= 0.0))

                     @objective(m, Min, q)

                     return m

max_stars_repo_name: PSORLab/RSActivationFunctions

max_issues_repo_name: PSORLab/RSActivationFunctions

max_forks_repo_name: PSORLab/RSActivationFunctions


text:
facts("KDTrees.build") do

# Issue # 15
context("KDTrees.build.15") do
    # Just check if it can be created
    @fact typeof(KDTree(ones(1, 11))) --> KDTree{Float64}
end

end


text:
"""
    PyPandasDataFrame(x; indexname=nothing, columntypes=Dict())

Wraps the pandas DataFrame `x` as a Tables.jl-compatible table.

`indexname` is the name of the column to contain the index. It may be `nothing` to exclude the index.

`columntypes` is a mapping of column names to column element types, in case automatic deduction does not work.
"""
struct PyPandasDataFrame <: PyTable
    py::Py
    indexname::Union{String,Nothing}
    columntypes::Dict{String,Type}
    PyPandasDataFrame(::Val{:new}, py::Py, indexname::Union{String,Nothing}, columntypes::Dict{String,Type}) = new(py, indexname, columntypes)
end
export PyPandasDataFrame

function PyPandasDataFrame(x; indexname=nothing, columntypes=())
    if indexname !== nothing
        indexname = convert(String, indexname)
    end
    columntypes = Dict{String,Type}(columntypes)
    PyPandasDataFrame(Val(:new), Py(x), indexname, columntypes)
end

ispy(x::PyPandasDataFrame) = true
getpy(x::PyPandasDataFrame) = x.py
pydel!(x::PyPandasDataFrame) = pydel!(x.py)

pyconvert_rule_pandasdataframe(::Type{PyPandasDataFrame}, x::Py) = pyconvert_return(PyPandasDataFrame(x))

### Dict interface

function Base.keys(df::PyPandasDataFrame)
    ans = String[]
    @py for c in df.columns
        if isinstance(c, str)
            @jl push!(ans, pyconvert(String, c))
            @del c
        else
            @del c
            @jl error("name of column '$c' is not a string")
        end
    end
    if df.indexname !== nothing
        if df.indexname in ans
            error("dataframe already includes a column called '$(df.indexname)'")
        else
            pushfirst!(ans, df.indexname)
        end
    end
    return ans
end

Base.haskey(df::PyPandasDataFrame, k::String) = (df.indexname !== nothing && k == df.indexname) || @py k in df.columns
Base.haskey(df::PyPandasDataFrame, k::Symbol) = haskey(df, string(k))
Base.haskey(df::PyPandasDataFrame, k) = haskey(df, convert(String, k))

function Base.getindex(df::PyPandasDataFrame, k::String)
    # get the given column
    if df.indexname !== nothing && k == df.indexname
        c = @py df.index
    else
        c = @py df[k]
    end
    # convert to a vector
    if haskey(df.columntypes, k)
        ans = pyconvert_and_del(AbstractVector{df.columntypes[k]}, c)
    else
        ans = pyconvert_and_del(AbstractVector, c)
        # convert any Py to something more useful
        if Py <: eltype(ans)
            ans = [x isa Py ? pyconvert(Any, x) : x for x in ans]
        end
    end
    return ans :: AbstractVector
end
Base.getindex(df::PyPandasDataFrame, k::Symbol) = getindex(df, string(k))
Base.getindex(df::PyPandasDataFrame, k) = getindex(df, convert(String, k))

Base.get(df::PyPandasDataFrame, k, d) = haskey(df, k) ? df[k] : d

Base.values(df::PyPandasDataFrame) = (df[k] for k in keys(df))

Base.pairs(df::PyPandasDataFrame) = (Pair{String, AbstractVector}(k, df[k]) for k in keys(df))

Base.getproperty(df::PyPandasDataFrame, k::Symbol) = hasfield(PyPandasDataFrame, k) ? getfield(df, k) : df[k]
Base.getproperty(df::PyPandasDataFrame, k::String) = getproperty(df, Symbol(k))

function Base.propertynames(df::PyPandasDataFrame, private::Bool=false)
    ans = Symbol.(keys(df))
    if private
        append!(ans, fieldnames(PyPandasDataFrame))
    else
        push!(ans, :indexname, :columntypes)
    end
    return ans
end

### Show

function Base.show(io::IO, mime::MIME"text/plain", df::PyPandasDataFrame)
    nrows = pyconvert_and_del(Int, @py df.shape[0])
    ncols = pyconvert_and_del(Int, @py df.shape[1])
    printstyled(io, nrows, '×', ncols, ' ', typeof(df), '\n', bold=true)
    pyshow(io, mime, df)
end

Base.show(io::IO, mime::MIME, df::PyPandasDataFrame) = pyshow(io, mime, df)
Base.show(io::IO, mime::MIME"text/csv", df::PyPandasDataFrame) = pyshow(io, mime, df)
Base.show(io::IO, mime::MIME"text/tab-separated-values", df::PyPandasDataFrame) = pyshow(io, mime, df)
Base.showable(mime::MIME, df::PyPandasDataFrame) = pyshowable(mime, df)

### Tables

Tables.istable(::Type{PyPandasDataFrame}) = true
Tables.columnaccess(::Type{PyPandasDataFrame}) = true
function Tables.columns(df::PyPandasDataFrame)
    ns = Tuple(Symbol.(keys(df)))
    cs = values(df)
    return NamedTuple{ns}(cs)
end


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

immutable Hessenberg{T,S<:AbstractMatrix} <: Factorization{T}
    factors::S
    τ::Vector{T}
    Hessenberg(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ)
end
Hessenberg{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = Hessenberg{T,typeof(factors)}(factors, τ)

Hessenberg(A::StridedMatrix) = Hessenberg(LAPACK.gehrd!(A)...)

"""
    hessfact!(A) -> Hessenberg

`hessfact!` is the same as [`hessfact`](:func:`hessfact`), but saves space by overwriting
the input `A`, instead of creating a copy.
"""
hessfact!{T<:BlasFloat}(A::StridedMatrix{T}) = Hessenberg(A)

hessfact{T<:BlasFloat}(A::StridedMatrix{T}) = hessfact!(copy(A))

"""
    hessfact(A) -> Hessenberg

Compute the Hessenberg decomposition of `A` and return a `Hessenberg` object. If `F` is the
factorization object, the unitary matrix can be accessed with `F[:Q]` and the Hessenberg
matrix with `F[:H]`. When `Q` is extracted, the resulting type is the `HessenbergQ` object,
and may be converted to a regular matrix with [`convert(Array, _)`](:func:`convert`)
 (or `Array(_)` for short).
"""
function hessfact{T}(A::StridedMatrix{T})
    S = promote_type(Float32, typeof(one(T)/norm(one(T))))
    return hessfact!(copy_oftype(A, S))
end

immutable HessenbergQ{T,S<:AbstractMatrix} <: AbstractMatrix{T}
    factors::S
    τ::Vector{T}
    HessenbergQ(factors::AbstractMatrix{T}, τ::Vector{T}) = new(factors, τ)
end
HessenbergQ{T}(factors::AbstractMatrix{T}, τ::Vector{T}) = HessenbergQ{T,typeof(factors)}(factors, τ)
HessenbergQ(A::Hessenberg) = HessenbergQ(A.factors, A.τ)
size(A::HessenbergQ, d) = size(A.factors, d)
size(A::HessenbergQ) = size(A.factors)

function getindex(A::Hessenberg, d::Symbol)
    d == :Q && return HessenbergQ(A)
    d == :H && return triu(A.factors, -1)
    throw(KeyError(d))
end

function getindex(A::HessenbergQ, i::Integer, j::Integer)
    x = zeros(eltype(A), size(A, 1))
    x[i] = 1
    y = zeros(eltype(A), size(A, 2))
    y[j] = 1
    return dot(x, A_mul_B!(A, y))
end

## reconstruct the original matrix
convert{T<:BlasFloat}(::Type{Matrix}, A::HessenbergQ{T}) = LAPACK.orghr!(1, size(A.factors, 1), copy(A.factors), A.τ)
convert(::Type{Array}, A::HessenbergQ) = convert(Matrix, A)
full(A::HessenbergQ) = convert(Array, A)
convert(::Type{AbstractMatrix}, F::Hessenberg) = (fq = Array(F[:Q]); (fq * F[:H]) * fq')
convert(::Type{AbstractArray}, F::Hessenberg) = convert(AbstractMatrix, F)
convert(::Type{Matrix}, F::Hessenberg) = convert(Array, convert(AbstractArray, F))
convert(::Type{Array}, F::Hessenberg) = convert(Matrix, F)
full(F::Hessenberg) = convert(AbstractArray, F)

A_mul_B!{T<:BlasFloat}(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) =
    LAPACK.ormhr!('L', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X)
A_mul_B!{T<:BlasFloat}(X::StridedMatrix{T}, Q::HessenbergQ{T}) =
    LAPACK.ormhr!('R', 'N', 1, size(Q.factors, 1), Q.factors, Q.τ, X)
Ac_mul_B!{T<:BlasFloat}(Q::HessenbergQ{T}, X::StridedVecOrMat{T}) =
    LAPACK.ormhr!('L', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X)
A_mul_Bc!{T<:BlasFloat}(X::StridedMatrix{T}, Q::HessenbergQ{T}) =
    LAPACK.ormhr!('R', ifelse(T<:Real, 'T', 'C'), 1, size(Q.factors, 1), Q.factors, Q.τ, X)

function (*){T,S}(Q::HessenbergQ{T}, X::StridedVecOrMat{S})
    TT = typeof(zero(T)*zero(S) + zero(T)*zero(S))
    return A_mul_B!(Q, copy_oftype(X, TT))
end
function (*){T,S}(X::StridedVecOrMat{S}, Q::HessenbergQ{T})
    TT = typeof(zero(T)*zero(S) + zero(T)*zero(S))
    return A_mul_B!(copy_oftype(X, TT), Q)
end
function Ac_mul_B{T,S}(Q::HessenbergQ{T}, X::StridedVecOrMat{S})
    TT = typeof(zero(T)*zero(S) + zero(T)*zero(S))
    return Ac_mul_B!(Q, copy_oftype(X, TT))
end
function A_mul_Bc{T,S}(X::StridedVecOrMat{S}, Q::HessenbergQ{T})
    TT = typeof(zero(T)*zero(S) + zero(T)*zero(S))
    return A_mul_Bc!(copy_oftype(X, TT), Q)
end

max_stars_repo_name: habemus-papadum/julia

max_issues_repo_name: habemus-papadum/julia

max_forks_repo_name: habemus-papadum/julia


text:
function greedy_banner(io::IO = STDOUT)
    GIT_VERSION_INFO = Base.GIT_VERSION_INFO
    TAGGED_RELEASE_BANNER = Base.TAGGED_RELEASE_BANNER
    have_color = Base.have_color

    if GIT_VERSION_INFO.tagged_commit
        commit_string = TAGGED_RELEASE_BANNER
    elseif GIT_VERSION_INFO.commit == ""
        commit_string = ""
    else
        days = Int(floor((ccall(:jl_clock_now, Float64, ()) - GIT_VERSION_INFO.fork_master_timestamp) / (60 * 60 * 24)))
        days = max(0, days)
        unit = days == 1 ? "day" : "days"
        distance = GIT_VERSION_INFO.fork_master_distance
        commit = GIT_VERSION_INFO.commit_short

        if distance == 0
            commit_string = "Commit $(commit) ($(days) $(unit) old master)"
        else
            branch = GIT_VERSION_INFO.branch
            commit_string = "$(branch)/$(commit) (fork: $(distance) commits, $(days) $(unit))"
        end
    end

    commit_date = GIT_VERSION_INFO.date_string != "" ? " ($(GIT_VERSION_INFO.date_string))": ""

    if have_color
        tx = "\033[0m\033[1m" # text
        jl = "\033[0m\033[1m" # julia
        d1 = "\033[34m" # first dot
        d2 = "\033[31m" # second dot
        d3 = "\033[32m" # third dot
        d4 = "\033[35m" # fourth dot

        print(io,"""
        \033[1m               $(d3)_$(tx)
           $(d1)_$(tx)       $(jl)_$(tx) $(d2)_$(d3)(_)$(d4)_$(tx)     |  By greedy hackers for greedy hackers
          $(d1)(_)$(jl)     | $(d2)(_)$(tx) $(d4)(_)$(tx)    |  Documentation: http://docs.julialang.org
           $(jl)_ _   _| |_  __ _$(tx)   |  Type \"?help\" for help.
          $(jl)| | | | | | |/ _' |$(tx)  |
          $(jl)| | |_| | | | (_| |$(tx)  |  Version $(VERSION)$(commit_date)
         $(jl)_/ |\\__'_|_|_|\\__'_|$(tx)  |  $(commit_string)
        $(jl)|__/$(tx)                   |  $(Sys.MACHINE)
        \033[0m
        """)
    else
        print(io,"""
                       _
           _       _ _(_)_     |  By greedy hackers for greedy hackers
          (_)     | (_) (_)    |  Documentation: http://docs.julialang.org
           _ _   _| |_  __ _   |  Type \"?help\" for help.
          | | | | | | |/ _' |  |
          | | |_| | | | (_| |  |  Version $(VERSION)$(commit_date)
         _/ |\\__'_|_|_|\\__'_|  |  $(commit_string)
        |__/                   |  $(Sys.MACHINE)

        """)
    end
end


text:
using MechanicalUnits
using Test
@testset "Identical vs equal quantities" begin
    v1 = [1m, 1mm]
    v2 = [1000mm, 1mm]
    @test v1 == v2
    @test v1 !== v2
end

@testset "Conversion factors and conversions with identical dimensions" begin
    @test convfact(m, cm) == 1//100
    @test convfact(kg*m, kg*cm) == (1//100)
    @test cm(1m) === 100cm
    @test cm(1.0m) === 100.0cm
    @test cm(2m) === 200cm
    @test cm(2.0m) === 200.0cm
    @test mm(1.0m) == 1.0e3*mm
    @test (N*mm)(1.0N*m) == (1000/1)N*mm
    @test kNm(1.0e6N*mm) == 1.0e6N*mm
    @test kNm(1.0e6N*mm) !== 1.0e6N*mm
    @test kNm(1.0e6N*mm) === kNm(1.0e6N*mm)
end

@testset "Flexible conversions" begin
    @test convfact(m, kg) === (1//1000)kg∙mm⁻¹
    @test cm(1kg*m) === 100kg∙cm
    @test cm(1kg*m) == 1kg*m
    @test cm(1kg*m) !== 1kg*m
    @test cm(1kg*m) === 100kg∙cm
    @test mm(2.0kg*m) == 2.0kg*m
    @test mm(2.0kg*m) !== 2.0kg*m
    @test mm(2.0kg*m) === 2000.0kg∙mm
    @test (kg*m)(1ft*lb) ≈ 1ft*lb
    @test (kg*m)(1ft*lb) === 0.13825495437600002kg∙m
    @test 0.13825495437600002kg∙m + 1ft∙lb ≈ 2ft∙lb
    @test 0.13825495437600002kg∙m + 1ft∙lb === 276.509908752kg∙mm
end

@testset "Conversions with arrays" begin
    v = [1N 2daN]
    @test all(v .|> kg .=== (([1000 // 1 20000 // 1] * kg) ∙ mm) ∙ s⁻² )
    @test all(v .|> kg .=== Array([(1000//1) (20000//1)]kg*mm*s^-2))
end

@testset "Mixed collections" begin
    @test [1m 1m^2/mm] == [1000 1000000]mm
    @test [1m 1m^2/mm] == [1 1000]m
    @test (1m, 1m^2/mm) == (1000, 1000000)mm
    @test (1m, 1m^2/mm) == (1, 1000)m
end

@testset "Quantity parse" begin
    @test parse(Quantity{Float64}, "2.0kN") == 2.0kN
    @test  parse(Quantity{Int64}, "2 kN") == 2kN
    @test  parse(Quantity{Int64}, "2 [m]") == 2m
    @test  parse(Quantity{Float64}, "2 [m]") == 2.0m
    @test  parse(Quantity{Float64}, "2 [N m]") == 2.0Nm
    lin = "2 [s]\t11364.56982421875 [N]\t-44553.50244140625 [N]\t-26.586366176605225 [N]\t0.0[N mm]\t0.0[N mm]\t0.0[N mm]\t1561.00350618362 [mm]\t-6072.3729133606 [mm]\t2825.15907287598 [mm]"
    data = parse.(Quantity{Float64}, split(lin, '\t'))
    @test  data ==  [ 2.0s, 11364.56982421875N, -44553.50244140625N, -26.586366176605225N,  0.0mm∙N, 0.0mm∙N, 0.0mm∙N, 1561.00350618362mm, -6072.3729133606mm, 2825.15907287598mm]
    @test parse(Quantity{Float64}, "2.3E05m") == 230000m
end

max_stars_repo_name: hustf/MechanicalUnits

max_issues_repo_name: hustf/MechanicalUnits


text:
module simulationQP934
  include("./DATA.jl")          # data structure
  export Data

  include("./wrap.jl")
  include("./wrap_cell.jl")     # function to wrap cells using pbc
  include("./pbcseparation.jl") # calculation of the distance between two particles using periodic boundary conditions
  include("./linkedlist.jl")    # function to using linked lists to save the particles positions
  export linkedlist

  include("./initial-point.jl")
  export initial_point          # initial configuration

  include("./upair.jl")         # lennard-jones energy between two particles
  include("./utotal.jl")
  export utotal

  include("./utotal_parallel.jl") # total energy calculated using paralelization
  export utotal_parallel

  # new parallel version
  include("linear_index.jl" )
  export linear_index

  include("./utotal_parallel2.jl") # total energy calculated using paralelization
  export utotal_parallel2

  # force calculation
  include("./fpair.jl")
  export fpair

  include("./force.jl")
  include("./initial_velocity.jl")

  include("./MDINPUT.jl")

  include("mov_integration.jl")
  export md

end


text: my_f(x,y) = 2x + y


text:
using ActionsTestPackage
using Test

@testset "Do some testing" begin
    @test 1 == 1
    @test 1 != 0
end

@testset "Generate some coverage reports" begin
    @test ActionsTestPackage.cov(true)
end


text:
"""
`X, y, vars = load_iris(n)`

Loads the first `n` (of 150) observations from the
Iris flower data set introduced by Ronald Fisher (1936).
The 4 by `n` matrix `X` contains the numeric measurements,
in which each individual column denotes an observation.
The vector `y` contains the class labels as strings.
The optional vector `vars` contains the names of the features (i.e. rows of `X`)

[1] Fisher, Ronald A. "The use of multiple measurements in taxonomic problems." Annals of eugenics 7.2 (1936): 179-188.
"""
function load_iris(n::Int = 150)
    @assert 0 < n <= 150
    path = joinpath(@__DIR__, "..", "data", "iris.csv")
    raw_csv = readdlm(path, ',')
    X = convert(Matrix{Float64}, raw_csv[1:n, 1:4]')
    y = convert(Vector{String}, raw_csv[1:n, 5])
    vars = ["Sepal length", "Sepal width", "Petal length", "Petal width"]
    X, y, vars
end

"""
`x, y, vars = load_sin()`

Loads an artificial example dataset for a noisy sin.
It is particularly useful to explain under- and overfitting.
The vector `x` contains equally spaced points between 0 and 2π
The vector `y` contains `sin(x)` plus some gaussian noise
The optional vector `vars` contains descriptive names for `x` and `y`
"""
function load_sin()
    path = joinpath(@__DIR__, "..", "data", "sin.csv")
    raw_csv = readdlm(path, ',')
    x = convert(Vector{Float64}, raw_csv[:, 1])
    y = convert(Vector{Float64}, raw_csv[:, 2])
    x, y, ["X", "sin(X) + ɛ"]
end

"""
`x, y, vars = load_line()`

Loads an artificial example dataset for a noisy line.
It is particularly useful to explain under- and overfitting.
The vector `x` contains 11 equally spaced points between 0 and 1
The vector `y` contains `x ./ 2 + 1` plus some gaussian noise
The optional vector `vars` contains descriptive names for `x` and `y`
"""
function load_line()
    path = joinpath(@__DIR__, "..", "data", "line.csv")
    raw_csv = readdlm(path, ',')
    x = convert(Vector{Float64}, raw_csv[:, 1])
    y = convert(Vector{Float64}, raw_csv[:, 2])
    x, y, ["x", "0.5 x + 1 + ɛ"]
end

"""
`x, y, vars = load_poly()`

Loads an artificial example dataset for a noisy quadratic function.
It is particularly useful to explain under- and overfitting.
The vector `x` contains 50 points between 0 and 4
The vector `y` contains `2.6 * x^2 + .8 * x` plus some gaussian noise
The optional vector `vars` contains descriptive names for `x` and `y`
"""
function load_poly()
    path = joinpath(@__DIR__, "..", "data", "poly.csv")
    raw_csv = readdlm(path, ',')
    x = convert(Vector{Float64}, raw_csv[:, 1])
    y = convert(Vector{Float64}, raw_csv[:, 2])
    x, y, ["x", "2.6 x² + .8 x + ɛ"]
end

"""
x, y, vars = load_spiral()`

Loads an artificial example dataset for a noisy spiral function.
It is particularly useful to explain representation learning and nonlinearity.
The matrix `x` contains 194 points between 0 and 6.5 lying on the spiral.
The vector `y` contains the corresponding labels, i.e "ones" or "zeros".
The optional vector `vars` contains descriptive names for `x` and `y`
"""
function load_spiral(n::Int = 194)
    path = joinpath(@__DIR__, "..", "data", "spiral.csv")
    raw_csv = readdlm(path, ',')
    x = convert(Matrix{Float64}, raw_csv[1:n, 1:2])
    y = convert(Vector{Int}, raw_csv[1:n, 3])
    x, y, ["r*sin(θ)", "r*cos(θ)", "class"]
end


text:
"""
$(TYPEDEF)
Abstract parent struct for DFG variables and factors.
"""
abstract type DFGNode
end

"""
$(TYPEDEF)
An abstract DFG variable.
"""
abstract type AbstractDFGVariable <: DFGNode
end

"""
$(TYPEDEF)
An abstract DFG factor.
"""
abstract type AbstractDFGFactor <: DFGNode
end

"""
$(TYPEDEF)
Abstract parent struct for solver parameters.
"""
abstract type AbstractParams end

"""
$(TYPEDEF)
Abstract parent struct for a DFG graph.
    """
abstract type AbstractDFG{T<:AbstractParams} end

"""
$(TYPEDEF)
Empty structure for solver parameters.
"""
struct NoSolverParams <: AbstractParams
end

"""
$(TYPEDEF)
Abstract parent struct for big data entry.
"""
abstract type AbstractBigDataEntry end


text:
using BinaryBuilder, Pkg

"""
    offset_version(upstream, offset)

Compute a version that allows distinguishing between changes in the upstream
version and changes to the JLL which retain the same upstream version.

When the `upstream` version is changed, `offset` version numbers should be reset
to `v"0.0.0"` and incremented following semantic versioning.
"""
function offset_version(upstream, offset)
    return VersionNumber(
        upstream.major * 100 + offset.major,
        upstream.minor * 100 + offset.minor,
        upstream.patch * 100 + offset.patch,
    )
end

# GCC version for building the whole system
gcc_version = v"6"

# Versions of various COIN-OR libraries

Bonmin_upstream_version = v"1.8.8"
Bonmin_gitsha = "65c56cea1e7c40acd9897a2667c11f91d845bb7b"
Bonmin_version_offset = v"0.0.1"
Bonmin_version = offset_version(Bonmin_upstream_version, Bonmin_version_offset)

Couenne_version = offset_version(v"0.5.8", v"0.0.1")
Couenne_gitsha = "7154f7a9b3cd84be378d02b483d090b76fc79ce8"

Cbc_upstream_version = v"2.10.5"
Cbc_gitsha = "7b5ccc016f035f56614c8018b20d700978144e9f"
Cbc_version_offset = v"0.0.1"
Cbc_version = offset_version(Cbc_upstream_version, Cbc_version_offset)

Cgl_upstream_version = v"0.60.3"
Cgl_gitsha = "31797b2997219934db02a40d501c4b6d8efa7398"
Cgl_version_offset = v"0.0.0"
Cgl_version = offset_version(Cgl_upstream_version, Cgl_version_offset)

Clp_upstream_version = v"1.17.6"
Clp_gitsha = "756ddd3ed813eb1fa8b2d1b4fe813e6a4d7aa1eb"
Clp_version_offset = v"0.0.1"
Clp_version = offset_version(Clp_upstream_version, Clp_version_offset)

Osi_upstream_version = v"0.108.6"
Osi_gitsha = "dfa6449d6756fdd96912cf96e168d0be07b1d37c"
Osi_version_offset = v"0.0.0"
Osi_version = offset_version(Osi_upstream_version, Osi_version_offset)

CoinUtils_upstream_version = v"2.11.4"
CoinUtils_gitsha = "f709081c9b57cc2dd32579d804b30689ca789982"
CoinUtils_verson_offset = v"0.0.0"
CoinUtils_version =
    offset_version(CoinUtils_upstream_version, CoinUtils_verson_offset)

Ipopt_upstream_version = v"3.14.4"
Ipopt_gitsha = "d872b3a3d17863c6a2a27475cc9af9e933cb7e92"
Ipopt_verson_offset = v"0.0.0"
Ipopt_version = offset_version(Ipopt_upstream_version, Ipopt_verson_offset)

ALPS_upstream_version = v"1.5.7"
# This is not the exact 1.5.7 tag, but a few commits later on stable/1.5
ALPS_gitsha = "5b1a0b524979764d6ca929446762762712c035bb"
ALPS_version_offset = v"0.0.2"
ALPS_version = offset_version(ALPS_upstream_version, ALPS_version_offset)

BiCePS_version = offset_version(v"0.94.4", v"0.0.0")
BiCePS_gitsha = "8e41545a3b1a36ca1d306b3af96f3804dc57e61f"

CHiPPS_BLIS_version = offset_version(v"0.94.8", v"0.0.2")
# This is not the exact 0.94.8 tag, but a few commits later on releases/0.94.8
CHiPPS_BLIS_gitsha = "0ad6d4530d48e3b5f417a3407f5f2e8605145b50"

SYMPHONY_upstream_version = v"5.6.17"
SYMPHONY_gitsha = "f917d42e6655a82ea4e9290aa7d41b0f60a91f20"
SYMPHONY_version_offset = v"0.0.0"
SYMPHONY_version =
    offset_version(SYMPHONY_upstream_version, SYMPHONY_version_offset)

MibS_version = offset_version(v"1.1.3", v"0.0.1")
MibS_gitsha = "4b7ec93c4bd1d6a978deff9987cf1df74f6598d3"

SHOT_gitsha = "11fda1ecb84af9718f1e0c0ebf7ae5ae8c45041a"
SHOT_version = offset_version(v"1.1.0", v"0.0.0")

# Third-party packages needed by COIN-OR libraries.
ASL_version = v"0.1.3"
METIS_version = v"5.1.1"
MUMPS_seq_version = v"5.4.1"
OpenBLAS32_version = v"0.3.10"

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

max_stars_repo_name: sharanry/Yggdrasil

max_issues_repo_name: sharanry/Yggdrasil

max_forks_repo_name: sharanry/Yggdrasil