text:
# This file is mostly generated by `scripts/generate_precompile.jl`

const __bodyfunction__ = Dict{Method,Any}()

# Find keyword "body functions" (the function that contains the body
# as written by the developer, called after all missing keyword-arguments
# have been assigned values), in a manner that doesn't depend on
# gensymmed names.
# `mnokw` is the method that gets called when you invoke it without
# supplying any keywords.
function __lookup_kwbody__(mnokw::Method)
    function getsym(arg)
        isa(arg, Symbol) && return arg
        @assert isa(arg, GlobalRef)
        return arg.name
    end

    f = get(__bodyfunction__, mnokw, nothing)
    if f === nothing
        fmod = mnokw.module
        # The lowered code for `mnokw` should look like
        #   %1 = mkw(kwvalues..., #self#, args...)
        #        return %1
        # where `mkw` is the name of the "active" keyword body-function.
        ast = Base.uncompressed_ast(mnokw)
        if isa(ast, Core.CodeInfo) && length(ast.code) >= 2
            callexpr = ast.code[end-1]
            if isa(callexpr, Expr) && callexpr.head == :call
                fsym = callexpr.args[1]
                if isa(fsym, Symbol)
                    f = getfield(fmod, fsym)
                elseif isa(fsym, GlobalRef)
                    if fsym.mod === Core && fsym.name === :_apply
                        f = getfield(mnokw.module, getsym(callexpr.args[2]))
                    elseif fsym.mod === Core && fsym.name === :_apply_iterate
                        f = getfield(mnokw.module, getsym(callexpr.args[3]))
                    else
                        f = getfield(fsym.mod, fsym.name)
                    end
                else
                    f = missing
                end
            else
                f = missing
            end
        else
            f = missing
        end
        __bodyfunction__[mnokw] = f
    end
    return f
end

function _precompile_()
    ccall(:jl_generating_output, Cint, ()) == 1 || return nothing
    try; isdefined(Atom, Symbol("#101#102")) && precompile(Tuple{getfield(Atom, Symbol("#101#102")),Array{Any,1}}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#107#108")) && precompile(Tuple{getfield(Atom, Symbol("#107#108")),Hiccup.Node{:table}}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#107#108")) && precompile(Tuple{getfield(Atom, Symbol("#107#108")),Juno.Model}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#115#116")) && precompile(Tuple{getfield(Atom, Symbol("#115#116")),Text{String}}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#174#175")) && precompile(Tuple{getfield(Atom, Symbol("#174#175"))}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#181#185")) && precompile(Tuple{getfield(Atom, Symbol("#181#185"))}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#191#195")) && precompile(Tuple{getfield(Atom, Symbol("#191#195"))}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#203#207")) && precompile(Tuple{getfield(Atom, Symbol("#203#207"))}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#210#211")) && precompile(Tuple{getfield(Atom, Symbol("#210#211")),Base.MethodList}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#210#211")) && precompile(Tuple{getfield(Atom, Symbol("#210#211")),MD}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#264#266")) && precompile(Tuple{getfield(Atom, Symbol("#264#266")),FuzzyCompletions.DictCompletion}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#264#266")) && precompile(Tuple{getfield(Atom, Symbol("#264#266")),FuzzyCompletions.FieldCompletion}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#264#266")) && precompile(Tuple{getfield(Atom, Symbol("#264#266")),FuzzyCompletions.KeywordCompletion}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#264#266")) && precompile(Tuple{getfield(Atom, Symbol("#264#266")),FuzzyCompletions.MethodCompletion}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#264#266")) && precompile(Tuple{getfield(Atom, Symbol("#264#266")),FuzzyCompletions.ModuleCompletion}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#264#266")) && precompile(Tuple{getfield(Atom, Symbol("#264#266")),FuzzyCompletions.PathCompletion}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#264#266")) && precompile(Tuple{getfield(Atom, Symbol("#264#266")),FuzzyCompletions.PropertyCompletion}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#27#28")) && precompile(Tuple{getfield(Atom, Symbol("#27#28"))}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#31#32")) && precompile(Tuple{getfield(Atom, Symbol("#31#32")),String}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#33#35")) && precompile(Tuple{getfield(Atom, Symbol("#33#35")),String}); catch err; @debug err; end
    try; isdefined(Atom, Symbol("#49#50")) && precompile(Tuple{getfield(Atom, Symbol("#49#50")),String}); catch err; @debug err; end
    try; @assert(let fbody = try __lookup_kwbody__(which(Atom.fixpath, (String,))) catch missing end
        if !ismissing(fbody)
            precompile(fbody, (String,String,typeof(Atom.fixpath),String,))
        end
    end); catch err; @debug err; end
    try; @assert(precompile(Tuple{Core.kwftype(typeof(Atom._collecttoplevelitems_static)),NamedTuple{(:inmod,),Tuple{Bool}},typeof(Atom._collecttoplevelitems_static),Nothing,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Core.kwftype(typeof(Atom.modulefiles)),NamedTuple{(:inmod,),Tuple{Bool}},typeof(modulefiles),String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Core.kwftype(typeof(Atom.toplevelitems)),NamedTuple{(:mod, :inmod),Tuple{String,Bool}},typeof(toplevelitems),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Atom.EvalError},StackOverflowError,Array{Base.StackTraces.StackFrame,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Atom.GotoItem},String,Atom.ToplevelCall})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Atom.GotoItem},String,Atom.ToplevelMacroCall})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Atom.GotoItem},String,Atom.ToplevelModuleUsage})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Axes,F,Args} where Args<:Tuple where F where Axes},typeof(Atom.localdatatip),Tuple{Array{Atom.ActualLocalBinding,1},Base.RefValue{SubString{String}},Int64}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Axes,F,Args} where Args<:Tuple where F where Axes},typeof(todict),Tuple{Array{Atom.GotoItem,1}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Axes,F,Args} where Args<:Tuple where F where Axes},typeof(todict),Tuple{Array{OutlineItem,1}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Axes,F,Args} where Args<:Tuple where F where Axes},typeof(|>),Tuple{Array{Atom.GotoItem,1},Base.RefValue{typeof(todict)}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Base.RefValue},typeof(todict)})); catch err; @debug err; end
    try; @assert(precompile(Tuple{Type{Set},Array{OutlineItem,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(==),Array{Atom.GotoItem,1},Array{Any,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.appendline),String,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,FuzzyCompletions.DictCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,FuzzyCompletions.FieldCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,FuzzyCompletions.KeywordCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,FuzzyCompletions.ModuleCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,FuzzyCompletions.PathCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,FuzzyCompletions.PropertyCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,REPL.REPLCompletions.FieldCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,REPL.REPLCompletions.KeywordCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,REPL.REPLCompletions.ModuleCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,REPL.REPLCompletions.PathCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.completion),Module,REPL.REPLCompletions.PropertyCompletion,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.displayandrender),Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.displayandrender),Symbol})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.docs),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.eval),String,Int64,String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.evalall),String,String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.evalshow),String,Int64,String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.finddevpackages)})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.fullREPLpath),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.fullpath),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.fuzzycompletionadapter),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.getmodule),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.handlemsg),Dict{String,Any},String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.handlemsg),Dict{String,Any}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.isactive),Base.GenericIOBuffer{Array{UInt8,1}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.isanon),Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.md_hlines),MD})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.msg),String,Int64,Vararg{Any,N} where N})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.pkgpath),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.pluralize),Array{Int64,1},String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.processdoc!),MD,String,Array{Any,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.processval!),Any,String,Array{Any,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.processval!),Function,String,Array{Any,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.realpath′),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.Admonition})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.BlockQuote})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.Code})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.Footnote})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.Header{1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.Header{2}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.HorizontalRule})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.List})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMD),Markdown.Paragraph})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),Array{Any,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),Markdown.Code})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),Markdown.Footnote})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),Markdown.Image})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),Markdown.Italic})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),Markdown.LaTeX})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),Markdown.Link})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.renderMDinline),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.render′),Juno.Inline,Atom.Undefined})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.render′),Juno.Inline,Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.render′),Juno.Inline,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.render′),Juno.Inline,Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.render′),Juno.Inline,Nothing})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.render′),Juno.Inline,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.render′),Juno.Inline,Type{T} where T})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.replcompletionadapter),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.rt_inf),Any,Method,Type})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.trim),Array{Float64,1},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.withpath),Function,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Any})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Array{Any,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Array{String,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Atom.Undefined})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Base.EnvDict})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Dict{Method,Any}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Dict{String,Any}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Dict{String,Array{String,1}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Dict{String,Dict{String,Array{Atom.GotoItem,1}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,ErrorException})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Float16})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Float32})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Float64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,OrderedCollections.OrderedDict{String,Union{NamedTuple{(:rt, :desc),Tuple{String,String}}, NamedTuple{(:f, :m, :tt),Tuple{Any,Method,Type}}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Regex})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,Type{T} where T})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsicon),Module,Symbol,UInt32})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wsitem),Module,Symbol})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wstype),Module,Symbol,Any})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wstype),Module,Symbol,Atom.Undefined})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wstype),Module,Symbol,ErrorException})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wstype),Module,Symbol,Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wstype),Module,Symbol,Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Atom.wstype),Module,Symbol,Type{T} where T})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.broadcasted),Function,Array{Atom.ActualLocalBinding,1},SubString{String},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.broadcasted),Function,Array{Atom.ActualLocalBinding,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.broadcasted),Function,Array{Atom.GotoItem,1},Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.broadcasted),Function,Array{Atom.GotoItem,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.broadcasted),Function,Array{OutlineItem,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.combine_styles),Array{Atom.GotoItem,1},Base.RefValue{typeof(todict)}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Dict{Symbol,Any},1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.localdatatip),Tuple{Base.Broadcast.Extruded{Array{Atom.ActualLocalBinding,1},Tuple{Bool},Tuple{Int64}},Base.RefValue{SubString{String}},Int64}},Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Dict{Symbol,Any},1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(todict),Tuple{Base.Broadcast.Extruded{Array{Atom.GotoItem,1},Tuple{Bool},Tuple{Int64}}}},Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Dict{Symbol,Any},1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(todict),Tuple{Base.Broadcast.Extruded{Array{OutlineItem,1},Tuple{Bool},Tuple{Int64}}}},Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Dict{Symbol,Any},1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(|>),Tuple{Base.Broadcast.Extruded{Array{Atom.GotoItem,1},Tuple{Bool},Tuple{Int64}},Base.RefValue{typeof(todict)}}},Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Int64,1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.localdatatip),Tuple{Base.Broadcast.Extruded{Array{Atom.ActualLocalBinding,1},Tuple{Bool},Tuple{Int64}},Base.RefValue{SubString{String}},Int64}},Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{Nothing,1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.outlineitem),Tuple{Base.Broadcast.Extruded{Array{Atom.ToplevelItem,1},Tuple{Bool},Tuple{Int64}}}},Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.copyto_nonleaf!),Array{OutlineItem,1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.outlineitem),Tuple{Base.Broadcast.Extruded{Array{Atom.ToplevelItem,1},Tuple{Bool},Tuple{Int64}}}},Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(Atom.localdatatip),Tuple{Array{Atom.ActualLocalBinding,1},Base.RefValue{SubString{String}},Int64}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(todict),Tuple{Array{Atom.GotoItem,1}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(todict),Tuple{Array{OutlineItem,1}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.materialize),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Nothing,typeof(|>),Tuple{Array{Atom.GotoItem,1},Base.RefValue{typeof(todict)}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.Broadcast.restart_copyto_nonleaf!),Array{Union{Nothing, OutlineItem},1},Array{Nothing,1},Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.outlineitem),Tuple{Base.Broadcast.Extruded{Array{Atom.ToplevelItem,1},Tuple{Bool},Tuple{Int64}}}},OutlineItem,Int64,Base.OneTo{Int64},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base._promote_typejoin),Type{Nothing},Type{OutlineItem}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.allocatedinline),Type{Atom.GotoItem}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.allocatedinline),Type{Dict{String,Array{Atom.GotoItem,1}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to!),Array{Any,1},Base.Generator{Array{Any,1},typeof(Atom.renderMDinline)},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to!),Array{Hiccup.Node,1},Base.Generator{Array{Any,1},typeof(Atom.renderMD)},Int64,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Dict{Symbol,Any},1},Dict{Symbol,Any},Base.Generator{Array{DocSeeker.DocObj,1},typeof(Atom.renderitem)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:a},1},Hiccup.Node{:a},Base.Generator{Array{Any,1},typeof(Atom.renderMDinline)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:code},1},Hiccup.Node{:code},Base.Generator{Array{Any,1},typeof(Atom.renderMDinline)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:div},1},Hiccup.Node{:div},Base.Generator{Array{Any,1},typeof(Atom.renderMD)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:h1},1},Hiccup.Node{:h1},Base.Generator{Array{Any,1},typeof(Atom.renderMD)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:h2},1},Hiccup.Node{:h2},Base.Generator{Array{Any,1},typeof(Atom.renderMD)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:hr},1},Hiccup.Node{:hr},Base.Generator{Array{Any,1},typeof(Atom.renderMD)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:img},1},Hiccup.Node{:img},Base.Generator{Array{Any,1},typeof(Atom.renderMDinline)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:pre},1},Hiccup.Node{:pre},Base.Generator{Array{Any,1},typeof(Atom.renderMD)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{Hiccup.Node{:p},1},Hiccup.Node{:p},Base.Generator{Array{Any,1},typeof(Atom.renderMD)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Base.collect_to_with_first!),Array{String,1},String,Base.Generator{Array{Any,1},typeof(Atom.renderMDinline)},Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Dict{Any,Any}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Dict{Symbol,Any}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:a}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:blockquote}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:em}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:h1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:h2}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:hr}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:img}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:li}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:pre}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:p}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:td}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:tr}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Hiccup.Node{:ul}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),Method})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Juno.view),SubString{String}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Atom.EvalError{StackOverflowError}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Hiccup.Node{:div}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Hiccup.Node{:span}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Juno.Model})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Symbol})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Text{String}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(Media.render),Juno.Inline,Type{T} where T})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(clearsymbols)})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(convert),Type{Array{OutlineItem,1}},Array{Nothing,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(convert),Type{Array{OutlineItem,1}},Array{OutlineItem,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(convert),Type{Array{OutlineItem,1}},Array{Union{Nothing, OutlineItem},1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(convert),Type{Union{Nothing, Atom.Binding}},Atom.Binding})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(delete!),Dict{String,Dict{String,Array{Atom.GotoItem,1}}},String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(find_project_file),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getdocs),Module,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getfield′),Any,String,Atom.Undefined})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getfield′),Any,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getfield′),Any,Symbol,Atom.Undefined})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getfield′),Any,Symbol})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getfield′),Module,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getfield′),Module,Symbol,Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getfield′),Module,Symbol})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(getindex),Dict{String,Array{Atom.GotoItem,1}},String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(globaldatatip),String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(globalgotoitems),String,Module,Nothing,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(globalgotoitems),String,Module,String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(globalgotoitems_unloaded),String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(in),OutlineItem,Set{OutlineItem}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isempty),Array{Atom.ToplevelItem,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(ismacro),Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(ismacro),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Array{Any,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Array{String,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Atom.Undefined})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Base.RefValue{Bool}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Base.RefValue{Tuple{String,Int64}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Dict{Method,Any}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Dict{String,Any}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Dict{String,Array{String,1}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Dict{String,Dict{String,Array{Atom.GotoItem,1}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Function})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),HTML{String}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),OrderedCollections.OrderedDict{String,Union{NamedTuple{(:rt, :desc),Tuple{String,String}}, NamedTuple{(:f, :m, :tt),Tuple{Any,Method,Type}}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(isundefined),Type{T} where T})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(length),Base.KeySet{String,Dict{String,Array{Atom.GotoItem,1}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(length),Base.KeySet{String,Dict{String,Dict{String,Array{Atom.GotoItem,1}}}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(length),Dict{String,Array{Atom.GotoItem,1}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(map),Function,Array{Atom.GotoItem,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(map),Function,Array{OutlineItem,1}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(moduledefinition),Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(modulefiles),Module})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(modulefiles),String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(regeneratesymbols)})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(searchcodeblocks),MD})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(searchdocs′),String,Bool,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(searchdocs′),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(setindex!),Array{OutlineItem,1},OutlineItem,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(similar),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.localdatatip),Tuple{Base.Broadcast.Extruded{Array{Atom.ActualLocalBinding,1},Tuple{Bool},Tuple{Int64}},Base.RefValue{SubString{String}},Int64}},Type{Dict{Symbol,Any}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(similar),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.outlineitem),Tuple{Base.Broadcast.Extruded{Array{Atom.ToplevelItem,1},Tuple{Bool},Tuple{Int64}}}},Type{Nothing}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(similar),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(Atom.outlineitem),Tuple{Base.Broadcast.Extruded{Array{Atom.ToplevelItem,1},Tuple{Bool},Tuple{Int64}}}},Type{OutlineItem}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(similar),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(todict),Tuple{Base.Broadcast.Extruded{Array{Atom.GotoItem,1},Tuple{Bool},Tuple{Int64}}}},Type{Dict{Symbol,Any}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(similar),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(todict),Tuple{Base.Broadcast.Extruded{Array{OutlineItem,1},Tuple{Bool},Tuple{Int64}}}},Type{Dict{Symbol,Any}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(similar),Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1},Tuple{Base.OneTo{Int64}},typeof(|>),Tuple{Base.Broadcast.Extruded{Array{Atom.GotoItem,1},Tuple{Bool},Tuple{Int64}},Base.RefValue{typeof(todict)}}},Type{Dict{Symbol,Any}}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(sprint),Function,Base.Generator{CSTParser.EXPR,typeof(Atom.str_value)}})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(strlimit),String,Int64})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(toplevelitems),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(updatesymbols),String,String,String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(use_compiled_modules)})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(vcat),OutlineItem,OutlineItem,OutlineItem,Vararg{OutlineItem,N} where N})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(workspace),String})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(|>),Array{Atom.GotoItem,1},typeof(isempty)})); catch err; @debug err; end
    try; @assert(precompile(Tuple{typeof(|>),Array{Atom.ToplevelItem,1},typeof(length)})); catch err; @debug err; end
end


text:
using NeRCA
using Test

hits = [Hit(1, 8, 100, 20, false),
        Hit(2, 9, 101, 21, true),
        Hit(3, 8, 112, 22, true),
        Hit(4, 8, 114, 23, false),
        Hit(5, 8, 134, 24, true),
        Hit(6, 8, 156, 25, false),
        Hit(7, 8, 133, 26, true),
        Hit(8, 8, 145, 26, false),
        Hit(9, 10, 900, 26, false),
        Hit(1, 11, 1000, 26, false),
        Hit(1, 11, 1001, 26, false),
        Hit(1, 11, 1002, 26, false)]

# triggered()
thits = triggered(hits)
@test 4 == length(thits)
@test 9 == thits[1].dom_id

# nfoldhits()
twofoldhits = nfoldhits(hits, 10, 2)
@test 4 == length(twofoldhits)
threefoldhits = nfoldhits(hits, 15, 3)
@test 3 == length(threefoldhits)

# domhits()
dhits = domhits(hits)
@test 7 == length(dhits[8])
@test 20 == dhits[8][1].tot
@test dhits[8][6].triggered

# multiplicities
sorted_hits = sort(hits, by=h->h.t)
sort!(sorted_hits, by=h->h.dom_id)
mtps, mtp_ids = NeRCA.count_multiplicities(sorted_hits, 10)
@test (1, 1) == (mtps[1], mtp_ids[1])
@test (2, 2) == (mtps[2], mtp_ids[2])
@test (2, 2) == (mtps[3], mtp_ids[3])
@test (2, 3) == (mtps[4], mtp_ids[4])
@test (2, 3) == (mtps[5], mtp_ids[5])
@test (1, 4) == (mtps[6], mtp_ids[6])
@test (1, 5) == (mtps[7], mtp_ids[7])
@test (1, 6) == (mtps[8], mtp_ids[8])
@test (1, 7) == (mtps[9], mtp_ids[9])
@test (3, 8) == (mtps[10], mtp_ids[10])
@test (3, 8) == (mtps[11], mtp_ids[11])
@test (3, 8) == (mtps[12], mtp_ids[12])

ext: jl


text:
struct Figshare <: DataRepo
end

base_url(::Figshare) = "https://api.figshare.com/v2/articles"
# Note: Unlike other generators, FigShare base_url is sometimes a "directory" and sometimes a file
# But it is OK, because Figshare also overloads all the functions that use `base_url`
# Most importantly `mainpage_url`

description(repo::Figshare, mainpage) = mainpage["description"]

author(::Figshare, mainpage) = [value["full_name"] for value in mainpage["authors"]]

license(::Figshare, mainpage) = mainpage["license"]["name"] * " (" *mainpage["license"]["url"] * ")"

published_date(::Figshare, mainpage) = mainpage["published_date"]

dataset_cite(::Figshare, mainpage) = mainpage["citation"]

function get_urls(repo::Figshare, page)
    urls = []
    for ii in page["files"]
        push!(urls, ii["download_url"])
    end
    urls
end

function get_checksums(repo::Figshare, page)
    @info("Generated registration block uses MD5 hashes, the MD5.jl package will be required.")
    [(:md5, ii["computed_md5"]) for ii in page["files"]]
end

function data_fullname(::Figshare, mainpage)
    mainpage["title"]
end

function website(repo::Figshare, mainpage_url, mainpage)
    mainpage["url_public_html"]
end

function match_figshare(uri::String)
    identifier_match = match(r"\d{7}", uri)
    identifier_match === nothing ? nothing : identifier_match.match
end

function mainpage_url(repo::Figshare, dataname)
    #We are making it work for both figshare id or doi
    if match_doi(dataname) != nothing
        identifier = match_doi(dataname)
        down_url = base_url(repo) * "?doi=" * identifier
        doi_page = JSON.parse(text_only(getpage(down_url).root))
        url = doi_page[1]["url_public_api"]
        return JSON.parse(text_only(getpage(url).root)), url
    elseif match_figshare(dataname)!= nothing
        identifier = match_figshare(dataname)
        url = joinpath(base_url(repo), identifier)
        return JSON.parse(text_only(getpage(url).root)), url
    else
        throw(GeneratorError(repo))
    end
end


text:
# Autogenerated wrapper script for Singular_jll for x86_64-linux-musl-cxx03
export Singular, libfactory, libomalloc, libparse, libpolys, libsingular, libsingular_resources

using cddlib_jll
using FLINT_jll
using GMP_jll
using MPFR_jll
JLLWrappers.@generate_wrapper_header("Singular")
JLLWrappers.@declare_library_product(libfactory, "libfactory-4.2.1.so")
JLLWrappers.@declare_library_product(libomalloc, "libomalloc-0.9.6.so")
JLLWrappers.@declare_library_product(libpolys, "libpolys-4.2.1.so")
JLLWrappers.@declare_library_product(libsingular, "libSingular-4.2.1.so")
JLLWrappers.@declare_library_product(libsingular_resources, "libsingular_resources-4.2.1.so")
JLLWrappers.@declare_executable_product(Singular)
JLLWrappers.@declare_executable_product(libparse)
function __init__()
    JLLWrappers.@generate_init_header(cddlib_jll, FLINT_jll, GMP_jll, MPFR_jll)
    JLLWrappers.@init_library_product(
        libfactory,
        "lib/libfactory.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_library_product(
        libomalloc,
        "lib/libomalloc.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_library_product(
        libpolys,
        "lib/libpolys.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_library_product(
        libsingular,
        "lib/libSingular.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_library_product(
        libsingular_resources,
        "lib/libsingular_resources.so",
        RTLD_LAZY | RTLD_DEEPBIND,
    )

    JLLWrappers.@init_executable_product(
        Singular,
        "bin/Singular",
    )

    JLLWrappers.@init_executable_product(
        libparse,
        "bin/libparse",
    )

    JLLWrappers.@generate_init_footer()
end  # __init__()


text:
module PolyCompat

using ..Polynomials
indeterminate = Polynomials.indeterminate

#=
Compat support for old code. This will be opt-in by v1.0, through "using Polynomials.PolyCompat"
=#

## Poly

"""
    Poly{T}

Type of polynomial to support legacy code. Use of this type  is  not  encouraged.

This type provides support for `poly`, `polyval`, `polyder`, and
`polyint` to support older code. It should not be used for a new code
base. Call `using Polynomials.PolyCompat` to enable this module.

"""
struct Poly{T <: Number,X} <: Polynomials.StandardBasisPolynomial{T,X}
    coeffs::Vector{T}
    function Poly(a::AbstractVector{T}, var::Polynomials.SymbolLike = :x) where {T <: Number}
        # if a == [] we replace it with a = [0]
        X = Symbol(var)
        if length(a) == 0
            return new{T,X}(zeros(T, 1))
        else
        # determine the last nonzero element and truncate a accordingly
            last_nz = findlast(!iszero, a)
            a_last = max(1, last_nz === nothing ? 0 : last_nz)
            new{T,X}(a[1:a_last])
        end
    end
end

Polynomials.@register Poly

Poly{T,X}(coeffs::AbstractVector{S}) where {T,X,S} = Poly(convert(Vector{T},coeffs), X)

Base.convert(P::Type{<:Polynomial}, p::Poly{T}) where {T} = Polynomial{eltype(P),indeterminate(P,p)}(p.coeffs)
Base.convert(P::Type{<:Poly}, p::Poly{T,X}) where {T<:Number,X} = Polynomials.constructorof(P){_eltype(P),indeterminate(P,p)}(p.coeffs)
Base.eltype(P::Type{<:Poly{T,X}}) where {T, X} = P
_eltype(::Type{<:Poly{T}}) where  {T} = T
_eltype(::Type{Poly}) =  Float64

# when interating over poly return monomials
function Base.iterate(p::Poly, state=nothing)
    i = 0
    state == nothing && return (p[i]*one(p), i)
    j = degree(p)
    s = state + 1
    i <= state < j && return (p[s]*Polynomials.basis(p,s), s)
    return nothing
end
Base.collect(p::Poly) = [pᵢ for pᵢ ∈ p]

# need two here as `eltype(P)` is `_eltype(P)`.
Base.zero(::Type{P}) where {P <: Poly} = Poly{_eltype(P), Polynomials.indeterminate(P)}([0])
Base.zero(::Type{P},var::Polynomials.SymbolLike) where {P <: Poly} = Poly(zeros(_eltype(P),1), var)
Base.one(::Type{P}) where {P <: Poly} = Poly{_eltype(P), Polynomials.indeterminate(P)}([1])
Base.one(::Type{P},var::Polynomials.SymbolLike) where {P <: Poly} = Poly(ones(_eltype(P),1), var)
Polynomials.variable(::Type{P}) where {P <: Poly} = Poly{_eltype(P), Polynomials.indeterminate(P)}([0,1])
Polynomials.variable(::Type{P},var::Polynomials.SymbolLike) where {P <: Poly} = Poly(_eltype(P)[0,1], var)
function Polynomials.basis(P::Type{<:Poly}, k::Int, _var::Polynomials.SymbolLike=:x; var=_var)
    zs = zeros(Int, k+1)
    zs[end] = 1
    Polynomials.constructorof(P){_eltype(P), Symbol(var)}(zs)
end

function (p::Poly{T})(x::S) where {T,S}
    oS = one(x)
    length(p) == 0 && return zero(T) *  oS
    b = p[end]  *  oS
    @inbounds for i in (lastindex(p) - 1):-1:0
        b = p[i]*oS .+ x * b
    end
    return b
end

function Base.:+(p1::Poly, p2::Poly)
    indeterminate(p1) != indeterminate(p2) && error("Polynomials must have same variable")
    n = max(length(p1), length(p2))
    c = [p1[i] + p2[i] for i = 0:n-1]
    return Poly(c, indeterminate(p1))
end

function Base.:*(p1::Poly{T}, p2::Poly{S}) where {T,S}
    indeterminate(p1) != indeterminate(p2) && error("Polynomials must have same variable")
    n = length(p1) - 1
    m = length(p2) - 1
    R = promote_type(T, S)
    c = zeros(R, m + n + 1)
    for i in 0:n, j in 0:m
        c[i + j + 1] += p1[i] * p2[j]
    end
    return Poly(c, indeterminate(p1))
end

## Compat
## As this is an older package with many examples out in the wild
## rather than remove these, we limit them to this `Poly` type only

poly(r, var = :x) = fromroots(Poly, r; var = var)

polyval(p::Poly, x::Number) = p(x)
polyval(p::Poly, x) = p.(x)
polyval(p::AbstractPolynomial, x) = error("`polyval` is a legacy name for use with `Poly` objects only. Use `p(x)`.")

function Base.getproperty(p::Poly, nm::Symbol)
    if nm == :a
        return getfield(p, :coeffs)
    end
    return getfield(p, nm)
end

function Polynomials.integrate(p::P, k::S) where {T, X, P <: Poly{T, X}, S<:Number}

    R = eltype((one(T)+one(S))/1)
    Q = Poly{R,X}
    if hasnan(p) || isnan(k)
        return P([NaN]) # keep for Poly, not Q
    end
    n = length(p)
    a2 = Vector{R}(undef, n + 1)
    a2[1] = k
    @inbounds for i in 1:n
        a2[i + 1] = p[i - 1] / i
    end
    return Q(a2)
end

polyint(p::Poly, C = 0) = integrate(p, C)
polyint(p::Poly, a, b) = integrate(p, a, b)
polyint(p::AbstractPolynomial, args...)  = error("`polyint` is a legacy name for use with `Poly` objects only. Use `integrate(p,...)`.")

polyder(p::Poly, ord = 1) = derivative(p, ord)
polyder(p::AbstractPolynomial, args...) =  error("`polyder` is a legacy name for use with `Poly` objects only. Use `derivative(p,[order=1])`.")

polyfit(x, y, n = length(x) - 1, sym=:x) = fit(Poly, x, y, n; var = sym)
polyfit(x, y, sym::Symbol) = fit(Poly, x, y, var = sym)

export Poly, poly, polyval, polyint, polyder, polyfit

## Pade
include("../pade.jl")
using .PadeApproximation
export Pade
export padeval

end


text:
# Lifting

# # Specializations
# const unidistattrs = [:succprob, :failprob, :maximum, :minimum, :islowerbounded,
#                       :isupperbounded, :isbounded, :std, :median, :mode, :modes,
#                       :skewness, :kurtosis, :isplatykurtic, :ismesokurtic,
#                       :isleptokurtic, :entropy, :mean]

# for func in unidistattrs
#   expr =
#   quote
#     $func(x::RandVar, israndvar::Type{Val{false}}) = Djl.$func(distribution(x))
#     $func(x::RandVar, israndvar::Type{Val{true}}) = $(:l *ₛ func)(x)
#     $(:l *ₛ func)(x::RandVar) = lift($func)(x, Val{false})
#     $func(x::RandVar) = $func(x, Val{elemtype(x) <: RandVar})
#   end
#   eval(expr)
# end

# Lift all dist ops
for dop in distops_names
  expr = :($(dop *ₛ :ᵣ)(x::RandVar) = lift($dop)(x))
  eval(expr)
end


text:
# call this script from command line to compile
#   julia compile.jl [opt]
# optional: add --precompile to precompile the statements from statements_file.jl

using PackageCompiler
using Base.Filesystem

function build(args)
    cd("../..")

    # options
    # --precompile: precompile the statements using an existing statements file
    precompile_statements = false
    for arg_str in args
        if arg_str == "--precompile-statements"
            precompile_statements = true
        else
            println("Error: invalid option "*arg_str)
            exit()
        end
    end

    if precompile_statements
        create_app("Triangulation",
            "exe_triangulation_precompiled",
            precompile_statements_file="./Triangulation/build/statements_file.jl")
    else
        create_app("Triangulation",
        "exe_triangulation")
    end
end

if abspath(PROGRAM_FILE) == @__FILE__
    build(ARGS)
end


text:
export solve!

# TODO: add ability to enforce a goal on part of the states
function solve!(SS::ShootingSolution, SP::ShootingProblem)
	model, x_init, x_goal, tf = SP.PD.model, SP.PD.x_init, SP.PD.goal_set, SP.tf, SP.x_goal

	# Set up shooting function
	shooting_eval! = (F, p0) -> parameterized_shooting_eval!(F, p0, SP)

	# Run Newton method
	time_start = time_ns()
	sol_newton = nothing
	try
		sol_newton = nlsolve(shooting_eval!, SP.p0, iterations = 100, ftol=1e-3) # TODO(ambyld): Make number of iterations a parameter
	catch
		iter_elapsed_time = (time_ns() - time_start)/10^9
		push!(SS.prob_status, :Diverged)
		push!(SS.J_true, NaN)
		push!(SS.convergence_measure, NaN)
		push!(SS.iter_elapsed_times, iter_elapsed_time)
		return
	end
	iter_elapsed_time = (time_ns() - time_start)/10^9

	if sol_newton.f_converged
		# Recover trajectory
		N, tf, x_dim = SP.N, SP.tf, model.x_dim
		x0 = [x_init; sol_newton.zero]
		tspan = (0., tf)
		dt = tf/(N-1)
		prob = ODEProblem(shooting_ode!, x0, tspan, SP)
		sol_ode = DifferentialEquations.solve(prob, saveat=dt)
		xp = hcat(sol_ode.u...)
		X, P = xp[1:x_dim,:], xp[x_dim+1:end,:]
		U = get_control(X, P, SP)
		new_traj = Trajectory(X, U, tf, dt)

		push!(SS.prob_status, :Optimal)
		push!(SS.J_true, cost_true(new_traj, new_traj, SP))
		push!(SS.convergence_measure, convergence_metric(new_traj, SS.traj, SP))
		push!(SS.iter_elapsed_times, iter_elapsed_time)
		copy!(SS.traj, new_traj)
	else
		push!(SS.prob_status, :Diverged)
		push!(SS.J_true, NaN)
		push!(SS.convergence_measure, NaN)
		push!(SS.iter_elapsed_times, iter_elapsed_time)
	end
end

function parameterized_shooting_eval!(F::Vector{T}, p0::Vector{T}, SP::ShootingProblem) where T <: AbstractFloat
	model, x_init, x_goal, tf, dt = SP.PD.model, SP.PD.x_init, SP.x_goal, SP.tf, SP.dt
	x_dim = model.x_dim

	x0 = [x_init; p0]
	# N = SP.N
	tspan = (0., tf)
	# dt = tf/(500-1)
	prob = ODEProblem(shooting_ode!, x0, tspan, SP)
	sol = DifferentialEquations.solve(prob, dtmin=dt, force_dtmin=true, saveat=dt)

	a = [1.0*ones(6); 10.0*ones(7)]
	for i = 1:x_dim
		F[i] = x_goal[i] - sol.u[end][i]
	end
end


text:
using DashBootstrapComponents

toast = html_div([
    dbc_button(
        "Open toast",
        id = "simple-toast-toggle",
        color = "primary",
        className = "mb-3",
        n_clicks = 0,
    ),
    dbc_toast(
        [html_p("This is the content of the toast", className = "mb-0")],
        id = "simple-toast",
        header = "This is the header",
        icon = "primary",
        dismissable = true,
        is_open = false,
    ),
]);

callback!(
    app,
    Output("simple-toast", "is_open"),
    Input("simple-toast-toggle", "n_clicks"),
) do n
    if n > 0
        return true
    end
    return no_update()
end;

max_issues_repo_name: sthagen/dash-bootstrap-components

max_forks_repo_name: sthagen/dash-bootstrap-components


text:
q = Quaternion(1, 0, 0, 0)
r = σmap(q)

@test isapprox(r, ℝ³(1, 0, 0))


text:
include("../src/strip2.jl")

#using strip2
using DelimitedFiles
using Plots
gr()
# Strip2: 54deg x 54deg
# General constants
NN = 1024
pix_size = 0.5
beam_waist = 9.0

# SZ Effect
N_SZ_Clusters  = 500
A_SZ_Clusters = 50.0
SZ_beta = 0.86
SZ_Theta_core = 1.0

# Point Sources - poisson distribution
N_Sources_POIS = 5000
A_Sources_POIS = 200.0

# Point Sources - exponential distrubution
N_Sources_EXP = 50
A_Sources_EXP = 1000.0

# Read the CAMB cmb power spectrum.
m = readdlm("power_spectrum/CAMB_totalCls.dat")

ell  = m[:, 1]
DlTT = m[:, 2]
DlEE = m[:, 3]
DlBB = m[:, 4]
DlTE = m[:, 5]

Map_T, Map_Q, Map_U, Map_E, Map_B = strip2.make_CMB_pol_maps(NN, pix_size, ell,
                                                             DlTT, DlEE, DlTE, DlBB)


text:
using BHAPtfem
using Test

ProjDir = joinpath(dirname(@__FILE__), "..", "examples", "fisherpaper")
cd(ProjDir) do

  isdir("tmp") &&
    rm("tmp", recursive=true);

  include(joinpath(ProjDir, "a1/fisher_01.jl"))

  @test round(results[1][2][11, 2], digits =6) == -0.003333

  isdir("tmp") &&
    rm("tmp", recursive=true);

end # cd


text:
"""
    peakflops_gpu_matmul_scaling(peakflops_func = peakflops_gpu_matmul; verbose=true) -> sizes, flops
Asserts the scaling of the given `peakflops_func`tion (defaults to [`peakflops_gpu_matmul`](@ref))
with increasing matrix size. If `verbose=true` (default), displays a unicode plot. Returns
the considered sizes and TFLOP/s. For further options, see [`peakflops_gpu_matmul`](@ref).
"""
function peakflops_gpu_matmul_scaling(
    peakflops_func::F=peakflops_gpu_matmul;
    device=CUDA.device(),
    verbose=true,
    sizes=2 .^ (10:15),
    io::IO=stdout,
    kwargs...,
) where {F}
    flops = zeros(length(sizes))
    for (i, s) in enumerate(sizes)
        flops[i] = peakflops_func(; device=device, size=s, verbose=false, kwargs...)
        clear_gpu_memory(device)
    end
    if verbose
        peak_val, idx = findmax(flops)
        peak_size = sizes[idx]
        p = UnicodePlots.lineplot(
            sizes,
            flops;
            xlabel="matrix size",
            ylabel="TFLOP/s",
            title=string(
                "Peak: ", round(peak_val; digits=2), " TFLOP/s (size = $(peak_size))"
            ),
            xscale=:log2,
        )
        UnicodePlots.lineplot!(p, [peak_size, peak_size], [0.0, peak_val]; color=:red)
        println(io) # top margin
        show(io, "text/plain",p)
        println(io) # bottom margin
        println(io) # bottom margin
    end
    return sizes, flops
end

_flopcount_per_matmul(n) = Float64(n)^3

"""
    peakflops_gpu_matmul(; device, dtype=Float32, size=2^14, nmatmuls=5, nbench=5, verbose=true)
Tries to estimate the peak performance of a GPU in TFLOP/s by measuring the time
it takes to perform `nmatmuls` many (in-place) matrix-matrix multiplications.

**Keyword arguments:**
* `device` (default: `CUDA.device()`): CUDA device to be used.
* `dtype` (default: `Float32`): element type of the matrices.
* `size` (default: `2^14`): matrices will have dimensions `(size, size)`.
* `nmatmuls` (default: `5`): number of matmuls that will make up the kernel to be timed.
* `nbench` (default: `5`): number of measurements to be performed the best of which is used for the TFLOP/s computation.
* `verbose` (default: `true`): toggle printing.
* `io` (default: `stdout`): set the stream where the results should be printed.

See also: [`peakflops_gpu_matmul_scaling`](@ref), [`peakflops_gpu_matmul_graphs`](@ref).
"""
function peakflops_gpu_matmul(;
    device=CUDA.device(), dtype=Float32, size=2^14, nmatmuls=5, nbench=5, verbose=true, io::IO=stdout
)
    device!(device) do
        C = CUDA.zeros(dtype, size, size)
        A = CUDA.rand(dtype, size, size)
        B = CUDA.rand(dtype, size, size)

        CUDA.@elapsed mul!(C, A, B) # warmup

        t = Inf
        NVTX.@range "peakflops_gpu: bench loop" begin
            for i in 1:nbench
                NVTX.@range "peakflops_gpu: kernel" begin
                    Δt = CUDA.@elapsed for _ in 1:nmatmuls
                        mul!(C, A, B)
                        # cublasGemmEx_wrapper!('N','N',A,B,C)
                    end
                end
                t = min(t, Δt)
            end
        end

        flops = (_flopcount_per_matmul(size) * nmatmuls * 1e-12) / t
        if verbose
            printstyled(io,"Peakflops (TFLOP/s):\n"; bold=true)
            print(io," └ max: ")
            printstyled(io,round(flops; digits=2), "\n"; color=:green, bold=true)
        end
        return flops
    end
end

"""
Same as [`peakflops_gpu_matmul`](@ref) but uses CUDA's graph API to define and launch the kernel.

See also: [`peakflops_gpu_matmul_scaling`](@ref).
"""
function peakflops_gpu_matmul_graphs(;
    device=CUDA.device(), dtype=Float32, size=2^14, nmatmuls=5, nbench=5, verbose=true, io::IO=stdout
)
    device!(device) do
        C = CUDA.zeros(dtype, size, size)
        A = CUDA.rand(dtype, size, size)
        B = CUDA.rand(dtype, size, size)

        t = Inf
        for i in 1:nbench
            graph = CUDA.capture() do
                for _ in 1:nmatmuls
                    mul!(C, A, B)
                    # cublasGemmEx_wrapper!('N','N',A,B,C)
                end
            end
            exec = instantiate(graph)
            Δt = CUDA.@elapsed CUDA.launch(exec)
            t = min(t, Δt)
        end

        flops = (_flopcount_per_matmul(size) * nmatmuls * 1e-12) / t
        if verbose
            printstyled(io,"Peakflops (TFLOP/s):\n"; bold=true)
            print(io," └ max: ")
            printstyled(io,round(flops; digits=2), "\n"; color=:green, bold=true)
        end
        return flops
    end
end


text:
_lower_set(set::MOI.Interval) = MOI.GreaterThan(set.lower)
_upper_set(set::MOI.Interval) = MOI.LessThan(set.upper)
_lower_set(set::MOI.EqualTo) = MOI.GreaterThan(set.value)
_upper_set(set::MOI.EqualTo) = MOI.LessThan(set.value)
_lower_set(set::MOI.Zeros) = MOI.Nonnegatives(set.dimension)
_upper_set(set::MOI.Zeros) = MOI.Nonpositives(set.dimension)

"""
    SplitIntervalBridge{T, F, S, LS, US}

The `SplitIntervalBridge` splits a `F`-in-`S` constraint into a `F`-in-`LS` and
a `F`-in-`US` constraint where we have either:
* `F = MOI.Interval{T}`, `LS = MOI.GreaterThan{T}` and `US = MOI.LessThan{T}`,
* `F = MOI.EqualTo{T}`, `LS = MOI.GreaterThan{T}` and `US = MOI.LessThan{T}`, or
* `F = MOI.Zeros`, `LS = MOI.Nonnegatives` and `US = MOI.Nonpositives`.

For instance, if `F` is `MOI.ScalarAffineFunction` and `S` is `MOI.Interval`,
it transforms the constraint ``l ≤ ⟨a, x⟩ + α ≤ u`` into the constraints
``⟨a, x⟩ + α ≥ l`` and ``⟨a, x⟩ + α ≤ u``.
"""
struct SplitIntervalBridge{T, F<:MOI.AbstractFunction, S<:MOI.AbstractSet,
                           LS<:MOI.AbstractSet, US<:MOI.AbstractSet} <: AbstractBridge
    lower::CI{F, LS}
    upper::CI{F, US}
end
function bridge_constraint(
    ::Type{SplitIntervalBridge{T, F, S, LS, US}}, model::MOI.ModelLike, f::F,
    set::S) where {T, F, S, LS, US}
    lower = MOI.add_constraint(model, f, _lower_set(set))
    upper = MOI.add_constraint(model, f, _upper_set(set))
    return SplitIntervalBridge{T, F, S, LS, US}(lower, upper)
end

function MOI.supports_constraint(
    ::Type{SplitIntervalBridge{T}}, ::Type{<:MOI.AbstractScalarFunction},
    ::Type{<:Union{MOI.Interval{T}, MOI.EqualTo{T}}}) where T
    return true
end
function MOI.supports_constraint(
    ::Type{SplitIntervalBridge{T}}, ::Type{<:MOI.AbstractVectorFunction},
    ::Type{MOI.Zeros}) where T
    return true
end
MOIB.added_constrained_variable_types(::Type{<:SplitIntervalBridge}) = Tuple{DataType}[]
function MOIB.added_constraint_types(::Type{SplitIntervalBridge{T, F, S, LS, US}}) where {T, F, S, LS, US}
    return [(F, LS), (F, US)]
end
function concrete_bridge_type(
    ::Type{<:SplitIntervalBridge}, F::Type{<:MOI.AbstractScalarFunction},
    S::Type{<:Union{MOI.Interval{T}, MOI.EqualTo{T}}}) where T
    return SplitIntervalBridge{T, F, S, MOI.GreaterThan{T}, MOI.LessThan{T}}
end
function concrete_bridge_type(
    ::Type{<:SplitIntervalBridge{T}}, F::Type{<:MOI.AbstractVectorFunction},
    ::Type{MOI.Zeros}) where T
    return SplitIntervalBridge{T, F, MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives}
end

# Attributes, Bridge acting as a model
function MOI.get(::SplitIntervalBridge{T, F, S, LS},
                 ::MOI.NumberOfConstraints{F, LS}) where {T, F, S, LS}
    return 1
end
function MOI.get(::SplitIntervalBridge{T, F, S, LS, US},
                 ::MOI.NumberOfConstraints{F, US}) where {T, F, S, LS, US}
    return 1
end
function MOI.get(bridge::SplitIntervalBridge{T, F, S, LS},
                 ::MOI.ListOfConstraintIndices{F, LS}) where {T, F, S, LS}
    return [bridge.lower]
end
function MOI.get(bridge::SplitIntervalBridge{T, F, S, LS, US},
                 ::MOI.ListOfConstraintIndices{F, US}) where {T, F, S, LS, US}
    return [bridge.upper]
end

# Indices
function MOI.delete(model::MOI.ModelLike, bridge::SplitIntervalBridge)
    MOI.delete(model, bridge.lower)
    MOI.delete(model, bridge.upper)
end

# Attributes, Bridge acting as a constraint
function MOI.supports(
    ::MOI.ModelLike,
    ::Union{MOI.ConstraintPrimalStart, MOI.ConstraintDualStart},
    ::Type{<:SplitIntervalBridge})

    return true
end
function MOI.get(model::MOI.ModelLike, attr::Union{MOI.ConstraintPrimal, MOI.ConstraintPrimalStart},
                 bridge::SplitIntervalBridge)
    # lower and upper should give the same value
    return MOI.get(model, attr, bridge.lower)
end
function MOI.set(model::MOI.ModelLike, attr::MOI.ConstraintPrimalStart,
                 bridge::SplitIntervalBridge, value)
    MOI.set(model, attr, bridge.lower, value)
    MOI.set(model, attr, bridge.upper, value)
end
# The map is:
# x ∈ S <=> [1 1]' * x ∈ LS × US
# So the adjoint map is
# [1 1] * y ∈ S* <=> y ∈ (LS × US)*
# where [1 1] * y = y[1] + y[2]
# so we can just sum the dual values.
function MOI.get(model::MOI.ModelLike, attr::Union{MOI.ConstraintDual, MOI.ConstraintDualStart},
                 bridge::SplitIntervalBridge)
    return MOI.get(model, attr, bridge.lower) + MOI.get(model, attr, bridge.upper)
end
function _split_dual_start(value)
    if value < 0
        return zero(value), value
    else
        return value, zero(value)
    end
end
function _split_dual_start(value::Vector)
    lower = similar(value)
    upper = similar(value)
    for i in eachindex(value)
        lower[i], upper[i] = _split_dual_start(value[i])
    end
end
function MOI.set(model::MOI.ModelLike, attr::MOI.ConstraintDualStart,
                 bridge::SplitIntervalBridge{T}, value) where T
    lower, upper = _split_dual_start(value)
    MOI.set(model, attr, bridge.lower, lower)
    MOI.set(model, attr, bridge.upper, upper)
end

function MOI.get(model::MOI.ModelLike, ::MOI.ConstraintBasisStatus, bridge::SplitIntervalBridge)
    lower_stat = MOI.get(model, MOI.ConstraintBasisStatus(), bridge.lower)
    upper_stat = MOI.get(model, MOI.ConstraintBasisStatus(), bridge.upper)
    if lower_stat == MOI.NONBASIC_AT_LOWER
        @warn("GreaterThan constraints should not have basis status:" *
            " NONBASIC_AT_LOWER, instead use NONBASIC.")
    end
    if upper_stat == MOI.NONBASIC_AT_UPPER
        @warn("LessThan constraints should not have basis status:" *
            " NONBASIC_AT_UPPER, instead use NONBASIC.")
    end
    if lower_stat == MOI.NONBASIC
        return MOI.NONBASIC_AT_LOWER
    end
    if upper_stat == MOI.NONBASIC
        return MOI.NONBASIC_AT_UPPER
    end
    if lower_stat != upper_stat
        @warn("Basis status of lower (`$lower_stat`) and upper (`$upper_stat`) constraint are inconsistent," *
            " both should be basic or super basic.")
    end
    return lower_stat
end

# Constraints
function MOI.modify(model::MOI.ModelLike, bridge::SplitIntervalBridge, change::MOI.AbstractFunctionModification)
    MOI.modify(model, bridge.lower, change)
    MOI.modify(model, bridge.upper, change)
end

function MOI.set(model::MOI.ModelLike, ::MOI.ConstraintFunction,
                  bridge::SplitIntervalBridge{T, F}, func::F) where {T, F}
    MOI.set(model, MOI.ConstraintFunction(), bridge.lower, func)
    MOI.set(model, MOI.ConstraintFunction(), bridge.upper, func)
end

function MOI.set(model::MOI.ModelLike, ::MOI.ConstraintSet,
                 bridge::SplitIntervalBridge{T, F, S}, change::S) where {T, F, S}
    MOI.set(model, MOI.ConstraintSet(), bridge.lower, _lower_set(change))
    MOI.set(model, MOI.ConstraintSet(), bridge.upper, _upper_set(change))
end

function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintFunction,
                 bridge::SplitIntervalBridge)
    return MOI.get(model, attr, bridge.lower)
end
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintSet,
                 bridge::SplitIntervalBridge{T, F, MOI.Interval{T}}) where {T, F}
    return MOI.Interval(MOI.get(model, attr, bridge.lower).lower,
                        MOI.get(model, attr, bridge.upper).upper)
end
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintSet,
                 bridge::SplitIntervalBridge{T, F, MOI.EqualTo{T}}) where {T, F}
    return MOI.EqualTo(MOI.get(model, attr, bridge.lower).lower)
end
function MOI.get(model::MOI.ModelLike, attr::MOI.ConstraintSet,
                 bridge::SplitIntervalBridge{T, F, MOI.Zeros}) where {T, F}
    return MOI.Zeros(MOI.get(model, attr, bridge.lower).dimension)
end


text:
"""
```
eqcond(m::Li2020)
```

constructs the main loop of the functional iteration when solving
equilibrium in Li (2020) with jumps.
"""
function eqcond(m::Li2020)

    # Unpack items from m that are needed to construct the functional loop
    p_interpolant  = get_setting(m, :p_interpolant)
    xK_interpolant = get_setting(m, :xK_interpolant)
    xg_interpolant = get_setting(m, :xg_interpolant)
    κp_interpolant = get_setting(m, :κp_interpolant)
    firesale_interpolant  = get_setting(m, :firesale_interpolant)
    Q̂_interpolant         = get_setting(m, :Q̂_interpolant)
    Φ = get_setting(m, :Φ)
    Q = get_setting(m, :gov_bond_gdp_level) * get_setting(m, :avg_gdp)
    p₀, p₁ = boundary_conditions(m)[:p]
    max_jump = (p₁ - p₀) / p₁
    κp_grid = get_setting(m, :κp_grid)
    damping_function = get_setting(m, :damping_function)
    f_μK = get_setting(m, :μK)
    xg_tol = get_setting(m, :xg_tol)
    yg_tol = get_setting(m, :yg_tol)
    firesale_bound = get_setting(m, :firesale_bound)
    N_GH = get_setting(m, :N_GH)
    Q̂_tol = get_setting(m, :Q̂_tol)
    Q̂_max_it = get_setting(m, :Q̂_max_it)
    dt = get_setting(m, :dt)
    inside_iter_tol = get_setting(m, :inside_iteration_nlsolve_tol)
    inside_iter_max_iter = get_setting(m, :inside_iteration_nlsolve_max_iter)
    p_tol = get_setting(m, :p_tol)

    # Construct the initial guess for p by interpolating the solution from
    # the no jump equilibrium via SLM

    # The functional loop should return the proposals for the new values of the variables
    # over which we are iterating. For Li (2020), these are p, xg, and Q̂.
    f = function _functional_loop_li2020(stategrid::StateGrid, funcvar::OrderedDict{Symbol, Vector{S}},
                                         derivs::OrderedDict{Symbol, Vector{S}},
                                         endo::AbstractDict{Symbol, Vector{S}}, θ::NamedTuple;
                                         init_coefs::OrderedDict{Symbol, Vector{S}} =
                                         OrderedDict{Symbol, Vector{S}}(:p => Vector{S}(undef, 0)),
                                         individual_convergence::AbstractDict{Symbol, Vector{S}} =
                                         Dict{Symbol, Vector{S}}(),
                                         verbose::Symbol = :none) where {S <: Real}

        # Unpack variables of interest
        @unpack p, Q̂, xg = funcvar
        ∂p_∂w = derivs[:∂p_∂w]
        @unpack κp, ψ, xK = endo

        # Initialize storages for these values b/c they are separately stored at first due to tempered updating
        p_new  = similar(p)
        xg_new = similar(xg)
        κp_new = κp

        # Add boundaries
        p_new[1]    = p[1]
        p_new[end]  = p[end]
        xg_new[1]   = xg[1]
        xg_new[end] = xg[end]

        ## Step 1: Update for a new round
        p_fitted = extrapolate(interpolate((stategrid[:w], ), p, p_interpolant), Line())
        ψ  .= map((x, y) -> (Φ(x, θ[:χ], θ[:δ]) + θ[:ρ] * (x + y) - θ[:AL]) / (θ[:AH] - θ[:AL]), p, Q̂)
        xK .= ψ ./ stategrid[:w] .* p ./ (p + Q̂)

        solved_κp = trues(length(p)) # always solved at boundaries, but we need to know about the interior
        solved_xK = trues(length(p))
        solved_xg = trues(length(p))
        solved    = trues(length(p))

        ## Step 2: Solve p and xg for each grid point in the interior
        for i in 2:(length(stategrid) - 1)
            wᵢ     = stategrid[:w][i]
            pᵢ     = p[i]
            xKᵢ    = xK[i]
            xgᵢ    = xg[i]
            ∂p_∂wᵢ = ∂p_∂w[i]
            Q̂ᵢ     = Q̂[i]

            κp_new[i], xKᵢ, xg_new[i], succeed_κp, succeed_xK, succeed_xg =
                inside_iteration_li2020(wᵢ, p_fitted, pᵢ, ∂p_∂wᵢ, xKᵢ,
                                        xgᵢ, Q, Q̂ᵢ, max_jump, θ;
                                        κp_grid = κp_grid, xK_interpolant = xK_interpolant,
                                        damping_function = damping_function, xg_tol = xg_tol,
                                        nlsolve_tol = inside_iter_tol,
                                        nlsolve_iter = inside_iter_max_iter, verbose = verbose)

            ψᵢ = xKᵢ * wᵢ / (pᵢ / (pᵢ + Q̂ᵢ))
            p_new[i] = nlsolve(x -> Φ(x[1], θ[:χ], θ[:δ]) .+ θ[:ρ] .* (x[1] .+ Q̂ᵢ) .- (ψᵢ * θ[:AH] + (1. - ψᵢ) * θ[:AL]),
                           [(p₀ + p₁) / 2.]; ftol = p_tol).zero[1]
            solved_κp[i] = succeed_κp
            solved_xK[i] = succeed_xK
            solved_xg[i] = succeed_xg
        end

        # Where was the fixed point system correctly solved?
        solved_index = findall(map(i -> solved_xK[i] & solved_xg[i] & solved_κp[i], 1:(length(stategrid) - 1)))

        # Solve for p over the whole grid by interpolating over points with success
        p_new_slm = SLM(stategrid[:w][solved_index], p_new[solved_index]; increasing = true,
                        concave_down = true, left_value = p₀, right_value = p_new[solved_index[end]],
                        knots = Int(round(length(solved_index) / 2)), init = init_coefs[:p])
        if !isempty(init_coefs[:p]) && length(solved_index) == length(stategrid) - 1 # then we store the coefficients guess for the next round
            init_coefs[:p] .= vec(get_coef(p_new_slm))
        end

        # An alternative to SLM is Dierckx: p_new_spl  = Spline1D(w[solved_index], p_new[solved_index], bc = "extrapolate")
        # but it won't preserve features like monotonicity

        # Evaluate interpolants
        p_new[1:end - 1] .= eval(p_new_slm, stategrid[:w][1:end - 1])
        p_new[end] = p_new[end - 1]
        if !all(solved_xg) # if all(solved_xg), then linear interpolation will just return the same values as they currently are
            # Interpolate other quantities using a 1D cubic Spline
            xg_new_spl = extrapolate(interpolate((stategrid[:w][solved_xg], ), xg_new[solved_xg], xg_interpolant), Line())

            # xg_new_spl = Spline1D(stategrid[:w][solved_xg], xg_new[solved_xg], bc = "extrapolate")

            xg_new[1:end - 1] .= xg_new_spl(stategrid[:w][1:end - 1])
        end

        if !all(solved_κp)
            κp_new_spl = extrapolate(interpolate((stategrid[:w][solved_κp], ), κp_new[solved_κp], κp_interpolant), Line())

            # An alternative: Dierckx
            # κp_new_spl = Spline1D(stategrid[:w][solved_κp], κp_new[solved_κp], bc = "extrapolate")

            κp_new[1:end - 1] .= κp_new_spl(stategrid[:w][1:end - 1])
        end

        if verbose == :high
            println("$(100 * (length(solved_index) + 1) / length(stategrid[:w]))% of the inner iteration is solved")
            println("Calculating Q̂ . . .")
        end

        ## Step 3: Update Q̂ using simulation methods
        calc_Q̂ = haskey(individual_convergence, :Q̂) ? individual_convergence[:Q̂][1] == 0. : true

        if calc_Q̂
            prepare_Q̂!(stategrid, funcvar, derivs, endo, θ, f_μK, Φ, yg_tol, firesale_bound, firesale_interpolant, Q)

            Q̂_new = copy(funcvar[:Q̂])

            Q̂_calculation!(stategrid, Q̂_new, endo[:μw], endo[:σw],
                          endo[:κw], endo[:rf], endo[:rg], endo[:rh], Q, θ[:λ];
                          N_GH = N_GH, tol = Q̂_tol, max_it = Q̂_max_it, Q̂_interp_method = Q̂_interpolant, dt = dt,
                          verbose = verbose)
            # In the original code, a vector of zeros is used as the initial guess
#=            Q̂_new = Q̂_calculation(stategrid, zeros(eltype(m), length(stategrid)), endo[:μw], endo[:σw],
                                  endo[:κw], endo[:rf], endo[:rg], endo[:rh], Q, θ[:λ];
                                  N_GH = N_GH, tol = Q̂_tol, max_it = Q̂_max_it, Q̂_interp_method = Q̂_interpolant, dt = dt,
                                  verbose = verbose)=#

            if !isempty(individual_convergence)
                if sum(abs.(Q̂_new - funcvar[:Q̂])) < individual_convergence[:Q̂][2]
                    individual_convergence[:Q̂][1] = 1.
                    println(verbose, :high, "Q̂ has converged!")
                end
            end
        else
            Q̂_new = funcvar[:Q̂]
        end

        println(verbose, :high, "")

        return p_new, Q̂_new, xg_new # must be ordered in the same order as get_functional_variables(m)
    end
end

"""
```
inside_iteration_li2020(m, stategrid, funcvar, xK, xg, i; verbose = :low)
```

calculates a new xK, xg, and κp within a functional iteration loop
when solving equilibrium in Li (2020) with jumps.
"""
function inside_iteration_li2020(w::S, p_interp::Interpolations.AbstractInterpolation, p::S, ∂p_∂w::S,
                                 xK0::S, xg0::S, Q::S, Q̂::S, max_jump::S,
                                 θ::NamedTuple; κp_grid::AbstractVector{S} = Vector{S}(undef, 0),
                                 xK_max::S = 1e10, κp_residual_error::S = 1e30, xK_residual_error::S = 1e20,
                                 xg_residual_error::S = 1e20,
                                 xK_guess_prop::S = 0.9, xg_guess_prop::S = 0.999, κp_guess::S = 1e-3,
                                 xg_tol::S = 5e-4, residual_tol::Tuple{S, S, S} = (1e-6, 5e-5, 1e-3),
                                 xK_interpolant::Interpolations.InterpolationType = Gridded(Linear()),
                                 damping_function::Function = x -> 3e-8 ./ x,
                                 nlsolve_tol::S = 1e-8, nlsolve_iter::Int = 400, verbose::Symbol = :low) where {S <: Real}

    ## Set up

    # Set flags
    succeed_κp = false
    succeed_xK = false
    succeed_xg = false

    # Create useful functions that will be re-used
    yK_f(xK) = (p ./ (p .+ Q̂) .- w .* xK) ./ (1. .- w)
    yg_f(xg) = (Q ./ (p .+ Q̂) .- w .* xg) ./ (1. .- w)
    yg    = yg_f(xg0) # initializing this value for use in some of the following functions
    σp_f(xK) = ∂p_∂w .* w .* (1. .- w) .* (xK .- yK_f(xK)) ./ (1. .- ∂p_∂w .* w .* (1. .- w) .* (xK .- yK_f(xK))) .* θ[:σK]
    δₓ_f(xK, xg) = max.(θ[:β] .* (xK .+  xg .- 1.) .- xg, 0.)
    I_f(xK, xg) = map(x -> x ? 1. : 0., (θ[:β] .* (xK .+ xg .- 1.) .- xg) .> 0.)
    κd_f(xK, xg) = θ[:θ] .* max.(xK .+ (θ[:ϵ] - 1.), 0.) ./ (xK .+ xg .- 1.)
    κfs_f(xK, xg) = θ[:α] ./ (1. .- θ[:α]) .* δₓ_f(xK, xg) .* w  ./ (1. .- w)
    κb_f(κp, xK) = θ[:θ] .* (1. .- θ[:ϵ]) .+ (1. .- θ[:θ]) .* (xK .* κp .+ θ[:α] ./ (1. .- θ[:α]) .* δₓ_f(xK, xg0))
    κh_f(κp, xK) = yK_f(xK) .* κp .+ (1. .- yK_f(xK) .- yg) .* κd_f(xK, xg0) .- κfs_f(xK, xg0)

    ## Step 1. Solve the xK and κp together

    # Define some bounds for where to search
    xK_upper = min(∂p_∂w >= 0. ? (1. + 1. ./ (w .* ∂p_∂w)) : xK_max, p ./ (p .+ Q̂) ./ w)
    xK_lower = 1.
    κp_upper = max_jump
    κp_lower = 0.

    # Define the residual functions for the system of κp and xK
    function κp_residual(F, κp, xK)
        F .= p .- p_interp(w .* (1. .- κb_f(κp, xK)) ./ (1. .- κh_f(κp, xK) .- w .* (κb_f(κp, xK) .- κh_f(κp, xK)))) .-
            κp .+ ((any(κb_f(κp, xK) .> 1.) || any(κh_f(κp, xK) .> 1.) || any(κp .> κp_upper) || any(κp .< κp_lower)) ? κp_residual_error : 0.)
    end
    # xK residual isn't matching up, it looks like somehow one of the 1e20 conditions is getting triggered in Matlab
    function xK_residual(F, κp, xK, xK_res_upper)
        F .= 1e3 .* ((θ[:σK] .+ σp_f(xK)) .^ 2 .* (xK .- yK_f(xK)) .+
                     (θ[:λ] * (1. - θ[:θ])) .* ((κp .+ I_f(xK, xg0) .* (θ[:α] / (1. - θ[:α]) * θ[:β])) ./
                                                (1. .- xK .* κp .- (θ[:α] / (1. - θ[:α])) .* δₓ_f(xK, xg0))) .-
                     θ[:λ] .* (κp .- κd_f(xK, xg0)) ./ (1. .- yK_f(xK) .* κp .- (1. .- yK_f(xK) .- yg) .* κd_f(xK, xg0) .+ κfs_f(xK, xg0)) .-
                     (θ[:AH] - θ[:AL]) ./ p) .+
                     ((any(xK .> xK_res_upper) || any(xK .< xK_lower) || any((θ[:α] / (1. - θ[:α])) .* δₓ_f(xK, xg0) .+ xK .* κp .> 1.)) ?
                     xK_residual_error : 0.)
    end

    # For testing purposes
    if verbose == :high
        upper = (1. - θ[:α] / (1 - θ[:α]) * (θ[:β] * (xg0 - 1) - xg0)) / (0. + θ[:α] / (1 - θ[:α] * θ[:β]))
        xK_test_vec = range(xK_lower, stop = upper, length = 100)
        κp_test_vec = range(κp_lower, stop = .012, length = 200)
        # Plot these residuals xK_residual([0.], 0, xK_test_vec), κp_residual([0.], κp_test_vec, xK)
    end

    # Normal case where bankers are leveraged
    if xK_upper > 1

        # Solve xK for different κp's
        xKs        = similar(κp_grid)
        solved_xKs = BitArray(undef, length(xKs))

        for (j, κp) in enumerate(κp_grid)
            xK_tighter_upper = (1. - θ[:θ] * (1. - θ[:ϵ]) - (1. - θ[:θ]) * (θ[:α] / (1. - θ[:α])) * (θ[:β] * (xg0 - 1.) - xg0)) /
                ((1. - θ[:θ]) * (κp + θ[:α] / (1. - θ[:α]) * θ[:β]))
            xK_guess = xK_guess_prop * min(xK0, (1 - θ[:ϵ]) / κp, xK_tighter_upper)
            if xK_guess < 1.
                xK_guess = (1. + xK0) / 2.
            end
            out = nlsolve((F, xK) -> xK_residual(F, κp, xK, min(xK_tighter_upper, xK_upper)),
                          [xK_guess]; ftol = nlsolve_tol)

            xKs[j] = out.zero[1]
            residual = out.residual_norm # w/1 variable, this is precisely the residual

            if abs(residual) > residual_tol[1] # Is the residual too big?

                # If the solution is on the order of yK = 0, then it's fine
                if abs(xKs[j] - p / (p + Q̂) / w) < residual_tol[2] &&
                    xK_residual([0.], κp, xKs[j], min(xK_upper, xK_tighter_upper))[1] < 0.
                    residual = 0.
                end

                # Full liquidity insurance scenario
                if abs(xKs[j] - (1. - θ[:β]) / θ[:β] + xg0 - 1.) < residual_tol[1]
                    xKs[j] = (1. - θ[:β]) / θ[:β] * xg0 + 1.
                    residual = 0.
                end
            end
            solved_xKs[j] = abs(residual) < residual_tol[1]
        end

        # Now solve for κp
        roots_xK = extrapolate(interpolate((κp_grid[solved_xKs], ), xKs[solved_xKs], xK_interpolant), Line())
        if all(abs.(xKs .+ xg0 .- 1.) .>= residual_tol[1]) # Banks are still leveraged
            out = nlsolve((F, κp) -> κp_residual(F, κp, roots_xK(κp)), [κp_guess]; ftol = nlsolve_tol, iterations = nlsolve_iter)
            κp = out.zero[1]
            succeed_κp = out.f_converged

            xK_tighter_upper = (1. - θ[:θ] * (1. - θ[:ϵ]) - (1. - θ[:θ]) *
                                θ[:α] / (1. - θ[:α]) * (θ[:β] * (xg0 - 1.) - xg0) ) /
                                ((1. - θ[:θ]) * (κp + θ[:α] / (1. - θ[:α]) * θ[:β]))
            out = nlsolve((F, xK) -> xK_residual(F, κp, xK, min(xK_tighter_upper, xK_upper)), [roots_xK(κp)];
                          ftol = nlsolve_tol, iterations = nlsolve_iter)
            xK  = out.zero[1]
            succeed_xK = out.f_converged

            # At the corner xK = 1 / w?
            if abs(xK - p / (p + Q̂) / w) < residual_tol[2]
                xK = p / (p + Q̂) / w
                succeed_xK = xK_residual([0.], κp, xK, min(xK_tighter_upper, xK_upper))[1] < 0
            end

            # Full liquidity insurance scenario
            if abs(xK - (1. - θ[:β]) / θ[:β] * xg0 - 1.) < residual_tol[1]
                xK = (1 - θ[:β]) / θ[:β] * xg0 + 1
                succeed_xK = true
            end

            # Solve for xg now
            xg_upper = Q / (w * (p + Q̂))
            xg_lower = max(θ[:ϵ], 1. / (1. - θ[:β]) * (θ[:β] * (xK - 1.) - (1. - θ[:α]) / θ[:α] * (1. - xK * κp)))
            function xg_residual(F, xg)
                F .= 1e3 .* (I_f(xK, xg) .* (θ[:λ] * (1. - θ[:θ]) * θ[:α] / (1. - θ[:α]) * (1. - θ[:β])) ./
                             (1. .- xK .* κp .- (θ[:α] / (1. - θ[:α])) .* δₓ_f(xK, xg)) .- θ[:λ] .* κd_f(xK, xg) ./
                             (1. .- yK_f(xK) .* κp .- (1. .- yK_f(xK) .- yg_f(xg)) .* κd_f(xK, xg) .+
                              κfs_f(xK, xg)) - damping_function(max.(yg_f(xg), 1e-15))) .+
                              ((any(xg .> xg_upper) || any(xg .< xg_lower)) ? xg_residual_error : 0.)
            end

            if verbose == :high
                xg_test_vec = range(xg_lower, stop = 0.97 * xg_upper, length = 200)
                # Plot xg_residual(xg_test_vec)
            end

            out = nlsolve(xg_residual, [min(xg0, xg_guess_prop * xg_upper)]; ftol = nlsolve_tol, iterations = nlsolve_iter)
            xg  = out.zero[1]
            succeed_xg = out.f_converged

            # Full liquidity insurance
            if abs(xg - θ[:β] / (1. - θ[:β]) * (xK - 1.)) < residual_tol[1]
                xg = θ[:β] / (1. - θ[:β]) * (xK - 1.)
                succeed_xg = true
            end

            # Boundary case
            if (abs(xg - θ[:ϵ]) < residual_tol[1]) && (xg_residual([0.], xg)[1] < 0)
                xg = θ[:ϵ]
                succeed_xg = xg_residual < xg_residual([0.], xg)
            end

            # Second to last case
            if abs(xg - Q / (w * (p + Q̂))) < residual_tol[3]
                xg = Q / (w * (p + Q̂))
                succeed_xg = true
            end

            # Check if the xg solution passes a weaker tolerance
            if !succeed_xg
                out = nlsolve(xg_residual, [min(xg0, xg_guess_prop * xg_upper)]; ftol = xg_tol, iterations = nlsolve_iter)
                xg  = out.zero[1]
                succeed_xg = out.f_converged

                # Full liquidity insurance
                abs(xg - θ[:β] / (1. - θ[:β]) * (xK - 1.))
                if abs(xg - θ[:β] / (1. - θ[:β]) * (xK - 1.)) < residual_tol[2]
                    xg = θ[:β] / (1. - θ[:β]) * (xK - 1.)
                    succeed_xg = true
                end
            end
        end
    end

    ## Step 3: Finish up the inside iteration
    if !(succeed_κp && succeed_xK && succeed_xg)
        warn_str = "At w = $(w), the model has not been solved for "
        to_warn  = Vector{String}(undef, 0)
        if !succeed_κp
            push!(to_warn, "κp")
        end
        if !succeed_xK
            push!(to_warn, "xK")
        end
        if !succeed_xg
            push!(to_warn, "xg")
        end
        all_warns = join(to_warn, ", ")

        if verbose == :low || verbose == :high
            @warn warn_str * all_warns * "."
        end
    end

    return κp, xK, xg, succeed_κp, succeed_xK, succeed_xg
end

"""
```
function prepare_Q̂!(stategrid::StateGrid, funcvar::OrderedDict{Symbol, Vector{S}}, derivs::OrderedDict{Symbol, Vector{S}},
    endo::OrderedDict{Symbol, Vector{S}}, θ::NamedTuple, f_μK::Function, Φ::Function, yg_tol::S, firesale_bound::S,
    firesale_interpolant::Function, Q::S) where {S <: Real}
```

calculates the quantities needed for Q̂. Most of this function is a copy of augment_variables!, but
some quantities don't need to be calculated and have been omitted for speed purposes.
"""
function prepare_Q̂!(stategrid::StateGrid, funcvar::OrderedDict{Symbol, Vector{S}}, derivs::OrderedDict{Symbol, Vector{S}},
                    endo::OrderedDict{Symbol, Vector{S}}, θ::NamedTuple, f_μK::Function, Φ::Function, yg_tol::S, firesale_bound::S,
                    firesale_interpolant::Interpolations.InterpolationType, Q::S) where {S <: Real}
    @unpack ψ, xK, yK, yg, σp, σ, σh, σw, μR_rd, rd_rg, rd_rg_H, μb_μh, μw, μp, μK, μR, rd, rg, μb, μh, κp, invst, κb, κd, κh, κfs, firesale_jump, κw, δ_x, indic, rf, rh, rd_rf, μp, μK, μR = endo
    @unpack p, xg, Q̂ = funcvar
    ∂p_∂w = derivs[:∂p_∂w]
    ∂²p∂w² = derivs[:∂²p_∂w²]
    w    = stategrid[:w]

    # Calculate various quantities
    ∂p_∂w  .= differentiate(w, p)    # as Li (2020) does it
    ∂²p∂w² .= differentiate(w, ∂p_∂w)
    invst  .= map(x -> Φ(x, θ[:χ], θ[:δ]), p)
    ψ      .= (invst .+ θ[:ρ] .* (p + Q̂) .- θ[:AL]) ./ (θ[:AH] - θ[:AL])
    ψ[ψ .> 1.] .= 1.

    # Portfolio choices
    xK   .= (ψ ./ w) .* (p ./ (p + Q̂))
    xK[1] = xK[2]
    yK   .= (p ./ (p + Q̂) - w .* xK)  ./ (1. .- w)
    yK[1] = 1.
    yK[end] = yK[end - 1]
    yg   .= (Q ./ (p + Q̂) - w .* xg) ./ (1. .- w)
    yg[end] = yg[end - 1]
    yg[yg .< yg_tol] .= yg_tol # avoid yg < 0
    δ_x   .= max.(θ[:β] .* (xK + xg .- 1.) - xg, 0.)
    indic .= δ_x .> 0.

    # Volatilities
    σp .= ∂p_∂w .* w .* (1. .- w) .* (xK - yK) ./ (1. .- ∂p_∂w .* w .* (1. .- w) .* (xK - yK)) .* θ[:σK]
    σp[end] = 0. # no volatility at the end
    σ  .= xK .* (θ[:σK] .+ σp)
    σh .= yK .* (θ[:σK] .+ σp)
    σw .= (1. .- w) .* (σ - σh)

    # Deal with post jump issues
    firesale_jump .= xK .* κp + (θ[:α] / (1 - θ[:α])) .* δ_x
    firesale_ind  = firesale_jump .< firesale_bound
    firesale_spl  = extrapolate(interpolate((w[firesale_ind], ), firesale_jump[firesale_ind], firesale_interpolant), Line()) # linear extrapolation
    firesale_jump .= firesale_spl(w)

    # Jumps
    κd  .= θ[:θ] .* (xK .+ θ[:ϵ] .- 1.) ./ (xK .+ xg .- 1.) .* (xK .+ θ[:ϵ] .> 1.)
    κb  .= θ[:θ] .* min.(1. - θ[:ϵ], xK) + (1. .- θ[:θ]) .* firesale_jump
    κfs .= (θ[:α] / (1 - θ[:α])) .* δ_x .* w ./ (1. .- w)
    κfs[end] = 0.
    κh  .= yK .* κp + (1. .- yK .- yg) .* κd - κfs
    κw  .= 1. .- (1. .- κb) ./ (1. .- κh .- w .* (κb - κh))

    # Main drifts and interest rates
    μR_rd   .= (θ[:σK] .+ σp) .^ 2 .* xK - θ[:AH] ./ p + (θ[:λ] * (1. - θ[:θ])) .*
        (κp + indic .* (θ[:α] / (1 - θ[:α]) * θ[:β])) ./ (1. .- firesale_jump) +
         ((xK .+ θ[:ϵ]) .< 1.) .* (θ[:λ] * θ[:θ]) ./ (1. .- xK)
    rd_rg   .= (θ[:λ] * (1 - θ[:θ]) * θ[:α] / (1 - θ[:α]) * (1 - θ[:β])) .* indic ./ (1. .- firesale_jump)
    rd_rg_H .= θ[:λ] .* κd ./ (1. .- yK .* κp .- (1. .- yK .- yg) .* κd .+ κfs)
    index_xK = xK .<= 1. # In this scenario, the rd-rg difference must be solved from hh's FOC
    rd_rg[index_xK] = rd_rg_H[index_xK]
    μb_μh   .= (xK - yK) .* μR_rd + (xK .* θ[:AH] - yK .* θ[:AL]) ./ p - (xg - yg) .* rd_rg
    μw      .= (1. .- w) .* (μb_μh + σh .^ 2 - σ .* σh - w .* (σ - σh) .^ 2 -
                       θ[:η] ./ (1. .- w))
    μw[end]  = μw[end - 1] # drift should be similar at the end
    μp      .= ∂p_∂w .* w .* μw + (1. / 2.) .* ∂²p∂w² .* (w .* (1. .- w) .* (σ - σh)) .^ 2
    μp[end]  = μp[end - 1] # drift should be similar at the end
    μK      .= map(x -> f_μK(x, θ[:χ], θ[:δ]), p)
    μR      .= μp .- θ[:δ] + μK + θ[:σK] .* σp - invst ./ p

    # Other interest rates
    rd    .= μR - μR_rd
    rg    .= rd - rd_rg
    rd_rf .= (θ[:λ] * (1. - θ[:θ]) * θ[:α] / (1 - θ[:α]) * (-θ[:β])) .* indic ./ (1. .- firesale_jump)
    rf    .= rd - rd_rf
    rh    .= rd - θ[:λ] .* κd ./ (1. .- yK .* κp - (1. .- yK .- yg) .* κd .+ κfs) # risk free rate for households
end

"""
```
Q̂_calculation!(stategrid::StateGrid, Q̂::AbstractVector{S}, μw::AbstractVector{S}, σw::AbstractVector{S},
    κw::AbstractVector{S}, rf::AbstractVector{S}, rg::AbstractVector{S}, rh::AbstractVector{S}, Q::S, λ::S;
    N_GH::Int = 10, tol::S = 1e-5, max_it::Int = 1000, Q̂_interp_method = Gridded(Linear()),
    testing::Bool = false, verbose::Symbol = :none) where {S <: Real}
```

calculates Q̂ using Gauss-Hermite quadrature. This function modifies Q̂ in place.
"""
function Q̂_calculation!(stategrid::StateGrid, Q̂::AbstractVector{S}, μw::AbstractVector{S}, σw::AbstractVector{S},
                       κw::AbstractVector{S}, rf::AbstractVector{S}, rg::AbstractVector{S}, rh::AbstractVector{S}, Q::S, λ::S;
                       N_GH::Int = 10, tol::S = 1e-5, max_it::Int = 1000,
                       Q̂_interp_method::Interpolations.InterpolationType = Gridded(Linear()), dt::S = 1. / 12.,
                       testing::Bool = false, verbose::Symbol = :low) where {S <: Real}

    ## Set up
    spread = rf - rg
    ϵ_nodes, weight_nodes = gausshermite(N_GH) # approximates exp(-x²)
    ϵ_nodes .*= sqrt(2)      # Normalize ϵ and weight nodes to correctly
    weight_nodes ./= sqrt(π) # approximate a standard Normal distribution

    if testing
        err_vec = Vector{S}(undef, max_it)
    end

    ## Main calculation loop
    err     = 1.
    iter_no = 0
    while (err > tol) && (iter_no < max_it)
        iter_no += 1     # Benchmark tests show that, when length(stategrid[:w]) = 100, copying w/in while loop is faster
        Q̂_last = copy(Q̂) # than having this defined outside the while loop by 5-6 ms. Also 100 times faster than MATLAB!
        Q̂_interp = extrapolate(interpolate((stategrid[:w], ), Q̂_last,
                                           Q̂_interp_method), Line())  # Linear extrapolation
        # Calculate Q̂ everywhere except w = 0
        for i in 2:length(stategrid[:w])

            # Unpack objects characterizing equilibrium
            wᵢ  = stategrid[:w][i]
            μwᵢ = μw[i]
            σwᵢ = σw[i]
            κwᵢ = κw[i]

            # Calculate expectation
            w_noshock   = wᵢ .* (1. .+ μwᵢ * dt .+ σwᵢ .* ϵ_nodes)
            w_shock     = w_noshock .- wᵢ .* κwᵢ
            expectation = (1. - λ * dt) * (weight_nodes' * Q̂_interp(w_noshock)) + λ * dt * (weight_nodes' * Q̂_interp(w_shock))
            Q̂[i]        =  Q * spread[i] * dt + exp(-rf[i] * dt) * expectation
        end

        # Handle case of w = 0
        Q̂[1] = Q * spread[1] / rf[1]

        # Calculate errors
        err = sum(abs.(Q̂ - Q̂_last))
        if testing
            err_vec[iter_no] = err
        end
    end

    if verbose == :high && (iter_no < max_it || err < tol)
        println("Finished calculating Q̂")
    end

    if testing
        return Q̂, err_vec
    else
        return Q̂
    end
end

"""
```
eqcond_nojump(m::Li2020)
```

constructs the ODE characterizing equilibrium
with no jumps and the events deciding termination
"""
function eqcond_nojump(m::Li2020)
    Φ  = get_setting(m, :Φ)
    ∂Φ = get_setting(m, :∂Φ)
    ∂p_∂w0, ∂p_∂wN = get_setting(m, :boundary_conditions)[:∂p_∂w]

    f1 = function _ode_nojump_li2020(p, θ, w)
        if w == 0.
            ∂p_∂w = ∂p_∂w0
        elseif w == 1.
            ∂p_∂w = ∂p_∂wN
        else
            ψ = max(min((Φ(p, θ[:χ], θ[:δ]) + θ[:ρ] * p - θ[:AL]) / (θ[:AH] - θ[:AL]), 1.), 0.)
            xK = (ψ / w)
            yK = (1. - ψ) / (1. - w)
            σp = sqrt((θ[:AH] - θ[:AL]) / (p * (xK - yK))) - θ[:σK]
            σ  = xK * (θ[:σK] + σp)
            σh = yK * (θ[:σK] + σp)

            ∂p_∂w = max(0., σp ./ (w .* (1. - w) .* (xK - yK) .* (θ[:σK] + σp)))
        end

        return ∂p_∂w
    end

    # Terminal condition
    ode_condition(p, w, integrator) = p - get_setting(m, :boundary_conditions)[:p][2]
    ode_affect!(integrator) = terminate!(integrator)
    cb = ContinuousCallback(ode_condition, ode_affect!)

    return f1, cb
end

# For use during the solve step since we also store the first derivative's boundary conditions
# but they are not used by the ODE solver.
function nojump_ode_init(m::Li2020)
    return get_setting(m, :boundary_conditions)[:p][1]
end


text:
using Logging: Logging, AbstractLogger

struct ProgressLogRouter{D<:AbstractLogger,P<:AbstractLogger} <: AbstractLogger
    defaultlogger::D
    progresslogger::P
end

_hasprogress(; progress = nothing, _...) = progress === "done" || progress isa Real

function Logging.handle_message(logger::ProgressLogRouter, args...; kwargs...)
    level, _, _module, group, id = args
    if _hasprogress(; kwargs...)
        Logging.handle_message(logger.progresslogger, args...; kwargs...)
    elseif level >= Logging.min_enabled_level(logger) &&
           Logging.shouldlog(logger, level, _module, group, id)
        Logging.handle_message(logger.defaultlogger, args...; kwargs...)
    end
end

Logging.shouldlog(logger::ProgressLogRouter, args...) =
    Logging.shouldlog(logger.defaultlogger, args...) ||
    Logging.shouldlog(logger.progresslogger, args...)

Logging.min_enabled_level(logger::ProgressLogRouter) = min(
    Logging.min_enabled_level(logger.defaultlogger),
    Logging.min_enabled_level(logger.progresslogger),
)


text:
using SearchLight

try
  SearchLight.Configuration.load()

  if SearchLight.config.db_config_settings["adapter"] !== nothing
    eval(Meta.parse("using SearchLight$(SearchLight.config.db_config_settings["adapter"])"))
    SearchLight.connect()
  end
catch ex
  @error ex
end


text:
#Attempts to read every .mtx file in the test directory
using MatrixMarket

include("dl-matrixmarket.jl")

num_errors = 0
num_pass = 0

for filename in readdir()
    endswith(filename, ".mtx") || continue
    try
        A = MatrixMarket.mmread(filename)
        println(filename, " : ", typeof(A), "  ", size(A))
        num_pass += 1
    catch err
        println()
        println()
        println("PARSE ERROR")
        println(filename, " : ", typeof(err), " : ", :msg in names(err) ? err.msg : "")
        if !isa(err, ErrorException)
            println(filter(x->x[1]!=symbol("???"),
                    map(x->ccall(:jl_lookup_code_address, Any, (Ptr{Void}, Cint), x, true),
                    catch_backtrace())))
        end
        println()
        println()
        num_errors += 1
    end
end

println("Summary: $num_errors parse errors in $(num_errors + num_pass) matrices ")

exit(num_errors)